Mailcatcher & Laravel 4 – Sending Development Emails

During application development sending test emails can usually be a pain, even when using a modern frmaework like the excellent Laravel 4. During development it is very desirable to debug emails without actually sending them.There are a few options I’ve come across:

  1. Use Laravel 4’s Mail pretend feature. Simply set the configuration key “pretend” to true in app/config/mail.php. Laravel will now not send emails, instead write the content of each email to the application log
  2. Manually change the “to” email to your own so emails are delivered to your favourite email client – again, messy if sending lots of emails and if you ever made a mistake
  3. Print out the email data directly to the screen, but don’t send the actual email – the worst solution in my opinion

Options 2 and 3 are particularly fraught with issues. For instance, assume the application was to send out 1000 member renewal reminders and during development the route that sends out the emails was hit. Very soon, we’d have some very real (and confused, annoyed etc.) customers contacting you – disaster!

It would be perfect if the application could mimic sending out the email as normal and allow us to easily debug it. Enter Mailcatcher

Using Mailcatcher to Send Local Emails

Mailcatcher sets up a local SMTP server on your local computer. It intercepts any messages sent to it, of course not forwarding the actual message onto the intended email address and stores it locally.

Installing Mailcatcher is extremely simple, making use of Ruby gems, from the command line run:

gem install mailcatcher
mailcatcher

Once installed, simply visit http://127.0.0.1:1080 and view any mails send by your application:

mailcatcher laravel 4

If using a modern web browser that makes use of WebSockets, the web interface will update without a page refresh, as messages are sent.

Without sending the actual message the following is now easily visible:

  • The HTML version and view exactly how the message has rendered the mail client
  • The plain text version as appropriate
  • Any attachments
  • How the subject, from and to fields look
  • Most importantly, the actual content of the email – important when sending out lots of emails where the email data originates from a data source

It’s also possible to view the source, viewing all message headers (even custom headers) – simply click on a message then the “source” tab:

mailcatcher laravel 4 message source

Mailcatcher & Laravel 4

In Laravel 4 there are a couple of basic tweaks required:

Make sure your “local” (in my case) environment is being detected correctly – Mailcatcher should only be used to “send” emails during development (read more about environment configuration in Laravel 4):

// bootstrap/start.php
$env = $app->detectEnvironment(array(
 'local' => array('*.dev', '*.local'),
));

Create a custom mail.php configuration file that is used for the “local” environment:

// app/config/local/mail.php
return [
'driver' => 'smtp',
'host' => '127.0.0.1',
'port' => 1025,
'from' => ['address' => 'subscriptions@mysite.co.uk', 'name' => 'Some From Name'],
'encryption' => '',
];

Then send the email using Laravel 4 as normal:

// app/routes.php
Route::get('/', function()
{
        // Some email data (could come from a database) ...
	$emailData = [
		'username' => 'Mr Smith',
		'subscription' => 'Premium',
		'expires' => Carbon::now()->toDayDateTimeString(),
		'period' => 'month',
		'cost' => '£74.99'
	];

	Mail::send('emails.users.renewal', $emailData, function($message) use ($emailData)
	{
		// Set a custom header
		$message->getHeaders()->addTextHeader('Custom-header', 'super custom header');

		$message->to('google@google.co.uk', 'Jet Li')->subject($emailData['username'] . ' - Your Subscription at Site.co.uk');
	});

});

Visit http://127.0.0.1:1080 again and notice the freshly sent email. Note in the second screenshot (above) there is the custom header (interestingly coined “Custom-header”) displayed in the source view of the message.

As a bonus, Mailcatcher makes it easier to perform unit testing on the application. It is now possible to not only test if an email has been delivered (with the correct subject and recipients etc.), but also if the said email is correctly formatted – all without actually sending an email message. I’d recommend having a read of a fuller example that discusses testing with Mailcatcher

Published by

Rob Allport

Web Developer based in Stoke-on-Trent Staffordshire Google+ - Twitter

Leave a Reply

Your email address will not be published. Required fields are marked *