Back to tutorials
Tutorial

Mail Transfer Troubleshooting Tutorial (2026): Fix VPS Email Delays, Bounces, and Queue Backlogs with Postfix

Mail transfer troubleshooting tutorial for Postfix: fix delays, bounces, DNS, TLS errors, and queue backlogs on a hosting VPS in 2026.

By Anurag Singh
Updated on Jun 19, 2026
Category: Tutorial
Share article
Mail Transfer Troubleshooting Tutorial (2026): Fix VPS Email Delays, Bounces, and Queue Backlogs with Postfix

Email issues on a VPS usually aren’t “email is down.” Something in the chain breaks: DNS, TLS, routing, reputation, or a queue that can’t drain. This mail transfer troubleshooting tutorial gives you a production-style workflow to find the failing link fast and fix it with evidence, not hunches.

The commands below use Ubuntu 24.04 LTS with Postfix 3.8+. The same diagnostics apply on Debian 12/13 and AlmaLinux/Rocky equivalents.

If you don’t want to run a mail stack long-term, a managed VPS hosting plan from HostMyCode can take the operational work off your plate. You can stay focused on apps and clients.

What you’ll troubleshoot (and what “good” looks like)

Set a baseline before you touch any config. A healthy mail pipeline behaves predictably:

  • Outbound submission (your app/WordPress/cPanel) connects to the local MTA or relay on port 587/25 and gets a fast response.
  • Queue stays small: a few deferred items during remote outages is normal; thousands is a signal.
  • Logs tell the story: every delay has a reason (DNS lookup, TLS verify, connection refused, policy rejection, rate-limited).
  • DNS aligns with identity: reverse DNS matches your HELO, SPF authorizes the sending IP, DKIM signs, DMARC sets policy.

If your symptoms are “mail arrives hours late,” “bounces to some providers,” or “the queue grows forever,” start here.

Prerequisites and a safe baseline

You’ll need root or sudo access. Install a few tools that make SMTP troubleshooting quicker:

sudo apt update
sudo apt install -y postfix mailutils dnsutils jq openssl

Also rule out basic resource failures. Low disk space can break Postfix in non-obvious ways (temp files, deferred queues, log writes).

If that’s even a possibility, fix it first using our disk space troubleshooting tutorial.

Step 1: Identify the symptom pattern in 2 minutes

Run these commands and keep the output. Treat this as your “before” snapshot.

# Queue summary
mailq

# Postfix service status
sudo systemctl status postfix --no-pager

# Last 200 log lines (Ubuntu/Debian)
sudo journalctl -u postfix -n 200 --no-pager

Then bucket what you’re seeing:

  • Lots of “deferred” messages: routing/DNS/TLS/connectivity or remote rate-limits.
  • “bounced” messages: remote policy rejection (SPF/DKIM/DMARC, PTR missing, blocked IP, invalid HELO).
  • Queue is empty but users still complain: the problem is before Postfix (WordPress mail config, PHP mail(), SMTP credentials), or inbound delivery is going to the wrong MX.

Step 2: Find the exact failure reason per message ID

Pick one queued message ID from mailq and trace it end-to-end.

# Replace 0F3A1234AB with a real queue ID from mailq
sudo postcat -q 0F3A1234AB | sed -n '1,80p'

# Log search for that queue ID
sudo journalctl -u postfix --no-pager | grep -F "0F3A1234AB" | tail -n 50

Common telltales and what they usually mean:

  • connect to ...:25: Connection timed out → outbound port 25 blocked by your network, upstream firewall, or remote host is dropping.
  • Host or domain name not found. Name service error → your resolver or DNS is broken; sometimes a missing MX/A record.
  • Relay access denied → your Postfix is not accepting mail from your app host/IP (mynetworks), or SASL submission misconfigured.
  • 450 4.7.1 ... rate limited → remote side throttling; tune concurrency and backoff.
  • 550 5.7.1 ... SPF fail / DKIM / DMARC → DNS/authentication alignment issue.

Step 3: Verify outbound connectivity (ports 25, 587) without guessing

If you’re seeing connection timeouts, check reachability from the VPS. Don’t blame Postfix until you confirm the network path.

# Test TCP to a known MX (example: Gmail)
# You should see "Connected" quickly.

nc -vz gmail-smtp-in.l.google.com 25

# Test submission to your own relay (if you use one)
# Replace with your relay host
nc -vz smtp.your-relay.example 587

If port 25 is blocked and you need consistent delivery, send outbound mail through a submission relay on 587 with TLS.

HostMyCode customers often do this on a separate HostMyCode VPS dedicated to mail, or by using a provider relay. For a practical build, follow our email relay setup tutorial.

