Mutt: Viewing Attachments / HTML via .mailcap and a Custom Fortune as a Signature in Mutt

It’s funny how small, trivial things can lead you to make radical changes in the tools you use. As regular readers of this blog know, I collect sayings that I publish every month. I then compile these sayings into a custom fortune file that displays one saying every time I login to my computer or open a new terminal window/shell process.

I recently learned that I can call this custom fortune file as a signature and have one added automatically to every email I write by adding this line to my .muttrc configuration file.

set signature="fortune /usr/share/games/fortunes/cafebedouin -s|"

This is simply calling the fortune program, specifying the location of the file and the -s flag is telling fortune to find a small quote to add. This is a completely trivial feature, but I love it. It is what provided the motivation to actually get mutt to work as my main email client.

My main problem with mutt has been that I couldn’t figure out how to get it to render HTML emails in a readable format, which makes mutt a poor choice as an everyday email client. Half of the emails I receive are in HTML format. The problem, it turns out, is that my email provider encrypts all my email, so I needed an additional line in .mailcap that processes the pgp/mime format, like so:

text/plain; cat %s; copiousoutput
text/html; mkdir -p /tmp/mutt \; cp %s /tmp/mutt \; firefox /tmp/mutt/$(basename %s) &
text/html; lynx -nonumbers -dump %s; copiousoutput; nametemplate=%s.html 
pgp/mime; lynx -dump %s; copiousoutput; nametemplate=%s.html

This points to something I didn’t understand. .mailcap is basically how you tell mutt to process email attachments, and you simply associate file types with programs on your system. There’s also default behavior, where the text/html with copiousoutput will be used when you hit enter by default and when you go to view the attachment, mutt will call the first relevant line in mailcap, as mentioned here.. The same idea applies to other file types, such as images.

