Old School Email with Mutt

2015/07/03

For a long time I have managed email with Thunderbird and its awesome Nostalgy add-on. This add-on is what makes Thunderbird work for me – I cannot stand the point&click&drag&drop mentality of a program like Mac’s Mail.app.

I also like to separate private mails from work mail, so I don’t accidentally end up in my work inbox when reading my private mail. Hence I have a need for two mail clients that are at least acceptable.

Now I have finally plucked up enough courage to try a true text-based email client: Mutt. Besides the text interface, there are two other perks that makes Mutt attractive to me:

This post is about the daunting task of setting up Mutt and its associates OfflineIMAP, msmtp and Notmuch. My setup is closely based on the excellent tutorial by Steve Losh and an updated version found here that uses multiple accounts.

In the setup Mutt serves only as an email reader/writer – it does not interact directly with any servers. OfflineIMAP makes a local copy of all emails on an account, msmtp sends mails and Notmuch indexes the local mails for fast searching.

My full configuration is part of my dotfiles repository and here I only explain selected parts.

The setup I describe here is tested on OS X Yosemite as this is runs on my primary home computer.

OfflineIMAP

OfflineIMAP performs two-way syncing: Changes on the server (i.e. new mails) are transferred to the local machine and changes on the local machine (e.g. deletion of mails) are transferred to the server.

In order not to mess around with my regular email accounts I make a new account for testing my configurations: test@dahl-jacobsen.dk.

After a while I got cocky, added one my real email addresses and experimented with this instead – that was a bad idea as I ended up deleting most of the emails on the server. At that point I really appreciated that the paid email service includes support and daily backups.

I haven’t had the guts to recreate the problem with mass deletion, but I am pretty sure that the trouble stems from me changing the nametrans function between two syncs (as explained in the next section).

Therefore a note to self: When changing the nametrans function or deleting folders in the local copy the affected accounts should be deleted in ~/.offlineimap where OfflineIMAP saves configurations.

Supposedly, new versions of OfflineIMAP are not backwards compatible and my setup uses

$ offlineimap --version
6.5.7

Private email

It is possible to name folders differently on the server and the local computer by specifying a nametrans function. A nametrans function is needed for both the remote and local repository and they should be inverses.

For my private email I use a small modification of simple function suggested in the OfflineIMAP documentation that removes the leading INBOX. from the server names:

Work email

My work uses an Exchange server and I found Mutt help here for this situation.

Here I do not use nametrans as the folder names do not have any weird leading phrases.

However, there are a bunch of folders on the server that I am not interested in, ruled out by the folderfilter under the remote repository:

folderfilter = lambda folder: folder not in ['Trash', 
			 'Deleted Items', 
			 'Calendar', 
			 'Contacts', 
			 'Junk E-Mail', 
			 'Tasks']

When first running OfflineIMAP I was informed that SSL was needed and that a certain certificate did not match that of the server. Apparently Mac insists on dealing with certificates through its Keychain (unlike various GNU/Linux distributions where they can be installed with the package manager). I stopped the complaining by simply adding the line

cert_fingerprint = XXX

under the remote repository with XXX being the announced certificate of the server.

Authentication

OfflineIMAP supports different ways of saving credentials for each account – entering my password on every run is not an option for me and neither is a clear text password in the config file.

On OS X I shamelessly copy from Steve Losh: The passwords are saved in OS X’s Keychain and accessed by OfflineIMAP through a custom Python function. The nice thing about this approach is that it is little hassle accessing the passwords – even if Keychain asks for permission it only takes a Space to confirm.

Unfortunately, this approach is not applicable to GNU/Linux, but that will be a topic for later.

For both the IMAP and SMTP server a Keychain item is added with

Mutt

Organizing folders

On the GNU/Linux distributions I have tried, the Mutt version available is compiled with the sidebar patch.

On Mac, Mutt is available through Homebrew – but the sidebar patch is unfortunately not included. I found several guides claiming that running a brew edit mutt and adding appropriate options would include the sidebar; I was not able to make that approach work.

Instead I installed Mutt from a third party formulae. As explained in this fine guide the following command does the trick:

brew install kevwil/patches/mutt --with-gpgme --with-trash-patch --with-sidebar-patch --with-confirm-attachment-patch

Which folders are shown in the sidebar can be customized with the following lines in muttrc:

mailboxes +account/folder1 \
	  +account/folder2

Attachments

Mutt is made for viewing text emails. Attachments are handled externally in the file ~/.mutt/mailcap by specifying rules based on file types. For e.g. JPG images add the line

image/jpg; ~/.mutt/view_attachment.sh %s jpg

The script view_attachment.sh is found here. Put it in the location specified in the mailcap file and make it executable.

HTML emails

For viewing HTML emails inside Mutt I use the browser elinks. Add the following lines to muttrc:

auto_view text/html
alternative_order text/plain text/enriched text/html

HTML emails are then dumped to the tmpdir set in muttrc and displayed with elinks in Mutt.

To open URL’s in mails without the interfering mouse, I use urlview which on OS X is available through Homebrew. Make ~/.urlview containing

COMMAND open %s

This command opens a URL in the default browser (on OS X), but assumes that the URL is correct, i.e., that the protocol is included. Sloppy links like www.something.com will not be opened correctly. The script can be tested with urlview <file> where <file> contains URL’s.

Add the following line to muttrc:

macro pager \Cu "|urlview<enter>" "call urlview to open links"

Pressing CTRL-u when reading an email runs urlview on the mail and returns a list of the links in the mail.

Account settings

I manage settings for the individual accounts by adding

folder-hook maps/*   source ~/.mutt/accounts/maps

to muttrc and filling up the sourced file. One particular difference is how my two mail providers handle sent mail. For my private mail I do not save local copies – specified by unset record – as the sent mail are saved on the served and downloaded with the next run of OfflineIMAP.

The Exchange server does not save the sent mail so here I specify where to save sent mail with

set record=+work/"Sent Items"

When running OfflineIMAP the sent messages are uploaded to the server.

Using Mutt

As mentioned in the beginning I am a Mutt novice, so this is a collection of commands I find myself using repeatedly after a couple of days in Mutt’s company:

An introduction can be found here and examples here.

msmtp

As mentioned in the beginning, msmtp is used for sending email. On OS X Homebrew comes to the rescue once again: brew install msmtp

Msmtp is configured with ~/.msmtprc. For my private account I have:

account test
host send.one.com
port 2525
protocol smtp
from test@dahl-jacobsen.dk
user test@dahl-jacobsen.dk
tls on
tls_starttls on
tls_certcheck off
auth login

Msmtp also looks in OS X’s Keychain for the password. To tell Mutt which msmtp account and mail account that belongs together, I add the following lines to accounts/test:

set from     = "test@dahl-jacobsen.dk"
set sendmail = "/usr/local/bin/msmtp -a test"
set sendmail_wait = 0

To quote Steve Losh:

The sendmail_wait line tells Mutt to wait for the msmtp program to finish sending the mail before returning control, instead of running it in the background.

Notmuch

Notmuch delivers fast indexing and searching. Generate the config file ~/.notmuch-config by running notmuch setup and build an index by running notmuch new. The first run might be a little time consuming, but subsequent runs will be much faster as only new emails will be processed. To invoke a search directly with notmuch, run notmuch search.

Integration with Mutt is available through the Perl script notmuch-mutt, but it has quite a number dependencies that I cannot figure out how to resolve on OS X.

Steve Losh suggests the Python script mutt-notmuch-py instead. The README for the script and the documentation in the source says that this script is exclusively for Gmail, but I have no problem running it from Mutt and get results for my non-Gmail accounts.

To call the script from within Mutt, add the following line to your muttrc:

macro index S "<enter-command>unset wait_key<enter><shell-escape>mutt-notmuch-py ~/mail/temporary/search<enter><change-folder-readonly>+temporary/search<enter>" "search mail (using notmuch)"

This temporarily returns you to the shell and prompts for a search phrase. The emails matching the search criteria (if any) are symlinked to ~/mail/temporary. I add this temporary folder to the sidebar for easy navigation.