The Problem: Raw IMAP is kind of a bummer.

I cant recall what prompted it but I wiped my neomutt setup sometime towards the end of last year and just got around to piecing it back together. Here are some issues I immediately noticed:

The most glaring problem was imap slowness. My hack to get around this was to utilize the tagging functionality. I would tag emails by month and only display one month at a time in the index. It worked well enough but its 2019 I shouldnt need hacky methods to keep my MUA from exploding. My solution was mbsync. Why? I had lots of issues with offlineimap when I used it a year ago - mostly regarding mail delivery time. In any case mbsync was simple.

The Solution: Mbsync to the rescue.

Create Both
Expunge Both
# Save the synchronization state files in the relevant directory
SyncState *

IMAPAccount username
Passcmd "pass mail/gmail/username"
Authmechs LOGIN
CertificateFile /etc/ssl/certs/ca-certificates.crt

IMAPStore username-remote
Account username

MaildirStore username-local
Path ~/.mail/username/
Inbox ~/.mail/username/inbox/
Subfolders Verbatim

Channel username-inbox
Master :username-remote:
Slave :username-local:
Patterns "INBOX"

Channel username-sent
Master :username-remote:"[Gmail]/Sent Mail"
Slave :username-local:sent
Create Both
Expunge Both
SyncState *

Channel username-spam
Master :username-remote:"[Gmail]/Spam"
Slave :username-local:spam
Create Both
Expunge Both
SyncState *

Channel username-trash
Master :username-remote:"[Gmail]/Trash"
Slave :username-local:trash
Create Both
Expunge Both
SyncState *

Group username
Channel username-inbox
Channel username-sent
Channel username-spam
Channel username-trash

Mbsync is fairly straight forward with one caveat, which I’ll get to.

  1. Give it your credentials and auth method. I’m using pass for the password, you can use gpg or what have you.
  2. Name your remote imap connection (username-remote). And account (how you’ll call Mbsync - in this case username).
  3. Maildirstore is your local store. Where your mail will be saved to. Give it a name. username-local just seems intuitive. YMMV.
    • Set the path.
    • Define an inbox (mind the /).
    • Suborders Verbatim tells it to respect the folder hierarchy. There are several options that you can read about in the doc. You probably want this one if you’re using Gmail.
  4. Define your channels. Mbsync uses channels. A channel is just the link between two stores. Your local and remote.
    • Define its name.
    • Set the problematic name of the upstream store and the folder name according to imap. Set the problematic name of the downstream store and the folder name according to where you want to store it.
    • Tell Mbsync if you want to create/delete either dir’s if they do/do not exist.
    • Tell it how to sync.
  5. Group these channels to a particular account.

Dont forget the SSL cert portion. Unless you’re too cool for SSL.

There are are a few caveats. According to the documentation (or how I read it anyway) after the first inbox channel sync you should be able to add a Pattern “*” or “! [Gmail]folder” to either sync everything under the sun, or everything but [Gmail]folder. Which, actually you can do but it creates a DIR hierarchy like this:


This proved to be problematic for to neomutt retrieving the folders. I found it necessary to define them each individually which created the folders on the same level and made Neomutt a happy puppy.

How do I retrieve new mail you ask? Well here’s a trivial way. I’m not sure where I got this but if anyone knows shoot me an email so I can credit them:


## Check mbsync email 3 times per minute based on a cronjob firing this script
killall mbsync &>/dev/null
mbsync -a -q
sleep 20
killall mbsync &>/dev/null
mbsync -a -q
sleep 20
killall mbsync &>/dev/null
mbsync -a -q

Here’s the cronjob

*/1 * * * * ~/bin/

An Excuse to mess with .muttrc

That’s it for retrieval and syncing of email. Now we’ve just got to get into Neomutt. Since you’re in there, it might be a good time to take a look at your .muttrc to make sure you’re up to date with any changes or maybe tweak that setting you’ve been meaning to but you’ve been too busy.

set folder              = "~/.mail/username/"
set spoolfile           = "~/.mail/username/inbox"
set postponed           = "=drafts"
set trash               = "=trash"
set record              = "=sent"
set alias_file          = "$my_path/"alias

# mailboxes
mailboxes "=inbox" "=sent" "=drafts" "=spam" "=trash"
  1. set spoolfile =”~/.mail/username/inbox”.
  2. All other mailbox folders are defined by what we named them in mbsync, prepended with an “=”.
  3. Identify each mailbox with “mailboxes = “=inbox” etc (for sidebar). full .muttrc on my github

Sending mail: Because people want to hear from you. Maybe.

MSMTP handles this pretty easily. I just rolled Neomutt into this because I use it for other things anyway.

auth    on
tls     on
tls_trust_file /etc/ssl/certs/ca-certificates.crt
logfile    ~/.msmtp.log

account username
port    587
user    username
passwordeval "pass show mail/gmail/username"

account default : username

I don’t think this really needs much explanation. Here’s the relevant .muttrc bits:

set sendmail            = "msmtp -a username"

That’s really all there is to it. I’ve been running with this setup for about 5 days now and I’m very pleased. No more seemingly random timeouts. No more timeouts when moving offices and connecting to a different WAP. No more hacks to stop Neomutt from barfing on a couple thousand emails like its the 90’s.

As always, comment, questions, suggestions? Id love to hear them.