Step 4: Check DNS the way receivers check it (MX, A/AAAA, PTR)

Mail routing and trust start with DNS. Verify inbound routing (MX), your mail hostname (A/AAAA), and your IP identity (PTR).

# Replace example.com
DOMAIN=example.com

# Inbound routing
 dig +short MX $DOMAIN

# Hostname resolution used by your mail server
 dig +short A mail.$DOMAIN
 dig +short AAAA mail.$DOMAIN

# Reverse DNS for your outbound IP
# Replace 203.0.113.10
 dig +short -x 203.0.113.10

Fixes that actually change outcomes:

  • MX points to the right host. If you migrated and forgot MX, inbound mail keeps flowing to the old server.
  • PTR should match your sending identity. Ideally your VPS IP reverse-resolves to mail.example.com, and that name forward-resolves back to the same IP.

If PTR is missing or wrong, expect bounces or spam-folder placement at providers that enforce IP identity checks.

Use our dedicated walkthrough: reverse DNS setup guide.

Step 5: Confirm Postfix identity (hostname, HELO, and banner)

Receivers compare your HELO, PTR, and message headers. Small mismatches may not hard-bounce, but they often reduce trust.

# Your system hostname
hostnamectl

# Postfix key identity settings
sudo postconf -n | egrep 'myhostname|mydomain|myorigin|mydestination|smtpd_banner'

A sane baseline on a single-domain mail host:

  • myhostname = mail.example.com
  • smtpd_banner = $myhostname ESMTP
  • myorigin = $mydomain (or set explicitly)

Apply changes and reload cleanly:

sudo postconf -e 'myhostname = mail.example.com'
sudo postconf -e 'smtpd_banner = $myhostname ESMTP'
sudo systemctl reload postfix

Step 6: Diagnose TLS errors (and fix the real cause)

TLS problems show up in two places: outbound delivery and inbound submission. Outbound failures happen when your server can’t negotiate with a remote host. Inbound failures happen when clients can’t connect.

Start by checking what Postfix is configured to use. Then confirm certificate expiry.

# Show Postfix TLS settings
sudo postconf -n | egrep 'smtpd_tls|smtp_tls|tls_' 

# Check your cert dates (adjust paths)
sudo openssl x509 -in /etc/letsencrypt/live/mail.example.com/fullchain.pem -noout -dates

Two common pitfalls:

  • Postfix points to an old cert path after a renewal or hostname change.
  • Let’s Encrypt renewal succeeded, but Postfix wasn’t reloaded, so it still serves the old cert.

If renewals or validation are failing, work through our SSL renewal troubleshooting tutorial.

Then reload Postfix:

sudo systemctl reload postfix

Step 7: Fix “queue won’t drain” by tuning concurrency and timeouts

Sometimes nothing is “broken.” Postfix may be sending too aggressively and getting throttled. Or it may be slow enough that backlogs accumulate.

Start by measuring queue size and age.

# Count queue items
mailq | grep -c '^[A-F0-9]'

# Show deferred queue with timestamps (quick scan)
sudo postqueue -p | sed -n '1,120p'

If one provider returns lots of temporary failures (4xx), dial down parallelism and tighten timeouts. These settings are a reasonable starting point for mixed destinations:

# Safer delivery behavior for mixed providers
sudo postconf -e 'default_destination_concurrency_limit = 10'
sudo postconf -e 'smtp_destination_concurrency_limit = 5'
sudo postconf -e 'smtp_connect_timeout = 15s'
sudo postconf -e 'smtp_helo_timeout = 15s'
sudo postconf -e 'smtp_data_xfer_timeout = 180s'

sudo systemctl reload postfix

Flush only after the root cause is fixed (DNS/TLS/connectivity). Flushing early just repeats the same failures faster.

sudo postqueue -f

Step 8: Spot authentication and policy failures (SPF, DKIM, DMARC) fast

If your VPS IP isn’t authorized in SPF, or you aren’t DKIM-signing, major providers may reject mail. Some will quietly route it to spam.

Start by checking SPF:

# SPF is a TXT record on the root domain
dig +short TXT example.com | tr '"' ' ' | sed 's/  */ /g'

Next, verify DKIM at the message level. Send an email to a test inbox you control. Then inspect headers for DKIM-Signature and Authentication-Results.

If you haven’t set these up (or they’re wrong), follow our step-by-step guide: SPF/DKIM/DMARC setup guide. It’s often the quickest fix for “works for some recipients” deliverability.

Step 9: Troubleshoot inbound mail not arriving (MX, firewall, and service listeners)

