GuidesGuide

Migrate Email Accounts with imapsync Without Losing Mail

The most reliable way to move mailboxes between servers without losing messages is to copy them over IMAP with imapsync before you switch the MX records, then run the sync again after the switch to pick up anything that landed on the old server in the meantime. imapsync copies folders, messages and flags (read, unread, flagged), and on later runs it only transfers what's missing. Below you'll find the Ubuntu 24.04 commands, password handling, folder mapping, MX cutover timing and a final checklist.

Your options

Method Use it when Drawbacks
imapsync (IMAP to IMAP) Almost always: different servers, different mail software, many mailboxes Needs each mailbox's password (or admin access)
Mail client (drag folders in Thunderbird) Two or three small mailboxes Slow, easy to miss a folder, no way to check what's different
Copy Maildir files (rsync) Same software on both ends (e.g. Dovecot to Dovecot) with root access Formats and folder names must match; indexes need rebuilding
Panel import The new panel can read the old one's backup Depends on what the panel supports

imapsync works from a third position: it connects to both servers as an IMAP client, reads from one and writes to the other. It never touches files on disk and doesn't care what mail server runs behind IMAP.

Before you start

  1. Take inventory: list the mailboxes, their size, forwarders, aliases and autoresponders. Forwarders and autoresponders don't travel over IMAP; you'll recreate them.
  2. Create the mailboxes on the new server, with a quota at least as large as the space used on the old one. A full mailbox rejects messages and imapsync will report errors.
  3. Lower the TTL of the MX record (and the mail server hostname) to 300 seconds at least a day before the cutover.
  4. Pick where to run imapsync: the new server works fine, or any third machine with good bandwidth to both.
  5. Use stable hostnames: for --host1 and --host2 use the server hostname or IP address, not mail.yourdomain.com. Once you change DNS, that name points to the new server, and later syncs would read from the wrong place.

Installing imapsync on Ubuntu 24.04

imapsync isn't in the Ubuntu 24.04 repositories: you install the Perl dependencies and download the script from the author's site, as described in the official Ubuntu instructions.

sudo apt-get update
sudo apt-get install -y libauthen-ntlm-perl libclass-load-perl \
libcrypt-openssl-rsa-perl libcrypt-ssleay-perl libdata-uniqid-perl \
libdigest-hmac-perl libdist-checkconflicts-perl libencode-imaputf7-perl \
libfile-copy-recursive-perl libfile-tail-perl libio-compress-perl \
libio-socket-inet6-perl libio-socket-ssl-perl libio-tee-perl \
libjson-webtoken-perl libmail-imapclient-perl libmodule-scandeps-perl \
libnet-dbus-perl libnet-dns-perl libnet-ssleay-perl libpar-packer-perl \
libproc-processtable-perl libreadonly-perl libregexp-common-perl \
libsys-meminfo-perl libterm-readkey-perl libtest-fatal-perl \
libtest-mock-guard-perl libtest-mockobject-perl libtest-pod-perl \
libtest-requires-perl libtest-simple-perl libunicode-string-perl \
liburi-perl libtest-nowarnings-perl libtest-deep-perl libtest-warn-perl \
make time cpanminus
wget -N https://imapsync.lamiral.info/imapsync
chmod +x imapsync
./imapsync          # checks that every dependency loads
sudo cp imapsync /usr/bin/

The code is free and open under the NOLIMIT Public License; the author also sells it along with support, which funds its development.

Passwords: keep them off the command line

With --password1, anyone on the machine can read the password with ps. The imapsync docs recommend password files with 600 permissions:

umask 077
printf '%s\n' 'OldPassword' > /root/pass-old.txt
printf '%s\n' 'NewPassword' > /root/pass-new.txt

If you don't know the mailbox passwords, you have three options: ask the users (rarely practical), reset them on the old server shortly before the migration and hand out the new ones, or use an administrative login if the old server supports one (a Dovecot master user, for example). Whichever you pick, delete the password files when you're done.

Step 1: test the login

