My mail provider wrote to say they were decommissioning the server my domains were on, and that I had to move to another service. One month’s notice. I had 20+ business mailboxes to move, and the DNS and every client had to be across before the old server went away.
The mailboxes are a copy job and the domain is a DNS change, and the two do not have to happen together. Copying mail leaves delivery where it is. Changing the MX record is the moment new mail starts arriving somewhere else, so the damage comes from flipping that record before the copy has finished or before the old TTL has drained.
I do it in this order. Sync first, while the old server is still receiving mail. Lower the TTL. Change the records. Watch for mail to arrive on the new server. Sync again the next day, so the messages that landed on the old server during the overlap get copied too.
Look at what your mail clients connect to before you touch a record.
A phone or laptop configured with the provider’s hostname, mail12.hosting.example or similar, keeps that hostname until someone edits it. IMAP and SMTP settings do not follow a redirect. Changing provider then means touching every client.
Point the clients at a name you own, mail.example.com, and CNAME that at the provider:
mail.example.com. CNAME mail12.hosting.example.
Clients talk to mail.example.com, and that name resolves to wherever the CNAME points. The next migration is a DNS edit instead of a round of “please update your settings” emails. Set this up while you are still on the old provider, well before the move, and give it time to settle. The current setup keeps working unchanged.
I run a managed business email service, so the move was not only my mail. I had to tell my clients what was happening and walk them through it. The CNAMEs were already in place, so their users kept the same settings in their mail clients and nothing changed for them. The cutover was a DNS edit on my side, and for the people reading and sending mail it was seamless.
MX records are separate, and an MX record cannot be a CNAME. They point straight at the provider’s mail exchangers, and they are the records you change at cutover.
The accounts have to exist on the new side before imapsync has anywhere to write.
A handful of mailboxes can be created by hand in the new panel, with a password on each. Past that, check whether either side has an API. A provider with one lets you list every account on the old server, create the matching account on the new server, and set a temporary password, all from a script. You find out about a missed mailbox now, not a week later when someone asks where their mail went.
Write the list down either way. One line per account, old host, old user, new host, new user. imapsync runs once per mailbox, and that list is what you loop over.
Both servers need IMAP reachable from the machine you run this on. Most panels ship with the IMAP toggle off.
imapsync \
--host1 mail.oldprovider.example --user1 you@example.com --password1 'oldpass' \
--host2 mail.example.com --user2 you@example.com --password2 'newpass'
Run one small mailbox first and read the result in webmail on the new side. The old server calls the folder Sent and the new one calls it Sent Items, and imapsync creates a second folder unless you map them:
imapsync ... --f1f2 Sent=Sent Items --f1f2 "Sent Messages=Sent Items"
--dry prints what it would do without writing anything. With the small mailbox looking right, run the rest. A large mailbox takes hours and the connection drops partway, so run it under tmux and rerun the same command after a drop. imapsync matches messages it has already copied and skips them, which makes the rerun safe.
Delivery is untouched through all of this. The old server keeps receiving, and people keep working.
I had an agent do most of the repetition, listing the mailboxes and running imapsync over them, and the first sync still took a few hours. The whole move took about a week, because the waits sit on either side of the copying: the old TTL has to drain, and a day has to pass between the two syncs. In a hurry I think 24 hours is doable. Less than that means cutting DNS over before the old TTL has drained, and some mail keeps arriving at a server you are about to lose.
A resolver holds your answer for as long as the TTL says. A record at 86400 seconds sticks around for a day after you change it, and with that TTL part of the world keeps delivering to the old server until tomorrow.
Lower it ahead of time. 300 seconds is a fine value for the MX, SPF, and the mail CNAME.
example.com. 300 MX 10 mail.example.com.
mail.example.com. 300 CNAME mail12.hosting.example.
Wait out the old TTL before changing anything else. A previous TTL of a day means waiting a day. After that, every resolver refreshes within five minutes, and the cutover lands in one step instead of trickling in.
These go in before the MX change, and each one can coexist with the record the old server already uses. Adding them does not move delivery.
Enable DKIM in the new provider’s panel. It generates a selector and a public key, and you add that key as a TXT record under the selector’s name. Receivers look DKIM up per selector, so the new selector sits next to the old one and the old server keeps signing with its own.
SPF is a single TXT record on the domain, so you edit the one you have and add the new provider to it. A second include: authorises both servers. Mail leaving the old server still passes, and mail leaving the new server passes from the first message.
example.com. 300 TXT "v=spf1 include:oldprovider.example include:newprovider.example -all"
newselector._domainkey.example.com. 300 TXT "v=DKIM1; k=rsa; p=MIGf...QAB"
DMARC is one TXT record at _dmarc. It tells receiving servers what to do with a message whose SPF or DKIM check fails. A domain that already has the record should keep it: the check is against the domain, not the server, so it stays valid through the move. A domain without one gets a record at p=none before the cutover, which sends you reports and rejects nothing while mail comes from two servers.
_dmarc.example.com. 300 TXT "v=DMARC1; p=none; rua=mailto:dmarc@example.com"
The first message out of the new server should already have SPF and DKIM published. Without them the receiver sees a failed check and spam-folders or rejects the message. After the old server is gone, take its include: out of the SPF record, read the DMARC reports, and move p=none to quarantine and then reject.
Point the records at the new provider. The MX hostnames come from their setup instructions, and they are plain hostnames. Repoint the mail CNAME at the new provider’s hostname.
example.com. 300 MX 10 mx1.newprovider.example.
example.com. 300 MX 20 mx2.newprovider.example.
mail.example.com. 300 CNAME mx1.newprovider.example.
Send yourself a message from an outside account and see which server receives it. Arrival on the new server tells you the MX change has reached the resolver that handled that message. Resolvers that fetched the record in the minutes before the edit still deliver to the old server, and the second sync exists to collect that mail.
Clients on mail.example.com follow the CNAME without a settings change. A client hardcoded to the old provider’s hostname keeps delivering there until someone edits it, so find those before you cancel the old service.
Both servers stay up for a day. Mail in flight, mail from resolvers still holding the old MX, and mail from the client nobody could find all land on the old server in that window.
Run the same imapsync commands again 24 hours later. The first pass took the bulk, so this one moves only what arrived since, and it finishes quickly. Read the old server’s queue and the newest messages in its inboxes before you trust the result. Anything that arrived after the second run gets a third run. The command is identical and it skips what it already copied.
Empty inboxes on the old server mean the copy is finished. Keep that account alive for another week if you can, for the client or script still submitting to it. Then put the TTLs back to 3600. At 300 seconds every resolver refetches your MX record all day, and there is no reason to keep paying that once the move is done.
Doing the above by hand is tolerable for a few accounts and miserable for fifty. API access on both sides keeps every step and drops the hand-copying.
mail CNAME, SPF, and DKIM through the DNS provider’s API.The order stays. The gain is that a script does not skip a mailbox on step 2 or forget one on step 6.
If you would rather not run this yourself, email me at hi@stnly.com. I will handle the move for you, and any issues that come up along the way.
Published on by Stanley