Inbound failures often feel like “email vanished.” In many cases, the message never reached your server.

First, confirm the VPS is actually listening.

sudo ss -lntp | egrep ':25\b|:587\b|:465\b'

You should see Postfix master listening on 25 (SMTP) and typically 587 (submission). If it isn’t listening, check /etc/postfix/master.cf for submission services and restart Postfix:

sudo nano /etc/postfix/master.cf
sudo systemctl restart postfix

Then verify firewall rules. If you recently hardened the server, it’s easy to block SMTP by accident.

Our firewall troubleshooting tutorial is a good companion when mail and web both break after rule edits.

Step 10: Clean up a backlog safely (without losing evidence)

After you correct DNS/TLS/connectivity, you still have to work through the backlog. Do it in a controlled way:

  • Sample first: inspect 5–10 representative queue items and confirm the “status=” reason is now resolved.
  • Flush: postqueue -f.
  • Watch logs live: confirm successful deliveries.
# Live logs while draining queue
sudo journalctl -u postfix -f

If a stream is clearly spam (or a compromised script), stop the source before you retry anything. After that, remove those queue items as needed.

Keep notes and samples for incident response.

Step 11: Add lightweight monitoring so you catch delays before clients do

Mail failures often build slowly. The queue grows for hours, then support tickets arrive. Track queue length and a few basic health signals so you see it early.

A practical option is Netdata with safe access and alerting. We cover setup here: server monitoring setup guide.

At minimum, log queue size every 5 minutes. This lets you correlate spikes with deploys, DNS changes, or provider throttling:

sudo tee /usr/local/bin/postfix-queue-size.sh >/dev/null <<'EOF'
#!/bin/sh
COUNT=$(mailq | grep -c '^[A-F0-9]')
DATE=$(date -Is)
echo "$DATE queue=$COUNT"
EOF
sudo chmod +x /usr/local/bin/postfix-queue-size.sh

# Run every 5 minutes
( sudo crontab -l 2>/dev/null; echo "*/5 * * * * /usr/local/bin/postfix-queue-size.sh >> /var/log/postfix-queue-size.log" ) | sudo crontab -

Step 12: Prevent repeat incidents (quick checklist)

  • Keep PTR aligned with your mail hostname and ensure forward-confirmed reverse DNS.
  • Publish SPF, sign with DKIM, and enforce a reasonable DMARC policy.
  • Reload Postfix after certificate renewals; verify cert paths in main.cf.
  • Set sane delivery concurrency limits to avoid provider throttling.
  • Monitor queue size and alert on abnormal growth.
  • Back up configs: /etc/postfix, TLS cert locations, and DNS zone records.

If you’re juggling multiple client domains, running mail on a busy web server gets confusing quickly. Splitting roles (web VPS + mail VPS) reduces blast radius and makes incidents easier to isolate.

If you want predictable delivery and room to tune Postfix properly, start with a VPS that gives you full control and consistent network performance. HostMyCode offers HostMyCode VPS plans for hands-on admins and managed VPS hosting when you’d rather have experts handle the day-to-day operations.

FAQ

Should I delete the mail queue to “fix” stuck email?

No. A growing queue is a symptom, not the root cause. Find the error in the logs first, fix DNS/TLS/connectivity, then flush. Delete only known-bad mail after you stop the source.

Why do some providers accept my mail while others bounce it?

Provider policies vary. The usual causes are missing/incorrect PTR, SPF misalignment, missing DKIM, or your server presenting an invalid HELO hostname.

How do I know if port 25 is blocked from my VPS?

Run nc -vz gmail-smtp-in.l.google.com 25. If it times out consistently, your network or upstream likely blocks outbound SMTP, and you should use a relay over 587.

What’s the fastest way to improve deliverability after a migration?

Update MX and TTLs carefully, set PTR for the new IP, and confirm SPF/DKIM/DMARC are still correct. If you’re planning a cutover, our DNS workflow in this DNS propagation tutorial helps reduce downtime and confusion.

Summary: a repeatable workflow for Postfix mail failures

Good mail troubleshooting is disciplined log reading plus careful DNS checks. Start with one message ID and learn why it’s stuck. Confirm network reachability, then fix identity (PTR/HELO) and authentication (SPF/DKIM/DMARC).

Once the cause is resolved, flush the queue and watch deliveries complete in real time.

If you want a clean foundation for reliable mail and web workloads, HostMyCode’s VPS hosting gives you the access you need for proper debugging, and managed VPS hosting is there when you want the operational burden off your plate.

Mail Transfer Troubleshooting Tutorial (2026): Fix VPS Email Delays, Bounces, and Queue Backlogs with Postfix | HostMyCode