imapsync \
--host1 old.example.com --user1 john@yourdomain.com --passfile1 /root/pass-old.txt \
--host2 new.example.com --user2 john@yourdomain.com --passfile2 /root/pass-new.txt \
--justlogin

Most servers use the full email address as the username; some older setups only use the part before the @.

SSL and certificates

imapsync tries IMAP over SSL (port 993) on its own and falls back to STARTTLS on port 143. By default, though, it does not verify the server certificate. If both servers have a valid certificate for the hostname you're using, turn verification on:

  --sslargs1 SSL_verify_mode=1 --sslargs2 SSL_verify_mode=1

If one server still has a self-signed certificate, verification will fail: either run imapsync from a trusted network or install a valid certificate first.

Step 2: dry run and folders

Before copying anything, see what imapsync would do with --dry and --justfolders:

imapsync \
--host1 old.example.com --user1 john@yourdomain.com --passfile1 /root/pass-old.txt \
--host2 new.example.com --user2 john@yourdomain.com --passfile2 /root/pass-new.txt \
--dry --justfolders

The output lists the source folders and what they'll be called on the destination. imapsync handles separators (. or /) and prefixes (INBOX.) by itself, and --automap (on by default) matches special folders such as Sent, Drafts, Trash and Junk.

When automatic matching isn't enough:

# map one folder to another (full names)
--f1f2 'INBOX.spam=Junk' \
--f1f2 'INBOX.Sent Items=Sent'
# skip folders you don't need
--exclude '^Trash$|^INBOX\.Trash$'
# put everything under one folder on the destination
--subfolder2 'Old server archive'

Repeat the dry run until the list looks right. Only then drop --dry.

Step 3: the real copy

imapsync \
--host1 old.example.com --user1 john@yourdomain.com --passfile1 /root/pass-old.txt \
--host2 new.example.com --user2 john@yourdomain.com --passfile2 /root/pass-new.txt \
--sslargs1 SSL_verify_mode=1 --sslargs2 SSL_verify_mode=1

Check the summary at the end. The line that matters looks like this:

The sync looks good, all 1745 identified messages in host1 are on host2.

Total mailbox sizes can differ even after a perfect sync, because servers compute message sizes differently: look at message counts and errors, not megabytes. The full log goes to the LOG_imapsync/ folder.

Many mailboxes: a loop

With a mailboxes.txt file (permissions 600) in the format old_user;old_password;new_user;new_password:

#!/bin/bash
umask 077
while IFS=';' read -r u1 p1 u2 p2; do
[ -z "$u1" ] && continue
f1=$(mktemp); f2=$(mktemp)
printf '%s\n' "$p1" > "$f1"; printf '%s\n' "$p2" > "$f2"
imapsync --host1 old.example.com --user1 "$u1" --passfile1 "$f1" \
--host2 new.example.com --user2 "$u2" --passfile2 "$f2" \
< /dev/null || echo "$u1" >> failed-mailboxes.txt
rm -f "$f1" "$f2"
done < mailboxes.txt

The < /dev/null stops imapsync from reading the list meant for the loop. Afterwards, rerun only the mailboxes in failed-mailboxes.txt.

Delta runs

imapsync recognizes messages it already copied by their Message-Id and Received headers: running the same command again copies only new messages and resyncs flags (read, flagged). No duplicates.

For every run after the first, limiting it to recent messages makes it much faster:

  --maxage 7    # only messages from the last 7 days

Two options to handle with care: --delete2 deletes messages on the destination that no longer exist on the source (only useful if the destination is an exact mirror nobody is using yet), and --delete1 deletes from the source. A normal migration needs neither.

When to switch the MX records

The lowest-risk sequence:

When What to do
2 days before MX and mail hostname TTL down to 300 seconds
1 day before First full imapsync copy (the long one)
Cutover day, morning Delta with --maxage 7, then switch MX, SPF and DKIM to the new server
Right after Update users' mail apps (IMAP and SMTP server)
Cutover day, evening Delta with --maxage 2 for mail that hit the old server during propagation
Days +1 and +3 More deltas: some senders cache DNS longer than they should
After 1-2 weeks Turn off mail on the old server

