Syncing mails with mbsync (instead of OfflineIMAP)
Update: Ryan Lue pointed me to his little_red_flag daemon which triggers mbsync synchronization if changes happen both locally and remotely. Try it out!
A lot of people recommend OfflineIMAP for syncing mails between a remote IMAP account and a local maildir mailbox for mutt1 pleasure. However, OfflineIMAP’s quality is far from what I think is necessary for a tool handling sensitive data such as mail. Looking for an alternative, I stumbled upon [mbsync][] which was maintained by Ted Ts’o for a while. Setting it up to synchronize with the Google mail servers is pretty simple once you know the quirks of Google’s IMAP implementation and mbsync’s weird configuration approach.
To get it working with Google I had to compile mbsync from source — the
packaged version didn’t work for me. mbsync just wouldn’t download any mails.
So, go ahead, download the mbsync source and configure && make && make install
it. mbsync groups its .mbsyncrc
configuration into account details, stores and
channels that connect stores for synchronization. A typical GMail account would
look like this:
IMAPAccount gmail
Host imap.gmail.com
User foo.bar@gmail.com
Pass secret
UseIMAPS yes
CertificateFile /etc/ssl/certs/ca-certificates.crt
Saving the password plaintext is not the best idea. Fortunately, the latest
mbsync sources come with the PassCmd
setting, which is just a command that is
run in a subprocess of mbsync. With a tiny Python script such as this:
#!/usr/bin/env python
import argparse
import keyring
import getpass
if __name__ == '__main__':
SERVICE = 'mbsync'
parser = argparse.ArgumentParser()
group = parser.add_mutually_exclusive_group(required=True)
group.add_argument('--set', '-s', type=str, help='Account to save password')
group.add_argument('--get', '-g', type=str, help='Account to get password')
args = parser.parse_args()
if args.set:
password = getpass.getpass()
keyring.set_password(SERVICE, args.set, password)
else:
print(keyring.get_password(SERVICE, args.get))
and PassCmd
set to:
PassCmd "imap-pass -g foo.bar@gmail.com"
we have a relatively secure way of retrieving the login password through our system’s keyring. Now we have to define a proxy store for the IMAP account and a store for our local maildir
IMAPStore gmail-remote
Account gmail
MaildirStore gmail-local
Path ~/mail/gmail/
Inbox ~/mail/gmail/INBOX
To sync between those stores, you have to set up a channel. Most options are
self-explanatory, however you must take care to use the correct label names for
the sent, draft, starred etc. mail. The names depend on the language set in the
web interface! For me, the verbose flag -V
came in handy because this displays
the communication with the IMAP server, including listing all the available IMAP
directories.
Channel gmail
Master :gmail-remote:
Slave :gmail-local:
Patterns "INBOX" "[Gmail]/Sent Mail" "[Gmail]/Drafts" "[Gmail]/Starred"
Create Both
Expunge Both
SyncState *
Now, running mbsync gmail
syncs mail on the Google servers with your local
maildir in ~/mail/gmail
.
I wanted to write a post about mutt for quite a while now, but I am not ready with my configuration nor do I have much time to document my progress. Hence, I will present different aspects one by one. [mbsync]: http://isync.sourceforge.net/mbsync.html