The Mutt e-mail client

Configuring mutt as a text-based e-mail client.

All mail clients suck. This one just sucks less. — Michael R. Elkins

Mutt is a text-based e-mail client for UN*X systems. It doesn’t do nicely formatted HTML emails or images, but it’s extremely customizable and completely keyboard-driven.

I have been using Mozilla’s Thunderbird for a while now and I’m not completely satisfied with the way it handles mailboxes. It’s time to try something ‘new’: Mutt. The plan is to use Mutt for all things e-mail for a full month.

A word of warning: Mutt is known for its complicated setup (there are literally hundreds of configuration commands), and I had to stitch together quite a few blog posts before I got a working setup. If you don’t like braking and rebuilding stuff or hunting down a missing comma for half an hour, Mutt is probably not for you.

Fetching emails with isync

I use isync to synchronize my e-mail locally and Mutt to read and send emails. IMAP only. Mutt can do more, much more, but you will have to look elsewhere for that.

Mutt comes with IMAP support built-in. This works superbly but is a bit slower when dealing with larger mailboxes. Mutt’s built-in IMAP support fetches your e-mail as soon as you start the program. There is a cache that is quite fast but requires a bit of patience every time you open the program. It also means you can’t read your e-mail offline. I want a little more and use isync to download or better, synchronise, my e-mail locally via a crontab.

isync syncs your different e-mail accounts to a local folder structure. As much as it can be used outside of Mutt, they work together nicely and it makes Mutt faster and available on the go.

Be careful because isync doesn’t download but synchronizes your mailbox! If you mess up the configuration, you could easily delete all your mail from the mail server. Play with a test account first and/or make sure you have a backup before you try this. You do have a backup, right?

The executable isync is called ‘mbsync’ and can be configured with a ‘.mbsyncrc’ configuration file in your home dir. Let’s configure our different IMAP accounts and add a crontab to fetch our new e-mail.

Create a ‘~/.mbsyncrc’ file with the following:

SyncState *
Create Both


IMAPAccount john-account
    Pass       secret_password
    UseIMAPS   yes
    RequireSSL yes

IMAPStore john-remote
    Account john-account

MaildirStore john-local
    Path  ~/.mail/john/
    Inbox ~/.mail/john/INBOX

Channel john-inbox
    Master ":john-remote:INBOX"
    Slave  ":john-local:INBOX"

Channel john-sent
    Master ":john-remote:Sent"
    Slave  ":john-local:sent"

Group john
    Channel john-inbox
    Channel john-sent

Repeat this for every account you wish to synchronize. The example will only synchronize your inbox and sent mailbox, add other folders you might need, like a trash or spam folder. I had to create each of the account directories in ‘~/.mail’ manually as well.

Now add a crontab command to fetch all e-mail every 5 minutes:

*/5 * * * * mbsync -a

The ‘mbsync -a’ command fetches all configured e-mail accounts. You can define different schedules with ‘mbsync john’, for example, which only synchronizes the account in our configuration example.

Once done, you will see a folder for each channel in the ~/.mail/john directory with all your emails. You now have an offline copy, which is great.

Installing Mutt

Mutt time! Mutt doesn’t come with a sidebar folder view out-of-the-box, but you probably want one. There is a patch, but you need to instruct Homebrew to include it when installing Mutt.

brew edit mutt

to modify the Homebrew formula and add

option "with-sidebar-patch", "Apply sidebar patch"

at the bottom of the block with all the options and add

patch do
  url ""
  sha1 "1e151d4ff3ce83d635cf794acf0c781e1b748ff1"
end if build.with? "sidebar-patch"

at the end of the section with all the patches.

And, finally, install Mutt:

brew install mutt --with-sidebar-patch

Configuring Mutt

Muttt’s config lives in the ‘.muttrc’ file in your home dir, right next to the isync config file. However, I prefer a ‘.mutt’ folder with a ‘muttrc’ (no dot here) file to have all the Mutt dependencies in a single place.

Let’s start by telling Mutt where to look. Add the following to the ‘~/.mutt/muttrc’ file:

set folder           = ~/.mail            # mailboxes
set alias_file       = ~/.mutt/alias
set header_cache     = ~/.mutt/cache/headers
set message_cachedir = ~/.mutt/cache/bodies
set certificate_file = ~/.mutt/certificates
set mailcap_path     = ~/.mutt/mailcap    # filetypes
set tmpdir           = ~/.mutt/temp

