Personally, I had horrible luck with Mandrill's deliverability. Their logs would show a message as Delivered, recipients swore they never received them - not in spam or anywhere else. However, @jekinney makes a very good point about sending to thousands of recipients.
I've been using Mailgun for a while now and find them to be rock solid. Very recently I switched to using their API directly rather than using Laravel's built in Mail, it opened a lot of doors such as batch sending (I had previously been putting everyone in a BCC) and recipient variables, accessible within the HTML of the email.
I have also been inlining CSS in my mail, so I have a master Blade template that I inject other email templates into, then pass through an inline script that returns HTML which can be sent using the Mailgun API.
Here is part of a class that sends out batch emails:
/**
* Get all email recipients and include their user details for Mailgun's
* template tags - %recipient.userToken%
*/
private function getRecipients()
{
foreach (User::get() as $user)
{
$this->recipients[$user->email] = [
'id' => $user->id,
'userToken' => $user->user_token,
'first_name' => $user->first_name,
'last_name' => $user->last_name,
'email' => $user->email
];
}
}
private function sendEmail()
{
$subject = 'Demo Subject';
/**
* Data for the Blade template
*/
$data = [
'foo' => 'bar'
];
// Inline the CSS for the email
$inliner = new InlineEmail('emails.some-email', $data);
$content = $inliner->convert();
// Create Emails table entry for this email. Used for Mailgun webhooks
$email = Email::create(['user_id' => $this->userId, 'subject' => $subject, 'email_id' => str_random()]);
// Prepare the email addresses
$emailAddresses = array_column($this->recipients, 'email');
$this->mailgun->sendMessage('demo.org', [
"from" => 'support@demo.org',
"to" => implode(',', $emailAddresses), // Comma separated list of email addresses
"subject" => $subject,
"html" => $content, // Inlined CSS HTML from Blade
"text" => "Plain text message here",
"recipient-variables" => json_encode($this->recipients), // Required for batch sending, matches to recipient details
"v:messageId" => $email->id, // Custom variable used for webhooks
]);
}
And here is my email inliner:
<?php namespace App\Library;
use TijsVerkoyen\CssToInlineStyles\CssToInlineStyles;
/**
* Class inlineEmail
*
* Returns rendered Email view with inlined CSS
* @package App\Library
*/
class InlineEmail {
/**
* Filename of the view to render
* @var string
*/
private $view;
/**
* Data - passed to view
* @var array
*/
private $data;
/**
* @param string $view Filename/path of view to render
* @param array $data Data of email
*/
public function __construct($view, array $data)
{
// Render the email view
$emailView = view($view, $data)->render();
$this->view = $emailView;
$this->data = $data;
}
/**
* Convert to inlined CSS
*
* @return string
* @throws \TijsVerkoyen\CssToInlineStyles\Exception
*/
public function convert()
{
$converter = new CssToInlineStyles();
$converter->setUseInlineStylesBlock();
$converter->setCleanup();
$converter->setStripOriginalStyleTags();
$converter->setHTML($this->view);
$content = $converter->convert();
return $content;
}
}