Painless Email Testing

Leo Sjöberg • October 2, 2015

For many applications that you build, there is always email involved. Often, this comes in the form of password resets and user verification. However, a recurring question is always "how do you test it". Do you just send the emails to a log file? Should you use a service like mailtrap.io, do you hook it up with your live server? The answer to all of the above is no (unless you're writing tests, in which case the log file is excellent for assertions). Instead, you run a local SMTP server. In the past, setting up your own SMTP server might have been an incredible pain, but nowadays, MailCatcher exists, and has made life a lot easier for many developers. Despite that, I won't recommend it. I'm not saying it's bad, but the installation is slow because, well, it's a ruby gem.

Introducing MailHog

MailHog is what local mail testing should be; easy, fast and requiring no installation. MailHog is built on Go, and comes as a precompiled executable which you just place on your local server, or if you're using Docker, simply use the dockerfile or run it from Docker Hub.

Installing MailHog (64-bit Linux)

Installing mailhog is incredibly easy; all you have to do is download the file and make it executable! However, then you might also want the service to start automatically whenever you start your local environment and whatnot. For that reason, some guy on the internet decided to make a shell script for it!

You can find the original shell script at https://gist.github.com/varghesejacob/68caf7aeee53305a1ffa#file-mailhog-bash-script and for convenience, it's right here too:

1#!/usr/bin/env bash
2 
3echo ">>> Installing Mailhog"
4 
5# Download binary from github
6wget --quiet -O ~/mailhog https://github.com/mailhog/MailHog/releases/download/v0.1.7/MailHog_linux_amd64
7 
8# Make it executable
9chmod +x ~/mailhog
10 
11# Make it start on reboot
12sudo tee /etc/init/mailhog.conf <<EOL
13description "Mailhog"
14start on runlevel [2345]
15stop on runlevel [!2345]
16respawn
17pre-start script
18 exec su - vagrant -c "/usr/bin/env ~/mailhog > /dev/null 2>&1 &"
19end script
20EOL
21 
22# Start it now in the background
23sudo service mailhog start

Please note that this is for version 0.1.7 of MailHog. If a new version is released, edit the shell script before running it.

Hence, the definite easiest way to install MailHog is the following (supposing you are already SSH'd into your dev machine):

1$ wget -O mailhog-install https://gist.githubusercontent.com/varghesejacob/68caf7aeee53305a1ffa/raw/0e7efd5181d8d07ca45b3d81dd1239f3d7b0b2ec/Mailhog%2520Bash%2520Script
2 
3$ ./mailhog-install

That's all you need to get running. The script will install MailHog v0.1.7, make sure it starts on reboot, and then start the service.

Please note that this will not allow you to change any of the MailHog configuration, but will only use defaults; you will have to edit those afterwards.

Using MailHog

Once MailHog is installed, all you have to do is the following:

  1. Set your SMTP host to localhost
  2. Set your SMTP port to 1025

To then access your mailbox, simply visit your dev server on port 8025 (note that you can of course also run the mail server locally in which case you would simply access localhost:8025). In my case, my server exists at 192.168.10.10, so I can access MailHog through 192.168.10.10:8025. All emails you send are now sent to this mailbox. Note that accessing your server on port 8025 will always lead to mailhog, so you could also set up your local hosts file to point mail.dev to your ip address, and could then access email via mail.dev:8025.

Proxying for ease

Okay, so you don't want to have to type out the :8025 at the end of your domain all the time, or perhaps you just think mail.dev:8025 looks really ugly. Well, the good news are that if your dev server is on Nginx, setting up a proxy to forward to 8025 is incredibly easy! All you have to do is set up a new virtual host for your desired domain, I'll be using mail.dev for this example.

  1. Create the host file
1sudo nano /etc/nginx/sites-available/mail.dev
  1. Well there, paste the following code:
1server {
2 listen 80;
3 server_name mail.dev;
4
5 location / {
6 proxy_pass http://192.168.10.10:8025;
7 proxy_set_header Host $host;
8 proxy_set_header X-Real-IP $remote_addr;
9 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
10 proxy_connect_timeout 150;
11 proxy_send_timeout 100;
12 proxy_read_timeout 100;
13 proxy_buffers 4 32k;
14 client_max_body_size 8m;
15 client_body_buffer_size 128k;
16 }
17}

This will forward all your calls to mail.dev to http://192.168.10.10:8025. If you use another domain or another IP, make sure to change those.

Hopefully, you enjoyed this little read on mail testing, and will be able to use it for your own development!