
Most mail delivery failures don’t start inside Postfix or Exim. In 2026, “we suddenly can’t send/receive” usually traces back to DNS drift, incorrect MX priority, missing reverse DNS, or an SMTP service that answers but fails modern TLS checks.
This email routing troubleshooting tutorial gives you a repeatable workflow. You can isolate the fault and fix it without random changes.
The examples assume a Linux VPS (Ubuntu 24.04 LTS or AlmaLinux 10) running Postfix or Exim (common on control panels). If you care about stable IP reputation and clean rDNS/PTR, start with a VPS instead of shared mail.
A HostMyCode VPS gives you the control (and predictable network paths) that makes troubleshooting faster and less ambiguous.
What you’ll verify first (the 10-minute triage checklist)
Before touching configs, pin down what’s actually broken. Many “email is down” tickets are really two problems stacked together.
- Inbound problem: other people can’t email you (bounces, delays, or messages land elsewhere).
- Outbound problem: your server can’t deliver to Gmail/Microsoft/other domains.
- Both: usually DNS (MX, A/AAAA, delegation) or a firewall/provider block on 25/587.
Run these checks from a shell on your VPS (or any Linux box):
# Replace with your domain
DOMAIN=example.com
# 1) What MX records exist and in what priority order?
dig +short MX $DOMAIN
# 2) What do those MX hosts resolve to?
for mx in $(dig +short MX $DOMAIN | awk '{print $2}'); do
echo "--- $mx"; dig +short A $mx; dig +short AAAA $mx
done
# 3) Is SMTP reachable from the internet?
# (Run from a different network if possible)
# Replace with your MX hostname/IP
nc -vz mail.example.com 25
# 4) Do you have a PTR (reverse DNS) for your sending IP?
# Replace with your public IPv4
IP=203.0.113.10
dig +short -x $IP
Interpret the results in plain terms. If MX points to the wrong host, it’s a routing problem. If SMTP is unreachable, it’s a firewall or upstream block. If PTR is missing or mismatched, expect policy rejections and inconsistent deliverability.
Email routing troubleshooting tutorial: map the intended mail flow
Write down the “truth” for your setup before you change anything. A quick map helps you avoid fixing in circles.
- Inbound: Internet → MX host(s) → your mail server → mailbox (IMAP) or forwarder.
- Outbound: your apps/users → SMTP submission (587) → MTA (Postfix/Exim) → recipient domain’s MX.
Two patterns show up most often:
- Single VPS mail: MX points to your VPS hostname (mail.example.com) and that host’s A record points to your VPS IP.
- Hybrid mail: website on VPS, but email on a third-party provider (Google Workspace/Microsoft/Zoho). In that setup, MX should not point at your VPS.
If you migrated recently, re-check the MX records. It’s easy to move the website and forget the mail routing.
Related internal guides you may want open in another tab:
Step 1: Fix MX records and priorities (the most common routing mistake)
MX records must point to hostnames, not IPs. Those hostnames must resolve to the correct A records (and optionally AAAA records). Priority matters: lower numbers win.
What “good” looks like
example.com. 300 IN MX 10 mail.example.com.
mail.example.com. 300 IN A 203.0.113.10
If you run a backup MX, give it a higher number. It should only receive mail when the primary is down:
example.com. 300 IN MX 10 mail1.example.com.
example.com. 300 IN MX 20 mail2.example.com.
MX anti-patterns that break delivery
- MX points to a hostname that has no A/AAAA record (NXDOMAIN or empty). Senders will queue and then bounce.
- MX points to a CNAME. Some providers tolerate it, many don’t. Use A/AAAA.
- Priority reversed. Your “backup” becomes primary, and mail lands on the wrong box.
- Old MX still present. Some senders will try both; you’ll see “random” missing messages.
If your DNS is at HostMyCode, you can manage and audit records alongside your domain registration using HostMyCode domains.
The practical advantage is speed and clarity. You can change records and then confirm authoritative answers without switching dashboards or guessing where the source of truth lives.
Confirm what the world sees (authoritative DNS)
Your local resolver may show cached answers. Query the authoritative nameservers to confirm the real state.
# Find authoritative NS for the domain
DOMAIN=example.com
dig +short NS $DOMAIN
# Query a specific NS directly (replace ns1...)
NS=ns1.yourdns.tld
dig @$NS +noall +answer MX $DOMAIN
dig @$NS +noall +answer A mail.$DOMAIN
If authoritative MX is correct but your local resolver still shows old data, you’re waiting on caches. For planned cutovers, lower TTL 24 hours before the change.
For a full migration playbook, see this staging cutover migration tutorial.
Step 2: Stop “mail loops” and split-brain routing during migrations
Split-brain routing means some senders deliver to Server A, while others deliver to Server B. You’ll usually see it right after a migration or nameserver change.
Signs:
- Some senders insist messages were delivered, but your mailbox never sees them.
- Two servers both accept SMTP for the same domain.
- Users “lose” mail that actually landed on the old server.
Mitigations:
- Remove old MX records completely. Don’t just add the new one and hope traffic shifts.
- Keep the old server accepting mail for 48–72 hours only if it forwards cleanly to the new server.
- Don’t run a catch-all on the old box. It hides routing failures and makes audits harder.
On a control panel setup (cPanel/WHM), also confirm the routing toggle matches reality. If MX now points away from the cPanel server, the domain must be set to “Remote Mail Exchanger.”
HostMyCode covers that panel-side switch here: cPanel Email Routing Tutorial (Local vs Remote).
Step 3: Verify SMTP ports and firewall paths (25, 587, 465)
If DNS looks right but mail can’t reach your server, test reachability next. SMTP is not treated like a normal service by many networks. Wrong assumptions here waste time.
Inbound ports (server side)
- 25/tcp: server-to-server SMTP (must be reachable for inbound mail).
- 587/tcp: submission (users/apps sending mail with auth). Recommended.
- 465/tcp: implicit TLS submission (still used by some clients).
On your VPS, confirm the services are actually listening:
sudo ss -ltnp | egrep ':(25|465|587)\s'
Then validate firewall rules. On Ubuntu with UFW:
sudo ufw status verbose
sudo ufw allow 25/tcp
sudo ufw allow 587/tcp
sudo ufw allow 465/tcp
On AlmaLinux/Rocky with firewalld:
sudo firewall-cmd --list-ports
sudo firewall-cmd --permanent --add-service=smtp
sudo firewall-cmd --permanent --add-service=submission
sudo firewall-cmd --permanent --add-service=smtps
sudo firewall-cmd --reload
If firewall changes break DNS resolution or lock you out of SSH, use this firewall troubleshooting tutorial to recover safely.
Outbound blocks (provider or reputation)
Even with a clean local firewall, your provider may restrict outbound port 25 on some plans to limit abuse. If outbound 25 is blocked, send through a smart host (SMTP relay) over 587 with authentication.
For control panels, the clean setup is here: cPanel SMTP Relay Setup Tutorial.
Step 4: Diagnose common bounce messages and fix the real cause
Don’t troubleshoot by guesswork. Read the SMTP response code and the text. Then fix what it’s actually signaling.
“550 5.7.1 SPF fail” / “DMARC policy reject”
Your authentication doesn’t match the system that’s sending mail. During migrations, this often turns into a routing issue. Mail starts originating from a new VPS IP, a relay, or a different provider. DNS still points to the old sender.
- Fix SPF to include the correct sending IP or relay.
- Ensure DKIM signing matches the From domain.
- Set DMARC to monitoring (p=none) during migrations, then tighten later.
Use HostMyCode’s step-by-step: Email Authentication Setup Guide.
“450 4.7.25 Reverse DNS required” / “PTR record missing”
Many receivers penalize or reject mail from IPs without rDNS. Set PTR to a hostname. Then make that hostname resolve back to the same IP (forward-confirmed reverse DNS).
# Check PTR
IP=203.0.113.10
# Reverse
dig +short -x $IP
# Forward for the PTR hostname (replace if needed)
PTR=mail.example.com
dig +short A $PTR
Fix workflow: Reverse DNS Setup Tutorial.
“TLS required” / STARTTLS failures / certificate name mismatch
Receivers enforce TLS more aggressively now. Mail clients also balk at weak ciphers or mismatched names. Confirm STARTTLS works. Then confirm the certificate matches the SMTP hostname you publish.
# Test STARTTLS on port 25
openssl s_client -starttls smtp -connect mail.example.com:25 -servername mail.example.com
If renewal keeps failing, fix ACME challenges and certificate chains using: SMTP TLS Troubleshooting Tutorial and TLS renewal troubleshooting.
“421 Service not available” / “Connection timed out”
This points to transport, not authentication. Work the basics first:
- Firewall on the server.
- Upstream security group/provider filtering.
- Mail daemon down or overloaded.
Quick checks:
# Postfix
sudo systemctl status postfix
sudo journalctl -u postfix -n 200 --no-pager
# Exim (common on cPanel)
sudo systemctl status exim
sudo tail -n 200 /var/log/exim_mainlog 2>/dev/null || true
Step 5: Confirm your server identifies itself correctly (hostname, HELO/EHLO)
Receivers care about the HELO/EHLO name. If it’s “localhost” or a generic name that doesn’t resolve, you’ll see deferrals. You’ll also see more spam-folder placement.
Check your hostname:
hostname -f
For a typical single-domain mail host, set a real FQDN and make DNS match:
# Ubuntu/Debian
sudo hostnamectl set-hostname mail.example.com
# Ensure /etc/hosts has a sane entry (avoid mapping your public IP here)
sudo nano /etc/hosts
Then confirm both sides line up:
- mail.example.com has an A record to your VPS IP.
- PTR for the IP points to mail.example.com (or another hostname that forward-resolves back to the IP).
Step 6: Check queue behavior to separate DNS problems from content/reputation problems
If outbound mail stalls, the queue will tell you why. Don’t purge it until you’ve identified the failure mode and confirmed the fix.
Postfix queue diagnostics
sudo postqueue -p
# Inspect a specific message (replace QUEUEID)
sudo postcat -q QUEUEID | sed -n '1,120p'
Common patterns to look for:
- Host or domain name not found → recipient domain DNS issue from your resolver, or local DNS misconfig.
- Connection timed out → network block, remote outage, or your IP blackholed.
- 5xx policy reject → auth (SPF/DKIM/DMARC), rDNS, or reputation.
If you want a structured backlog playbook, use: Mail Queue Troubleshooting Tutorial.
Step 7: Validate DNS glue and nameserver delegation (only if you run your own NS)
If your MX hostname sits under a domain that uses your own nameservers, glue record mistakes can take mail down. This can happen even when the zone file “looks fine.”
A common failure is simple: ns1/ns2 IPs changed during a VPS migration, but registrar glue never got updated.
Checks:
# Delegation check
DOMAIN=example.com
dig +trace NS $DOMAIN | sed -n '1,160p'
Fixing this usually means correcting registrar glue and confirming WHM/BIND zone sanity. If you’re on cPanel, follow: cPanel Nameserver Setup Guide (Glue Records).
Step 8: Make your fixes safe: change one variable, then retest
Email incidents drag on when several changes land at once. Then nobody knows which change helped. Use a strict loop and stay in control:
- Capture the failing symptom (bounce, SMTP code, timestamps).
- Change one thing (MX, firewall rule, PTR, TLS cert).
- Re-test with the same method (dig, openssl s_client, nc, a controlled email to a test inbox).
- Document the new state and keep going only if needed.
Practical test emails:
- Send from your domain to a Gmail/Microsoft test mailbox and keep the full headers.
- Send from an external mailbox back to your domain and confirm receipt.
- Verify SPF/DKIM/DMARC results in headers (Authentication-Results).
Operational hardening that prevents routing incidents next month
Once delivery is stable, add a few controls. They reduce the odds you’re back here after the next change window.
- Pin DNS ownership: coordinate domain, DNS, and hosting changes. Avoid the “three vendors, no source of truth” setup.
- Monitor the right signals: SMTP reachability, queue length, and TLS expiration.
- Back up mail configs: /etc/postfix, /etc/exim*, panel configs, and DNS zone exports.
Two practical add-ons:
- Set up incident-friendly logging using: Log Monitoring Setup Guide.
- Build a restore-first plan (mail + DNS included) using: Disaster Recovery Tutorial.
If you want email routing issues to be solvable in minutes, you need clean DNS control, stable IPs, and the ability to set PTR correctly. Start with a HostMyCode VPS, or choose managed VPS hosting if you’d rather have our team handle the tricky edge cases.
FAQ: quick answers for common email routing fixes
How long do MX changes take to work?
Usually as fast as your TTL allows. With a 300-second TTL, many senders switch within minutes, but caches can linger. Always verify authoritative DNS first.
Can I point MX directly to my VPS IP?
No. MX must point to a hostname. Create something like mail.example.com with an A record to the IP, then point MX to mail.example.com.
Do I need IPv6 (AAAA) for my mail server?
Only publish AAAA if IPv6 routing works and your MTA listens on it. A broken AAAA often causes delays because some senders try IPv6 first.
Why do I get “reverse DNS required” even though my mail works sometimes?
Different receivers enforce different rules. You might deliver to smaller providers and then get blocked by larger ones. Setting PTR and matching forward DNS removes the inconsistency.
What’s the safest way to handle outbound 25 blocks?
Use an authenticated SMTP relay over 587 and align SPF/DKIM/DMARC for that relay. You avoid fighting network restrictions and keep deliverability predictable.
Summary: the repeatable workflow that fixes routing fast
Start with DNS (MX + A/AAAA). Then confirm SMTP reachability, validate PTR, and verify TLS. Use the exact SMTP codes and the mail queue to prove what’s failing.
During migrations, eliminate split-brain by removing old MX records. Also set the correct “local vs remote” routing in your panel.
If you’re rebuilding your mail stack on a clean IP with proper DNS control, HostMyCode can help with VPS hosting and a smoother transition via HostMyCode migrations.