mailchannels/mailchannels-php package ships a Symfony Mailer transport.
If you already have a Symfony application that builds Symfony\Component\Mime\Email objects and sends them through
MailerInterface, you can switch to MailChannels with just a few lines of configuration.
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.Prerequisites
Before you send your first message, follow the PHP quickstart 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
Install the SDK and the Symfony Mailer component:Configuring Symfony
1
Register the transport factory
Symfony discovers mailer transports through tagged services. Register the factory in See Symfony’s docs on custom transport factories
for background on how this mechanism works.
config/services.yaml:config/services.yaml
2
Point MAILER_DSN at MailChannels
Set the
MAILER_DSN environment variable, in your .env file or your environment:.env
- Scheme:
mailchannelsormailchannels+api(both accepted). - DSN user: your MailChannels API key.
- DSN host: leave as
defaultfor the production API endpoint.
Sending mail
Once configured, send mail through the standardMailerInterface. No MailChannels-specific code is required for a
basic send:
Email supports (multiple recipients, reply-to, attachments, and so on).
This transport only builds one personalization per message. If you need to send multiple individualized emails in one
request, call the SDK’s
Client directly instead of going through MailerInterface. See
How emails are structured for more information on personalizations.Control headers
Symfony’sEmail object has no equivalent for some MailChannels API features. Reach those instead through custom
headers prefixed with x-mailchannels-, set on the Email’s header bag. The x-mailchannels-* headers are stripped
before the message is sent, so recipients never see them.
If the same custom header is added twice, only the last value is used.
"true" / "false"; anything else throws
Symfony\Component\Mailer\Exception\TransportException. An empty value is treated as unset (falls back to the default).
Each of these corresponds directly to a field on the send endpoint. See that
reference for full semantics.
Reading the result
- Synchronous send (
x-mailchannels-send-async: false): the sent message’s ID is written back onto Symfony’sSentMessageobject, so you can read it after sending. - Queued (default): the API doesn’t return a message ID per call, so Symfony’s own generated message ID is left
untouched on
SentMessage.
Error handling
Any SDK exception raised while sending (authentication, validation, rate limiting, server errors) is caught and re-thrown asSymfony\Component\Mailer\Exception\TransportException.
Access the original exception via $e->getPrevious() to inspect it:
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 Symfony’s Template Support, or use the SDK’s
Clientdirectly; see Templates for how. - DKIM only via the MailChannels API, as described above.
Next steps
- Read the webhooks guide to learn how to get real-time notifications about email delivery, bounces, and complaints.
- Explore the API reference to see what else you can do with the API.