image/*; mkdir -p /tmp/mutt \; cp %s /tmp/mutt \; xdg-open /tmp/mutt/$(basename %s) &

So, once the change above is made, you then need to change this line in .muttrc:

alternative_order text/html text/plain text/enriched text multipart/alternative 
auto_view text/html

# Removes temporary attachment files
folder-hook . `rm -f /tmp/mutt/*`

And now, it works beautifully. I’ve completely stopped using thunderbird, and I only use mutt. And, it has improved my email experience so much. I receive something like 50-100 emails a day, most of them newsletters or promotional material from organizations I signed up to hear more about. But, mutt makes it so easy to navigate and delete email.

Since making the transition, my inbox – which I had always relatively good control over and rarely had more than a day’s worth of email in – is down to a couple of leftover emails per day. I read what I want and delete them. I highly recommend making the transition.

Mutt on OpenBSD & Linux: configuring gpg/gpg2 & ~/.muttrc

Update: August 2019. In August 2017, I wrote this post to document my process for getting gpg2 working on OpenBSD 6.1 after not finding a straight-forward explanation online. In the two years since, I have used these notes to set up mutt on both OpenBSD and several varieties of Linux, such as Debian derivatives, Arch and others. With a little work, I have managed to get mutt working on each of these systems.

Update: July 2022, for more general help with .muttrc, you might also find this example useful.

In the update, I went through through and cleaned up the post a bit for clarity and fixed some formatting now that WordPress has better options for including code. If you are trying to get gpg/gpg2 working with mutt, hopefully, this will help you too. If you find errors, please feel free to comment below and I’ll try to fix them.

Install mutt and gnupg

[OpenBSD] # pkg_add -i mutt gnupg 

A series of options will display. Pick the current version of mutt-1.8.0v3-gpgme-sasl and gnupg-2.1.15p2.

[Ubuntu/Debian] # sudo apt-get install mutt gnupg

Change to the relevant package manager equivalent if you don’t use apt. You may also need to add cyrus-sasl to your package manager on linuxes without it baked in.

Copy gpg.conf to your home directory

[OpenBSD] $ cp /usr/local/share/gnupg/options.skel ~/.gnupg/gpg.conf
[Ubuntu/Debian]$ cp /usr/share/doc/mutt/examples/gpg.rc ~/.gnupg/gpg.conf

On Ubuntu/Debian, this step might not be necessary. If using gpg2, you’ll need to substitute gpg2 for all the gpg commands in the config file should you need it.

Add text to gpg.conf

# Enable gpg-agent
 use-agent
 pinentry-mode loopback

This step seemed required on OpenBSD. On many varieties of Linux, it does not seem to matter. I’d guess gnome has something that automagically handles this in the background.

Start the gpg-connect-agent daemon

$ gpg-connect-agent

On some linux distros, this step may already be taken care of for you.

Import your secret and public gpg keys

$ gpg2 --decrypt file.sec.gpg | gpg2 --import --batch

If you don’t have gpg keys yet, check out man for gpg or the Ubuntu privacy documentation for details about doing it.

Check your gpg keyring

$ gpg2 -K

Important step. It’s very easy during the import process to type in a key, password, or command wrong and not import your secret keys. I ended up troubleshooting my mutt configuration for a couple of hours before I figured out it wasn’t working because I didn’t have my gpg keys on my keyring. Save yourself this trouble and check.

Create a text file with your email password

set imap_pass = "yourpassword"
set smtp_pass = "yourpassword"

Save this file to ~/.gnupg/email-password.gpg

Encrypt your email-password.gpg file

$ gpg2 --encrypt /home/cafebedouin/.gnupg/email-password.gpg

Add a .mailcap configuration file for HTML email in Mutt

Put the following in your ~/.mailcap file or create one if it doesn’t exist. Install lynx or another text browser of your choice. If different, change lynx to the alternative in the text below.

text/html;  /usr/bin/firefox %s >/dev/null 2>&1; needsterminal
text/html;  lynx %s; copiousoutput; nametemplate=%s.html

Create a ~/.muttrc configuration file

# .muttrc                                                                      
                                                                               
# GPG                                                                          
# gpg.rc is unnecessary on some systems.                            
# On OpenBSD, you're probably going to need it.                              
# OpenBSD: /usr/local/share/examples/mutt/gpg.rc                               
#                                                                              
# source ~/.mutt/gpg.rc                                                        

set pgp_use_gpg_agent = yes                                                    
set pgp_sign_as = 0O0ABCDZ  # replace with your key                            
set pgp_timeout = 7200                                                         
set crypt_autosign = no                                                        
set crypt_replyencrypt = no 

# password: tell mutt where to find your encrypted
# password, depending on what you installed, you 
# may need to change initial command to gpg
source "gpg2 -dq ~/.mutt/email-password.gpg |"                       
                                                                               
# mailbox configuration                                                        
set imap_user           = login@example.net                                    
                                                                               
# Only need the example.net if your root email address is different from server, otherwise just use your login                     
set folder              = imaps://login@example.net@example.com:993            
set spoolfile           = imaps://login@example.net@example.com/INBOX               
set smtp_url            = smtp://login@example.net@example.com:587                  
set postponed           = +Drafts                                              
set record              = +Sent                                                
set trash               = +Trash 
mailboxes               = +INBOX                                               
set hostname            = example.net                                          
set from                = login@example.net                                    
                                                                               
# mutt configuration                                                           
set ssl_starttls        = yes                                                  
set use_from            = yes                                                  
set postpone            = ask-yes                                              
set delete              = ask-yes                                              
set editor              = "emacs -nw" # or vi               
set pager               = lynx                                          
set charset             = "utf-8"                                              
set visual              = "emacs"                                              
set signature           = ~/.mutt/sig.txt
set alias_file          = ~/.mutt/aliases                                      
set mailcap_path        = ~/.mailcap                                           
set fcc_clear                                                                  
set noconfirmappend                                                            
set hidden_host                                                                
                                                                               
auto_view text/html             # auto render html to text                     
alternative_order text/plain text/enriched text/html    # read html last       
                                                                               
# Reduce polling frequency to a sane level                                     
set mail_check=60                                                              
                                                                               
# keep a cache of headers for faster loading (1.5.9+?)                         
set header_cache=~/.hcache                                                     
set edit_headers=yes                                                           
                                                                               
# Display download progress every 10K                                          
set net_inc=10 

The line to decrypt your password activates the gpg-connect-agent daemon and will not ask for you to enter it again for the duration of pgp_timeout specified in the file.

This should get you to a working set-up to read and write email. If you are having trouble logging in, double check your encrypted password file, particularly if your password requires escaping special characters.

Good luck!