I have recently been moving several clients off of a basic email server to a Google Apps account (Free or Business, depending on the client), and several have had up to a couple years worth of email. I’ve tried several different techniques, but recently found some great command line kung fu that made the process extremely easy and much more accurate than the past attempts.
There are several different methods available for migrating email from various servers to Google Apps, including POP transfer from within each account’s settings, dragging and dropping via IMAP with a mail client like Thunderbird, or using the official email migration API from Google. However, each of these methods has its downsides: POP is slow and kludgy, dragging and dropping only works for low volume accounts, and the email migration API requires code be written and using a for-pay Apps account. What’s a geek to do? Turn to free and open source solutions!
A little bit of searching turns up that a command line tool known as imapsync does a fantastic job of, well, syncing IMAP accounts. I was tipped off by a blog post on Marius Ducea’s blog (lots of good stuff on that site by the way), which contains a basic introduction to imapsync and how to use it. The author of imapsync, Gilles Lamiral, continues to develop the software and is taking donations for different features, and also charges for the source and for support (visit Gilles’ site here). However, thanks to the licensing of imapsync (NSWF), it is also available for free from other hosted repositories. I was using CentOS, and got my copy from the following:
After getting a copy of the Perl script, I ran perl -c imapsync to check dependencies as Ducea instructs, and found I was missing the Mail::IMAPClient module. That was a quick fix with
sudo cpan Mail::IMAPClient
Voila! The script ran just fine at that point. Ducea provides some good templates for running a sync between two servers, and it worked almost 100% right off the bat. However, I was getting issues with sent messages and deleted messages ending up in Google Apps with labels such as “[IMAP]/Sent Messages,” which obviously was not what I wanted. (Note: most such errors can be avoided by appending
--dry --justfolders to the command and checking the output to see what imapsync discovers as folders/labels that already exist, and those which it plans on creating.)
A little more searching turned up Mark’s Pages of Stuff’s post about moving to Google Apps, and with a little modification there as well, I was able to get messages moved properly from the IMAP’s sent folder into Google Apps’s sent folder, trash, etc. On Mark’s posting, he uses folder labels like “[Google Mail] Bin,” but he notes that Google changes the name of labels based on locale. He just happens to be in England. However, running imapsync with
--dry --justfolders will show you all the folders that exist on both the origin and target servers, so make sure that when you are planning your own migration that you inspect these values. For me, based in the US, the folders used the [Gmail] prefix and Trash instead of Bin.
Finally, after several test runs, I got the command line down to exactly what I needed, and I was off to the races. I set up a small bash script that would iterate over the several mailboxes I needed to migrate, pressed enter, and got about 30 messages in when the process died saying “Out of memory.” Out of memory, really? I was confused for a bit until I checked the message that it was dying on each time, and found that it had a rather massive attachment on it. The origin server, a small, shared hosting situation, must have capped the memory below the size of the attachment.
Luckily, imapsync has a
--maxsize option, which will allow it to skip messages that total over a certain level of bytes. A little bit of experimenting on the server showed that I could only work with messages of about up to 2 MB in size, which was rather small, but doable in this situation. I added the –maxsize switch to the command, and ran through all of migrations again.
The final command that I used to migrate each account was as follows:
imapsync --syncinternaldates --host1 <ORIGIN MAIL SERVER> --port1 993 --ssl1 --user1 <ORIGIN USERNAME> --password1 <ORIGIN USER PASSWORD> --host2 imap.gmail.com --port2 993 --ssl2 --user2 <TARGET EMAIL ADDRESS> --password2 <TARGET USER PASSWORD> --useheader 'Message-Id' --skipsize --noauthmd5 --reconnectretry1 1 --reconnectretry2 1 --maxsize 2194304 \ --folder "INBOX.Sent Messages" --prefix2 '[Gmail]/' --regextrans2 's/Sent Messages$/Sent Mail/g' \ --folder "INBOX.Deleted Messages" --prefix2 '[Gmail]/' --regextrans2 's/Deleted Messages$/Trash/' \ --folder "INBOX.Drafts" --prefix2 '[Gmail]/' --regextrans2 's/INBOX\.Drafts$/Drafts/'
(The three folder lines were unique to the IMAP configuration on the origin server, and will likely change for you. Also don’t forget
--dry --justfolders while testing!)
After running the migrations on the underpowered origin server, I switched over to a VPS and ran the commands again, but this time without the –maxsize switch. No memory issues were encountered on the robust VPS, and I also was able to catch the last few newer emails that had been missed since the first migration.
Finally, after each account was migrated, I placed a forward on the email account on the origin server to redirect all new mail to
<account>@<domain>.test-google-a.com, which acts as a secondary address for all Google Apps accounts before you switch over MX records. This allowed me to to a cutover from the old server to the new server without losing any new messages, and worked flawlessly.
All in all, the process took about 5 hours to transfer all of the data, and about an hour of research and playing around. Much better than dragging and dropping, or writing an entire mini-application to utilize the email migration API. Thanks to some great resources like imapsync and several helpful blogs, this was a much more pain-free experience than in the past!