Don't shut down the old server right away: as long as some sender still sees the old MX, mail lands there. Delta runs bring it across without asking users to do anything. For SPF, DKIM and DMARC on the new server, see the SPF, DKIM and DMARC guide.

Users on POP3 who download everything to their computer already have their messages locally: just update their settings, and make sure their client doesn't delete mail from the server before the migration is finished.

Checklist

  • List of mailboxes, sizes, forwarders, aliases and autoresponders
  • Mailboxes created on the new server with enough quota
  • MX TTL lowered at least 24 hours ahead
  • Password files at 600, no passwords on the command line
  • --justlogin succeeds for every mailbox
  • --dry --justfolders reviewed, folders mapped correctly
  • First full copy done, "Detected 0 errors" in the summary
  • Forwarders and autoresponders recreated
  • MX, SPF, DKIM (and DMARC) published for the new server
  • Mail apps and phones updated
  • Delta runs the same evening and on the following days
  • Password files deleted, old server off after 1-2 weeks

How Koapanel handles it

If the destination server runs Koapanel with the mail service turned on, many migrations don't need imapsync at all (Mail):

  • from a cPanel backup, or from cPanel over SSH as root, mailboxes are created with all their messages, their original password and the quota they had. cPanel stores passwords as SHA512-CRYPT or MD5-CRYPT hashes, and Koapanel's mail server verifies them as they are, so users keep their passwords. Forwarders come across too (Migration).
  • from Plesk, mailboxes are created; when the password in the backup is encrypted with the old server's key, the panel generates a new one and shows it once in the summary.
  • over SSH as the account user, or from a generic Linux server, mailboxes aren't copied: create them in the panel and move the messages with a mail client or with imapsync as shown above (SSH migration).

Each migration's summary shows, mailbox by mailbox, the message count, space used and whether the password was kept. With mail turned off, mailboxes are only listed.

A handy side effect of the cPanel import: since passwords are the same on both servers, you can run imapsync deltas after the MX switch with credentials you already have, without resetting anything.

After the import, the Mail DNS tab shows the MX, SPF, DKIM and DMARC records to publish and checks them; with Cloudflare or 1PrimeCDN connected, Set up mail DNS publishes them for you after showing the changes. For sites and databases, see how to migrate from cPanel or from Plesk.

Limits worth knowing: mail in Koapanel is optional and enabled by the administrator, and many cloud providers block outbound port 25, in which case you need an SMTP relay. The panel checks port 25, reverse DNS and blocklists before turning the service on.

FAQ

Does imapsync create duplicates if I run it several times?

No: it recognizes messages already on the destination by their headers and copies only new ones. Duplicates only show up with special options, such as --useuid without the cache.

Can I migrate without knowing the mailbox passwords?

Yes, if you have admin access to the old IMAP server (a Dovecot master user, for example); otherwise you'll need to reset the passwords. Koapanel's cPanel import keeps the original passwords.

How long does it take?

It depends on bandwidth and message count. Run the first full copy the day before the MX switch, so the cutover day only involves quick delta runs.

Are forwarders and autoresponders copied?

Not over IMAP: recreate them on the new server. Koapanel's cPanel import brings forwarders across too.

Do I need to tell users?

Yes, if the IMAP and SMTP server names in their mail apps change. If the name stays the same (say mail.yourdomain.com), the new server has a valid certificate for it and the password is unchanged, mail apps reconnect on their own; it's still good practice to announce the cutover date.

Try it

Install Koapanel for free on a fresh Ubuntu 24.04 VPS following the installation guide, turn on mail and try importing a cPanel backup. All migration options are on the Migration page.

Try Koapanel on your server

One command on Ubuntu 24.04, free up to 3 sites. Are you a provider or an agency? Let's talk wholesale pricing and migrations.

More guides