Back to tutorials
Tutorial

Email deliverability troubleshooting tutorial (2026): Fix VPS emails going to spam with logs, DNS checks, and reputation basics

Email deliverability troubleshooting tutorial (2026) to fix VPS email in spam using logs, DNS validation, and reputation checks.

By Anurag Singh
Updated on Jun 05, 2026
Category: Tutorial
Share article
Email deliverability troubleshooting tutorial (2026): Fix VPS emails going to spam with logs, DNS checks, and reputation basics

When a customer says, “Your emails are landing in spam,” don’t guess. Fix it with evidence.

On a VPS, deliverability failures usually fall into three buckets: DNS/authentication, server identity (HELO/rDNS), or reputation (IP/domain history and sending behavior). This email deliverability troubleshooting tutorial gives you a repeatable workflow. Pull facts from mail logs, validate DNS from the command line, then apply the fix that actually moves mail toward the inbox.

The steps below assume Ubuntu 24.04/22.04 or Debian 12 with a typical Postfix setup. The same approach works on Exim, but log locations and config commands differ.

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

Before you touch a config file, line up the signals mailbox providers still rely on in 2026. Don’t look for clever tricks. Aim for consistent behavior that holds up under inspection.

  • From domain alignment: SPF passes for the envelope sender, DKIM passes for the From: domain, and DMARC passes with alignment.
  • Server identity: your hostname matches the SMTP banner and HELO/EHLO; your IP has rDNS that points back to that hostname.
  • TLS and modern ciphers: STARTTLS works reliably; no legacy protocols.
  • Low complaint signals: you’re not blasting questionable lists; bounces are controlled; sending rate stays predictable.

If you want a fast “did I miss a DNS basic?” checklist, keep this open next to the steps below: SPF, DKIM, and DMARC setup guide.

Prerequisites: access, tools, and a safe place to test

You’ll need root (or sudo) on the mail server. You’ll also need access to edit DNS for your sending domain. Install a few utilities first:

sudo apt update
sudo apt install -y dnsutils openssl jq

Create two “probe” mailboxes you control at major providers (for example, one Outlook/Hotmail and one Gmail/Google Workspace). You’re not load-testing. You’re collecting headers and watching placement after each change.

If this VPS also hosts websites, think hard about separation. Mail on its own VPS limits fallout from a compromised CMS, noisy neighbors, or abuse complaints tied to web apps.

HostMyCode keeps that split simple with a HostMyCode VPS sized for mail and DNS work.

Step 1: capture the exact failure from logs (don’t rely on the user’s screenshot)

Start where the truth lives: the SMTP conversation.

On Postfix, check /var/log/mail.log (Debian/Ubuntu) or /var/log/maillog (RHEL-like).

Find a message by recipient or queue ID:

sudo grep -R "to=<user@example.com>" /var/log/mail.log | tail -n 50

If your logs don’t include the subject (many don’t), follow the queue ID instead. Grab it from the “queued as …” line, then trace it:

sudo grep -R "queued as" /var/log/mail.log | tail -n 20
sudo grep -R "ABC123DEF" /var/log/mail.log

Classify what you see:

  • Hard blocks (SMTP 550/554): the recipient server rejects you immediately. Fix identity, DNS/auth, and reputation signals first.
  • Deferrals (4xx): temporary rejections and throttling. This often points to rate or reputation.
  • Accepted but spam-foldered: no SMTP error. You’ll need the delivered message headers.

Quick queue snapshot:

sudo postqueue -p

If the queue is climbing, you may be blocked, throttled, or routing incorrectly. Don’t “just keep retrying.” Excessive retries can make a weak reputation look worse.

Step 2: read the delivered message headers like a forensic report

If the provider accepts the message but drops it into spam, the headers usually show what failed.

Send a test message to your own mailbox. Then open “original message” / “show source,” and capture:

  • Authentication-Results (SPF/DKIM/DMARC pass/fail)
  • Received: chain (does it show your expected hostname and IP?)
  • Any provider hints (policy/bulk markers, trust indicators, and similar)

Example red flag:

Authentication-Results: mx.google.com;
       spf=fail (google.com: domain of bounce@yourdomain.com does not designate 203.0.113.10 as permitted sender) ...

