Bali, Indonesia
Insights

Mail Still Arriving at the Old Server After MX Cutover? Check Its Logs and Queue

October 31, 2026
0:00
You changed the MX record, the new server is receiving mail, and most people are happy. Yet a few people still say a message never showed up, and the new server's logs have no trace of it. In most cases nothing was lost in transit. The old server accepted those messages and delivered them into mailboxes nobody checks anymore, or left them sitting in its queue. Start your search on the old machine, not the new one. This pattern often reaches support as 'the new server is dropping mail', and engineers spend time on spam filters and quotas on the new side. The new server cannot drop a message it never received. Work through it in order: what DNS tells senders, what the old server logged, what is in its queue, and how to move the leftovers.
An MX record names the host that accepts mail for a domain. Sending servers look it up, then look up that host's A or AAAA record to get an IP address. Each answer comes with a TTL (time to live), which is how long a resolver may cache it. Until a sender's cached answer expires, that sender keeps using the old address. A common trap: many migrations keep the same MX hostname, such as mail.example.com, and only change its A record. In that case the MX TTL is not the one that matters. The A record's TTL is. The reverse also happens: the MX moves to a new hostname, but the old hostname still resolves to the old server, and anything that cached the old MX keeps connecting there. Compare the authoritative answer with what a public resolver returns:
BASH
# What your zone's authoritative nameserver publishes (replace ns1.example.net)
dig +noall +answer MX example.com @ns1.example.net

# What a public resolver currently returns, including the remaining TTL
dig +noall +answer MX example.com @1.1.1.1

# If the MX hostname did not change, check its A record as well
dig +noall +answer A mail.example.com @1.1.1.1
Check the full MX set while you are here. A forgotten lower-priority backup MX that still points at the old server keeps receiving mail long after every TTL has expired. That is a configuration problem, not a cache problem, and waiting will not fix it. If DNS looks clean everywhere you check, late arrivals are coming from senders with stale caches or from senders retrying messages they already queued against the old address. Both taper off over time, but taper off is not zero. The old server's logs show how much is still coming in.
The old server usually keeps accepting this mail because, from its point of view, nothing has changed. The domain is still listed as local, so it accepts the message and delivers it into the local mailbox. It never consults the new MX record, because it believes it is the final destination. Log locations depend on the MTA and the setup. Postfix typically writes to /var/log/mail.log on Debian and Ubuntu, or /var/log/maillog on RHEL-family systems. Exim writes to /var/log/exim_mainlog on cPanel servers and /var/log/exim4/mainlog on Debian. Older entries are usually in rotated and compressed files, so use zgrep for those.
BASH
# Postfix: successful deliveries to the domain that did not go out over SMTP
grep 'to=<[^>]*@example.com>' /var/log/mail.log | grep 'status=sent' | grep -v 'relay=smtp'

# Exim: group log lines per message for the domain, then show delivery lines
exigrep '@example.com' /var/log/exim_mainlog | grep '=>'
In Postfix, a local delivery shows a relay such as relay=local, relay=virtual, or a Dovecot/LMTP relay, depending on how mailboxes are delivered. The matching smtpd line with client= shows which host handed over the message. In Exim, <= marks a message arriving, => a delivery, == a deferral, and ** a permanent failure. The T= field on a delivery line shows the transport. Local transport names vary by configuration, but they are easy to tell apart from remote_smtp. The timestamps matter most. Any local delivery after the cutover is a message the customer has not seen. Also check where these messages came from. Some are external senders with stale DNS. Others come from the old server itself, such as a web form or cron job still running there. In Postfix, those enter through the pickup service. In Exim, they arrive locally rather than from a remote host. They keep arriving no matter what DNS says, because they never use it.
The queue and the mailboxes are easy to mix up. A message that was accepted and delivered locally is not in the queue. It is already in a mailbox on disk. The queue holds messages the server is still trying to deliver: outbound mail from the old server, forwards to external addresses, and anything that hit a temporary error. A full queue on the old server is not proof that inbound mail is stuck. An empty queue is not proof that nothing was missed. Check both.
BASH
# Postfix: queue summary line, deferred mail by destination, one message in full
postqueue -p | tail -n 1
qshape deferred
postcat -q QUEUE_ID

# Exim: message count, first part of the listing, headers of one message
exim -bpc
exim -bp | head -n 50
exim -Mvh MESSAGE_ID
If the queue holds messages bound for your own domain, they were heading to a local mailbox and something deferred them. Look up their queue IDs in the log to find out why. If the queue is mostly outbound mail deferred by remote providers, that is a separate issue. It still needs handling before shutdown, because deleting the queue deletes those messages. Do not flush the whole queue out of habit. Forced retries against rate-limited providers can make things worse, as covered in Should You Run postqueue -f or Let Postfix Retry Deferred Mail on Its Own?.
Two separate problems need fixing: mail that keeps arriving, and mail already delivered to the old mailboxes. For new arrivals, stop the old server from treating the domain as local and send that mail to the new server. On plain Postfix, remove the domain from whichever setting makes it local (mydestination, virtual_mailbox_domains, or similar, depending on the setup). Then add a transport entry such as example.com smtp:[203.0.113.10] to the file your transport_maps points to, run postmap on that file, and reload Postfix. The square brackets tell Postfix to connect to that address directly instead of looking up MX records, which avoids depending on the old server's own resolver cache. Queued messages for the domain keep their old routing until you run postsuper -r ALL, which requeues them so the new transport applies. On cPanel, the equivalent is changing the domain's Email Routing from local to a remote mail exchanger. Exim then routes the domain by its MX record, so first confirm that the old server itself resolves the new MX. Otherwise it may route mail back to itself. For mail already delivered, copy it mailbox to mailbox over IMAP from the old server to the new one. Tools like imapsync are built for this. They are typically designed to skip messages already copied when you run them again, which suits a final delta pass. Run the copy after you have stopped local delivery, so nothing new lands behind you. One warning for the shutdown step. Turning the old server off, or closing port 25, while it still accepts mail locally does not lose anything new. Senders get a connection failure, defer, and usually reach the new server on retry. However, any mail delivered to old mailboxes before that point stays there unless you copy it. Deleting the server or its disks before the final copy permanently loses those messages. Treat that step as irreversible and do it last.
You are ready to decommission when all of the following are true:
  1. Public resolvers return only the new MX and A records, with no backup MX pointing at the old host.
  2. The old server's logs show no local deliveries for the domain since you changed its routing.
  3. Its queue has no messages for the domain, and any remaining outbound mail has been delivered or handled on purpose.
  4. A final IMAP sync pass copies nothing new.
  5. Any scripts or cron jobs that sent mail from the old server have been moved or disabled.
Leave the old server running and forwarding for a while after that. A reasonable rule of thumb is comfortably longer than the old TTL and longer than a typical sender's retry window, which is often several days by default. Then check the logs once more before you turn it off. In practice, an MX change does not stop delivery to the old server. It only stops new lookups from returning it. Until every cache has expired and every retry has finished, the old server is still part of your mail path. Make it forward instead of deliver, copy what it already received, and let its logs tell you when it has gone quiet.