
Most “email problems” on a VPS aren’t login or TLS issues. They’re bounces: hard rejections like 550 5.7.1, policy blocks like 554, or quiet filtering caused by broken SPF/DKIM alignment.
This email bounce troubleshooting tutorial shows you how to read bounce codes, confirm what your server actually tried to send, and fix the root cause without destabilizing your sites.
These steps assume Postfix on Ubuntu/Debian (a common VPS mail stack).
If you don’t want to spend your week managing DNS hygiene, reputation, and mail hardening, consider managed VPS hosting from HostMyCode. Routine upkeep is shared instead of dumped on you.
What you’ll troubleshoot (and what you won’t)
This guide stays focused on bounce-style failures: rejections by the recipient server, spam-policy blocks, and authentication problems (SPF/DKIM/DMARC).
It does not cover “can’t connect” failures like timeouts or client authentication issues.
- Covered: 550/551/552/553/554 bounces, SPF/DKIM/DMARC failures, rDNS/hostname mismatches, reputation and blacklist signals, content-triggered filtering, rate limits, and mailing list blowups.
- Not covered: “Connection timed out”, STARTTLS negotiation failures, or 535 auth. If that’s your issue, use a connection-focused SMTP guide instead.
Prerequisites: get access to logs and DNS
You’ll need root (or sudo) on the VPS.
You’ll also need the ability to edit DNS for the sending domain.
On most systems, Postfix-related logs live in /var/log/mail.log and /var/log/mail.err.
sudo -i
ls -lah /var/log/mail*
If this bounce work is happening during a host move, slow down. Treat DNS like a change window.
The checklist in this DNS migration tutorial helps you avoid the classic outcome: the website loads, but email quietly breaks.
Email bounce troubleshooting tutorial: reproduce the bounce and capture the evidence
Resist the urge to “fix” things immediately.
First reproduce the bounce in a controlled way. Then keep the exact rejection text.
- Send a single test message (plain text, minimal links) to a mailbox you control.
- Wait for the bounce email to return (or check the recipient’s SMTP logs if you control it).
- Save the full bounce including headers. The important parts are the status code and the “Diagnostic-Code”.
On the VPS, locate the send attempt in the Postfix logs.
You want the line that shows status=bounced and the remote server’s response.
grep -R "status=bounced" /var/log/mail.log | tail -n 50
If the bounce gives you a Queue ID, trace that one message end-to-end:
grep -R "QUEUEID" /var/log/mail.log
Replace QUEUEID with the actual ID (example: 3F2C012345).
Decode the bounce: what 550 vs 554 usually means
Two bounces can share the same number and still require different fixes.
Use the code first. Then trust the text that follows it.
- 550 5.7.1 / 5.7.26: policy rejection. Common causes: missing/invalid SPF/DKIM, DMARC “reject”, bad rDNS/HELO, or reputation.
- 550 5.1.1: mailbox doesn’t exist. Your list is dirty or you mistyped the address.
- 552 5.3.4: message too large. Fix attachment policies or app behavior.
- 553 5.7.1: sender address/domain not allowed or fails checks.
- 554: transaction failed (often spam filtering/content rules, or “sender blocked”).
Copy the exact phrase after the code into your notes.
“SPF fail”, “DKIM missing”, “DMARC fail”, “rDNS”, “HELO”, “blocked using”, and “policy” usually point straight to the next step.
Step 1: verify your server identity (hostname, rDNS, and HELO)
A large share of bounce pain comes from identity not lining up.
Recipient systems expect a consistent chain: IP → reverse DNS → hostname → forward DNS (A/AAAA) → SMTP banner/HELO.
Start by checking what your server is presenting:
hostnamectl
postconf -n | grep -E "^(myhostname|mydomain|myorigin|smtpd_banner)"
Minimum expectations for deliverability in 2026:
myhostnameis a real FQDN likemail.example.com.mail.example.comhas an A (and optionally AAAA) record pointing to the VPS.- The VPS IP has a PTR (reverse DNS) record pointing back to
mail.example.com.
Verify reverse and forward DNS from the server:
apt-get update && apt-get install -y dnsutils
IP=$(curl -s https://api.ipify.org)
# Reverse lookup
dig -x "$IP" +short
# Forward lookup
dig A mail.example.com +short
If the PTR is missing or points somewhere else, fix that before touching SPF/DKIM.
HostMyCode’s PTR record setup tutorial walks through the common provider control panels and the gotchas.
Step 2: fix SPF so your VPS is allowed to send
SPF tells recipients which servers are permitted to send for your domain.
Typical bounce text includes “SPF fail” or “not authorized”.
Your SPF record must include the VPS IP (or an allowed sender via include:).
It also has to match the domain used in MAIL FROM / Return-Path.
Check what SPF you publish right now:
dig TXT example.com +short | tr '"' '\n' | grep -i spf
Common SPF patterns (choose one):
- Single VPS sender (IPv4):
v=spf1 ip4:203.0.113.10 -all - VPS + a third-party sender:
v=spf1 ip4:203.0.113.10 include:_spf.yourprovider.com -all
Common failure: too many DNS lookups.
SPF has a hard lookup limit. Long chains of include: often end in “permerror”. Keep it short and intentional.
Step 3: enable DKIM signing (and prove it’s working)
In 2026, DKIM is table stakes for consistent delivery. That’s especially true for transactional or any bulk-ish sending.
Many 550/554 rejections come down to “DKIM missing” combined with strict DMARC on the recipient side.
If you already run OpenDKIM, confirm the service is healthy.
Also confirm Postfix is actually talking to it. Typical files:
/etc/opendkim.conf/etc/opendkim/keys//etc/postfix/main.cf
Quick checks:
systemctl status opendkim --no-pager
postconf -n | grep -E "milter|smtpd_milters|non_smtpd_milters"
In /etc/postfix/main.cf, you typically want something like:
smtpd_milters = unix:/run/opendkim/opendkim.sock
non_smtpd_milters = $smtpd_milters
milter_default_action = accept
milter_protocol = 6
Then reload Postfix:
systemctl reload postfix
To validate DKIM, send a test email to a mailbox that displays “Authentication-Results” headers.
You should see dkim=pass.
If you see dkim=fail, the DNS key is wrong, the selector doesn’t match, or you’re signing with a key you didn’t publish.
Step 4: set DMARC to get signal (without blocking legitimate mail)
DMARC ties SPF and DKIM to the visible From: identity.
For troubleshooting, you want visibility first.
Start in monitoring mode. Tighten policy only after you trust your alignment.
Recommended starter DMARC record for many VPS senders:
_dmarc.example.com. TXT "v=DMARC1; p=none; rua=mailto:dmarc@example.com; adkim=s; aspf=s; fo=1"
If you want an alignment-focused walkthrough, use this DMARC setup tutorial.
Step 5: check IP reputation and obvious blacklist signals
Authentication won’t rescue a burned IP.
Bounce text often spells this out with words like “blocked”, “spam”, “reputation”, or a named list/provider.
Your goal is to figure out whether the block is widespread (multiple large providers) or limited to one network.
Start with what your own system can tell you:
- Are you sending from a fresh IP with no history?
- Did you recently send a burst (newsletter) from a server that usually sends password resets?
- Do your logs show lots of bounces to nonexistent users (dirty list)?
On Postfix, look for patterns: repeated blocks and a rising bounce rate.
grep -R "status=bounced" /var/log/mail.log | awk '{print $NF}' | tail -n 50
grep -R "blocked" /var/log/mail.log | tail -n 50
If you confirm a listing, follow a real delisting process instead of randomly retrying.
HostMyCode’s email blacklist removal tutorial is written for VPS operators who need a clean recovery path.
Step 6: confirm you aren’t an open relay (and that you aren’t leaking credentials)
Sometimes reputation collapses because the server is being abused.
A compromised WordPress plugin or stolen SMTP creds can turn a quiet VPS into a spam cannon. Providers will react fast.
Basic open relay review from the VPS:
postconf -n | grep -E "smtpd_recipient_restrictions|smtpd_relay_restrictions|mynetworks"
In most hosting-friendly defaults, you should see permit_mynetworks and permit_sasl_authenticated.
You should also see a strong default deny (like reject_unauth_destination).
If you can’t confidently interpret what you’re seeing, stop and verify before you send more mail.
Also check for sudden volume changes from web apps.
On WordPress, audit mail plugins, rotate credentials, and add rate limits at the application layer where possible.
Step 7: content and format fixes for 554 “spam-like” bounces
Many 554 bounces are content-driven, not identity-driven.
If the same content triggers the same rejection, iterate quickly. Isolate the cause before you change anything else.
Common content triggers:
- URL shorteners or tracking links on a new domain
- HTML-only emails with little text
- Attachment-heavy messages or uncommon file types
- From: name mismatching the domain (looks like spoofing)
- Too many recipients per message (especially on cold IPs)
Fix approach:
- Send plain text only. If it lands, your HTML version is the issue.
- Remove all links. Add them back one at a time.
- Ensure your visible From domain aligns with DKIM and/or SPF (DMARC alignment).
- Reduce batch size. If you need volume, warm up properly.
If you’re on a new IP (or recovering from a block), ramp volume on purpose.
The schedule in this VPS email warmup tutorial helps you avoid the “send 10k on day one” mistake.
Step 8: align your envelope sender with your domain (Return-Path matters)
Sometimes the visible From: header looks fine, but the envelope sender (Return-Path) is from a different domain.
DMARC doesn’t directly validate Return-Path, but plenty of filters treat it as a trust signal.
Check what Postfix uses as its origin and whether you’re rewriting senders:
postconf -n | grep -E "^(myorigin|myhostname|mydomain|sender_canonical_maps)"
If an app sets odd Return-Path values (common with custom scripts), standardize sender addresses per site.
In multi-tenant hosting, make this a policy: define allowed sender domains per customer, and reject everything else.
Step 9: quick diagnostic checklist (10 minutes)
- PTR: IP reverse DNS points to
mail.example.com - A record:
mail.example.comresolves back to the same IP - Banner/HELO: Postfix uses that hostname (no “localhost”)
- SPF: includes your sending IP and ends with
-all(or~allduring testing) - DKIM: you can see
dkim=passin Authentication-Results - DMARC:
p=noneinitially, then tighten after reports look clean - Volume: low and consistent until reputation is stable
- List hygiene: remove
550 5.1.1recipients immediately
Step 10: prevent repeat incidents with monitoring and queue hygiene
After you clear the bounces, keep watch so you don’t end up here again.
You don’t need an elaborate setup. You need early warning for queue growth, bounce spikes, and authentication regressions.
At minimum, track queue size and deferred mail:
mailq | tail -n 5
postqueue -p | grep -c '^[A-F0-9]'
If the queue grows and doesn’t drain, address it before providers start throttling or blocking you.
For queue-specific fixes, see this mail queue troubleshooting tutorial.
Where HostMyCode fits (VPS choices for email sending)
If you’re sending mail for a business, boring reliability beats clever features.
You want stable IP assignment, control over rDNS, and enough CPU headroom so Postfix and milters don’t fight your PHP workers during traffic spikes.
- For hands-on admins: start with a HostMyCode VPS and keep your mail stack minimal.
- If you need help keeping deliverability stable: choose managed VPS hosting so you’re not debugging bounces during an outage.
Summary: fix the cause, not the symptom
Email bounces are usually specific, and they’re usually accurate.
Capture the exact code and diagnostic text. Then work in order: identity (hostname/PTR), SPF, DKIM, DMARC alignment, and only then reputation and content.
Avoid “retry harder” as a strategy.
Until your server identity and authentication story is consistent, retries just create more negative signals.
If you want a hosting platform where you can control DNS cleanly and run a stable mail stack alongside your sites, use HostMyCode VPS (Affordable & Reliable Hosting) and build on a predictable baseline.
If bounces are putting business email at risk, HostMyCode can help you stabilize the sending setup quickly. Start with a HostMyCode VPS, or offload the ongoing mail/DNS maintenance to managed VPS hosting so you can stay focused on your applications.
FAQ
Why do I get 550 5.7.1 even though SPF shows “pass”?
Many filters require DKIM and/or DMARC alignment, not just SPF.
Also confirm rDNS and that your HELO hostname is valid and matches forward DNS.
Should I set DMARC to “reject” immediately?
No. In 2026, start with p=none to collect reports and verify alignment. Move to quarantine or reject once you’ve confirmed legitimate sources.
What’s the fastest way to spot a dirty mailing list?
Look for repeated 550 5.1.1 bounces (user unknown).
Remove those recipients immediately; continuing to send to them harms reputation.
Do I need a separate hostname like mail.example.com?
It’s strongly recommended. It keeps your server identity consistent and makes PTR, TLS, and authentication easier to reason about.
My mail works for some providers but not others. Why?
Providers enforce different policies.
One may accept mail with SPF-only, while another requires DKIM alignment and has stricter reputation thresholds.