Installation
composer require daily/mandrill-dm
Add the service provider to config/app.php:
'providers' => [
// ...
Daily\Mandrill\MandrillServiceProvider::class,
],
Configuration Publish the config file:
php artisan vendor:publish --provider="Daily\Mandrill\MandrillServiceProvider"
Update .env with your Mandrill API key:
MANDRILL_API_KEY=your_api_key_here
First Use Case Send a basic email via a Laravel controller:
use Daily\Mandrill\Mandrill;
public function sendEmail()
{
$mandrill = app(Mandrill::class);
$response = $mandrill->messages->send([
'message' => [
'subject' => 'Test Email',
'from_email' => 'from@example.com',
'from_name' => 'Sender Name',
'to' => [
['email' => 'recipient@example.com', 'name' => 'Recipient'],
],
'text' => 'Plaintext content',
'html' => '<p>HTML content</p>',
],
]);
return $response;
}
Sending Emails
Use the messages->send() method for one-off emails or messages->sendTemplate() for template-based emails:
$response = $mandrill->messages->sendTemplate([
'template_name' => 'welcome',
'template_content' => [
['name' => 'user', 'content' => 'John Doe'],
],
'message' => [
'subject' => 'Welcome!',
'from_email' => 'noreply@example.com',
'to' => [['email' => 'user@example.com']],
],
]);
Queueing Emails Integrate with Laravel queues for async sending:
$mandrill = app(Mandrill::class);
$mandrill->queueMessage($messageData); // Custom method to dispatch a job
Tip: Extend the package to add a MandrillMessage job class for queue support.
Handling Responses Validate API responses in a service layer:
public function sendWithValidation(array $data)
{
$response = $mandrill->messages->send($data);
if ($response['status'] !== 'sent') {
throw new \RuntimeException('Email failed to send: ' . $response['reject_reason']);
}
return $response;
}
Template Management Fetch and update templates dynamically:
$templates = $mandrill->templates->listTemplates();
$template = $mandrill->templates->getTemplate('welcome');
Laravel Mail Integration
Override Laravel’s SwiftMailer transport to use Mandrill:
// config/mail.php
'transport' => 'mandrill',
Note: Requires custom transport binding (see Gotchas).
Event-Driven Workflows Use Mandrill webhooks for real-time event handling (e.g., email opens, clicks):
$mandrill->webhooks->add([
'url' => route('mandrill.webhook'),
'events' => ['open', 'click'],
]);
Batch Processing Send bulk emails efficiently:
$mandrill->messages->send([
'message' => [
'to' => array_map(fn($email) => ['email' => $email], $emails),
// ... other fields
],
]);
open_basedir Restrictions
The package is explicitly designed for environments with open_basedir enabled. If issues arise:
vendor/daily/mandrill-dm/ is whitelisted in open_basedir.API Rate Limits Mandrill enforces rate limits (e.g., 10 emails/sec). Implement exponential backoff:
use Daily\Mandrill\Exceptions\RateLimitExceededException;
try {
$response = $mandrill->messages->send($data);
} catch (RateLimitExceededException $e) {
sleep($e->getRetryAfter());
retry();
}
Laravel Mail Transport Quirks If using Mandrill as a transport:
Illuminate\Mail\TransportManager to bind the custom transport:
$this->app->bind('mandrill', function ($app) {
return new \Daily\Mandrill\Transport($app['config']['mail.mandrill']);
});
config/mail.php includes:
'transports' => [
'mandrill' => [
'api_key' => env('MANDRILL_API_KEY'),
],
],
Template Variables Mandrill templates require exact variable names. Validate with:
$template = $mandrill->templates->getTemplate('welcome');
if (!in_array('user', $template['model_fields'])) {
throw new \InvalidArgumentException("Template missing 'user' variable.");
}
Enable Debug Mode
Set MANDRILL_DEBUG=true in .env to log raw API requests/responses:
$mandrill->setDebug(true);
Common Errors
| Error | Solution |
|---|---|
Invalid API Key |
Verify MANDRILL_API_KEY in .env and config. |
Template Not Found |
Check template_name spelling and ensure template exists in Mandrill. |
Rate Limit Exceeded |
Implement retry logic with backoff. |
open_basedir Restricted Path |
Whitelist the vendor directory in php.ini. |
Custom Request Handling
Extend the Daily\Mandrill\Client class to add methods:
namespace App\Services;
use Daily\Mandrill\Client;
class CustomMandrill extends Client
{
public function sendTransactional($data)
{
return $this->post('messages/send-transactional', $data);
}
}
Event Listeners
Hook into Mandrill events (e.g., sent, hard_bounce) via webhooks or polling:
$mandrill->events->listEvents(['type' => 'sent', 'limit' => 10]);
Mocking for Tests Use Laravel’s mocking to simulate Mandrill responses:
$this->mock(Daily\Mandrill\Mandrill::class)->shouldReceive('messages->send')
->once()->andReturn(['status' => 'sent']);
Local Development Use a local Mandrill proxy (e.g., Mandrill Local) to avoid hitting rate limits during development. Configure the proxy URL in the package’s config:
'proxy_url' => env('MANDRILL_PROXY_URL', null),
How can I help you explore Laravel packages today?