stop touching the computer

How to Add Needless Complexity to Your Life

I used Apple Mail forever until recently, when my Exchange account starting causing it to blow itself up. Instead of installing Thunderbird and moving on with my life, I decided it was a good idea to start being a Serious Email User, and so I installed the Serious Email Client mutt. But since this is a piece of Serious Software, there wasn't any easy-to-find, good documentation focused on actually sending and receiving email as opposed to Installing and Configuring mutt. (Even the hard-to-find ones didn't go in-depth enough, and weren't written for OS X.) So this my attempt to get everything necessary---and nothing more---written down in one place.

mutt is just for reading email

The program mutt was not originally designed to do the actual sending and receiving of email. It can do that now, but it was built as a way to view local mail and to compose messages (except not really---you do the actual writing in your $EDITOR). Mail is fetched from a mail server using another program---I'll be using getmail. Mail is sent using yet another program---msmtp.

And there's no point in having mutt if you've got nothing to read, so before we even bother installing mutt we're going to set up getmail.

you get mail with getmail

The easiest way to install getmail is with Homebrew:

brew install getmail

The official configuration documentation is not always very clear, but it is comprehensive. So we'll try to simplify it here, with some help from the blogosphere.

First set up the config directory, with restricted permissions for Serious Security:

mkdir -m 700 ~/.getmail

In that folder you'll need to set up a config file for each email account you want to retrieve messages from. If you just have one, name the file getmailrc, which is what getmail looks for by default. The examples below are for setting up a Gmail account, so I named the below config file gmailrc:

type = SimpleIMAPSSLRetriever
server = imap.gmail.com
port = 993
mailboxes = ALL
username = gmail-address
ssl_version = tlsv1_2

type = Maildir
path = ~/Mail/gmail/

message_log = ~/.getmail/gmail.log
read_all = false

The most common alternative to SimpleIMAPSSLRetriever is probably SimplePOP3SSLRetriever, but there are lots of types supported by getmail.

If you only want to download your inbox, don't specify mailboxes. If you want to download a subset of your mailboxes, replace mailboxes = ALL with a list of desired mailboxes in the following format:

mailboxes = ("INBOX", "INBOX.spam")

getmail's ssl_version defaults to SSLv23, which needs to be overridden since it allows SSLv3, which is now known to be vulnerable.

Replace gmail-address with your full Gmail email address, then create a Maildir directory structure in ~/Mail/gmail:

mkdir -m 700 -p ~/Mail/gmail/{cur,new,tmp}

(getmail supports mbox in addition to Maildir; I don't really know the relative strengths and weaknesses but I went with Maildir ¯\_(ツ)_/¯.)

The [options] are not required, but read_all = false is a very good idea (especially with mailboxes = ALL) because otherwise getmail will download all your mail every time you run it.

You can specify password in your config file, but then it's sitting there in plain text and that's Bad. So instead, add the password to Keychain Access:

security add-internet-password -a 'gmail-address' -s 'imap.gmail.com' -r imap -P 993 -w app-specific-password

Replace gmail-address again with your full Gmail email address, and app-specific-password with a Google App Password.

Important: if your password has characters like $ that shells treat specially, make sure to put single quotes around the whole password.

Then run getmail, with the --rcfile flag if you have config files that aren't named getmailrc (you can use the flag multiple times):

getmail --rcfile=gmailrc --rcfile=otheraccount

Add that command to your cron jobs or use Apple's launchd to run it regularly.

then you install mutt

brew install mutt --with-gpgme --with-confirm-attachment-patch

The --with-gpgme flag enables GPGME (GnuPG Made Easy), which is apparently the right way to do encryption with mutt. The --with-confirm-attachment-patch flag causes mutt to warn you before sending a message with "attach" in the body but no attachment. Both of these flags are optional, and there are other flags you might want to add; see brew info mutt.

The only setting you have to add to your mutt configuration file (by default, ~/.muttrc) is set mbox_type=Maildir (or set mbox_type=mbox as the case may be). You'll probably want to specify the location of your Gmail folder, though:

set mbox_type=Maildir
set folder = "~/Mail/gmail/"
set spoolfile = "~/Mail/gmail/"
set record = "~/Mail/gmail/sent/"

The sent folder is technically another Maildir box, so you'll need to populate it with the same three folders:

mkdir -m 700 -p ~/Mail/gmail/sent/{cur,new,tmp}

Fine-tuning your configuration and getting comfortable with the program isn't what this post is about; take a look at sample .muttrc files, Steve Losh's excellent guide and the list of mutt commands.

I will mention one customization that I had to come up with for reading HTML emails on OS X. It's easy enough to pass HTML emails and HTML attachments to a text-based browser like lynx or w3m, but when I get Today in Tabs I want to be able to open the tabs in Safari or whatever real browser I usually use. You can pass links from w3m to Firefox if you're using Linux, but on OS X you'd have to be using w3m from within emacs to be able to do that. Piping the HTML directly to Safari doesn't work either, because the temporary file that mutt creates has the .txt extension, so Safari doesn't render the HTML. My solution is to add this to your .muttrc:

macro pager \cb 'cat > /tmp/mutt_mail.html; open /tmp/mutt_mail.html' 'open email in default browser'

When you hit ^b (control-b) while viewing an HTML message or attachment, what that does is spit the HTML into a temporary file, then open it in your default browser.

(I wouldn't have figured this out if not for Bruno Postle's page on following links.)

and send mail with msmtp

By now you know the drill:

brew install msmtp

Then set up your configuration file, with permissions set to 600, at ~/.msmtprc:

tls on
tls_starttls on
tls_trust_file [see below]
logfile ~/Mail/msmtp.log

account gmail-address
host smtp.gmail.com
port 587
protocol smtp
auth on
from gmail-address
user gmail-address

OS X doesn't have the /etc/ssl/certs/ca-certificates.crt file that some Linux systems do. All our certificates are in the Keychain Access application; so we need to export them:

  1. Open Keychain Access (open -a /Applications/Utilities/Keychain\ Access.app/).

  2. From the "Keychains" column, select "System Roots."

  3. Select All, then go to File → Export Items... (⇧⌘E).

  4. Save the .pem file wherever, then set tls_trust_file to the path to it (for example, ~/Mail/certs/Certificates.pem).

Then return to your .muttrc and add: set sendmail = "/usr/local/bin/msmtp"

Add another Keychain entry:

security add-internet-password -a 'gmail-address' -s 'smtp.gmail.com' -r smtp -P 587 -w app-specific-password

Again, replace gmail-address with your full Gmail email address, and app-specific-password with a Google App Password.


At this point you should be able to send and receive email using mutt! Wooooww. Now you can dick around with further niceties: