Intro

If you haven’t heard of mutt you’re missing out.

Mutt is a small but very powerful text-based mail client for UNIX operating systems

It’s a command line based mail reader (MUA). The neomutt project is a contemporary fork of the original mutt with added features, patch sets and fixes.

I started seriously using mutt as my full-time mail client in 2012. I found its simplicity refreshing. It quickly became apparent how much useless baggage modern graphical mail clients (e.g., thunderbird, outlook, etc) actually bog you down with, not to mention the harrowing way they actually encode mail. Its taken me a long time to appreciate this:

All mail clients suck. This one just sucks less.

mutt is minimal however surprisingly extensible. As is the case with most well designed software, its UNIX design roots becomes apparent; do one thing well while allowing other complimentary programs to bolster it. Such as periodic IMAP polling using cron and isync, or address book integration using abook, or cryptography support using gpg. In the same way git revolutionised VCS by being distributed-first, mutt when paired with isync, mailboxes are local fully fledged copies, making it possible to work with your email in a disconnected fashion. This is powerful; you can still compose emails while offline (e.g., on a flight or on the road), search over all your email whenever you like with notmuch and just sleep better at night knowing your email is backed up on your own hardware.

Like all worthy endeavours there is effort and time involved. You’re going to need to understand how to craft a neomuttrc. The docs are dense and the number of configuration levers you can pull can seem overwhelming.

Getting started with mutt

If you’re starting out on your mutt journey for the first time, I highly recommend checking out the mutt-wizard project started by Luke Smith. Luke is a smart unit with a PhD in linguistics. His configuration files are also a wealth of knowledge. I can also highly recommend checking out HexDSL and his dots repo, from which I have learned so much.

Finally of course RTFM.

2022 setup

My current (2022) terminal based mail setup is a mash-up of:

  • fastmail as of 2022 is my paid for mail/contacts/calendar provider. Exceptional value for money, privacy controls and features technical users (like me) care deeply about. I’m so happy after being on gmail since 2005
  • neomutt as my MUA
  • isync IMAP downloads and syncs mail locally, run by cron periodically */30 * * * * mbsync -a. See my .mbsyncrc for a working fastmail setup
  • msmtp to send outgoing email using SMTP
  • pass to safely encrypt credentials in my publicly viewable dot files
  • pam-gnupg a PAM module that hands over your login password to gpg-agent, i.e., automatically log into GPG once logged into your system, see doco for setup. On Debian I manually built it as described below
  • lynx to view HTML encoded emails (gross)
  • abook command line based address book, using tab in the recipient field within neomutt will auto-suggest
  • notmuch index and search mail, ctrl-f in mutt will trigger this. Run notmuch setup if you don’t have a ~/.notmuch-config yet. Search examples:
    • from:will@example.com AND to:john@example.com OR to:jane@example.com
    • date:”2015-09-01″..”2015-09-02″
    • budget AND FY14 OR FY15 AND date:”2015-09-01″..”2015-09-02″
  • gpg for crypto

My 2022 neomuttrc integrates with the above and customises neovim further:

  • vim keys where possible
  • neovim as default editor
  • reads encrypted credentials using pass
  • has a signature block
  • configures each fastmail mailbox individually as a channel in ~/.mbsyncrc
  • push toast notifications when new mail arrives notify-send
  • logical key binds (gi go to inbox, Mi move to inbox, Ci copy to inbox) possible targets i inbox, a archive, s sent, d drafts, t trash.
  • helpful regex highlights
  • contacts integration with abook

cron

To neatly glue this together in the background:

*/15 * * * * mbsync -a && notmuch new
0 */3 * * * fastmail-abook-sync

GPG crypto

Integrates gpg. Handy for encrypting, decrypting, creating and validating digital signatures all conveniently within mutt:

  1. Install gpg
  2. Copy /usr/share/doc/neomutt/samples/gpg.rc to ~/.config/neomutt/
  3. Set the default key, by grabbing the last 8 hex digits from the fingerprint of your public key, by running gpg --list-keys
  4. After composing mail in mutt, but before sending, hit p to bring up gpg options (such as encrypt, sign, both)
  5. When reading mail, mutt will try to automatically decrypt and verify signatures destined to you

