Testing Email in Your Web App

I’m in the middle of creating a new VM and I had a few minutes while I clone my SVN repository. I figured I’d recount some of the work I did to set up a better way to test SMTP this week.

I needed a clean way to functionally test the sending of email as part of recent feature builds. I recently had to work on a feature that allows users sends out an emails with attachments. This feature was coded and unit tested appropriately. I even added properties to drive the sending or logging of emails to ensure that things were working as expected. Then… QA asks how can they see the real email? Even with all the support that was added to help testing, I was still unable to produce a live email. This is what QA wanted for verification and it is a reasonable request. So, what to do?

After poking around a bit, I found a number of one off tools that provide the ability to trap email. Papercut is a great one and this is very useful. Another cool option would be to use a service like mailtrap. Yet another would be to set up support to trap mail and offer the ability to view it via Outlook or some other client.

Each option has its pros/cons:

  • Tools like papercut are great for local testing, but does not scale when you add testers into the mix. The target SMTP host becomes dynamic. I wanted one test host to point to and that’s that!
  • mailtrap.io is exactly what I want, but its not hosted internally.  I can’t send out mail to an external host even if it is test data!
  • Rolling your own is a PITA.

So, I decided to roll my own to get a feel for what it would be like to set up a mail server and a block emails from reaching the receiver.  I used the following tools:

  • fakemail – A perl module with supporting script to serve as a simple SMTP gateway that logs mail to file.
  • dovecot – A mail server that supports  various mailbox formats and protocols

The idea here is that I could leverage fakemail to accept SMTP requests from my application and have it simply drop emails to disk without ever sending them to the ultimate recipient.  I could then use dovecot to host an IMAP server that reads the trapped emails from disk using maildir format to present them to anyone who asked for them. All of this is property driven, so I would just need to point to the real mail server in the production environment.

It’s still early days, but this solution seems to work out so far.  I am able to map to the IMAP server and fetch emails as they are trapped using Outlook.  I can read the content without any problem and I can forward them on to internal users (hey, that gives me another idea for an “internal only” outbound server).

I’d like to set up a dead simple webmail client (something like Squirrelmail) to allow anyone to access trapped mail.  I might do this if I get some more time.