DKIM failures are also common. They usually happen when the selector is wrong or the DNS record is malformed.

Step 3: verify your outward identity (hostname, HELO, and rDNS)

Mailbox providers still score “does this server look like who it claims to be?” A mismatch is an easy reason to distrust you.

If the server introduces itself as server.local while reverse DNS points elsewhere, filters notice.

3.1 Check your server’s hostname and mailname

hostname -f
cat /etc/mailname 2>/dev/null || true
postconf -n | grep -E 'myhostname|mydomain|myorigin|smtpd_banner'

What you want:

  • myhostname = mail.yourdomain.com
  • smtpd_banner matches that hostname (or at least doesn’t advertise something unrelated)

If needed, set myhostname in /etc/postfix/main.cf:

sudo postconf -e "myhostname = mail.yourdomain.com"
sudo postconf -e "myorigin = yourdomain.com"
sudo systemctl restart postfix

3.2 Validate reverse DNS (PTR) matches your mail hostname

From your laptop or another server, check the PTR:

dig -x 203.0.113.10 +short

That should return something like mail.yourdomain.com.. Then confirm forward DNS points back to the same IP:

dig mail.yourdomain.com A +short

If rDNS is wrong, change it in your VPS provider panel. On HostMyCode, you can set rDNS on most plans; this walkthrough shows the exact steps: Reverse DNS setup guide (rDNS).

Step 4: run a strict DNS authentication audit (SPF, DKIM, DMARC) from CLI

Even if you configured this months ago, DNS can drift. Teams add new senders. TXT records get split badly. DKIM selectors can change during mail updates.

Treat this as an audit, not a checkbox.

4.1 SPF: confirm the sending IP is authorized

Pull SPF records:

dig yourdomain.com TXT +short | tr -d '"' | grep -i "v=spf1"

Sanity checks:

  • Only one SPF record for the domain.
  • It includes your sending IP (ip4:203.0.113.10) or uses includes that do.
  • It ends with a clear policy (prefer -all once stable; use ~all during transitions).

The classic breakage: two SPF TXT records. Many providers treat that as permerror.

4.2 DKIM: verify selector exists and matches your MTA

First identify your selector from the signing config. With OpenDKIM, you’ll often see:

sudo grep -R "Selector" /etc/opendkim.conf /etc/opendkim/* 2>/dev/null || true
sudo grep -R "KeyTable" /etc/opendkim.conf /etc/opendkim/* 2>/dev/null || true

Then query DNS:

dig selector1._domainkey.yourdomain.com TXT +short

If you get nothing back, the record isn’t published (or you’re querying the wrong selector). If it is present, confirm the key wasn’t broken by quoting or copy/paste formatting.

4.3 DMARC: check policy, alignment, and reporting addresses

dig _dmarc.yourdomain.com TXT +short | tr -d '"'

A practical 2026 baseline:

  • Start with p=none while you troubleshoot.
  • Move to p=quarantine once SPF/DKIM pass reliably.
  • Use adkim=s; aspf=s only if you’ve checked how strict alignment affects every sender you use.

If you need an implementation-focused reference for standing up auth, this HostMyCode guide stays down in the weeds: SMTP setup tutorial with Postfix + SPF/DKIM/DMARC. Use it for setup details; keep this article as the troubleshooting flow.

Step 5: check TLS and STARTTLS (providers penalize weak transport)

TLS won’t guarantee inbox placement. But broken or missing STARTTLS is a credibility hit. This matters even more for business mail.

From another machine, probe port 25:

openssl s_client -starttls smtp -connect mail.yourdomain.com:25 -servername mail.yourdomain.com -showcerts

Confirm:

  • The certificate is valid and matches mail.yourdomain.com.
  • You’re not presenting an expired or self-signed cert.
  • The negotiated protocol is modern (TLS 1.2/1.3).

If you offer submission on 587 (recommended), test that too:

openssl s_client -starttls smtp -connect mail.yourdomain.com:587 -servername mail.yourdomain.com

If you need a clean SSL baseline for the same hostname/domain, this is the quickest walkthrough: Let’s Encrypt SSL certificate setup on Ubuntu.

Step 6: confirm you’re not an open relay (and that auth is required where it should be)

An open relay can wreck deliverability in hours. Even without an open relay, a compromised WordPress site can still pump spam through local mail and burn your IP before you notice.

Quick Postfix checks:

sudo postconf -n | grep -E 'smtpd_recipient_restrictions|mynetworks|smtpd_relay_restrictions|smtpd_tls_auth_only'

Healthy patterns usually include:

  • smtpd_relay_restrictions = permit_mynetworks, permit_sasl_authenticated, defer_unauth_destination
  • mynetworks limited to localhost and trusted ranges (not 0.0.0.0/0).

The best external relay test is from a non-trusted IP using a tool like swaks from your workstation. If you can’t do that right now, at least scan logs for unusual volume and unfamiliar authenticated users.

Step 7: reputation triage—what you can and cannot fix quickly

Sometimes everything is configured correctly and you’re still losing. That’s usually reputation.

Providers weigh history, user feedback, and sending patterns heavily. A new VPS IP often starts “cold.” An abused IP can be “hot” in the worst way.

7.1 Spot signs of reputation problems

  • SMTP rejections that mention “policy,” “spamhaus,” “blocklist,” or “poor reputation.”
  • Deferrals that mention rate limits or temporary blocks.
  • Gmail/Outlook accepting mail but consistently putting it in spam even with SPF/DKIM/DMARC passing.

7.2 Immediate mitigation actions

  • Stop bulk sending until things stabilize. Keep it to essential transactional messages.
  • Reduce rate: smaller batches, spaced out over time.
  • Separate streams: don’t send marketing and password resets from the same domain/subdomain.
  • Fix bounces: remove dead addresses. Repeated bounces are a loud negative signal.

If WordPress sites on the same VPS send mail directly, route them through authenticated submission on 587 with per-site credentials. Or move transactional sending to a dedicated domain (like mail.yourdomain.com with a clean From domain policy).

That separation often prevents one compromised site from taking down your whole IP.

Step 8: audit outbound volume and detect compromise (WordPress is the usual suspect)

If a site gets compromised, attackers will try PHP mail() or stolen SMTP creds. Before you chase subtle DNS details, confirm the server isn’t quietly leaking mail.

8.1 Count Postfix deliveries per hour

sudo awk '{print $1" "$2" "$3}' /var/log/mail.log | tail -n 5
sudo grep "status=sent" /var/log/mail.log | awk '{print $1" "$2" "$3}' | uniq -c | tail -n 24

This is crude, but it’s fast. You’re hunting for sudden spikes and odd patterns.

8.2 Identify top sasl usernames (if you use SMTP auth)

sudo grep "sasl_username=" /var/log/mail.log | awk -F'sasl_username=' '{print $2}' | awk '{print $1}' | sort | uniq -c | sort -nr | head

If you see a username you don’t recognize, rotate credentials immediately and disable that account.

8.3 If PHP is sending mail, find the source

On many stacks, PHP-originated mail shows up as local submissions.

If you care about attribution, move WordPress to SMTP submission. That way you can tie sending to a specific site and credential set.

For the security posture that usually prevents these incidents, this guide pairs well: Nginx rate limiting to protect WordPress login.

Step 9: correct common Postfix misconfigurations that hurt deliverability

These are small settings, but they create a lot of “why is everything in spam?” tickets.

9.1 Ensure a valid HELO name

Use a consistent HELO name that matches your PTR/hostname:

sudo postconf -e "smtp_helo_name = mail.yourdomain.com"
sudo systemctl restart postfix

9.2 Don’t send from domains you don’t control

If your app sends From: support@gmail.com through your VPS, alignment fails. Filtering then gets strict fast.

Send from a domain you control, and publish SPF/DKIM/DMARC for it.

9.3 Prefer submission (587) for apps and users

Port 25 is for server-to-server. For clients (apps, CMS, users), use submission with auth and TLS.

You get better control, cleaner logs, and fewer abuse paths.

If you manage mail for multiple sites and don’t want patching and monitoring to become a “someday” task, managed VPS hosting can keep the baseline from drifting.

Step 10: create a repeatable “test message” and track progress

Change one thing at a time. Then send the same structured message to your test inboxes so you can compare results.

Start with plain text (no images, no tracking):

  • Subject: Deliverability test - yourdomain.com - 2026-06-05
  • Body: one short paragraph and a single link to your domain

After each change:

  1. Send the test.
  2. Check Authentication-Results for pass/fail changes.
  3. Check placement (Inbox vs Spam).
  4. Re-check mail logs for SMTP warnings and deferrals.

Step 11: harden the server so deliverability doesn’t degrade again

Deliverability falls apart quickly on an unstable server. One compromise can undo months of clean sending.

  • Patch aggressively: unattended upgrades on Ubuntu are worth enabling for security updates.
  • Lock down SSH: keys only, no root login.
  • Firewall: allow 22/25/587/993/995 only if you run those services.
  • Monitor logs: alert on spikes in outbound email and auth failures.

If you haven’t done a baseline hardening pass, follow: VPS hardening tutorial for Ubuntu and the companion UFW firewall setup tutorial.

Step 12: if you must migrate to a new IP/VPS, do it without breaking mail

Sometimes the cleanest fix is a new IP. Another good reason is isolating mail away from web workloads.

If you migrate, do it like a planned change, not a scramble.

  • Lower DNS TTLs (MX, A/AAAA for mail) 24 hours before the move.
  • Move configs and keys (DKIM private keys, TLS certs, Postfix settings).
  • Keep the old server online to drain queues.
  • Warm up sending gradually.

For the web side of a move (often done alongside mail changes), this guide covers a near-zero downtime process: server migration tutorial.

Quick troubleshooting map (symptom → likely cause → first check)

  • SMTP 550 “SPF fail” → SPF missing/wrong → dig yourdomain.com TXT and headers
  • SMTP 550 “PTR required” / “HELO invalid” → rDNS/hostname mismatch → dig -x, postconf myhostname
  • Accepted but spam → reputation/content/alignment → headers + rate + DMARC alignment
  • Deferrals 4xx → throttling/reputation → reduce rate, check logs, verify auth passes
  • Sudden spike in outbound mail → compromise → mail volume counts, sasl users, CMS audit

Summary: the stable path to better inbox placement

Getting out of spam folders on a VPS usually comes down to fundamentals: consistent hostname and rDNS, correct SPF/DKIM/DMARC, working TLS, and tight control over who can send.

Once the basics are clean, slow your sending down. Then watch headers and placement until things improve.

Keep the box patched and monitored. Reputation is slow to earn and quick to lose.

If you’re rebuilding your mail stack or you want mail isolated from web hosting, start with a clean VPS and keep mail on its own resources. A HostMyCode VPS gives you predictable IP ownership and full control of DNS and MTA configuration, and managed VPS hosting is a good fit if you want ongoing help keeping the baseline secure.

If your business depends on password resets, invoices, and support emails, treat mail like production infrastructure. HostMyCode offers VPS plans that work well for separating mail from web workloads, and managed VPS hosting if you want an expert keeping services, updates, and security defaults on track.

FAQ

How long does it take for deliverability fixes to show results?

DNS/auth fixes (SPF/DKIM/DMARC, rDNS) can change results within minutes to a few hours once caches expire. Reputation recovery can take days to weeks, depending on past abuse and current volume.

Should I use p=reject in DMARC to improve inbox placement?

Not as a first move. Get consistent SPF/DKIM passing and aligned, then move from p=none to p=quarantine. Use p=reject only after you’re confident you won’t break legitimate senders.

Do I need port 25 open on my VPS?

If your server sends mail directly to other providers, yes. If you only submit mail to a relay/smarthost, you may only need 587 outbound. For inbound mail hosting, you’ll also need 25 inbound plus IMAP/POP as applicable.

Why do emails pass SPF/DKIM but still land in spam?

Authentication is necessary but not sufficient. Providers also score IP/domain reputation, sending patterns, user complaints, and message content. Use headers to confirm passes, then reduce volume and clean lists while reputation stabilizes.

Is it better to run mail on the same server as my WordPress site?

For small personal sites it can work, but it’s riskier. A compromised plugin can send spam and damage your IP reputation. Splitting mail to a dedicated VPS is usually the cleaner operational choice.