Back to tutorials
Tutorial

Email Deliverability Troubleshooting Tutorial (2026): Fix VPS Spam Folder Issues with SPF, DKIM, DMARC, and SMTP Checks

Email deliverability troubleshooting tutorial (2026): fix VPS spam folder issues using SPF, DKIM, DMARC, and SMTP diagnostics.

By Anurag Singh
Updated on Aug 04, 2026
Category: Tutorial
Share article
Email Deliverability Troubleshooting Tutorial (2026): Fix VPS Spam Folder Issues with SPF, DKIM, DMARC, and SMTP Checks

Most “my emails go to spam” complaints trace back to a few fixable issues. Common causes include missing DNS records, a hostname mismatch, a broken TLS chain, or an SMTP banner that misrepresents your server.

This email deliverability troubleshooting tutorial gives you a repeatable checklist. You can run it on any VPS (or dedicated server) without guesswork.

You’ll verify DNS (SPF/DKIM/DMARC). You’ll also confirm SMTP identity (HELO/EHLO, hostname alignment, plus rDNS where it applies). Then you’ll validate TLS and learn the patterns that trigger mailbox filtering.

The goal isn’t to “trick spam filters.” It’s to make your mail system look competently run.

What you need before you start (and what to write down)

  • Your sending domain (example: example.com)
  • Your From address you’re testing (example: billing@example.com)
  • Your mail server hostname (example: mail.example.com)
  • Your public sending IP (example: 203.0.113.10)
  • Your MTA: Postfix, Exim (common with cPanel/WHM), or another SMTP daemon

If you’re mid-migration, pause changes first. Half-moved DNS often causes intermittent deliverability failures.

Those issues are painful to diagnose.

If you’d rather have the move executed for you, use HostMyCode migration help: HostMyCode migrations.

Email deliverability troubleshooting tutorial: the 12-step checklist (run in order)

Run these steps in sequence. Each step gives you a clear pass/fail signal.

Each step also points to the next fix.

Step 1: Confirm the server is actually sending from the IP you think it is

On the VPS, confirm the public IP used for outbound traffic:

curl -4 https://ifconfig.me

If it doesn’t match the IP in DNS and SMTP settings, stop. Fix routing or NAT first.

This mismatch is common with firewalls, cloud NAT, and multi-IP hosts.

Step 2: Check if you’re already blocklisted (quick triage)

Blocklists aren’t the full story. Still, they’re a fast signal when mail doesn’t land anywhere.

Use a reputable multi-RBL checker from your workstation. If you’re listed, fix the cause first.

Common causes include an open relay, a compromised CMS, or leaked SMTP creds. Then request delisting.

If you suspect a compromised WordPress site, don’t stop at password changes.

Look for PHP mailer scripts, injected cron jobs, and shady plugins.

After cleanup, consider moving mail off the web server (or using a separate mail VPS). That containment helps when the next incident happens.

Step 3: Verify your domain’s SPF record resolves correctly

From any Linux shell with dig:

dig +short TXT example.com

You want one SPF record. Multiple SPF TXT records can trigger a “permerror” at some providers.

  • Good example: v=spf1 ip4:203.0.113.10 -all
  • Common problem: two separate TXT records that both start with v=spf1

If you send from multiple systems (your VPS plus a helpdesk tool plus a newsletter provider), combine them into a single SPF record.

Use include: carefully.

Keep SPF DNS lookups under the limit (10). If you’re unsure what’s being served during a change window, use this reference: DNS propagation troubleshooting after a hosting change.

Step 4: Confirm DKIM exists and the selector matches what your server signs with

First, identify the DKIM selector your system uses. In cPanel/WHM, it’s usually shown under Email Deliverability.

On a Postfix + OpenDKIM server, check:

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

Then query the DKIM TXT record (replace selector):

dig +short TXT default._domainkey.example.com

If there’s no record, many providers still accept the mail. However, they often filter it aggressively.

Also watch for a truncated or malformed record. Those failures can look “random” across recipients.

If you rotated keys recently, confirm you didn’t break older signatures for mail that was already queued.

For a safe rotation pattern, see: DKIM key rotation tutorial.

Step 5: Validate DMARC policy and reporting (start with p=none if you’re unsure)

DMARC is where alignment gets enforced. If you haven’t audited every sender, start in monitoring mode.

Collect reports first.

dig +short TXT _dmarc.example.com

A practical 2026 starter record:

v=DMARC1; p=none; rua=mailto:dmarc-reports@example.com; ruf=mailto:dmarc-forensics@example.com; fo=1; adkim=s; aspf=s

