Migrating mail between IMAP servers using mbsync

My university recently announced a switch from Zimbra to Microsoft Exchange server. The thought didn't sit well with me, so I decided to migrate the mails to my own mail server instead. A generalised account of what I used to achieve this, can be found below.

Setting up mbsync

First, install mbsync (usually packaged as isync) through your distribution's package manager. If that somehow isn't an option, you can also grab the source on the project's page.

Next create a file .mbsyncrc in your home directory, e.g. using vim ~/.mbsyncrc, following the template below:

 # The IMAP server you wish to copy mails from.
IMAPAccount original
Host original.imap.domain.tld
User myusername
Pass mypassword
UseIMAPS yes
CertificateFile /etc/ssl/certs/ca-certificates.crt

 # The IMAP server you wish to copy mails to.
IMAPAccount target
Host target.imap.domain.tld
User myusername
Pass mypassword
UseIMAPS yes
CertificateFile /etc/ssl/certs/ca-certificates.crt

 # Link IMAP server to remote used below. Note Account is set to 'original' now -- we'll be set it to 'target' later!
IMAPStore my-remote
Account original

 # The local storage we'll be using. Note the trailing slash at the end of the Path!
MaildirStore my-local
Path ~/.mail/my/
Inbox ~/.mail/my/Inbox

 # This is where the magic happens. Note Sync is set to 'Pull' now -- we'll set it to 'Push' later!
Channel my-channel
Master :my-remote:
Slave :my-local:
Patterns *
Create Both
Sync Pull
SyncState *

We also need to create the directory in which we intend to store mails:

$ mkdir -p ~/.mail/my

Retrieving your email

After verifying your config file is correct, invoke:

$ mbsync my-channel

Depending on the amount of email you have stored, this will take some time. If your email provider has set a rate limit, you may need to invoke the command again after it exits with an error.

Preparing to upload

When all mail is synchronised correctly, we have to strip some metadata before we can send it all to the new server.

First, remove all .mbsyncstate and .uidvalidity files:

$ find . -type f -name '.??*' -delete

Strip mbsync's unique identifiers from mail file names:

$ find . -type f -name '*U=*' | { while read f; do mv "$f" "`echo $f | sed -e 's/,U=[0-9]*//'`"; done }

Verify all identifiers have been stripped using the command below. There should be no output.

$ find . -type f -name '*U=*'

Lastly, we have to change the Sync setting in our config to 'Push' instead of 'Pull' and set our remote server to 'target' instead of 'original'. Change the relevant lines using your favourite text editor, e.g. vim ~/.mbsyncrc.

Push mail to new server

After verifying your config file is correct, invoke:

$ mbsync my-channel

That's all! You can now set up your new IMAP server in whatever mail program you like to use. Note: if you don't see any of the folders uploaded, you will probably need to edit the IMAP folder subscriptions.


Thanks, this helped me! I ended up finding it easier to transfer directly from server to server though - I've written a description up here: http://superuser.com/a/952215/17025

Leave a comment