therobfonz/laravel-mandrill-driver
A Laravel mail driver for Mandrill. Use it as a mail transport to send transactional email through Mandrill's API, integrating cleanly with Laravel's Mail facade, mailables, and queued mail without extra boilerplate.
Install the driver and let Laravel's package discovery register MandrillServiceProvider:
composer require luisdalmolin/laravel-mandrill-driver
There is no publishable config file — the driver reads its key from config/services.php, so add an entry if one isn't already present:
// config/services.php
'mandrill' => [
'secret' => env('MANDRILL_SECRET'),
],
Then point the mailer at it:
MAIL_MAILER=mandrill
MANDRILL_SECRET=your-mandrill-api-key
The API key lives in the Mandrill dashboard under Settings → SMTP & API Info. Note that Mandrill is the transactional arm of Mailchimp and requires a paid Mailchimp plan plus a verified sending domain before any send will succeed.
First use case: send a Mail::raw against yourself to confirm the whole chain works before touching templates:
Mail::raw('Hello from Mandrill', fn ($m) => $m->to('[email protected]')->subject('Smoke test'));
If that lands, everything after it is just Laravel's normal Mailable/Notification API — the driver is a transport, not a wrapper, so php artisan make:mail, Markdown mailables, attachments, and queued mail all work unchanged.
Look first at: config/mail.php (confirm mandrill is a valid mailer), config/services.php, and the MandrillTransport class in the package source when you need to understand what's on the wire.
Standard Mailable flow. Nothing Mandrill-specific is required. Build Mailables as usual and let MAIL_MAILER=mandrill route them through the driver, which posts the raw MIME payload to Mandrill's messages/send-raw endpoint.
Per-environment mailers. Keep Mandrill for production and log/array drivers locally so you never burn reputation or quota on dev traffic:
// config/mail.php
'mailers' => [
'mandrill' => [
'transport' => 'mandrill',
],
],
MAIL_MAILER=mandrill # production
MAIL_MAILER=log # local
Mandrill-specific behaviour via X-MC-* headers. Because the driver sends raw MIME, Mandrill's SMTP header conventions are the main extension surface. Set them on the message and they pass straight through:
$message->getHeaders()->addTextHeader('X-MC-Tags', 'welcome,onboarding');
$message->getHeaders()->addTextHeader('X-MC-Track', 'opens,clicks');
$message->getHeaders()->addTextHeader('X-MC-Subaccount', 'acme');
$message->getHeaders()->addTextHeader('X-MC-GoogleAnalyticsCampaign', 'spring-promo');
Wrap this in a small MandrillHeaders trait or a base Mailable so tags stay consistent across your app and you can segment reporting in the Mandrill dashboard later.
Queue everything. The transport makes a synchronous HTTP call at send time. Implement ShouldQueue on your Mailables (or use Mail::queue) so a slow or failing Mandrill API never blocks a request cycle.
Testing. Mail::fake() short-circuits before the transport, so it verifies your application logic but never exercises the driver. For anything that depends on the actual payload (headers, tags, attachments), add one focused test that fakes the HTTP client or runs against a low-volume verified address in CI.
Provider-level extension. If you need to inject defaults (a subaccount, standard tags, a global metadata blob) for every message, don't repeat headers everywhere — subclass MandrillTransport and re-register it in your own AppServiceProvider::boot() with Mail::extend('mandrill', ...) after the package provider has run.
services.mandrill.secret. A missing env var produces an error on the first send, not at boot. Assert it in a config test or a php artisan about check.config:cache discipline. If you cache config during deploy, the MANDRILL_SECRET env var must be present before the cache is built. Changing .env afterwards has no effect until you re-cache.MAIL_FROM_ADDRESS domain are rejected at the API level. Align MAIL_FROM_ADDRESS with a domain you've completed DKIM/SPF setup for in Mailchimp.rejected, invalid, or hard-bounced statuses. Log the response payload for at least the first few weeks of production traffic, and consider a small wrapper that inspects results and raises an application-level event on partial failure.Envelope manipulation that isn't reflected in the message headers will silently drop recipients.X-Mailer, message IDs) and Mandrill interprets X-MC-*. Avoid hand-setting X-MC-* values you've also configured at the account/subaccount level — account settings win in confusing ways.$tries, backoff(), and failed() on the Mailable or job.$message->toString() in a local test — you're debugging raw MIME plus Mandrill's header conventions, not an SDK object model. Mandrill's own "Outbound Activity" log is the ground truth for what it received.composer update is the entire upgrade path; just confirm your symfony/mailer constraint resolves cleanly.How can I help you explore Laravel packages today?