Simple local only mail

I’m working on an application that needs to send notifications via email, and I want to be able to test it in the development environment. In the past, I’ve either been able to set up a small Windows mail server (hMailServer is great for this) or just use my standard email account. However, I’m a little restricted in my current environment, and working in a virtual machine. What I really need is a local-only mail solution that will work on my Xubuntu VM.

In the past I’ve shied away from setting up a mail server on Linux. I failed miserably to set up sendmail in the past. Today I decided to try postfix, and found it very easy to set up a system to work the way I wanted it to.

Being lazy, I just used the Ubuntu software centre to install postfix. The installation process popped up a config screen, and I selected the local only option. Looking at the postfix documentation, I came up with this configuration (etc/postfix/main.cf):

myorigin = localhost

smtpd_banner = $myhostname ESMTP $mail_name (Ubuntu)
biff = no

# appending .domain is the MUA's job.
append_dot_mydomain = no

# Uncomment the next line to generate "delayed mail" warnings
#delay_warning_time = 4h

readme_directory = no

# TLS parameters
smtpd_tls_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem
smtpd_tls_key_file=/etc/ssl/private/ssl-cert-snakeoil.key
smtpd_use_tls=yes
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache

# See /usr/share/doc/postfix/TLS_README.gz in the postfix-doc package for
# information on enabling SSL in the smtp client.

myhostname = localhost
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
mydestination = robvm, localhost.localdomain, localhost
relayhost =
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128
mailbox_size_limit = 0
recipient_delimiter = +
inet_interfaces = loopback-only
default_transport = error
relay_transport = error

I restarted postfix (‘sudo postfix reload’) and was then able to test (see this)

telnet localhost 25
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
220 localhost ESMTP Postfix (Ubuntu)
helo localhost
250 localhost
mail from: rob@localhost
250 2.1.0 Ok
rcpt to:rob@localhost
250 2.1.5 Ok
data
354 End data with .
Hello there
.
250 2.0.0 Ok: queued as E8B7960091C
quit
221 2.0.0 Bye
Connection closed by foreign host.

That worked fine, but I wasn’t sure where the email was going. I needed a client.

I first tried the default email client, which was Thunderbird. However, the configuration seemed to expect an internet mail server and I gave up on that idea pretty quickly.

Claws to the rescue. This mail client is easy to install via the software centre. The main issue was getting the basic settings right. These worked for me:

Claws mail client account preferences

Hey presto, “get mail” retrieved the message I’d created while testing at the command line. With the configuration above, I was even able to send more messages to myself.

Looking at this, it became obvious where the emails were being stored: /var/mail/rob. A quick look there and I found a text file containing all my emails.

Next step was to create an anonymous alias that I could use in my rails code. To do this I updated my etc/aliases file by adding this to the end:

developer: rob

At first this had no effect. I then found this article by Elliot Smith, which told me what I was missing:

sudo newaliases

That command regenerates your alias database file. As soon as I did that, I found I was able to send emails to developer@localhost.

Last but not least I needed to set up my rails app to work with this configuration. I added this to /config/environments/development.rb:

  config.action_mailer.smtp_settings = {
    :address              => "localhost",
    :port                 => 25,
    :domain               => 'localhost',
    :authentication       => 'none',
    :openssl_verify_mode => 'none'
  }

And added this to the end of that file

class OverrideMailReciptient
  def self.delivering_email(mail)
    mail.to = "developer@localhost"
  end
end
ActionMailer::Base.register_interceptor(OverrideMailReciptient)

Overriding the mail recipient causes all emails leaving your rails app, to be redirected to the given address. With that in place, I could play with things like devise sign up confirmation emails without anything leaving my virtual environment. Just what I wanted.

It was all so simple, I don’t really know why I haven’t done this before.

Update: Catching all emails
I’ve needed to update my settings so that I can send an email to any email address, and it will end up in the rob@localhost mailbox. To do this, I followed the instructions given here.

I created /etc/postfix/virtual :

/.*/  rob@localhost

I then added this to the bottom of etc/postfix/main.cf :

# Set up rob@localhost to catch mail not directed to a specfic email address
virtual_alias_maps = regexp:/etc/postfix/virtual
virtual_alias_domains =

I then ran these two commands to create the mapping and restart postfix:

sudo postmap /etc/postfix/virtual
sudo postfix reload

Now all emails sent to localhost:25 end up in the rob@localhost mailbox.

This entry was posted in Ruby. Bookmark the permalink.