Managing multiple email accounts with Mutt and Fetchmail

Recently, I switched to ProtonMail as a way of increasing my privacy online and moving away from the “data as currency” model of Google and Facebook (as part of this same effort, I closed my Facebook in favor of creating this blog!). However, most of what I describe here has been my setup for a while due to my penchant for two things:

  1. Wanting to keep my emails backed up (and a local copy always at hand).
  2. Wanting a simple but powerful email reader so that it gets out of the way while enabling as much customization as needed.

At the same time, I wanted a system where I could easily add and remove accounts while adding/removing as little configuration as possible, and this informs the way I partition my configuration files (as will be apparent).

As the title suggests, there are two different parts to this setup: fetchmail and mutt.

Since fetchmail does not natively provide for encryption of the configuration file (and the file contains sensitive information), I wrote a wrapper around it which decrypts the file and passes it to fetchmail via stdin. That part will not be discussed here and can be set up after glancing at the fetchmail manual page (in short, do something like gpg -d -o - /path/to/encrypted/config | fetchmail -d -f -).

As for the configuration file itself, this should serve as a good template:

set postmaster "<local username>"
set bouncemail
set no spambounce
set softbounce
set properties ""
poll <imap server> with proto IMAP
       user 'username' there with password 'password' is '<local username>' here
       options keep ssl sslproto "TLS1+" mda "<mda> $HOME/.local/mail/Gmail/"
  folder "<folder>"

You can replicate the last bit (poll ...folder "") as many times as you need to add multiple accounts. is the username you want mail to be delivered under (I recommend running fetchmail as your user unless there are extenuating circumstances). username and password are self-explanatory. The exact structure of can differ based on the server (for example, with Gmail, some folders require a prefix of [Gmail]), but usually Inbox will work without any prefix. Oh, and is a Mail Delivery Agent — you’ll want one that delivers to a maildir. The one I use is the stand-alone MDA from getmail called getmail_maildir and requires no configuration.

A special note for Protonmail Bridge users: In the options section, you’ll want keep no sslcertck sslfingerprint "48:63:2E:30:62:FC:23:B3:9A:42:CD:02:1E:FF:F8:52" since otherwise fetchmail will throw an error as the Bridge’s certificate isn’t trusted.

At this point, fetchmail should be good to go. Before you try running it, you should create the maildirs you setup in the fetchmail config. This is really easy; if the maildir is $DIR, you can just run mkdir -p $DIR/{cur,tmp,new} and you’re done. Now, you can try running fetchmail -f /path/to/config/file. If all goes well and you don’t have any unread emails, fetchmail should exit normally without downloading any emails. At this point, I’d run fetchmail -a -f /path/to/config/file to get a copy of all emails, read or not. Note that fetchmail uses whether an email is read to determine whether or not to download it.

The next piece of the puzzle is mutt. All of my mutt configuration goes in ~/.config/mutt/muttrc. I have a master RC file that looks something like this (along with many other variables that I won’t go into here):

set folder="~/.local/mail"
mailboxes "+Gmail" "+Brown" "+CaltechAlumni" "+ProtonMail" "+ProtonMail-Custom"
folder-hook Brown 'source ~/.config/mutt/muttrc/muttrc.localb; macro index cb <refresh>'
folder-hook Gmail 'source ~/.config/mutt/muttrc/muttrc.localg; macro index cg <refresh>'
folder-hook CaltechAlumni 'source ~/.config/mutt/muttrc/muttrc.localca; macro index ca <refresh>'
folder-hook ProtonMail 'source ~/.config/mutt/muttrc/muttrc.localp; macro index cp <refresh>'
folder-hook ProtonMail-Custom 'source ~/.config/mutt/muttrc/muttrc.localpc; macro index cq <refresh>'

source ~/.config/mutt/muttrc/muttrc.macros

In my case, I store all of my email in ~/.local/mail, so I set that as the “base” location, if you will, by setting the folder variable. Then, +Gmail expands to ~/.local/mail/Gmail. In this way, I don’t need to spell out the full location for each mailbox.

Additionally, when I switch mailboxes, I load a mailbox-specific config file. For example, the Gmail one looks like this:

set spoolfile="~/.local/mail/Gmail"

set smtp_url="smtps://chiraag.nataraj\@gmail.com@smtp.gmail.com/"
set from="ಚಿರಾಗ್ ನಟರಾಜ್ <chiraag.nataraj@gmail.com>"
set realname="ಚಿರಾಗ್ ಮಂಜುನಾಥ ನಟರಾಜ್"
set imap_user=chiraag.nataraj@gmail.com
set record="^"

set signature="~/.config/mutt/signatures/signature.home"
set header_cache=~/.cache/mutt/mutt_cache.gmail

send-hook . "source 'gpg -d ~/.config/mutt/mutt_secure/gmail.password.gpg |'"

source ~/.config/mutt/muttrc/muttrc.macros
source ~/.config/mutt/muttrc/muttrc.autocrypt

In other words, I set the SMTP URL (for sending email from this mailbox), name, signature, and so on. Additionally, I tell it to decrypt the file containing the password for my Gmail account before opening up my editor to compose an email. This means I don’t need to needlessly decrypt the file until necessary.

You might notice this mutt.macros thing lying around. That file looks like this:

macro index ca '<sync-mailbox><enter-command>source ~/.config/mutt/muttrc/muttrc.localca<enter><change-folder>!<enter>'
macro index cb '<sync-mailbox><enter-command>source ~/.config/mutt/muttrc/muttrc.localb<enter><change-folder>!<enter>'
macro index cg '<sync-mailbox><enter-command>source ~/.config/mutt/muttrc/muttrc.localg<enter><change-folder>!<enter>'
macro index cp '<sync-mailbox><enter-command>source ~/.config/mutt/muttrc/muttrc.localp<enter><change-folder>!<enter>'
macro index cq '<sync-mailbox><enter-command>source ~/.config/mutt/muttrc/muttrc.localpc<enter><change-folder>!<enter>'

This is just an easy way for me to switch between different mailboxes. Each of my mailbox-specific config files sources this file. In the folder-hook, I then ‘reset’ the macro for the current mailbox to simply refresh the screen (basically a no-op).

This system means that if I want to add a new mailbox to mutt, I do the following:

  1. Create a new mailbox-specific config file with the necessary details.
  2. Add the mailbox to my master configuration file.
  3. Add a keybinding for switching to that mailbox to mutt.macros.

In addition, I need to do silly things like creating a mailbox-specific signature and stuff, but that’s not too bad.

With some work, I could probably even automate the current system for adding a mailbox, but I am fairly satisfied with how the system currently works.

Leave a Reply

Your email address will not be published. Required fields are marked *

7 + 2 =