Titus Stahl

My Mutt configuration

For a very long time, I was looking for a better way to deal with my emails. At the minimum, the desired configuration should fulfill the following needs:

  • I need to handle multiple email accounts
  • the mails should be saved in the Maildir format, to enable systematic backups and to enable complex filtering with Maildirproc.
  • I need seamless GPG integration
  • the GPG integration should allow for encryption rules to enforce encryption to contacts for which a key is available and to allow automatic encryption with multiple keys for mailing list addresses
  • Ideally, the setup should allow for fast (as fast as popular webmail services) search over the approximately 150,000 mails I have in my archives
  • There should be a quick way to move mails from my inbox to an archive folder (as needed for an Inbox Zero approach)
  • I’d like to synchronize my ownCloud address book via CardDAV (which is also supported by my phone)

For the last few years, I have used Thunderbird with a locally running instance of the Dovecot IMAP server to access my mails, and offlineimap to synchronize them with my email accounts.

While this works well and Thunderbird is the only GUI client that supports (via Enigmail) complex GPG rules, it also left many things to desire:

  • Generally, the Thunderbird interface is sluggish and not very nice to look at
  • The setup uses a lot of local resources as the IMAP server has to run in the background
  • Thunderbird is slow with large folders
  • Search is generally horrible
  • I never really got CardDAV to work

A couple of years ago, I already tried to switch to the console client Mutt. While Mutt has several advantages, such as

  • accessing Maildir directly
  • very fast user interface
  • high configurability

I found it lacking at the time, as it was missing the ability to define complex GPG rules and fast search. I also kept accidentally creating folders when archiving messages with the “s>” shortcut and I found it to annoying to add attachments via the text user interface where you have to navigate folders with the keyboard.

Now, I looked at the situation again, and I found solutions to all these problems — and some other very convenient features. To document this for myself and in the hope, that it may be useful to others, I’ll document them here.

GnuPG

While Mutt always had GPG integration, recent nightly builds have enabled “multiple crypt hooks”. This means that you can configure Mutt to encrypt to multiple keys for a single address which enables encrypted mailing lists (where all recipients are known and have a key).

This can be configured as follows:

1
2
3
crypt-hook '^user@domain\.com$' '0x12345678'
crypt-hook '^user@domain\.com$' '0x22345678'
crypt-hook '^user@domain\.com$' '0x32345678'

For the normal case of individual e-mail-addresses you can generate a configuration file automatically from your keyring with the generate_pgp_auto script. The resulting file can then be included into your mutt configuration.

Notmuch

For search, I can only recommend the excellent notmuch which searches my 150K emails within a couple of seconds, fast enough to not really care about the speed anymore. You should use it with the notmuch-mutt script and you can configure it as follows in your `.muttrc’

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#notmuch
macro index <F8> \
"<enter-command>set my_old_pipe_decode=\$pipe_decode my_old_wait_key=\$wait_key nopipe_decode nowait_key<enter>\
<shell-escape>/home/yourusername/.mutt/notmuch-mutt -r --prompt search<enter>\
<change-folder-readonly>`echo ${XDG_CACHE_HOME:-$HOME/.cache}/notmuch/mutt/results`<enter>\
<enter-command>set pipe_decode=\$my_old_pipe_decode wait_key=\$my_old_wait_key<enter>" \
      "notmuch: search mail"

macro index <F9> \
"<enter-command>set my_old_pipe_decode=\$pipe_decode my_old_wait_key=\$wait_key nopipe_decode nowait_key<enter>\
<pipe-message>/home/yourusername/.mutt/notmuch-mutt -r thread<enter>\
<change-folder-readonly>`echo ${XDG_CACHE_HOME:-$HOME/.cache}/notmuch/mutt/results`<enter>\
<enter-command>set pipe_decode=\$my_old_pipe_decode wait_key=\$my_old_wait_key<enter>" \
      "notmuch: reconstruct thread"

macro index <F6> \
"<enter-command>set my_old_pipe_decode=\$pipe_decode my_old_wait_key=\$wait_key nopipe_decode nowait_key<enter>\
<pipe-message>/home/yourusername/.mutt/notmuch-mutt tag -- -inbox<enter>\
<enter-command>set pipe_decode=\$my_old_pipe_decode wait_key=\$my_old_wait_key<enter>" \
      "notmuch: remove message from inbox"

This sets up F8 to search your email and displays the result as a folder in Mutt with all the usual functions enabled.

Addresses

For Ctrl-T address completion, I synchronize my OwnCloud with pyCardDAV. In addition, I also scan my local Maildirs for e-mail addresses with lbdb.

Finally, I also add all adresses in any mail that I open to the local lbdb database by keeping

1
set display_filter="~/.mutt/add-address.sh"

in my .muttrc.

This is my add-address.sh:

1
2
3
4
#!/bin/sh
MESSAGE=$(cat)
echo "${MESSAGE}" | lbdb-fetchaddr
echo "${MESSAGE}"

Finally, I have two scripts in my .mutt/address-providers directory:

First, pycard:

1
2
#!/bin/sh
pc_query -m "$1"

Second, lb-query:

1
2
#!/bin/sh
/home/titus/.mutt/lb-query "$1"

Now, both scripts can be integrated into Mutt with the following configuration option:

1
set query_command = "echo ; /bin/run-parts -a '%s' /home/titus/.mutt/address-providers/|grep '@'"

After this lengthy setup, Mutt will be configured to use your online address book and also all locally collected addresses.

Forwarding

Fixing forwarding in Mutt is absolutely essential

1
2
3
4
5
6
7
## subject line for forwarded messages
set forward_format="Fwd: %s"
## Don't decode MIME messages to text/plain when forwarding
set forward_decode=no
# forward including attachments
set mime_forward=yes 
set mime_forward_rest=yes

Adding attachments with the GUI

I have already described in another blog post how to configure Mutt to add attachments with a GUI dialog.

Archiving

It’s easy to set the a key as a shortcut for moving mails into the “archive” folder of the current mail account:

1
2
# a always saves to archive
macro index,pager a "<tag-prefix><save-message>=archive<enter>"

Using vim as an editor

For composing and editing mails, I use vim with the right spell check options already preconfigured:

1
set editor="vim -f -c 'set spell spelllang=de,en,nl'"

Taskwarrior Integration

Finally, you can also integrate Mutt with Taskwarrior.

This concludes my Mutt configuration – it really works great and allows me to go through a lot of emails in a short time, perfectly synchronized between multiple computers and makes using end-to-end encryption really easy.