Local mailserver for development

Debugging emails in an application is usually very tedious. Some frameworks and libraries try to help you with debugging, but even the best tools usually fail when it comes to batch sending mails.

The best way to debug emails on your local development machine is having a small mailserver installed that does not actually send mails in the wild, but collects them locally.

It's not as hard as you might expect:

1. Install and configure exim

Exim is a small and very lightweight message transfer agent (MTA). To install it on Debian/Ubuntu type:

sudo apt-get install exim4

To configure exim call dpkg-reconfigure

sudo dpkg-reconfigure exim4-config
Follow the dialog and select the following options:
  • General type of mail configuration: local delivery only; not on a network

  • Delivery method for local mail: Maildir format in home directory

  • Split configuration into small files: Yes

Next up create the file /etc/exim4/conf.d/router/175_exim4-config_catchall and place the following content in it (replace <username> with your username):

catchall:
    driver  = redirect
    domains = ! +local_domains
    data    = <username>@localhost

Restart exim afterwards:

sudo service exim4 restart

To test if the configuration works run

echo "Hello World" | mail -s "Hi" foobar@example.com

You should find a new file in ~/Maildir/new that contains your send mail.

2. Install Mutt

Mutt is a small mailclient to read mails on the console. You love the console, don't you? If not, you can also easily configure Evolution or Thunderbird to show your emails.

Install mutt from the package manager

sudo apt-get install mutt

and create the configuration file /etc/Muttrc.d/maildir.rc with this content

set mbox_type=Maildir
set folder="~/Maildir"
set mask="!^\.[^.]"
set mbox="~/Maildir"
set record="+.Sent"
set postponed=".Drafts"
set spoolfile="~/Maildir"

Now you can call mutt to see your mails.

Shortcuts for mutt

  • ? shows the help

  • D + ~s .* + $ deletes all mails

  • ~d>1d removes all mails older than one day

3. Configure your application

Just tell your application to use sendmail to send the mails. Usually the PHP function mail() is configured to use sendmail too. As this is the easiest way for libraries to send emails, it is available in most libraries.

You can also use SMTP to send emails through localhost on port 25.

One Comment

Respond to this post

Peter Niederlag wrote

First of all, thx for sharing this blog!

Regarding handling mail in development context I'd like to share my findings with you.

Inspired my Michiel's work on TYOPO3 automation (https://github.com/Tuurlijk/TYPO3.Packer/blob/master/ansible/roles/common/tasks/mailcatcher.yml) with Ansible/Packer/Vagrant/ we found http://mailcatcher.me/ to be an incredible helpful thing for handling mail in development context.

Currently we role out mailcatcher in our Vagrant box and adapt exim to route *all* mails to mailcatcher.

- configure exim for local delivery only, set smarthost to 127.0.1.1::1025
- start mailcatcher --smtp-ip 127.0.1.1 --http-ip xxx,xxx.xxx.xxx

xxx.xxx.xxx.xxx is your private ip of the dev-box(vagrant/virtualbox), needed in order to reach mailcatcher from outside. setting up port-forwarding via vagrant could probably work as well.

you need to set a different IP from 127.0.0.1 in order to make exim happy, exim won't use the smarthost if it's configured to use 127.0.0.1(only the port being different).

This way there are no worries about changing any mail configurations inside TYPO3/php and *all* mails on the dev-box can easily be debugged.

Greets,
PeterN

2015-10-09 09:37