
A mail queue that won’t drain looks minor—until it breaks password resets, WooCommerce order emails, and contact forms. This VPS mail queue troubleshooting tutorial gives you a repeatable workflow. Identify what’s stuck, capture the real SMTP error, fix the cause, then clear the backlog without hurting deliverability.
The steps apply to the two setups you’ll see most often: Postfix (common on Ubuntu/Debian VPS builds) and Exim (typical on cPanel/WHM servers). You’ll inspect queue IDs and pull the full remote response.
Then you’ll correct DNS/hostname issues and retry or remove messages in a controlled way.
What you’ll check (and what you should not do)
- Check first: queue size, top senders, top recipients, and the exact SMTP response codes (4xx vs 5xx).
- Fix root causes: rDNS/PTR, HELO/EHLO identity, SPF/DKIM/DMARC alignment, outbound port blocks, rate limits, and authentication failures.
- Avoid: blindly flushing the queue repeatedly, mass-deleting without exporting evidence, or switching SMTP ports “until it works” without verifying policy.
If you’re building or rebuilding mail on a server, keep that separate from the queue incident. For a clean baseline (SPF, DKIM, DMARC, rDNS, and ports), use VPS email setup tutorial.
Prerequisites and a safe-change checklist
You’ll need SSH access with sudo/root and the ability to edit DNS for the sending domain(s). Before you touch config, capture a snapshot.
You want a clear “before/after” diff and an audit trail.
- Record: server public IP, hostname (FQDN), and the main mail domain(s).
- Confirm the MTA: Postfix (Ubuntu/Debian) or Exim (cPanel/WHM).
- Export evidence: a few queue IDs and their failure reasons.
- If this VPS also hosts production sites, schedule changes during a low-email window.
Transactional mail is easier when outbound networking is stable and you can inspect what the server is doing. A HostMyCode VPS gives you root access for queue tools, logs, and DNS checks.
Step 1: Identify your mail server (Postfix vs Exim)
On most Linux VPS systems, one of these will show up:
ps aux | egrep 'postfix|exim' | grep -v egrep
systemctl status postfix --no-pager
systemctl status exim4 --no-pager
Quick interpretation:
- Postfix: you’ll use
postqueue,postcat, and logs in/var/log/mail.logor/var/log/maillog. - Exim: you’ll use
exim -bp,exim -Mvh, and logs in/var/log/exim/mainlog(paths vary by distro/control panel).
Step 2: Measure the queue and find the worst offenders
Resist the urge to flush first. Measure the problem.
You need to know whether this is a small backlog or a runaway sender.
Postfix: queue size and top senders
# Total queued messages
postqueue -p | tail -n 1
# High-level view (fast): count queue IDs
postqueue -p | grep -E '^[A-F0-9]{10,}' | wc -l
# Top senders (rough but useful)
postqueue -p | awk 'NR>1 {print $7}' | grep -E '@' | sort | uniq -c | sort -nr | head
Exim: queue size and top senders
# Total queued messages
exim -bpc
# List queue (headers summary)
exim -bp | head -n 50
If a single sender dominates the list, assume one of three causes. It’s usually a compromised web script, a misconfigured app, or a bulk job blasting mail through localhost.
Mail issues often leave patterns. Look for spikes, repeated bounces, or the same error code looping.
Use the same log-reading discipline you use for web incidents. Keep this nearby: VPS log analysis tutorial.
Step 3: Pull the exact failure reason for a queue ID
Queue summaries often cut off the useful part. You need the complete SMTP response from the receiving server.
Postfix: inspect a message by queue ID
Pick one queue ID from postqueue -p, then:
# Show message (headers + body) for a queued item
postcat -vq QUEUEID | less
Look for lines like:
host gmail-smtp-in.l.google.com[...] said: 450-4.7.25 ...status=deferred (connect to ... timed out)status=bounced (host ... said: 550 5.7.1 ...)
Exim: inspect headers and log snippets
# Show message headers
exim -Mvh QUEUEID
# Show body (optional; be careful with sensitive data)
exim -Mvb QUEUEID | less
Step 4: Read mail logs the fast way (queue IDs and SMTP codes)
Queue tools tell you what’s waiting. Logs tell you what happened.
They also tell you whether it started five minutes ago or five days ago.
Postfix logs (Ubuntu/Debian typical paths)
# Watch new failures live
tail -f /var/log/mail.log
# Filter for a specific queue ID
grep -F 'QUEUEID' /var/log/mail.log | tail -n 50
# Find common SMTP status codes in recent lines
grep -E 'status=(deferred|bounced)' /var/log/mail.log | tail -n 200
Exim logs (common paths)
tail -f /var/log/exim/mainlog
grep -F 'QUEUEID' /var/log/exim/mainlog | tail -n 80
If you need an end-to-end workflow (queue IDs, headers, and correlating events), pair this with: Email log troubleshooting tutorial.
Step 5: Classify the failure (the fix depends on 4xx vs 5xx)
Not all errors are equal. Your next move depends on the response class.
- 4xx (temporary): Greylisting, rate limiting, temporary DNS failure, remote host busy. These should eventually deliver if your configuration is correct.
- 5xx (permanent): Authentication failure, policy rejection, bad HELO, missing rDNS, SPF hard-fail with strict receiver policy, or sending to invalid recipients. These will not “wait themselves out”.
Write down the top 2–3 recurring SMTP responses. That list becomes your real to-do list.
Step 6: Fix the top hosting-grade root causes
This is where the queue starts shrinking. Start with identity and DNS.
Next, confirm outbound connectivity. Then look for abuse signals and local auth problems.
6.1 Verify hostname + FQDN (HELO/EHLO identity)
Hostname mismatches cause more delivery pain than they should. When your server says one name but reverse DNS points elsewhere, many receivers will reject or throttle you.
hostnamectl
hostname -f
Best practice for 2026: set your system hostname to a real FQDN like mail.example.com. Then make sure it matches your PTR (reverse DNS).
For the step-by-step fix, use: email server hostname setup tutorial.
6.2 Confirm reverse DNS (PTR) and forward DNS alignment
If you see errors like “No PTR”, “Reverse DNS required”, or “HELO does not resolve”, fix rDNS first.
Most other tuning won’t matter until this is correct.
# Replace with your server public IP
IP=203.0.113.10
# Reverse lookup
dig +short -x $IP
# Forward lookup of the PTR name
PTR=$(dig +short -x $IP | sed 's/\.$//')
dig +short $PTR A
You want the A record to resolve back to the same IP. For a full walkthrough, see PTR record setup tutorial.
6.3 Check SPF, DKIM, and DMARC (policy rejections)
Rejections like “SPF fail”, “DKIM signature missing”, or “DMARC policy reject” usually mean your DNS doesn’t match your sending path.
It can also mean your server isn’t signing what you think it is.
- SPF: authorizes your sending IP(s).
- DKIM: signs outbound mail so receivers can verify it.
- DMARC: tells receivers what to do if SPF/DKIM fail and provides reporting.
If you’re unsure, validate the DNS records and confirm your MTA is actually signing mail. Use the baseline checklist in VPS email setup tutorial.
Then come back and retry the queue.
6.4 Confirm outbound SMTP connectivity (ports and blocks)
Some providers block outbound SMTP on port 25 by default. In other cases, your firewall blocks it. Or an upstream policy changed.
In the queue, this usually shows up as timeouts and “Connection refused”.
# Test TCP connectivity to a major receiver on port 25
nc -vz gmail-smtp-in.l.google.com 25
# Also test 587 (submission) if you relay via a smarthost
nc -vz smtp.office365.com 587
On Ubuntu with UFW:
ufw status verbose
On any Linux with iptables/nftables:
iptables -S | head
nft list ruleset | head
If you suspect a firewall problem and want a sanity check that won’t break production, compare your changes against the approach in VPS security audit tutorial.
6.5 Find and stop local abuse (compromised scripts and stolen SMTP creds)
If the queue grows faster than it drains, something is sending at a rate you didn’t plan for. Identify that sender and stop it before you “clean up”.
Otherwise, you’ll be right back here.
On a cPanel/WHM server (Exim)
WHM often records which account generated the message. Exim log filtering can also surface repeat offenders.
Watch for bursts to many recipients, or repeated bounces to addresses that don’t exist.
If this is account-level compromise, isolate it first. Then clean it.
On multi-tenant servers, file transfer hygiene matters too. Weak FTP practices show up in mail abuse incidents constantly. This guide helps: SFTP setup guide.
On a VPS with Postfix
Figure out which local user or process is generating mail. The method depends on your stack.
On PHP-heavy servers, look for suspicious sendmail usage. Also check cron jobs that “suddenly” started sending, or the presence of webshells.
Repeated submissions from the same process at the same timestamps are usually the first clue.
6.6 Fix authentication errors (SMTP AUTH / SASL)
Errors like 535 5.7.8 Authentication credentials invalid won’t resolve on their own. They also create noisy retries that inflate the queue.
- Confirm the app’s SMTP username/password is correct.
- Confirm the app is using the right host/port (often 587 with STARTTLS).
- Check whether the mailbox is locked, suspended, or over quota.
If this is on WHM, the diagnostics in cPanel email troubleshooting tutorial pair well with the queue work above.
Step 7: Safely retry, defer, or remove messages
After you fix the cause, start draining the queue. Go slowly.
A hard flush can hammer remote servers and push you back into rate limits.
Postfix: controlled queue handling
# Retry the queue now
postqueue -f
# Requeue everything (use sparingly)
postsuper -r ALL
To delete a single queued message:
postsuper -d QUEUEID
If you need to delete a whole class of messages (example: a compromised sender), do it surgically.
Export a list first. Then remove it.
# Example pattern search in queue output (adjust carefully)
postqueue -p | grep -i 'bad-sender@example.com' -B1 | grep -E '^[A-F0-9]{10,}' > /root/bad-queueids.txt
# Delete those queue IDs
while read -r qid; do postsuper -d "$qid"; done < /root/bad-queueids.txt
Exim: queue handling
# Force a queue run
exim -qff
# Remove a specific message
exim -Mrm QUEUEID
On busy hosting servers, don’t mass-remove mail until you’ve identified the sender. You’ll lose auditability.
You’ll also create support tickets you can’t answer.
Step 8: Prevent the queue from re-filling (practical guardrails)
Once mail flows again, add guardrails. A queue jam is often a symptom.
Missing limits are often the cause.
8.1 Add rate controls where they actually help
- App-level throttling for bulk mail (best option).
- Per-account limits in control panels (useful on reseller/shared setups).
- Queue lifetime tuning only after you understand the failure mode.
8.2 Ensure log retention so you can prove what happened
If mail logs rotate too aggressively, you’ll lose evidence. If they don’t rotate at all, you’ll fill disk.
Keep rotation predictable. The approach in Logrotate tutorial applies to mail logs as well.
8.3 Monitor for early warnings
- Alert on queue depth thresholds (example: > 500 queued messages).
- Alert on bounce spikes and repeated auth failures.
- Track disk usage on
/var; mail spools can grow quickly.
If disk pressure has bitten you before, keep this close: VPS disk space troubleshooting tutorial.
Step 9: Quick diagnostics table (symptom → likely cause → first fix)
| Queue symptom | Likely cause | First fix to try |
|---|---|---|
Many status=deferred with timeouts | Outbound port block, firewall, upstream issue | nc -vz receiver 25, verify firewall rules |
| 550 “No PTR” / “Reverse DNS required” | Missing or mismatched rDNS | Set PTR to FQDN; match A record to IP |
| 550/553 HELO/EHLO rejected | Bad hostname or HELO identity | Set correct FQDN hostname; confirm banner |
| 5.7.1 policy / SPF fail / DMARC reject | SPF/DKIM/DMARC misalignment | Fix DNS records and signing; retest |
| Queue dominated by one sender | Compromised site or misconfigured app | Disable sender, rotate creds, scan/patch app |
Summary: a mail queue should be boring
The goal isn’t “flush harder.” The goal is stable identity (hostname + rDNS), correct authentication (SPF/DKIM/DMARC), and sane sending rates.
With that in place, most 4xx deferrals clear naturally. And 5xx rejections stop being mysterious.
They become specific fixes.
If you run business-critical email on a VPS, pick an environment where you control DNS, logs, and outbound policy without fighting the platform. Managed VPS hosting from HostMyCode fits when you want help keeping mail, SSL, and system updates stable. If you prefer full control, start with a HostMyCode VPS and build a mail setup you can actually troubleshoot.
If your server’s mail queue keeps growing, you’re missing visibility, control of identity, or both. HostMyCode makes that manageable with HostMyCode VPS plans, plus hands-on support through managed VPS hosting if you’d rather not babysit the MTA.
FAQ
Should I delete a stuck mail queue to “fix” delivery?
Only after you’ve identified the cause and saved evidence (queue IDs and relevant log lines). Deleting the queue removes the symptom.
It won’t fix rDNS, SPF/DKIM, port blocks, or auth failures.
Is postqueue -f safe to run?
Yes, but don’t treat it as a cure. If the root cause is a policy rejection or a port block, flushing can speed up retry loops and trigger rate limits.
My queue is mostly 4xx deferrals. Do I need to change anything?
Not always. Greylisting and temporary throttles are normal. Verify identity (FQDN + PTR) and authentication (SPF/DKIM/DMARC), then let retries do their job.
What’s the fastest way to prove it’s an outbound port issue?
Test TCP connectivity from the server: nc -vz gmail-smtp-in.l.google.com 25. If it fails consistently, check firewall rules and your provider’s SMTP policy.
How do I stop one compromised site from filling the queue on a hosting server?
Pause or isolate the account, rotate mailbox and app passwords, and remove any backdoors. Then delete only the messages tied to that sender—not the entire queue.