Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
Dealing with email on a testing server

Dealing with email on a testing server

There are lots of setups with programs that can collect email in testing environments. Some of them require you to install perl, nodejs, ruby, ... or require you do do a sophisticated setup with your mailserver.

But there is a little program called mailhog that is just a standalone statically linked binary that has no dependencies.

That makes it very easy to use.


Just download the latest release and put it into your /usr/local/bin:

wget -O /usr/local/bin/mailhog
chmod +x /usr/local/bin/mailhog

You can just start the program by running /usr/local/bin/mailhog.

The SMTP will be available on port 1025 and the web UI on port 8025.


We want mailhog to start with system boot and restart when it would crash. You can do that sort of stuff with systemd. Create a file named /lib/systemd/system/mailhog.service with this in it:

Description=Mailhog SMTP

ExecStart=/usr/local/bin/mailhog -api-bind-addr -ui-bind-addr -smtp-bind-addr


Create the user mailhog with group mailhog and home directory /home/mailhog first, or leave it out and mailhog will run as root. Running stuff as root is a bad idea, especially if it is something that listens on the network.

It's also not a good idea to make mailhog accessible on your public IP. It does that by default so that's why you would add -api-bind-addr -ui-bind-addr -smtp-bind-addr to make it only listen on localhost.

Now enable the mailhog service to start it at boot time and then start it manually:

systemctl enable mailhog
systemctl start mailhog


We hook it up to postfix and make it so that if you mail to an email address ending in .external, it will be relayed to a real server. And, if doesn't we relay it to mailhog.

Eg: mail to tom@somedomain.tdl will go to mailhog and tom@somedomain.tdl.external will be delivered to tom@somedomain.tdl.

Postfix configuration /etc/postfix/

myhostname = myserver.mydomain.tld
relayhost = real-smtp-relay.mydomain.tld
smtp_generic_maps = pcre:/etc/postfix/smtp_generic_maps.pcre
transport_maps = hash:/etc/postfix/transport

The smtp maps make sure that the .external part is stripped off.

/(.*)\.external$/ $1

The transport maps decide that .external addresses will be relayed to the real SMTP server and the rest will be relayed to mailhog.

.external :
*           smtp:

Because the transport maps are hashed you need to run postmap /etc/postfix/transport.


I do want to make mailhog available on my public IP on /mailhog/. But I want to do it with an Apache proxy that requires basic HTTP authentication.

Create the file /etc/apache2/conf-available/mailhog.conf with this in it:

RewriteEngine On
RewriteCond %{HTTP:Upgrade} =websocket [NC]
RewriteRule /mailhog/(.*) ws://$1 [P,L]

ProxyPreserveHost Off
ProxyRequests Off
<Proxy *>
    AuthType Basic
    AuthName "Authentication required"
    AuthUserFile "/etc/apache2/mailhog.password"
    Require user mailhog

    Order deny,allow
    Allow from all
ProxyPass /mailhog/
ProxyPassReverse /mailhog/

Generate the password file:

htpasswd -c /etc/apache2/mailhog.password mailhog

Enable the necessary Apache modules, and enable the config:

a2enmod proxy proxy_http rewrite
a2enconf mailhog

systemctl reload apache2
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.