Address book integration

abook is a stand-alone TUI program dedicated to contact management. Contacts are stored in a plain text, human-readable database. How refreshing!

A thank you to José María Mateos who pointed out fastmail have a REST API for pulling your contacts back as a single vcard dump:

https://carddav.fastmail.com/dav/addressbooks/user/<username@domain.tld>/default

Here is a bash script to glue it up and place the output at ~/.abook/addressbook:

#!/bin/bash

tmpfile=$(mktemp)
destfile=$(mktemp)

wget -q https://carddav.fastmail.com/dav/addressbooks/user/ben@bencode.io/Default \
    --user ben@bencode.io \
    --password $(pass show fastmail | head -n 1) \
    -O $tmpfile

abook --convert \
    --informat vcard \
    --infile $tmpfile \
    --outformat abook \
    --outfile $destfile

rm $tmpfile
chmod 600 $destfile
mv $destfile ~/.abook/addressbook
  1. Start abook which brings a TUI (text user interface) up, you should see all your contacts neatly organised.
  2. In mutt, compose a new mail, enter part of the name of a known contact (e.g. ‘Tom’) and hit TAB to query your abook database.
  3. Schedule the above script fastmail-abook-sync in cron to run periodically 0 19 * * * fastmail-abook-sync

pam-gnupg

This is needed to automatically schedule isync to run using cron. Given pass (a gpg frontend) is being used to securely bind credentials into the various config files, pass will interactively prompt for the gpg passphrase to your secret key. Interactive user prompting doesn’t work too well with cron after all.

Luckily pam-gnupg solves this:

A PAM module that hands over your login password to gpg-agent, which can be useful if you are using a GnuPG-based password manager like pass.

In essence, all pam-gnupg does is to send the password as entered in the login prompt to gpg-agent. Therefore its important that your user account password is the same as the passphrase on your GPG key.

As this isn’t a widely used piece of software (e.g., doesn’t exist in the big repos for distros like Debian). Time to dust off automake and gcc:

sudo apt install libpam0g-dev     # install pam development headers
g clone git@github.com:cruegge/pam-gnupg.git
./autogen.sh
./configure
make
sudo make install

On Debian as root edit /etc/pam.d/login (system-local-login on Arch) adding the following block to the end:

auth     optional  pam_gnupg.so store-only
session  optional  pam_gnupg.so

Create ~/.gnupg/gpg-agent.conf with the following:

allow-preset-passphrase
max-cache-ttl 86400

Create ~/.pam-gnupg adding the 40 character gpg keygrip identifier of the encryption subkey you want to set the password for:

$ gpg -K --with-keygrip
sec   rsa2048 2018-11-16 [SC]
      9AB5DD43C5E5FD40475FA6DA0D776275F7F5B2E7
      Keygrip = 6F4ABB77A88E922406BCE6627AFEEE2363914B76
uid           [ultimate] Chris Ruegge <mail@cxcs.de>
ssb   rsa2048 2018-11-16 [E]
      Keygrip = FBDEAD7B0C484CDC85F1CF70352833EB0C921D58

$ echo FBDEAD7B0C484CDC85F1CF70352833EB0C921D58 > ~/.pam-gnupg

Finally make sure the user account password is identical to the gpg passphrase. I chose to update my gpg passphrase:

$ gpg --list-keys
pub   4096R/9AABBCD8 2013-10-04
uid                  Home Nas Server (Home Nas Server Backup)
sub   4096R/149D60C7 2013-10-04

$ gpg --edit-key 9AABBCD8

gpg> passwd
gpg> save

Time to test it out, sudo reboot and login. If you carefully followed the above steps you will now be able to run pass show fastmail without any additional password prompting. More usefully this means cron can now mbsync for you.