Why Are My Emails Going to Spam? A Developer's Deliverability Triage Guide
"Why are my emails going to spam?" is one of those questions with a hundred plausible answers and, fortunately, one correct order to check them in. Most advice starts with content — subject lines, "spam trigger words" — which is where you should look last. Modern filters at Gmail and Microsoft weigh authentication and sender reputation far more heavily than word choice. So triage like a filter thinks: authentication first, reputation second, the 2024+ bulk-sender rules third, content and engagement last.
Work through this in order and you'll find the problem in most cases within an hour.
Step 1: authentication — SPF, DKIM, DMARC, and alignment
Send a message to a Gmail address you control, open it, and click Show original. Gmail prints the verdict at the top and in the Authentication-Results header:
Authentication-Results: mx.google.com;
spf=pass smtp.mailfrom=bounce.yourdomain.com;
dkim=pass header.d=yourdomain.com header.s=s2026a;
dmarc=pass header.from=yourdomain.com
You're looking for three passes — and, critically, alignment: the domain that passed must match your visible From domain. spf=pass for your ESP's bounce domain does nothing for DMARC unless it aligns; it's often the aligned dkim=pass (header.d=yourdomain.com) doing the real work. If any of this is unfamiliar, the SPF, DKIM and DMARC explainer is the ten-minute version.
Common failures, in order of how often we see them:
spf=permerror— your SPF record is malformed or over the 10-DNS-lookup limit. This one is silent and vicious: mail keeps flowing on DKIM alone until DKIM hiccups, then everything tanks at once.dkim=failor missing — signing was never enabled at the provider (a published key that isn't signing does nothing), or a key rotation left mail signed with a selector that no longer resolves.- DMARC passes but you have no policy, or
p=none— not a spam cause by itself, but Gmail and Yahoo now expect DMARC from bulk senders (see step 3), and no enforcement means spoofers can burn your domain's reputation for you.
You can check all three records in one shot with the free DMARC / SPF / DKIM checker. Don't proceed to step 2 until authentication passes aligned — nothing downstream can compensate for failing it.
Step 2: reputation — IP, domain, and blacklists
Filters score two reputations: the sending IP and the From domain. Either can sink you.
- Check the blocklists. Query the major DNSBLs — Spamhaus is the one that matters most; SpamCop and Barracuda are worth checking too. A Spamhaus listing on your sending IP or domain is a drop-everything problem; each list documents its own delisting process.
- Shared IPs mean shared fate. On a shared ESP pool, a spammy neighbour can drag the IP's reputation down. Reputable ESPs police their pools; if your provider's shared IPs keep appearing on blocklists, that's your answer. Dedicated IPs give control, but only make sense with steady volume — a dedicated IP sending 200 emails a week never builds reputation.
- Domain reputation is slower and stickier. It follows you across IPs. New domains start cold: sending 50,000 messages on day one from a fresh domain looks exactly like a snowshoe spam run. Warm up gradually over weeks, starting with your most engaged recipients.
- Instrument it. Register for Google Postmaster Tools — it's free and shows your domain and IP reputation, spam-complaint rate, and authentication success rates as Gmail sees them. For Microsoft, SNDS gives the equivalent view. Flying without these is guessing.
Also verify your sending IP has valid reverse DNS (a PTR record that resolves back to a real hostname matching forward DNS) — you can sanity-check DNS records with the free DNS lookup tool. Mail from an IP with no or generic rDNS gets filtered aggressively.
Step 3: the Gmail/Yahoo bulk-sender requirements
In February 2024, Gmail and Yahoo turned long-standing best practices into hard requirements, and enforcement has only tightened since. If you send 5,000+ messages a day to Gmail addresses, you must have:
- Both SPF and DKIM passing (not either/or), with the From domain aligned.
- A DMARC policy —
p=nonesatisfies the letter of the rule, but see our guide on moving to p=reject for why you shouldn't stop there. - One-click unsubscribe (RFC 8058):
List-UnsubscribeandList-Unsubscribe-Postheaders on marketing/subscribed mail, honored within two days. - Spam complaint rate below 0.3% in Postmaster Tools — and ideally below 0.1%; sustained excursions above 0.3% get your mail junked wholesale.
- Valid forward and reverse DNS, and delivery over TLS.
Below 5,000/day the authentication basics still apply — SPF or DKIM at minimum, valid rDNS, low complaint rates. Treat the bulk-sender list as the target regardless of volume: it's simply a description of what good sending looks like, and the thresholds are Gmail's to change.
Step 4: content and engagement signals
Only now, with authentication and reputation clean, is content worth your time:
- Link domains matter more than words. Every domain you link to carries its own reputation. URL shorteners and tracking domains shared with spammers hurt; linking a domain that's on a blocklist hurts a lot. Link your own domains where possible.
- Avoid classic structural tells — a single large image with no text, mismatched link text vs. href, sloppy HTML from an old template.
- Engagement is the long game. Gmail weighs how recipients treat your mail: opens, replies, "not spam" rescues versus deletes-without-reading and complaints. The practical lever is list hygiene — send to people who asked, prune addresses that haven't engaged in months (a sunset policy), and never buy lists. Purchased lists are full of spam traps, and one trap hit does more damage than a thousand perfect subject lines can repair.
The triage checklist
- Send to Gmail, Show original — confirm
spf=pass,dkim=pass,dmarc=pass, aligned to your From domain. - Run your domain through the DMARC / SPF / DKIM checker — fix
permerror, missing DKIM, missing DMARC. - Check your sending IP and domain against Spamhaus (and SpamCop, Barracuda).
- Verify PTR / reverse DNS on the sending IP.
- Register Google Postmaster Tools; check domain reputation and spam rate (target < 0.1%).
- If you send 5,000+/day: confirm SPF and DKIM, DMARC published, one-click unsubscribe headers.
- New domain or IP? Warm up — ramp volume gradually to engaged recipients.
- Audit link domains in your templates; drop shorteners.
- Prune unengaged addresses; confirm you're only mailing people who opted in.
- Re-test after each fix — deliverability recovers in days-to-weeks, not minutes.
Keep it fixed
Deliverability isn't a problem you solve once — it's a state you drift out of: an SPF record accumulates one include too many, a DKIM selector vanishes in a DNS migration, someone relaxes the DMARC policy during an incident. CompleteStatus continuously monitors your SPF, DKIM and DMARC records, flags p=none, and alerts on any record change — alongside uptime, SSL, DNS and security-header monitoring in one dashboard, so the email checks live next to everything else you watch.
Start with the free DMARC / SPF / DKIM checker to see where your domain stands, then start monitoring free so the next regression alerts you before your customers' spam folders do. The free tier allows commercial use.