Two gotchas:

  • If you set p=reject too early, you can break password resets, invoices, and third-party tools.
  • Strict alignment (adkim=s, aspf=s) is excellent—but only after every sender is aligned and predictable.

If you want a fuller DMARC/SPF/DKIM walkthrough with examples, add this to your runbook: DMARC setup tutorial for a VPS mail server.

Step 6: Check the SMTP banner, hostname, and HELO/EHLO consistency

From your workstation (or another server), connect to port 25:

nc -vz mail.example.com 25
openssl s_client -starttls smtp -crlf -connect mail.example.com:25 -servername mail.example.com

Check these basics:

  • Banner shows a sensible hostname (not localhost or a random provider string).
  • Certificate matches the hostname you present (mail.example.com).
  • HELO/EHLO uses the same hostname and resolves.

On Postfix, these settings are usually in /etc/postfix/main.cf:

sudo postconf -n | egrep 'myhostname|mydomain|myorigin|smtpd_banner|smtp_helo_name'

A sane baseline:

myhostname = mail.example.com
mydomain = example.com
myorigin = $mydomain
smtpd_banner = $myhostname ESMTP
smtp_helo_name = $myhostname

On cPanel/WHM, you typically set this in WHM → Basic WebHost Manager Setup (hostname) and Service Configuration → Exim Configuration Manager.

Step 7: Make sure you’re not an open relay (yes, still happens)

Test from a non-trusted IP (not your server). Try to send to an external domain without authentication.

A healthy server rejects this with “Relay access denied” or similar.

If you want a quick reference for SMTP errors and TLS failures you’ll see during testing, use: SMTP troubleshooting tutorial (timeouts, TLS, auth failures).

Step 8: Verify TLS is modern and the chain is correct

Receivers increasingly penalize outdated TLS settings. They also penalize misconfigured certificate chains.

Test submission like this:

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

Minimum expectations for production SMTP submission in 2026:

  • TLS 1.2 or TLS 1.3 available
  • Correct intermediate chain (no “unable to verify the first certificate” once configured properly)
  • A certificate whose SAN includes mail.example.com

If you use Let’s Encrypt, watch renewals and reload hooks. An expired SMTP certificate breaks clients quickly.

It can also dent trust just as fast.

For the mechanics, see: SSL certificate deployment tutorial.

Step 9: Inspect a real message header to find the filter trigger

Get the full headers from a message that landed in spam. Then scan for:

  • SPF result (pass/fail/softfail/permerror)
  • DKIM result (pass/fail, selector, domain)
  • DMARC result (pass/fail, alignment)
  • Authentication-Results line (usually the receiver’s authoritative view)

Two patterns show up constantly:

  • SPF passes but DMARC fails: the visible From domain doesn’t align with the DKIM domain, or SPF authenticated a different envelope sender.
  • DKIM fails intermittently: mail gets modified in transit (some gateways), or your signing breaks on oversized headers/line-folding edge cases.

Step 10: Fix the “From” vs “Return-Path” mismatch (alignment)

DMARC checks alignment between the visible From domain and either:

  • SPF-authenticated domain (envelope sender / Return-Path), or
  • DKIM d= domain

If you use billing@example.com as From but your application sets Return-Path as bounce@another-domain.com, DMARC may fail.

It will still pass if DKIM aligns.

Practical fix options:

  • Change the application to use an envelope sender under the same domain (recommended).
  • Ensure DKIM signing uses d=example.com and the signature survives transit.
  • Relax alignment temporarily (aspf=r, adkim=r) while you clean up senders.

Step 11: Check sending rate, queue behavior, and spikes (reputation killers)

You can have perfect DNS and still get filtered. This usually happens when your sending pattern looks like abuse.

Typical triggers include sudden bursts, large recipient lists, and high bounce rates.

On Postfix:

mailq
postqueue -p
sudo journalctl -u postfix --since "2 hours ago" | tail -n 200

On cPanel/WHM (Exim):

exim -bp
exim -bpc
tail -n 200 /var/log/exim_mainlog

If you see thousands of outbound messages you didn’t expect, treat it like an incident.

Rotate SMTP credentials. Audit web apps. Add rate limiting.

On Nginx frontends, rate limiting often stops brute-force and form spam that turns into mail abuse: Nginx rate limiting tutorial.

Step 12: Put monitoring on mail signals so you catch regressions early

Deliverability often breaks right after changes. Common culprits include a DNS edit, an SSL renewal that didn’t reload services, a hostname reset, or a receiver-side block.

