Skip to content

Documentation

Send email from Laravel.

Two ways in: the Mailtruss mail driver, or plain SMTP settings.

Before you start

You need a verified sending domain (see Domains) and an API key (under API keys in the dashboard; it is shown once). Keep the key in an environment variable on your server, never in code that runs in a browser or an app.

Option 1: the Mailtruss mail driver

Install the PHP library. The service provider is auto-discovered. Add the key to config/services.php and a mailer to config/mail.php, then set MAIL_MAILER=mailtruss. Mailables, notifications and queued mail then go through the API: Bcc is kept, attachments and inline images work, and a retried queue job does not send twice (the Message-ID is the idempotency key).

Terminal
composer require mailtruss/mailtruss

Driver configuration

Three small edits: the key, the mailer, and which mailer is the default.

config and .env
// config/services.php
'mailtruss' => ['key' => env('MAILTRUSS_API_KEY')],
​
// config/mail.php, inside 'mailers'
'mailtruss' => ['transport' => 'mailtruss'],
​
// .env
MAIL_MAILER=mailtruss
MAILTRUSS_API_KEY=ms_live_...
MAIL_FROM_ADDRESS=hello@yourdomain.com

Option 2: SMTP

If you would rather not add a package, point Laravel's SMTP mailer at Mailtruss. The API key is the password, and any username works.

.env
MAIL_MAILER=smtp
MAIL_HOST=smtp.mailtruss.com
MAIL_PORT=587
MAIL_USERNAME=mailtruss
MAIL_PASSWORD=ms_live_... # a Mailtruss API key
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS=hello@yourdomain.com

Try it without sending real mail

From php artisan tinker, send a raw message to the test address. It needs no verified domain and reaches no real mailbox.

php artisan tinker
Mail::raw('Hello from Laravel', fn ($m) => $m->to('delivered@mailtruss.test')->subject('Test'));

See what happened

Open the message under Emails in the dashboard: it shows the recorded timeline, what each event proves, and a diagnosis if something went wrong. Or fetch it with GET /api/v1/emails/:id/events. To be told as it happens, add a webhook.

If it fails

API requests answer with an error name and message. The common ones:

  • 403 invalid_api_key or 401 missing_api_key: the key is wrong, revoked or not sent. Send it as Authorization: Bearer ms_live_….
  • 403 domain_not_verified: the from address is on a domain that is not verified. Publish the DNS records and re-check.
  • 422 validation_error: fix the field the message names. Nothing was sent and no quota was used.
  • 429 rate_limit_exceeded: back off for the Retry-After header. See rate limits.

Over SMTP, the relay answers with a reply code:

  • 535: the API key is wrong or revoked. Fix the password.
  • 550: refused for good (unverified domain, suppressed recipient, invalid message). Do not retry; the reply says why.
  • 552: too large, or the monthly limit is reached.
  • 451 or 452: temporary (rate limit, daily limit, or a brief problem on our side). Retry later; mail servers do this automatically.

Problems that happen after a message is accepted (bounces, complaints) are explained under delivery errors.

Other guides

Last updated

Something wrong or unclear on this page?

Report an issue