and set some nicer defaults:

set   wait_key   = no      # shut up, mutt
set   mbox_type  = Maildir # mailbox type
set   timeout    = 3       # idle time before scanning
set   mail_check = 0       # minimum time between scans
set   markers    = no      # no + sign for wrapped lines
unset move                 # gmail does that
set   delete               # don’t ask, just do
unset confirmappend        # don’t ask, just do
set   quit                 # don’t ask, just do
unset mark_old             # read/new is good enough
set   beep_new             # bell on new emails
set   pipe_decode          # strip headers and eval
set   thorough_search      # also when searching
color status cyan default  # while instead of black
bind index gg first-entry  # cursor to first a la vim
bind index G  last-entry   # cursor to last a la vim

Moving on to the sidebar. The following configures the up and down arrows to select a mailbox in the sidebar and the right arrow to open the selected mailbox. It also highlights the mailboxes with new emails.

set sidebar_delim   = "  │"
set sidebar_visible = yes
set sidebar_width   = 20
macro index,pager <up> "<sidebar-prev>" "previous folder in sidebar"
macro index,pager <down> "<sidebar-next>" "next folder in sidebar"
macro index,pager <right> "<sidebar-open>" "open folder in sidebar"
color sidebar_new color221 color233
set status_chars  = " *%A"
set status_format = "───────────────────[%r%m messages%?n? (%n new)?%?d? (%d to delete)?%?t? (%t tagged)? ]───%>─%?p?( %p postponed )?───"


Let’s configure an account. I created a file for each account and used the folder hooks to trigger the right config for the selected mailbox:

folder-hook example/* source ~/.mutt/accounts/example
folder-hook gmail/*   source ~/.mutt/accounts/gmail

And the ‘example’ file in the accounts folder:

set realname            = "John Doe"
set from                =
set use_from            = yes
set my_smtp_user        =
set smtp_pass           = password
set smtp_url            = smtps://$my_smtp_user:$
set ssl_force_tls       = yes
set smtp_authenticators = login

set spoolfile = +example/INBOX # inbox
set record    = +example/sent  # sent folder

mailboxes Example \ # fake mailbox as divider
          +example/INBOX \

Note that the password is not encrypted here. Therefore, only use this if you know what you are doing and make sure the file is only readable for your user. There are some ways around this if this scares you, but that’s beyond the scope of this post.

If your password contains special characters ($, &, %, #, * and the like), you’ll need to URL encode them. This took me a while to figure out. The password will be used in the ‘smtp_url’ setting so it makes sense you URL encode the special characters like you would in any URL. I used irb to quickly encode my password:

require "uri"

The mailboxes section at the end of the file sets the mailboxes you will see in the sidebar. These have to match the mailboxes you defined earlier in the ‘mbsync’ configuration file. The first "Example" line is not a real mailbox, but a little hack to have a visual separation between the accounts.

You’ll find plenty of Gmail example files if you want to add one of those. They are basically the same as the example above, but with Google’s SMTP server and your Gmail address.

Quick Look

By default, Mutt saves attachments you open within Mutt to disk. This works but is cumbersome if you simply want to look at a photo someone sent you or quickly scan an attached MS Word document. OS X has this awesome Quick Look feature that quickly opens most files without having to install separate applications. Why not use Quick Look for e-mail attachments in Mutt?

Did you know you can run Quick Look from the command line with ‘qlmanage -p file’? We’ll use this trick to tell Mutt to run Quick Look when opening attachments. Add a ‘mailcap’ file in the ‘~/.mutt’ folder you created earlier with the following:

text/html; qlmanage -p %s; nametemplate=%s.html
text/html; lynx -dump %s; nametemplate=%s.html; copiousoutput
application/pdf; qlmanage -p %s; nametemplate=%s.pdf
image/jpg; qlmanage -p %s; nametemplate=%s.jpg
image/jpeg; qlmanage -p %s; nametemplate=%s.jpg
image/pjpeg; qlmanage -p %s; nametemplate=%s.jpg
image/png; qlmanage -p %s; nametemplate=%s.png
image/gif; qlmanage -p %s; nametemplate=%s.gif
text/*; open %s
application/*; open %s

Run Mutt; search for an e-mail with an attachment; press enter with the attachment selected and voila, quick previews without saving.


I obviously didn’t find this all by myself so here are some of the most useful snippets I stole: