
Your VPS can serve pages all day while email quietly backs up. You often notice only when contact forms stop landing, password resets stall, or a client asks why invoices never arrived. This mail queue troubleshooting tutorial shows how to diagnose and fix a Postfix queue on a Linux VPS without guesswork. It also avoids “fixes” that create a new deliverability mess.
The steps assume Ubuntu 24.04 LTS or Debian 12. Most commands also work on AlmaLinux/Rocky, with a few path differences.
If you want a VPS built for hands-on admin work (root access, predictable networking, snapshots), start with a HostMyCode VPS. If you’d rather offload patching and baseline hardening, managed VPS hosting is the simpler option.
What you’ll confirm before changing anything (fast triage)
Most queue failures fall into four buckets: DNS problems, blocked ports/firewall rules, TLS handshake failures, or relay/auth restrictions.
Before you touch config, capture the current state. You’ll use it as a baseline and a clean before/after check.
- Do you have a backlog?
mailqshows queued messages and the current reason. - Is Postfix running? Check
systemctl status postfixand confirm something is listening withss -lntp | grep :25. - Can your server reach the outside? Test DNS and TCP from the VPS itself (not from your laptop).
- Are you accidentally blocking SMTP ports? UFW plus provider firewalls/security groups cause a lot of “mystery” outages.
One-minute snapshot of key signals:
sudo -i
hostname -f
postconf -n | sed -n '1,200p'
mailq | sed -n '1,60p'
journalctl -u postfix --since "2 hours ago" --no-pager | tail -n 120
If you recently touched firewall rules, use this companion guide to avoid locking yourself out or breaking mail ports: UFW firewall troubleshooting tutorial (2026).
Step 1: Read the queue like a technician (not like a victim)
Start with the queue. Postfix records delivery attempts and remote error codes per message.
Look for repetition. A dominant error string usually points straight at the cause.
mailq
Watch for repeat phrases like:
connect to ... timed out(network/firewall/provider block)Host or domain name not found(DNS resolver failure or bad MX)Relay access denied(misconfigured relayhost / auth / recipient restrictions)TLS is required, but was not offeredorhandshake failure(TLS config mismatch)450 4.7.1 ... try again later(remote throttling; treat as deliverability/backoff)
To inspect one queued message, copy its queue ID and run:
postcat -vq QUEUEID | sed -n '1,160p'
You’ll see the sender, recipient, and the last response from the remote server. This step keeps you from making random edits that don’t address the real failure.
Step 2: Confirm DNS works from the VPS (A, MX, and resolver sanity)
If DNS is flaky, Postfix can’t find destination MX records. Mail then sits in the queue until retries succeed.
Check two things: the resolver on the VPS, and the domain records you rely on.
Check the VPS resolver:
resolvectl status 2>/dev/null | sed -n '1,120p' || cat /etc/resolv.conf
dig +time=2 +tries=1 google.com A
dig +time=2 +tries=1 gmail.com MX
If these fail or time out intermittently, expect queue spikes that come and go. Fix the resolver first (provider DNS, systemd-resolved settings, or swap in stable resolvers).
Check your mail domain’s basics:
DOMAIN=example.com
DIGOPTS="+time=2 +tries=1 +short"
dig $DIGOPTS $DOMAIN MX
dig $DIGOPTS mail.$DOMAIN A
If you’re migrating DNS or hosting, plan the move and lower TTLs ahead of time. This guide walks through safe changes: DNS Migration Tutorial (2026).
Step 3: Prove connectivity to SMTP ports (25/465/587) and identify blocks
A “connection timed out” message is rarely a Postfix bug. It’s usually a blocked port, a firewall policy, or an upstream restriction.
Test outbound connections from the VPS:
# Test outbound SMTP to a known MX
nc -vz -w3 gmail-smtp-in.l.google.com 25
# Test outbound submission (useful if you relay through a provider)
nc -vz -w3 smtp.gmail.com 587
If port 25 fails, work through:
- UFW/iptables rules
- Provider-level firewall/security group
- Whether your upstream blocks outbound 25 by default (common on new instances)
Check UFW quickly:
sudo ufw status verbose
sudo ss -lntp | egrep ':(25|465|587)\s'
If you want a structured port review (web, DNS, mail, SSH), use: firewall audit tutorial (2026).
Step 4: Spot the exact Postfix error in logs (and map it to a fix)
Postfix logging is blunt, which helps. Pull the right slice of history, then focus on deferrals and auth/TLS warnings.
# Ubuntu/Debian
sudo grep -E "status=deferred|warning|error|lost connection" /var/log/mail.log | tail -n 120
# systemd journal view
sudo journalctl -u postfix --since "1 hour ago" --no-pager | tail -n 200
Common patterns and what they usually mean:
status=deferred (connect to ... timed out): outbound port blocked, routing issue, or remote greylisting with no retry success.status=deferred (Host or domain name not found): DNS failure on the VPS, or missing/invalid MX record.warning: SASL authentication failure: wrong credentials to relayhost or wrong SASL mechanism.no trusted CA certificates foundorcertificate verify failed: CA bundle missing/outdated, or strict TLS policy with a bad remote cert.
Step 5: Fix a backed-up queue safely (stop the bleeding, then drain)
If the queue is large, don’t “fix it” by forcing a flood of retries. That can trigger rate limits and extend the outage.
Stabilize first. Then drain steadily.
Option A: Pause deliveries while you fix config
sudo postsuper -h ALL # hold all queued mail
After you’ve corrected the problem:
sudo postsuper -H ALL # release held mail
sudo postqueue -f # flush queue (forces retry)
Option B: Delete obvious junk/bounces (be careful)
If the queue is full of spam or backscatter, deleting is often the least-bad outcome. Still, review a sample before removing anything.
mailq | head -n 50
sudo postsuper -d QUEUEID
Option C: Throttle retry behavior temporarily
When you’re draining a backlog, lower concurrency so deliveries don’t spike. Edit /etc/postfix/main.cf and add (or adjust) these lines:
default_destination_concurrency_limit = 5
smtp_destination_concurrency_limit = 2
Reload Postfix:
sudo postfix reload
Once the queue is back to normal, remove the throttles or raise them to match your workload.
Step 6: Repair relayhost + authentication issues (submission via 587)
Many VPS setups send outbound mail through a relay (a transactional provider or a separate SMTP host). In that setup, queued messages often show Relay access denied or SASL failures.
Verify your relayhost settings:
postconf relayhost smtp_sasl_auth_enable smtp_sasl_password_maps smtp_use_tls
A typical relay configuration in /etc/postfix/main.cf looks like:
relayhost = [smtp.relay.example]:587
smtp_sasl_auth_enable = yes
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
smtp_sasl_security_options = noanonymous
smtp_use_tls = yes
smtp_tls_security_level = encrypt
Create /etc/postfix/sasl_passwd:
[smtp.relay.example]:587 username:password
Then build the hash DB and lock permissions:
sudo postmap /etc/postfix/sasl_passwd
sudo chown root:root /etc/postfix/sasl_passwd /etc/postfix/sasl_passwd.db
sudo chmod 600 /etc/postfix/sasl_passwd /etc/postfix/sasl_passwd.db
sudo postfix reload
If you’re chasing timeouts, TLS alerts, or 535-style auth failures on submission ports, this companion is focused on that workflow: SMTP Troubleshooting Tutorial (2026).
Step 7: Fix TLS problems without turning TLS off
Turning off TLS to “get mail moving” usually creates a second incident. Keep TLS on, fix the trust chain, and make Postfix log what it’s doing.
Confirm CA certificates are installed and current:
sudo apt update
sudo apt install -y ca-certificates
sudo update-ca-certificates
Set sane outbound TLS defaults (in /etc/postfix/main.cf):
smtp_tls_security_level = may
smtp_tls_CAfile = /etc/ssl/certs/ca-certificates.crt
smtp_tls_loglevel = 1
Reload and retry:
sudo postfix reload
sudo postqueue -f
If one destination consistently fails negotiation, you can use per-destination TLS policies. Only do that after you’ve confirmed it’s the remote side and you accept the risk.
Step 8: Check your hostname, HELO, and reverse DNS (to reduce deferrals)
This guide focuses on queue recovery, not deliverability theory. Even so, basic identity checks can trap you in a defer/retry loop.
From the outside, that looks exactly like a “stuck queue.”
Confirm your FQDN matches what Postfix announces:
hostname -f
postconf myhostname mydomain myorigin smtp_helo_name
A clean baseline often looks like:
myhostname = mail.example.com
mydomain = example.com
myorigin = $mydomain
smtp_helo_name = $myhostname
Verify reverse DNS (PTR): many receivers defer or reject if PTR is missing or mismatched. HostMyCode covers it step-by-step here: VPS reverse DNS setup tutorial (2026).
Step 9: Prevent the queue from refilling (rate limits, bounces, and compromised scripts)
Sometimes the queue is the symptom, not the cause. A compromised CMS, a broken contact form, or an app that retries too aggressively can refill the queue right after you drain it.
Quick checks that catch 80% of repeats:
- Volume by sender: identify the top senders over the last hour.
- Local scripts gone wild: look for repeated
postfix/pickupentries tied to the same user or path. - Bounce storm: floods of NDRs often point to backscatter or bad recipient lists.
# Top SASL usernames (if relaying)
sudo grep "sasl_username=" /var/log/mail.log | awk -F'sasl_username=' '{print $2}' | awk '{print $1}' | sort | uniq -c | sort -nr | head
# See which local users are injecting mail frequently
sudo grep "postfix/pickup" /var/log/mail.log | awk '{print $(NF)}' | sort | uniq -c | sort -nr | head
If WordPress is the sender and you suspect plugin abuse, route mail through authenticated SMTP instead of PHP mail(). It reduces queue spikes and makes tracing far easier.
Step 10: Put monitoring on the mail queue (so you catch it early)
Email failures don’t always page you. Add a queue-length check and alert on sustained growth.
A simple threshold (for example, >200 queued messages for 10 minutes) can save you a long debugging session later.
Minimal check script (store as /usr/local/sbin/check-postfix-queue.sh):
#!/bin/sh
# prints queue length as an integer
mailq 2>/dev/null | tail -n 1 | awk '{print $5}' | tr -d '()' | awk '{print ($1==""?0:$1)}'
Make it executable:
sudo chmod +x /usr/local/sbin/check-postfix-queue.sh
Then wire it into whatever you already use (cron + email, your monitoring agent, or a hosted monitor). For a wider setup that includes uptime, resource alerts, and log signals, see: Server Monitoring Tutorial (2026).
Practical checklist: your “queue is stuck” runbook
- Run
mailq, capture the dominant error string, and inspect one message withpostcat -vq. - Check DNS resolution from the VPS with
dig(A/MX). - Test outbound TCP to port 25 (and 587 if relaying) with
nc -vz. - Review
/var/log/mail.log(orjournalctl) for timeouts, TLS errors, and SASL failures. - Hold the queue (
postsuper -h ALL) if you need time to fix configuration safely. - Fix relay credentials/TLS/hostname, reload Postfix, then release and flush.
- Throttle concurrency temporarily if you’re draining a large backlog.
- Confirm PTR/hostname alignment to reduce deferrals.
- Add queue monitoring so you catch the next issue in minutes, not days.
Summary: restore flow, then make it boring
Healthy mail is boring. Aim for reliable DNS, open-but-controlled ports, correct relay authentication, and TLS behavior that shows up clearly in logs.
Once mail is moving again, keep it that way with monitoring and a runbook you can follow half-asleep.
If you run mail and websites on the same box, stability beats cleverness. A HostMyCode VPS gives you the control you need for Postfix troubleshooting, and managed VPS hosting fits if you want help keeping the base system patched and predictable.
If your queue issues keep returning, it usually comes down to inconsistent DNS, firewall drift, or a server that’s hard to keep clean. HostMyCode can help you move to a plan that fits your workload and still gives you reliable admin access.
Start with a HostMyCode VPS, or choose managed VPS hosting if you want a tighter, maintained baseline.
FAQ
Should I delete the whole Postfix queue to fix stuck email?
Not by default. Hold the queue first, fix the root cause, then release and flush. Delete only messages you’ve confirmed are spam, backscatter, or irrecoverable.
My websites work, but outbound SMTP times out. Why?
HTTP/HTTPS can be fine while port 25 is blocked upstream or by firewall rules. Test with nc -vz gmail-smtp-in.l.google.com 25 from the VPS to confirm.
What’s the safest way to drain a huge queue?
Throttle concurrency temporarily, flush in controlled batches, and watch logs for deferrals. Sudden spikes can trigger rate limits and extend the outage.
Where do I look for the real error message?
Use /var/log/mail.log on Ubuntu/Debian and inspect a sample message with postcat -vq QUEUEID. The queue output alone is often too compressed.
Do I need reverse DNS (PTR) to fix mail queue issues?
PTR won’t fix a blocked port or broken DNS resolver, but it often reduces deferrals and repeated retries. That alone can shrink a queue that keeps re-growing.