Monitor the basics—uptime, queue depth, and key log patterns—so you see problems early.

Use this as your baseline: server monitoring tutorial for uptime and log signals.

Hands-on fixes: common deliverability failures and the exact repair

Failure: multiple SPF records

Symptom: headers show SPF “permerror” or inconsistent results across recipients.

Fix: keep a single TXT record beginning with v=spf1. Merge includes/IPs into one line, then delete the duplicate record.

Verification:

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

Failure: DKIM record exists, but your server signs with a different selector

Symptom: DKIM fails with “no key for signature” or “bad signature.”

Fix: publish the correct selector in DNS, or update your MTA/cPanel DKIM settings to match the selector you’ve already published.

Verification: send a test email to a mailbox that displays Authentication-Results. Confirm DKIM passes and the selector matches what you expect.

Failure: TLS handshake errors on port 587

Symptom: email clients fail intermittently, providers show “TLS required” or “certificate verify failed.”

Fix: install a valid certificate chain for your submission service. If you use Let’s Encrypt, confirm renewal hooks reload your mail service (Postfix/Exim/Dovecot) after renewal.

Verification:

openssl s_client -starttls smtp -connect mail.example.com:587 -servername mail.example.com | egrep 'Verify return code|subject=|issuer='

Failure: you’re sending from a web server IP with mixed tenant behavior

Symptom: even legitimate mail gets filtered, but your configuration checks out.

Fix: isolate mail sending. On multi-site servers, one compromised CMS can drag down the IP's reputation for everything.

The cleanest option is a dedicated mail VPS IP or a separate mail host.

HostMyCode helps here in two ways: a clean, dedicated IP on a HostMyCode VPS, or a more hands-off setup with managed VPS hosting where mail identity and updates stay consistent.

Pre-send checklist (print this for client handoff)

  • One SPF record only; includes kept under 10 lookups.
  • DKIM selector published and matches the server’s signer.
  • DMARC published (start with p=none), reporting mailbox working.
  • SMTP banner/HELO uses a resolvable hostname.
  • TLS certificate valid, hostname matches, renewal tested.
  • Outbound volume monitored; bounce spikes investigated.
  • App “From” and envelope sender align (or DKIM aligns for DMARC).

A migration note: deliverability often dips after moving hosting

Even with perfect DNS, a new IP often needs a short warm-up period. Don’t move a high-volume sender and immediately hammer the full list.

If you’re changing DNS at the same time, treat it like an operations change. Don’t treat it like a quick edit.

This walkthrough helps you avoid downtime and email breakage during moves: DNS migration tutorial (no downtime, no email breakage).

Summary: what “good” looks like after you finish

You should be able to send a test message and see SPF pass, DKIM pass, and DMARC pass with alignment.

Your SMTP identity (hostname, banner, certificate) should be consistent. Your queue should stay boring.

If you don’t want to assemble this stack yourself, HostMyCode can provision clean VPS instances suited for mail and hosting workloads.

Start with a HostMyCode VPS, or choose managed VPS hosting if you want patching and baseline hardening handled as part of operations.

If your business depends on receipts, password resets, and sales notifications, treat deliverability like uptime. A clean IP, stable DNS, and a correctly configured mail stack show up in inbox placement.

Run this checklist on a HostMyCode VPS for full control, or use managed VPS hosting if you want help keeping mail identity, updates, and monitoring consistent.

FAQ

Why does SPF pass but my emails still go to spam?

SPF only proves the sending IP is allowed for the envelope sender. Spam placement often depends on DMARC alignment, DKIM integrity, content, bounce rate, and IP reputation.

Check headers for DMARC and DKIM results.

Should I set DMARC to p=reject right away?

Not unless you’ve audited every sender that uses your domain. Start with p=none to collect reports, fix alignment gaps, then move to quarantine and finally reject when you’re confident.

Do I need rDNS (PTR) for deliverability?

It often helps, and some receivers treat missing or mismatched rDNS as a negative signal.

But this tutorial focuses on spam-folder diagnosis without centering on PTR setup. If rDNS is the missing piece in your headers/logs, fix it as part of the identity stack.

What port should my apps use to send mail from a VPS?

Use SMTP submission on 587 with STARTTLS and authentication. Port 25 is for server-to-server delivery and is more likely to be filtered or blocked depending on network policy.

How can I tell if a WordPress site is the source of outbound spam?

Look for spikes in your mail queue, repeated sends to many recipients, and PHP mailer activity in logs around the same time.

Disable suspect plugins, scan the site files, rotate credentials, and consider isolating mail to a separate host.