How to Move Your Email Hosting Without Losing Messages
You migrate email hosting without losing emails by copying the mailboxes first and switching the DNS records last. The order matters, because the DNS change is the point of no return, and any message that arrives after you copy but before you switch will be stranded on the old server unless you handle the overlap.
Why the order of operations decides whether you lose messages
Email delivery is a push protocol. The sending server looks up the MX record for your domain and delivers to whatever host that record points at. If you change the MX record before you have a complete copy of the mailboxes on the new host, any message that arrives in the gap is delivered to a server you are about to abandon. If you change the record after you have copied, you still have a gap: messages that arrive after the copy finishes but before the switch are on the old server, and your new server has no idea they exist.
The solution is a two phase move. Phase one copies the mailboxes while the old server is still authoritative. Phase two changes the MX record, then copies the delta, the messages that arrived during phase one. You repeat the delta copy until the delta is zero or near zero, then you remove the old mailbox or leave it in read only mode. This is the same pattern you would use for a database migration, and it works for email because IMAP gives you a way to enumerate and copy messages by unique identifier.
Step one: inventory the mailboxes and their sizes
Before you copy anything, you need a list of every mailbox on the old server, along with the folder structure inside each one. If your old host exposes IMAP, you can get this with a script that logs in as each user and lists folders. If your old host only gives you POP3, you are in a harder spot, because POP3 does not expose folders, and many providers only keep the INBOX. In that case, your migration is a flat download of the inbox, and you lose any server side folders. Check your old host's documentation for whether IMAP is enabled, and if it is not, ask them to enable it before you start.
A practical way to inventory is to use a command line IMAP client like imap-upload or a Python script using the imaplib module. The key is to get the folder list and the message count for each folder. Here is a shape of what you want to see:
Mailbox: [email protected]
INBOX: 1,234 messages
Sent: 456 messages
Archive: 2,100 messages
Trash: 89 messages
Total: 3,879 messages
Write that output to a file. You will compare it against the new server after the copy to verify nothing went missing. Do not trust the old host's web interface for counts, because it often hides system folders or shows cached values.
Step two: set up the new server and create the mailboxes
On the new host, create the same email addresses and the same folder structure that you found in the inventory. Most providers let you create mailboxes through a control panel, but if you have shell access, you can create them directly. The important part is that the new server must accept IMAP connections for each address before you start copying. You do not need to change any DNS yet, because you will connect directly to the new server's IP address or hostname, not through the domain's MX record.
For the copy itself, the most reliable tool is imapsync, which is a Perl script that logs into both servers over IMAP and copies messages by UID. It preserves flags, read/unread status, and folder hierarchy. The command looks like this:
imapsync \
--host1 old.example.net --user1 [email protected] --password1 'secret' \
--host2 new.example.net --user2 [email protected] --password2 'newsecret' \
--syncinternaldates
Run that for every mailbox. If you have many mailboxes, put the credentials in a file and loop over it. imapsync will output a summary line per folder, showing how many messages were copied and whether any were skipped. Save that output. It is your audit trail.
Step three: change the MX record and handle the overlap
Once the initial copy is done for all mailboxes, you change the MX record for your domain to point at the new host. Set the TTL low, like 300 seconds, at least a day before you plan to switch, so that the old value expires quickly. After you change the record, wait for the TTL to pass, then test with dig to confirm the new host is authoritative:
dig MX example.com +short
10 new.example.net.
Now you have a window where messages are going to the new server, but the old server still has the delta from the initial copy. Run imapsync again for each mailbox. This time it will only copy messages that arrived after the first run, because imapsync compares UIDs and only transfers new ones. You may need to run it two or three times, waiting a few minutes between runs, until the output says zero messages copied for every folder.
Step four: verify the copy, then decommission the old host
Verification is not optional. After the final delta copy, log into the new server and compare the message counts against your inventory file. For each mailbox, check the total and the per folder counts. Also spot check a few messages by subject line and date, especially messages in the Sent folder, which some migration tools silently drop if the folder name is localized. Use a script that connects to both servers and compares UIDVALIDITY and the set of UIDs in each folder. A mismatch means you missed something.
Only after verification should you disable the old mailboxes. Do not delete them yet. Set them to reject new mail or put them in read only mode, but keep them for at least a week. If you find a missing message later, you can still pull it from the old server. After a week, and after you have confirmed that no client is still configured to use the old server, you can delete them.
What to do next
Write down the exact commands you used and the output of each verification step. Store that in your incident runbook, because you will need it again when a client or a colleague asks you to do the same move for another domain. Then update your DNS SPF and DKIM records, because the old host's sending IP is no longer valid, and mail from the new host will fail authentication if those records are not updated. Test sending to an external address and check the headers for Received lines that show the new host. You are done when a message sent from the new server lands in an external inbox with a passing DKIM signature.
