Spam filtering feels arbitrary from the sending side. The same message reaches one colleague and vanishes for another; a campaign that performed fine in March disappears in April with nothing obviously changed. It is not arbitrary. It is a stack of specific checks, most of which you can inspect, and a reputation score you can influence but not see.
This guide covers the checks in the order the receiving server applies them, then the reputation and content signals that decide the borderline cases. The goal is that when a message lands in spam you can work out which layer rejected it rather than guessing.
The three questions every receiving server asks
When a message arrives, the receiving mail server has to decide whether to accept it, and if so where to file it. Before it looks at a single word of your copy, it establishes three things:
- Is the server that sent this allowed to send on behalf of that domain? That is SPF.
- Does the message carry a valid signature proving it was not altered in transit? That is DKIM.
- If either answer is no, what did the domain owner say to do about it? That is DMARC.
These three are the price of entry. Failing them does not merely risk the spam folder — since Gmail and Yahoo tightened their bulk sender requirements in 2024, messages that fail them are frequently rejected outright. Passing them, on the other hand, buys you nothing except the right to be judged on everything else. Publishers often set up all three, see no improvement, and conclude they do not matter. They are a floor, not a lever.
SPF: is this server allowed to send for you
Sender Policy Framework is a DNS record listing the servers permitted to send mail for your domain. A receiving server reads the envelope sender domain, looks up its SPF record, and checks whether the connecting IP appears in it.
A record looks like this:
v=spf1 include:_spf.google.com include:sendgrid.net ~all
The include: mechanisms delegate to the providers you actually send through. The final token is the policy for everything else: ~all means soft fail (accept but mark), -all means hard fail (reject). Most guides tell you to use -all. That is correct only once you are certain every legitimate sender is listed, and the list is longer than people expect — your marketing platform, your helpdesk, your invoicing tool, your CRM, and whatever your finance team signed up for without telling anyone.
Two limits cause most real SPF failures. First, evaluation is capped at ten DNS lookups; exceed it and the check returns a permanent error, which receivers treat as a failure. Each include: can chain to further lookups, so four or five providers is enough to blow the limit. Second, SPF breaks on forwarding: when a recipient auto-forwards your message, the forwarding server becomes the sender and is not in your record. This is not a bug you can fix, and it is precisely why DKIM exists.
DKIM: was this message tampered with
DomainKeys Identified Mail attaches a cryptographic signature to the message header. Your sending server signs selected headers and the body with a private key; the public key sits in DNS. The receiver fetches the key, recomputes the signature, and confirms the message is unmodified and genuinely from a system holding your key.
Because the signature travels with the message, DKIM survives forwarding where SPF does not. That makes it the more robust of the two, and the one worth fixing first if you can only fix one.
The failure modes are mundane. A key rotated at the provider but not in DNS. A key published as a 1024-bit key years ago and never upgraded to 2048. A mailing list that appends a footer to the body after signing, invalidating the signature. Two systems sending as the same domain where only one signs. None of these announce themselves; the message simply starts performing worse.
DMARC: what to do when the answers disagree
DMARC ties the other two together and adds two things: a policy telling receivers what to do with mail that fails, and a reporting channel telling you it happened.
v=DMARC1; p=none; rua=mailto:dmarc-reports@example.com; pct=100
The policy p= takes three values. none means take no special action but send me reports — the correct starting point, because it is diagnostic rather than destructive. quarantine means put failures in spam. reject means refuse them at the door.
The sequence that works is: publish p=none, read the aggregate reports for a few weeks until you recognise every sender in them, fix or authorise the legitimate ones, then move to quarantine, then to reject. Skipping to reject on day one is how companies discover their invoicing system was sending through a service nobody documented — by having every invoice bounce.
Those aggregate reports arrive as compressed XML and are unpleasant to read raw. Any DMARC reporting service will parse them into something legible, and for the first month that is worth the subscription.
Alignment, the part that trips everyone up
Here is the detail that explains most "but I set everything up and it still fails" cases. DMARC does not merely require that SPF or DKIM pass. It requires that a passing check be aligned with the domain in the visible From header.
A message can pass SPF perfectly for the envelope sender bounces@mail.provider.com while displaying dana@yourcompany.com in the From line. SPF passed. Alignment failed. DMARC fails the message anyway, because the two domains do not match.
The fix is to set up a custom return path or bounce domain — a subdomain of yours, such as mail.yourcompany.com, that your provider is authorised to use. Every serious sending platform supports this; it is usually a documented setup step that is easy to skip because everything appears to work without it. Relaxed alignment (the default) accepts a subdomain match, so mail.yourcompany.com aligns with yourcompany.com. Strict alignment demands an exact match.
Reputation is the real gatekeeper
Authentication proves identity. It says nothing about whether that identity is welcome. Reputation is what actually decides the inbox, and it attaches to both your sending domain and your sending IP.
Providers do not publish their formulas, but the inputs are well understood and consistent:
- Complaint rate. How often recipients click "report spam". The most damaging single signal. Above roughly 0.3% you are in trouble; below 0.1% is healthy.
- Bounce rate. Mail to addresses that do not exist marks you as someone sending to a list you did not verify. Above 2–3% starts to hurt.
- Engagement. Opens, replies, and messages moved out of spam are positive. Deletion without opening is mildly negative. Sustained non-engagement across a whole audience is strongly negative.
- Spam trap hits. Addresses that exist solely to catch senders who did not get permission. Pristine traps were never valid; recycled traps are abandoned mailboxes reactivated as traps. Hitting either is serious, and hitting recycled ones is the predictable consequence of mailing a list you have not re-verified in a year.
- Consistency. Predictable volume from a stable IP and domain reads as legitimate. Spikes read as a compromised account.
Domain reputation is the one that follows you. Changing IP addresses to escape a bad reputation is a well-worn tactic and providers account for it; burning a domain, by contrast, means changing the address your real customers know.
What in the message itself hurts you
Content filtering matters less than most people assume and is the layer they focus on most. The famous "spam trigger words" lists are largely folklore — no modern filter rejects a message for containing the word "free". What does measurably hurt:
- A single image and almost no text. Historically used to defeat text analysis, and still weighted accordingly.
- Link domains with poor reputation. Including link shorteners, which are heavily abused. Link to your own domain.
- Mismatched or disguised URLs. Display text saying one domain, href pointing at another.
- Broken or missing plain-text alternative. A multipart message whose text part is empty or nonsense looks automated.
- No visible unsubscribe. Absent one, unhappy recipients use the spam button instead, which is the outcome you were trying to avoid.
- Deceptive subject lines. A "Re:" on a first contact, or a fake reply chain. This also breaches CAN-SPAM.
Write the message you would send to one person, add a working unsubscribe link, and content filtering is very unlikely to be your problem.
Volume patterns and the cold start problem
A brand-new domain has no reputation, and no reputation is treated with suspicion rather than neutrality. Sending 5,000 messages on day one from a domain registered last week is the single most reliable way to get filtered, regardless of how clean the list is.
Warming up means starting small and increasing gradually while engagement stays healthy. A workable shape: start in the tens per day, roughly double weekly, and pause the ramp whenever bounces or complaints tick up. Reaching meaningful volume takes weeks, and there is no way to buy the time back.
Two related points. A domain that has been sending steadily for years still needs care: a sudden ten-fold spike looks like a compromise. And engagement during warm-up matters more than volume — a hundred messages a day that get replies build reputation faster than a thousand that get ignored.
Diagnosing a message that went to spam
When something lands in spam, work down the layers rather than guessing:
- Read the headers of the delivered message. Open it in the recipient's client and view the original. The
Authentication-Resultsheader states plainly whether SPF, DKIM and DMARC passed. If one saysfail, stop and fix that; nothing further matters. - Check alignment specifically. Compare the From domain against the envelope sender and the DKIM signing domain. A pass with a mismatch is the most commonly missed cause.
- Check whether it is one provider or all of them. Gmail filtering while Outlook delivers points at reputation with Google specifically. Everyone filtering points at authentication or a blocklist.
- Check the major blocklists. Spamhaus and friends publish lookup tools for your domain and sending IP, and delisting procedures when you are on one.
- Look at your own numbers. Your sending platform reports bounce and complaint rates. If bounces are above a few percent, the list is the problem — and the list is the thing you can actually fix today.
That last point is where most cold outreach problems actually originate. Authentication is a one-off setup; list quality is an ongoing discipline, and a list assembled from extracted addresses needs the full cleaning pass before it goes anywhere near a sequence. That process is covered in how to clean an email list before your first campaign, and what the verification results mean in what email verification results actually mean.