I've been looking for an easy way to sync my emails to my laptop (running Arch Linux). My requirements for such a program were the following:
- I had to be able to access my email while I was offline, and be able to compose drafts
- It had to be able to run under cron, which I use for all my automation tasks
- It had to be well configurable with some kind of plugin system
- It needed to work well with Mutt
- I had to be able to secure my passwords with GPG
- I could access the contacts of a different gmail account when composing emails (I use one gmail account for all of my contacts, but I'm mainly concerned with my school email)
The answer to all of these was . It lets me sync all of my email to my computer using a Maildir, and it does it fastOfflineIMAP
- It backs up all my email to a Maildir folder, which mutt can read. You can set it up to sync to a local IMAP server, but I thought that wasn't needed for me (I do a fair bit of email from the gmail web interface).
- I used a simple bash script that I call as a cron job every 5 minutes, as detailed below.
- You can add in functionality using a python script, which I use for nametrans
- It works so well with mutt, that it even automatically generates a mailbox list for me to include in Mutt.
- I can use python and gpg-agent to grab my passwords, which allows me to have them unlocked for a certain period of time while i'm at my computer, and lock them back up when I'm away. That way, they're stored encrypted.
So I first installed the couple programs I needed:
The first thing that I focused on was reading my mail. What good is anything else on your system if your mail isn't there? This is also probably what will take the longest, as syncing all of your mail with IMAP is gonna take a lot of time. There are a couple options that you can use to sync your mail, some of which I've used in the past:
- Mutt's IMAP
- OfflineIMAP (what I use)
- fetchmail + procmail (what I used to use)
I used to use fechmail + procmail. Fetchmail worked great for grabbing all of my mail off of the Gmail servers, and procmail sorted it out into folders. It also let me run some post-sync hooks for forwarding mail, etc. The problem was that the sync of mail was not bi-directional. I wanted to be able to change mail on my local laptop, and have that change reflected on the Gmail servers. The reason? I use gmail's web client a LOT, as I'm in university, and I'm usually on a million different computers. It really helps to have file's be marked as read on both servers, and to have my sorting be reflected in both places.
So what does OfflineIMAP do? It:
- Syncs all your mail from an IMAP server and your local machine, two-way.
- It creates folders on your local machine in the maildir format that corresponds to gmail's folders, but lets you change the name of these folders (known as nametrans)
- It can either run as a daemon or let it run on the user end, refreshing itself in a configured interval.
- It lets you run python scripts to do a number of tasks.
Let's get to installation. I use from the AUR. I like to have the most updated package, even if it breaks my system (I don't know why I do this to myself). If you want the more stable package, use offlineimap pacman -S offlineimap
Now to the configuration. My config (just a snippet) is the following:
[general] accounts = school, gmail maxsyncaccounts = 2 ui = machineui pythonfile = ~/.config/mutt/nametrans.py [Account school] localrepository = school-local remoterepository = school-remote status_backend = sqlite autorefresh = 3 quick = 10 postsynchook = notmuch new [Repository school-local] type = Maildir localfolders = ~/Maildir/school/ nametrans = nt_local [Repository school-remote] type = Gmail remoteuser = <email> remotepasseval = mailpasswd("school") realdelete = no cert_fingerprint = <cert fingerprint> nametrans = nt_remote [mbnames] enabled = yes filename = ~/.config/mutt/mailboxes header = "mailboxes " peritem = "+%(accountname)s/%(foldername)s" sep = " " footer = "\n" # Necessary as of OfflineIMAP 6.5.4 sslcacertfile = ~/.certs/imap_cert.crt
Now lets step through this. The accounts line tells me what accounts to sync. Notice that I included two accounts here, but the above config file only has one. I figured I'd cut the code down. I also have maxsync accounts = 2, because I have two accounts. The most important part here is the:
pythonfile = ~/.config/mutt/nametrans.py
That's because I have some very important stuff in that file. It defines my nametrans and lets me exclude folders from being synced. We'll get back to that later. The [Account school] block has the definition of my school account. Here's a commented version:
[Account School] localrepository = school-local #what the block is called that defines local stuff remoterepository = school-remote #ditto for the remote status_backend = sqlite #I want to use sqlite on the local side autorefresh = 3 # I want it to refresh every 3 minutes, change this to anything quick = 10 #No idea what this does postsynchook = notmuch new #This calls notmuch, described below
The really important part here is the postsynchook. It calls the program "notmuch new", which I'll write another blog post on, and link it here.
nametrans = nt_local
Notice my nametrans = nt_local. nt_local is a python function, defined in my nametrans.py file. You can see that . It is well commented, and you should be able to figure out what's going on. Using a python nametrans has saved me many upon many headaches, as the layout of the file is very easy to understand. What is nametrans? It translates the "tags" that gmail holds into local folder names. I don't want a folder in my system called "[Gmail]All_Mail", so i change it to "zarchive". The python file shows how I do this. Any function you include in that python file can be used in offlineimap. Neat!
One thing to notice is that it runs in a for python, which I use to make sure I don't break my python for this. If you want info on virtualenv, . If you don't want to run it in a virtualenv, change the first line of that file. This file must click here
remotepasseval = mailpasswd("school")
Notice the remotepasseval. It uses the mailpasswd function in the python file. Check it out. It lets you use a gpg'd file that contains your mail password in your config file. That way I only have to store my password in one place, and it's gpg'd.
The [mbnames] section defines a file (".config/mutt/mailboxes") that offlineimap updates after each sync. It creates a file that can be imported into mutt that contains all the mailbox names for my accounts. Coupled with mutt-sidebar, this really helps cut down my .