Victor is a full stack software engineer who loves travelling and building things. Most recently created Ewolo, a cross-platform workout logger.
Setting up a mail server and client on Ubuntu using postfix and mutt

In this tutorial we will setup a mail server using postfix and an email client using mutt on a Ubuntu system. Initially we will only configure postfix to deliver mail locally and then enhance it to allow sending mails externally via a gmail account.

Mutt is an powerful email client and can be used to receive, read and sent emails directly from the console. Mutt is higly configurable and a sample setup is provided to get started. Mutt can also be used directly in conjuction with gmail to send and receive messages but in this setup we will hand-off the sending of email to postfix so that other applications can also easily send mails to the outside.

Update September 30, 2016

Instructions on setting up mutt as a gmail client can be found here


Update February 27, 2018

Added debugging and ssl certificate information

Install postfix

The first order of business is to install postfix:

sudo apt-get install postfix
Under General type of mail configuration select Local only. Also, for the system mail name, you can put in localhost (presuming that you are sending email to @localhost).

By default, your mailbox is located at /var/mail/<username>.

Install mutt

Mutt can be installed via the following command:

sudo apt-get install mutt

We will now configure mutt by overwriting the contents of ~/.muttrc. The most important is the mailboxes property where we have set the inbox to be the one where postfix will deliver mail to.

set from = "Victor Parmar <victorparmar@gmail.com>"
set edit_headers = yes

set folder = ~/Mail                        # mailbox location
set tmpdir = "/tmp"
set record = "+sent"
set mbox = "+mbox"
set postponed = "+postponed"

set wait_key = no                          # shut up, mutt
set mbox_type = Maildir                    # mailbox type
set timeout = 3                            # idle time before scanning
set mail_check = 0                         # minimum time between scans
unset move                                 # gmail does that
set delete                                 # don't ask, just do
unset confirmappend                        # don't ask, just do!
set quit                                   # don't ask, just do!!
unset mark_old                             # read/new is good enough for me
set beep_new                               # bell on new mails
set pipe_decode                            # strip headers and eval mimes when piping
set thorough_search                        # strip headers and eval mimes before searching

ignore *                                   # ignore all headers
unignore from: to: cc: date: subject:      # show only these
unhdr_order *                              # some distros order things by default
hdr_order from: to: cc: date: subject:     # and in this order

set date_format = "%m/%d"
set index_format = "[%Z]  %D  %-20.20F  %s"
set sort = threads                         # like gmail
set sort_aux = reverse-last-date-received  # like gmail
set uncollapse_jump                        # don't collapse on an unread message
set sort_re                                # thread based on regex
set reply_regexp = "^(([Rr][Ee]?(\[[0-9]+\])?: *)?(\[[^]]+\] *)?)*"set date_format = "%m/%d"
set index_format = "[%Z]  %D  %-20.20F  %s"
set sort = threads                         # like gmail
set sort_aux = reverse-last-date-received  # like gmail
set uncollapse_jump                        # don't collapse on an unread message
set sort_re                                # thread based on regex
set reply_regexp = "^(([Rr][Ee]?(\[[0-9]+\])?: *)?(\[[^]]+\] *)?)*"

set sidebar_delim   = '  │'
set sidebar_visible = yes
set sidebar_width   = 24

set status_chars  = " *%A"
set status_format = "───[ Folder: %f ]───[%r%m messages%?n? (%n new)?%?d? (%d to delete)?%?t? (%t tagged)? ]───%>─%?p?( %p postponed )?───"

mailboxes /var/mail/vic \
          ~/Mail/sent \

set pager_index_lines = 10                 # number of index lines to show
set pager_context = 3                      # number of context lines to show
set pager_stop                             # don't go to next message automatically
set menu_scroll                            # scroll in menus
set tilde                                  # show tildes like in vim
unset markers                              # no ugly plus signs

push <show-version>

If you are feeling adventurous and already have some experience with mutt you can check out various other configurations such as this, this and this. There's also a web application which allows you to build your own muttrc: http://muttrcbuilder.org/!

Fire up mutt via mutt and voila, you have a fresh new email client!

A few mutt commands

For the most part, ? will open up a help window with the available commands and the top bar also indicates common actions, but nevertheless here are some useful commands:

Changing folders
c, ? to open the list of folders, tab to switch between mailboxes
Sync mailbox
$

Test local mail setup

At this point sending and receiving local mail should be working and can be tested via the following python script:

import smtplib
import string
SUBJECT = "Test email"
TO = "vic@localhost" # change to your username
FROM = "python@localhost"
text = "blah blah blah"
BODY = string.join((
        "From: %s" % FROM,
        "To: %s" % TO,
        "Subject: %s" % SUBJECT,
        "",
        text
        ),
"\r\n")
server = smtplib.SMTP('localhost')
server.sendmail(FROM, TO,BODY)
server.quit()
Running mutt after executing the above script should show an email from python@localhost in your inbox.

Configure postfix to use gmail relay

We will now configure postfix to use gmail's SMTP service to send emails. Note that you will need a gmail account and will also be storing the password for this account as cleartext in a root protected file.

Assuming postfix has already been installed, we will need to install the other required modules:

sudo apt-get install mailutils libsasl2-2 ca-certificates libsasl2-modules

Edit /etc/postfix/main.cf and add the following configuration:

relayhost = [smtp.gmail.com]:587
smtp_sasl_auth_enable = yes
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
smtp_sasl_security_options = noanonymous
smtp_tls_CAfile = /etc/ssl/certs/ca-certificates.crt
smtp_use_tls = yes

Make sure that the the following settings are also correctly set:

#inet_interfaces = loopback-only
inet_interfaces = all
#default_transport = error

For additional logging add the following lines:

debug_peer_list=smtp.gmail.com
debug_peer_level=3

Add your gmail credentials in /etc/postfix/sasl_passwd:

[smtp.gmail.com]:587    USERNAME@gmail.com:PASSWORD

Fix permissions and update postfix config to use sasl_passwd file:

sudo chmod 400 /etc/postfix/sasl_passwd
sudo postmap /etc/postfix/sasl_passwd

Restart postfix for the changes to take effect: sudo service postfix restart

By default, only the most secure sign-ins, such as logging in to Gmail on the web, are allowed for your Gmail account. To permit relay requests, log in to your Gmail account and turn on Allow less secure apps.

Testing the relay service can be done via the following: mail -s "Test subject" recipient@domain.com. Login to gmail and verify that the test email is present in the sent folder. Note that the sender email always overwritten with the account email whose credentials were provided in sasl_passwd no matter what is provided in the header.

Troubleshooting

  • postfix logs can be found at /var/log/mail.log
  • If you make any changes to the password file, make sure to rehash the new password file and restart Postfix
  • If you see any TLS errors, double check the configuration in main.cf
  • If you make any configuration changes, don't forget to restart Postfix for the changes to take effect
  • If you get an error "SASL authentication failed; server smtp.gmail.com", you need to unlock the captcha by visiting this page