> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mailchannels.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Laravel

> Send email through Laravel Mail using the MailChannels driver.

The `mailchannels/mailchannels-php` package includes a Laravel service provider that registers `mailchannels` as a
[Mail](https://laravel.com/docs/13.x/mail) driver.

Laravel's `Mail` facade is built on Symfony Mailer under the hood,
and uses the exact same transport as the [Symfony integration](/email-api/symfony).

<Info>
  This plugin is optional and lives alongside the rest of the PHP SDK. The plugin itself can only send mail. It
  doesn't implement the full API surface (sub-accounts, keys, webhooks, etc.). For those features, use the SDK's
  `Client` directly.
</Info>

## Prerequisites

Before you send your first message, follow the [PHP quickstart](/email-api/php/quickstart#prerequisites) prerequisite section.
This will walk you through creating an account, generating an API key, and adding the required Domain
Lockdown and SPF DNS records.

## Installation

```bash theme={null}
composer require mailchannels/mailchannels-php
```

The SDK also needs a PSR-18 HTTP client and PSR-17 factories. Symfony HTTP Client + Nyholm PSR-7 is a good fit here,
since Laravel Mail is built on Symfony Mailer (Guzzle works too, but install one or the other, not both):

```bash theme={null}
composer require symfony/http-client nyholm/psr7
```

### Configuring Laravel

<Steps>
  <Step title="Add a mailchannels mailer">
    Add a `mailchannels` mailer in `config/mail.php`:

    ```php config/mail.php theme={null}
    return [
        // ...
        'mailers' => [
            // ...
            'mailchannels' => [
                'transport' => 'mailchannels',
            ],
        ],
    ];
    ```
  </Step>

  <Step title="Add your API key">
    Add it to `config/services.php`:

    ```php config/services.php theme={null}
    return [
        // ...
        'mailchannels' => [
            'api_key'  => env('MAILCHANNELS_API_KEY'),
            'base_url' => env('MAILCHANNELS_API_URL'), // optional; omit for the default
        ],
    ];
    ```
  </Step>

  <Step title="Point Laravel at the new mailer">
    Set in your environment or `.env` file:

    ```bash .env theme={null}
    MAIL_MAILER=mailchannels
    MAILCHANNELS_API_KEY=your-api-key
    ```
  </Step>
</Steps>

## Sending mail

Once configured, send mail through the standard `Mail` facade. No MailChannels-specific code is required:

```php theme={null}
use App\Mail\WelcomeEmail;
use Illuminate\Support\Facades\Mail;

Mail::to('recipient@example.com')->send(new WelcomeEmail());
```

See Laravel's docs on [generating mailables](https://laravel.com/docs/13.x/mail#generating-mailables)
for everything else `Email` supports (multiple recipients, reply-to, attachments and so on).

Anything built with a Laravel [Mailable](https://laravel.com/docs/13.x/mail#generating-mailables) (`from`,
`to`/`cc`/`bcc`, `subject`, `text`/`html` bodies, attachments) can be sent through this transport.

<Note>
  Only one personalization is ever built per message. If you need to send multiple individualized emails in one request,
  call the SDK's `Client` directly instead of going through `Mail`. See
  [How emails are structured](/email-api/how-emails-are-structured) for more information on personalizations.
</Note>

### Control headers

A Laravel `Mailable` has no equivalent for some MailChannels-specific features. Reach those instead through custom
headers prefixed with `x-mailchannels-`. The `x-mailchannels-*` headers are stripped before the message is sent, so
recipients never see them.

Set these (and any other custom headers) from a `Mailable`'s `headers()`
method:

```php theme={null}
use Illuminate\Mail\Mailable;
use Illuminate\Mail\Mailables\Headers;

class WelcomeEmail extends Mailable
{
    public function headers(): Headers
    {
        return new Headers(
            text: [
                'X-Misc-Header' => 'welcome-2026',
                'x-mailchannels-transactional' => 'true',
            ],
        );
    }
}
```

<Note>
  If the same custom header is added twice, only the **last** value is used.
</Note>

Boolean headers accept only the literal strings `"true"` / `"false"`; anything else throws
`Symfony\Component\Mailer\Exception\TransportException`. An empty value is treated as unset (falls back to the default).

| Header                                 | Description                                                                                                                                                                                                                                         |
| -------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `x-mailchannels-send-async`            | Queue the message (`true`, the default) instead of sending it synchronously (`false`). Equivalent to calling the SDK's `queue()` vs. `send()`. Queued sends report delivery status via [webhooks](/email-api/webhooks) rather than in the response. |
| `x-mailchannels-click-tracking-enable` | Enable click tracking.                                                                                                                                                                                                                              |
| `x-mailchannels-click-tracking-domain` | Custom domain for click-tracking links. See [Custom tracking](/email-api/custom-tracking).                                                                                                                                                          |
| `x-mailchannels-open-tracking-enable`  | Enable open tracking.                                                                                                                                                                                                                               |
| `x-mailchannels-open-tracking-domain`  | Custom domain for open-tracking links. See [Custom tracking](/email-api/custom-tracking).                                                                                                                                                           |
| `x-mailchannels-unsubscribe-domain`    | Custom domain for unsubscribe links. See [Custom tracking](/email-api/custom-tracking).                                                                                                                                                             |
| `x-mailchannels-transactional`         | Whether the mail is transactional or non-transactional (marketing, etc.). Affects List-Unsubscribe handling, see [Unsubscribe](/email-api/unsubscribe).                                                                                             |
| `x-mailchannels-dkim-domain`           | Domain to use for DKIM signing.                                                                                                                                                                                                                     |
| `x-mailchannels-dkim-selector`         | Selector to use for DKIM signing.                                                                                                                                                                                                                   |
| `x-mailchannels-dkim-private-key`      | Private key to use for DKIM signing.                                                                                                                                                                                                                |
| `x-mailchannels-campaign-id`           | Campaign that this message is part of.                                                                                                                                                                                                              |

Each of these corresponds directly to a field on the [send endpoint](/api-reference/send/send-an-email). See that
reference for full semantics.

<Warning>
  This transport only supports DKIM via the `x-mailchannels-dkim-*` headers above.

  If a `DKIM-Signature` header is already present on the message, the message is rejected, since the provided signature
  won't match the message the API constructs.

  See [DKIM signing and key management](/email-api/configuring-dkim)
  for information on how MailChannels handles signing and keys.
</Warning>

<Note>
  Laravel's own mail queueing (`ShouldQueue` mailables, `Mail::queue()`) is unrelated to the `x-mailchannels-send-async`
  control header:

  The former controls *when your application* hands the message to the transport;
  the latter controls whether *MailChannels* processes it synchronously or asynchronously once it arrives.

  You can use them independently or together.
</Note>

## Error handling

Any SDK exception raised while sending (authentication, validation, rate limiting, server errors) is caught and
re-thrown as `Symfony\Component\Mailer\Exception\TransportException`.

Access the original exception via `$e->getPrevious()` to inspect it:

```php theme={null}
use Symfony\Component\Mailer\Exception\TransportException;

try {
    Mail::to($recipient)->send(new WelcomeEmail());
} catch (TransportException $e) {
    $previous = $e->getPrevious();
    if ($previous instanceof \MailChannels\Exception\RateLimitException) {
        // handle rate limit
    } elseif ($previous instanceof \MailChannels\Exception\ValidationException) {
        // handle validation error
    } else {
        // handle other transport errors
    }
}
```

## Limitations

* **One personalization per message.** No per-recipient template data or per-recipient header overrides through this
  transport.
* **No Mustache templating.** This transport has no way to use mailchannels' mustache template rendering. If you need
  to do so, use Laravel's [Blade Template Support](https://laravel.com/docs/13.x/blade), or use the SDK's `Client`
  directly; see [Templates](/email-api/templates) for how.
* **DKIM only via the MailChannels API**, as described above.

## Next steps

* Read the [webhooks guide](/email-api/webhooks) to learn how to get real-time notifications about email
  delivery, bounces, and complaints.
* Explore the [API reference](/email-api/api-reference-introduction) to see what else you can do with the API.
