OfflineIMAP and Deleting Folders

Posted: Sun, 3 June 2007 | permalink | No comments

(File this under "Reminders for the future Matt")

I use, and highly recommend, OfflineIMAP for the synchronisation of your e-mail between your daily working machine and your IMAP server (if you don't have an IMAP server available for your mail, it's high time you got one). You point it at an IMAP server somewhere far, far away, and a local Maildir, and all of your mail and folders magically get synchronised in both directions. New folder on the server? After the next run, it'll be on your local machine. Even more magical, though, is that any new mail or folders you create on your local machine will be uploaded to the server. Woohoo! Offsite Backups!

(Before you GUI mail users say "pfft, my client does that all for me", I'll remind you that I don't need to chew several hundred megs of core to delete my spam)

I've got some magical procmail rules (specifically, look for "ARTFUL PROCMAIL") that automatically filter list e-mail into individual folders (with automatic creation of the folder if necessary, of course). This makes mailing lists soooo much easier to handle. Of course, when I unsubscribe from the list a couple of weeks later, that folder is still sitting there, empty and forlorn.

I don't mind empty directories, except that they slow down the OfflineIMAP sync run, since it asks "any new mail in here?" for every one of them. I'd just delete them from my local machine periodically, except that OfflineIMAP can't delete folders off the server if you remove them from your local Maildir (and vice versa). Instead, the folder gets re-created on the local machine, which is definitely not the result I'm looking for. I'm pretty sure this is an IMAP limitation, so I'm not criticising John Goerzen for not implementing this particular feature. However, the empty folders bother me a bit, so I decided to do something about it. Namely, I hacked up some little shell one-liners.

These one-liners are all dependant on you having the same IMAP server (Courier) and folder name mapping (none) as me, otherwise there's a good chance that your file names won't match the patterns I've used. For reference, My folders on the server are dot-directories under $HOME/Maildir, and my folders all start with INBOX. on the client. Also, both sides use periods to separate folder levels. As an example, e-mail to the debian-devel-announce list gets stored in $HOME/Maildir/.lists.debian-devel-announce on the server, and $HOME/Maildir/INBOX.lists.debian-devel-announce on the client.

I've got one big before you start warning: this process involves deleting things. If you're not able to verify that what these snippets are doing is correct for your particular situation, then please do not run them. Also, if running them causes all your e-mail to disappear or your cat to fall pregnant (despite being spayed and/or male), then that isn't my fault. The only warranty I give is that It Works For Me. It May Not Work For You.

As a first step, make sure that your local and remote mail stores are in sync -- presumably by running OfflineIMAP. Otherwise, a folder which is empty on one side might not be quite-so-empty on the other side, and that would possibly make for sadness. Stopping e-mail from coming into your mailboxes would be good, too -- I just turned off my MTA for a few minutes, because clogging other people's queues is fun. Doing something smart with procmail would also work.

On the OfflineIMAP client machine (laptop, home desktop, whatever), cd into your local mail store, and run this to generate a list of IMAP folders that don't have anything in them:

 for i in INBOX.*; do find $i -type f | grep -q $i || \
 (echo $i | sed 's/^INBOX//'); done >/tmp/empties

The contents of /tmp/empties should look something like:

 .Deleted
 .junk
 .lists.debian-devel-announce
 .lists.something-funny
 .spam

Review the list of folders it produced (just to make sure nothing really unpleasant ended up in the list), and then run:

 for i in $(cat /tmp/empties); do rm -rf INBOX$i; done

to delete all the empty folders.

Next, copy the list of folders onto the IMAP server (yes, you need shell access on the server to do all of this; that's why I run a Linode), cd into your Maildir on the server, and run this:

 rm -rf $(cat /tmp/empties)

That removes the folders from the server as well.

For some reason, OfflineIMAP doesn't notice that a folder has gone away, and so it doesn't remove the metadata for the deleted folders from it's cache. I'm not sure if that hurts performance or is otherwise injurious to your health. To be ultra-neat, go into $HOME/.offlineimap (or wherever your metadata dir is) on the client machine and run

 for i in $(cat /tmp/empties); do find . -name INBOX${i}; done |xargs rm -rf

And that makes everything clean and tidy.

Now, of course, someone's going to point me to a small script that finds all of your local empty folders and deletes them locally then issues an IMAP "delete folder" command on the server. But I had fun working all this out, so it's not a complete waste.


Post a comment

All comments are held for moderation; markdown formatting accepted.

This is a honeypot form. Do not use this form unless you want to get your IP address blacklisted. Use the second form below for comments.
Name: (required)
E-mail: (required, not published)
Website: (optional)
Name: (required)
E-mail: (required, not published)
Website: (optional)