Skip to main content
Server & DevOpsAugust 25, 20266 min read

How to Move Off cPanel Without Breaking Mail

A web request that lands on the old server serves a slightly stale page. A message that lands on the old server sits in a mailbox the customer can no longer reach, and it never moves on its own. This is the migration order that keeps every message reachable throughout, with the inventory items that break silently, the TTL work that has to happen days ahead, repeated incremental imapsync passes across the cutover, and the authentication records that must travel with the mail. The DKIM private key does not come with the mailboxes, and that is the step most migrations discover afterwards.

Websites forgive a sloppy migration. Mail does not. A web request that lands on the old server for an hour serves a slightly stale page, and nobody notices. A message that lands on the old server for an hour sits in a mailbox the customer can no longer reach, and it will not move on its own.

The order below keeps every message reachable from start to finish and needs no downtime window. It works because the mailbox copy is repeatable and because the old server stays alive long past the point most people switch it off.

Inventory, because the surprises are all in what you did not list

Before anything moves, write down what exists. Mailboxes are the easy part. The items that break silently are the ones nobody mentions until the week afterwards.

  • Every mailbox, with its quota and its current usage
  • Forwarders and aliases, including forwarders that point off-domain
  • The catch-all setting, since a domain with a catch-all behaves very differently once it moves
  • Autoresponders and any server-side filters
  • Every application that sends through SMTP with a mailbox password, such as a website contact form or a CRM
  • The mail authentication records currently published, read from DNS rather than from the control panel

That last one matters more than it looks. A control panel shows what it believes it published, which is not always what resolvers actually answer.

dig +short MX customer.com
dig +short TXT customer.com
dig +short TXT _dmarc.customer.com

Lower the TTL first, and give it time to take effect

A TTL change only helps once the previous TTL has expired everywhere. Drop the TTL on the MX records and on the A records their hostnames resolve to, then wait at least the length of the old TTL before you plan the cutover. If the old TTL was a day, lowering it an hour beforehand achieves nothing whatsoever.

Negative answers cache separately, and that catches people out. RFC 2308 puts the negative cache duration in the SOA record, set "from the minimum of the MINIMUM field of the SOA record and the TTL of the SOA itself". The same RFC recommends a sane range, "Values of one to three hours have been found to work well and would make sensible a default. Values exceeding one day have been found to be problematic." A zone with a very long SOA minimum will cache the absence of a record you are about to create.

Copy the mailboxes while the old server is still live

Copy over IMAP rather than over the filesystem. It needs no root access on either side, it preserves folder structure and message flags, and above all it can be repeated.

imapsync describes itself as "an IMAP transfer tool" for migrating or backing up IMAP accounts, and one documented property is what makes this whole ordering work. "Incremental means you can stop the transfer at any time and restart it later efficiently, without generating duplicates."

Run it once with --dry first, which "Makes imapsync do nothing for real; it just prints what would be done without --dry".

imapsync \
  --host1 old-server.example.net --user1 sales@customer.com --password1 "OLD_PASS" --ssl1 \
  --host2 new-server.example.net --user2 sales@customer.com --password2 "NEW_PASS" --ssl2 \
  --automap \
  --useuid \
  --dry

The --ssl1 and --ssl2 options use IMAP over TLS, where "The default port is 993". The --automap option "guesses folder mapping, for folders well known as 'Sent', 'Junk', 'Drafts', 'All', 'Archive', 'Flagged'", which is what stops Sent Items arriving as a second folder called Sent. The --useuid option uses "UIDs instead of headers as a criterion to recognize messages".

Drop --dry for the real pass. Do not reach for --delete2 at any point in a migration. It deletes "messages in the host2 account that are not in the host1 account", which is destructive on the destination and will remove anything a user has already filed there since you started.

Loop it over an account list so the run is repeatable, because you are going to run it several more times.

# accounts.csv, one line per mailbox: address,old_password,new_password
while IFS=, read -r addr oldpw newpw; do
  imapsync --host1 old-server.example.net --user1 "$addr" --password1 "$oldpw" --ssl1 \
           --host2 new-server.example.net --user2 "$addr" --password2 "$newpw" --ssl2 \
           --automap --useuid
done < accounts.csv

The authentication records have to move with the mail

Here is where a technically successful migration turns into a deliverability incident.

SPF has to name the new sending host and has to stay inside the DNS lookup budget. RFC 7208 sets that budget hard. "SPF implementations MUST limit the total number of those terms to 10 during SPF evaluation, to avoid unreasonable load on the DNS. If this limit is exceeded, the implementation MUST return permerror." A record that has accumulated an include for every service the business ever trialled will break the moment you add one more.

DKIM catches almost everybody, because the private key lives on the sending server and does not travel with the mailboxes. The public key is published per selector under _domainkey, and the selector actually in use is written into every message the old server signed, in the s= tag of the DKIM-Signature header, alongside the signing domain in d=. Open a message the old server sent, read those two values, and you know exactly which record to look for. Substitute what you found for SELECTOR below.

dig +short TXT SELECTOR._domainkey.customer.com

Generate a fresh key on the new server, publish it under its own selector, and leave the old selector's record in place for a while. Both records can coexist, which means messages signed by either server verify during the overlap.

DMARC needs no change if the domain is not changing, but check it before the move rather than after. A p=reject policy will bounce mail from a new host that is not yet aligned.

Cutover, in the order that keeps mail flowing

  1. Run a full imapsync pass over every account while the old server is still receiving mail normally.
  2. Publish the new DKIM record, and update SPF so it names the new host while still naming the old one.
  3. Change the MX records to the new server. With the TTL already low, most resolvers follow within minutes.
  4. Leave the old server accepting and storing mail. Do not disable it, do not remove the accounts, do not cancel the hosting.
  5. Run imapsync again over every account, several times across the following days. The incremental behaviour means each pass only carries what arrived on the old server since the previous one.
  6. When a pass moves zero messages for every account across a full day, the old server has stopped receiving. Only then remove the old host from SPF and retire the mailboxes.

Step 4 is the one people skip and it is the entire reason this order has no downtime. While DNS is still in flux some senders will keep delivering to the old server, and step 5 is what collects that mail instead of losing it.

If a mail client still needs manual reconfiguration afterwards, the SRV records defined in RFC 6186 can do the job. It defines _imap, _imaps, _pop3, _pop3s and _submission service labels under the _tcp protocol label, with records in the form _imap._tcp SRV 0 1 143 imap.example.com..

Moving hosts without losing mail is migration services, and the record work that decides whether the mail lands afterwards is covered step by step in our guide to SPF, DKIM and DMARC.

Talk to the engineer who will own your stack.

No account managers, no offshore handoff. Senior DevOps, direct. Tell us what you are dealing with and you get a straight answer.