Blog · Deliverability
Why Are My Emails Going to Spam? Fix Email Deliverability in the Right Order
Why Are My Emails Going to Spam? Fix Email Deliverability in the Right Order
When mail stops landing, the order of your checks decides everything. Most teams start in DNS, because DNS is the part they can change without asking anyone. That is usually the wrong place to start. The reliable order is: work out which layer broke. Stop sending from the affected identity. Measure the list and the complaint rate. Verify authentication on the message that actually failed. Read your DMARC aggregate reports to find the sending source you forgot. Only then change the infrastructure.
The steps are not equally long. Step one takes ten minutes and tells you which of the remaining five to run.
The short answer
1. Find the layer. A technical fault hits every receiver at once. A reputation or complaint problem usually shows up at one receiver first.
2. Stop sending from the affected identity. Not all of it. The part that is failing.
3. Measure the list and the complaint rate. Hard bounces, soft bounces, and the 0.3 percent ceiling that decides whether you can ask Google for help.
4. Verify authentication on the failing message. Read the headers of a real message, not the DNS zone you set up a year ago.
5. Read the DMARC aggregate reports. The sending source that broke things is named there, and it is often one nobody remembers.
6. Change the infrastructure last. Reputation is an output of sending behaviour, not a setting.
Two things this order avoids. You do not rewrite DNS records that were fine last week, and you do not buy a new sending domain to fix a list that is full of dead addresses.
Steps four and five are the mechanical part of this, and they are the part people skip. A DMARC, SPF and DKIM checker plus an email header analyzer covers step four, and a dashboard that reads your DMARC aggregate reports per domain covers step five. DMARCFlow does both, at https://dmarcflow.com/en/dmarc-checker and in the reporting dashboard behind it.
Step 1: which layer actually broke?
Start with one question: where did the failure show up?
A broken SPF record, a missing DKIM selector or a misaligned From: header is a technical fault. It does not care which provider receives the mail, so it hits everywhere at once. A complaint-driven or reputation problem behaves differently. It usually shows up first at one receiver, often the strictest filter on your list, while the others keep delivering.
That asymmetry is the cheapest diagnostic you have. One receiver failing while another works points away from DNS and towards list, complaint and reputation problems. Everything failing at once points back at your own configuration.
Map the outcome before you read a DNS record
Every send ends in one of four states, and each one sends you down a different path.
| What happened | What it means | Where to look |
|---|---|---|
| It arrives in the inbox | Nothing broke | Nothing |
| It arrives in the spam folder | Accepted, then filtered | Reputation, complaint rate, content, engagement |
| It is deferred, then arrives later | The receiver asked for a retry | Rate limiting, greylisting, mailbox full |
| It is rejected outright | The receiver refused it | Authentication, policy, blacklists, bad addresses |
The third and fourth rows come straight from the SMTP standards. RFC 5321 section 4.2.1 defines the reply code severities, and RFC 3463 section 2 defines the enhanced three part code that goes with them. Class 4 is a persistent transient failure: the message is valid, but something temporary is in the way, so sending again may work. Class 5 is a permanent failure: resending the same message in the same form will not help.
The subject digit tells you the subject, and it is worth reading. Subject 1 is addressing, subject 2 is mailbox, subject 7 is security or policy. A 5.2.2 mailbox full is classified as a transient failure in RFC 3463, which means you retry it. A 5.7.x code is a policy decision taken about you, and the address is not the problem.
A 250 OK is not a delivery
An SMTP server returning 250 accepted the message and took responsibility for it. It did not put it in an inbox. After acceptance the receiving server can still route it to spam, delay it, or drop it, and it will not tell you. This is why "the dashboard says delivered and the customer says no" is not a contradiction, and why the next step is to work out which of the four states you are actually in.
Step 2: should you stop sending, and what exactly?
If one identity, one tool or one stream is failing, pause that one. Not the whole program. A transactional password reset and a weekly newsletter are not the same sender, and shutting both down because one is misaligned solves nothing and costs you mail you needed to deliver.
The reason to pause rather than keep sending is that reputation is a rolling average of recent behaviour. Additional sends from an identity that is currently being judged badly add evidence to the judgement. If the failure is a list problem, continuing to mail the list makes the list worse. If the failure is a complaint problem, more sends mean more complaints.
If you cannot tell which identity is affected yet, stop guessing and go back to step one. A pause on the wrong stream costs you deliveries for nothing.
Step 3: what do the list and the complaint rate tell you?
Two numbers decide most of this, and neither is visible in your sending dashboard.
Hard bounces, soft bounces and the code that separates them
Read the enhanced status code, not just the reply code. A 550 on its own tells you almost nothing. The subject and detail digits tell you what to do.
The decision each code drives is short. A 5.1.x address does not exist, so suppress it. A 4.x.x with a mailbox or routing subject is transient, so retry it with backoff and cap the retries. A 5.2.2 mailbox full is classified in RFC 3463 as a persistent transient failure, so retry it a few times before you suppress it. And a 5.7.x code is a policy failure about the sender, so do not suppress the recipient, because the address did not do anything wrong. The table further down has the full split.
The trap is treating every 5xx as permanent and every 4xx as safe to retry forever. If an address soft bounces across several sends, it is a hard bounce in practice, and an endless retry loop against a bad list is a reputation problem you built yourself.
The 0.3 percent ceiling, the 0.1 percent target and the 7 day wait
Google calculates the user reported spam rate daily. Its guidance is to keep the rate below 0.1 percent and to prevent it from ever reaching 0.3 percent or higher. The impact is graduated: rates above 0.1 percent already have a negative effect on inbox delivery for bulk senders, and rates of 0.3 percent or higher have a greater negative effect.
The 0.3 percent line is not an instant punishment. It makes you ineligible for mitigation, which is the route to asking Google to look at a delivery problem. You become eligible again when your spam rate stays below 0.3 percent for 7 consecutive days. That is why a team can be "punished" for a fortnight after a bad campaign even after they stopped sending.
What the spam rate dashboard actually measures
Two details decide whether you can trust the number you are looking at.
First, it counts messages that were delivered to an engaged recipient's inbox and then marked as spam by that recipient. Messages that Gmail filtered automatically do not count, and neither do messages a recipient never saw. So the dashboard can show a comfortable rate while your mail sits in spam. If the rate suddenly disappears after a period of high complaints, that is usually because Gmail is now filtering the mail automatically and nobody is reporting it any more.
Second, the dashboards are not real time. Google updates them typically within 24 hours, and they run on UTC, not on your local day. On days when your volume is low, Google may leave data out entirely to protect user privacy. So an empty chart is not evidence that nothing went wrong.
Step 4: is the authentication on the failing message actually right?
Your DNS zone tells you what you configured. The header of the message that failed tells you what actually happened. When the two disagree, the header wins.
Read the Authentication-Results header, not the DNS zone
Take one message that failed, copy the full header block, and read three lines: which domain SPF evaluated, which domain signed DKIM, and what the DMARC verdict was. A 250 OK in your log tells you the receiver accepted the message, and nothing about whether it passed alignment.
DMARCFlow's email header analyzer at https://dmarcflow.com/en/email-header-analyzer parses those results from a pasted header, which is faster than scrolling through raw Received: blocks and gives you the SPF, DKIM and DMARC verdicts in one place.
When the receiver rejects the message instead of filtering it, the code names the failing check. Gmail documents 4.7.31 for a missing DMARC record or a record without a valid policy, and 4.7.32 for a From: header that is not aligned with the authenticated SPF or DKIM organisational domain. Those two are the ones to look for first, because they are the failures that bounce mail rather than the failures that quietly cost you access to Google's support.
One detail in Google's list is worth knowing. It publishes a permanent variant for four of the six authentication failures, 5.7.25, 5.7.27, 5.7.29 and 5.7.30, for the PTR, SPF, TLS and DKIM cases. There is no permanent variant for a missing DMARC record or for an unaligned From: header. Those two keep arriving as temporary codes, which is why a domain with a broken DMARC setup looks like a flapping connection rather than a permanent rejection.
Alignment is judged at the organisational domain
Authentication passing is not enough. The authenticated domain has to align with the From: domain. RFC 7489 section 3.1.1 defines two modes. In relaxed mode, which is the default, the organisational domains of the authenticated domain and the From: domain must match, so d=mail.example.com aligns with user@example.com. In strict mode, only an exact match of the full domain name counts.
The organisational domain comes from the public suffix list, so a.b.c.example.com has the organisational domain example.com. And policy discovery means the record that governs is often not the record you remember: RFC 7489 section 6.6.3 says a receiver first queries the DMARC record at the domain in the From: header, and if there is none, it queries the organisational domain instead, and that record carries the policy asserted for its subdomains.
This is why "our subdomain has its own DMARC record" is often not the reassurance people expect, and why the DMARC checker for each sending domain, https://dmarcflow.com/en/dmarc-checker, is worth running on the organisational domain and on every subdomain you send from.
SPF fails silently at 10 DNS lookups
RFC 7208 section 4.6.4 sets the limit. The include, a, mx, ptr and exists mechanisms and the redirect modifier each cause a DNS query, and an SPF implementation must not exceed 10 of them. When the limit is passed, the result is permerror, which means the record is broken rather than the message merely unauthenticated. The all, ip4 and ip6 mechanisms cost nothing.
The failure mode is quiet. Nothing in your sending platform reports it, the SPF check on your own record looks fine, and mail from that identity starts failing somewhere downstream. SPF checkers that report the lookup count, https://dmarcflow.com/en/spf-checker for the record and the count, are worth more than ones that only say pass or fail.
Audit every tool that sends from your domain
This is the step most teams skip, and it is where a surprising share of cases end.
Your domain sends mail from more systems than you remember. The application. The CRM. The helpdesk. The billing system, usually set up in year one by someone who has left. Each one has its own DKIM selector, its own sending domain or subdomain, and its own From: address. One of them misaligned is enough to produce a stream of DMARC failures that has nothing to do with the tool you are debugging.
So: send a test message from every tool that sends from your domain, then read the header of each one. Write the list down. The surprising entry is usually the oldest one.
Step 5: which sending source did you forget?
Aggregate reports are the most underused diagnostic in email authentication. Everyone knows they exist, few teams read them properly, and they are where the answer usually sits.
RFC 7489 section 7.2.2 defines the format. The report metadata carries org_name, the reporting organisation, the report_id, and the date_range the report covers. Each record inside it carries the source_ip that sent the matching messages, the count of those messages, the policy_evaluated result, and the identifiers envelope_from and header_from.
Three uses, in order of how often they pay off.
1. Find the source you forgot. Sort the records by count and look for a sending source you do not recognise. A marketing tool from 2023, a transactional service nobody mentioned, a CRM that sends from a different domain.
2. See which domain was in play. envelope_from and header_from tell you the domain that authenticated and the domain the recipients saw. When they differ, you have found an alignment problem and the exact pair of names to check.
3. Compare volume over time. A source that appears suddenly and sits at the top of the report is a change, not a steady state, and it is usually the cause.
The practical problem is that this is a daily XML file per domain that you have to fetch, unzip and read. That is exactly the work a tool should do, and DMARCFlow's paid dashboard reads the aggregate reports per domain and lists the sending sources with their counts, so step five takes a minute instead of an afternoon.
Keep one thing in mind when you read them. Google calculates its own data daily and its dashboards typically update within 24 hours, so the reports describe yesterday. A report with no problems yesterday says nothing about the campaign you sent this morning.
Step 6: should you change the infrastructure now?
By now you know which layer broke. If it was the list, a new domain does not help. If it was a complaint problem, a new IP does not help. If it was a misaligned tool, publishing a new record does not help.
Reputation is an output, not a dial. Google describes it as "a rating of the quality of domains and IP addresses used to send email" that is "determined by the sending behavior of a domain or IP address". You do not set it, you earn it, and the way you earn it is by sending mail people want, to addresses that want it, with authentication that works. Chasing it directly is how teams end up warming domains forever.
Google's Domain Reputation dashboard publishes four ratings for a domain, and the wording tells you what each one means.
- Bad: "History of sending a high volume of spam regularly. Email from this domain or address is almost always marked as spam or rejected by the receiving server."
- Low: "History of sending a significant volume of spam regularly. Email from this domain or address is likely to be marked as spam."
- Medium: "History of sending legitimate email, but occasionally sends spam. Most email from this domain or address has a fair deliverability rate, except when there's a notable increase in spam."
- High: "History of very low spam rates, and complies with Gmail's sender guidelines. Email from this domain or address is rarely marked as spam by Gmail."
One detail in that dashboard catches people out. It "only displays messages sent from the exact domain used for DKIM and SPF authentication", so if you sign with mail.example.com but send from example.com, you are reading a partial picture.
The right time to buy a new domain or warm a new IP is after you have fixed the cause and know that the old identity needs a clean start. Before that, it is expensive theatre.
What not to do first
- Do not rewrite SPF or DKIM records before you have measured. A record that was working last week usually still works, and rewriting it changes the failure you are chasing.
- Do not buy a new sending domain. It costs you a new reputation, new keys, new reports and new warm-up, and it fixes nothing that is not a sending identity problem.
- Do not warm up a new IP while the old one is still sending. Warm-up is for a clean identity, not a cover-up.
- Do not send more volume to "rebalance" the reputation. More sends from a sender under judgement make the judgement worse.
- Do not suppress recipients because of a
5.7.xcode. The code is about you, so suppressing the address hides your problem and shrinks your list. - Do not treat Postmaster Tools as live data. It typically updates within 24 hours, runs on UTC, and hides data on low volume days.
The bounce codes that tell you which step you are on
| Code | Class | What it means | What to do |
|---|---|---|---|
4.x.x | Transient | Temporary problem, retry may succeed | Retry with backoff, cap the retries |
5.1.x | Permanent | Addressing problem, the address does not exist | Suppress immediately |
5.2.x | Usually transient | Mailbox status, for example full | Retry a few times, then suppress |
5.7.x | Permanent | Security or policy failure, about the sender | Fix your setup, keep the address |
That last row is the one that changes behaviour. A 5.7.x code means the receiver made a policy decision about your domain, so the address is still good. Suppressing it on the grounds that it is a 5xx is how a healthy list quietly shrinks.
The runbook
For the reader who wants to paste this into a ticket.
1. Which receivers are affected, and since when? One receiver or all of them?
2. For each failed send, what was the outcome: spam folder, deferred, or rejected?
3. Pause the affected identity. Not the whole program.
4. Pull the hard and soft bounce counts for the last 14 days, split by code.
5. Pull the complaint rate for the same window. Compare it with 0.1 percent and 0.3 percent.
6. Send a test from every tool that sends from this domain. Read the header of each one. Check the d= domain against the From: domain, and check the SPF lookup count.
7. Open the DMARC aggregate reports. List every sending source with its count. Mark the ones you do not recognise.
8. Now decide: list problem, configuration problem, or reputation problem.
9. Only then touch infrastructure.
The two numbers to look up first are the complaint rate and the list of DMARC report sources. Between them they rule out most of the possibilities before you touch a DNS record. DMARCFlow's domain report dashboard gives you the second one, the sending sources with their counts, without opening the XML by hand.
Frequently asked questions
Should I fix SPF and DKIM before I look at reputation?
No, and this is the most common wrong turn. Authentication is the layer that breaks everywhere at once. If only one receiver is failing, or only one stream is failing, the fault is more likely the list, the complaint rate or a single misaligned tool. Check the outcome first.
How do I tell a list problem from an authentication problem?
Authentication failures produce SMTP codes and DMARC report entries with a policy_evaluated result. They also show up in the Authentication-Results header of the failing message. A list problem produces no codes at all, because the mail was accepted and then judged on the content and the list, which is why the complaint rate and the bounce counts are the numbers to check first.
Why does my mail land at Gmail but arrive fine at Outlook?
Different providers apply different thresholds and different filtering. Gmail enforces its sender guidelines against mail to personal Gmail accounts, calculates a user reported spam rate, and applies reputation ratings per domain and per IP. Outlook enforces a different set of requirements and its own codes. When one receiver is failing and another is not, look at the per receiver data rather than assuming the mail is broken.
Should I buy a new domain to fix deliverability?
Only if the problem is the sending identity itself and you have already fixed the cause. A new domain starts with no reputation and its own warm-up, and it does nothing about a list full of dead addresses, a complaint rate above 0.3 percent, or a tool that signs with the wrong domain.
Which Gmail error codes should I check first?
4.7.31 if you have no DMARC record on the sending domain, and 4.7.32 if you have one but the From: header is not aligned with it. A missing DMARC record is the failure that generates the most traffic and the easiest one to fix. The full documented set is 4.7.23 for a missing or mismatched PTR record, 4.7.27 for SPF failing, 4.7.29 for missing TLS, 4.7.30 for DKIM failing, 4.7.31, 4.7.32, and the permanent variants 5.7.25, 5.7.27, 5.7.29 and 5.7.30. Anything in the 5.7.x range is about your setup, not about the recipient.
How long does it take to recover a damaged reputation?
Days for the configuration, weeks for the reputation. Fixing a misaligned selector or a missing record changes the next send. A reputation that was driven down by complaints or bounces is "determined by the sending behavior of a domain or IP address", so it recovers as you send cleanly again, and Google notes that spam rate data updates daily. If your complaint rate stays below 0.3 percent for 7 consecutive days, you are eligible for mitigation again.
Does a DMARC aggregate report tell me why a message failed?
It tells you who sent it and what the receiver decided, not why the content was disliked. Each record carries the source_ip, the count of matching messages, the policy_evaluated result including the DKIM and SPF alignment results, and the envelope_from and header_from domains. That is enough to identify an unknown sender or a misaligned domain. It says nothing about why a receiver moved a message to spam when the authentication passed.