- TOC {:toc}
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:
- I can use Vim (or any editor, really) to compose emails.
- The configuration files are in plain text.
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:
-
For the local repository:
nametrans = lambda folder: 'INBOX' if folder == 'INBOX' else 'INBOX.' + folder
-
For the remote repository:
nametrans = lambda folder: re.sub('^INBOX\.', '', folder)
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
- Keychain Item Name being the server (
http://imap.one.com
for my private email provider). - Account Name being the login name
- Password being, well, you know, the password.
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:
s
: Move/save message to folder. If you want to write the folder use=account/path/to/folder
. Press?
to see a file hierachy of folders; this is useful, but not very efficient for navigation (the folders are numbered and can be accessed as such, but the Vim-style withxj
will not move youx
folders down). Forward slash can be used for seaching though.c
: Open another folder. The navigation rules are the same as fors
. Note the shortcutc!
to go the spool directory (typically the inbox).t
: Tag messages. After tagging, the collection messages can be moved with;s
. The semicolon tells Mutt to apply the subsequent command to all tagged messages, not just the highlighted one.T
to mark messages based on a pattern. To limit the search to a particular field like ‘from’ or ‘subject’, use~f
or~s
, respectively. The full list of fields can be found in the manualTAB
: After deleting messages they are still visible in the folder and aTAB
moves the messages to theTrash
folder.a
: Attach file.
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.