DNS, Authentication, DMARC
SPF, DKIM, DMARC: The Deliverability Stack Explained for Outbound Teams
Three records, three jobs, one chain. Get the chain right and most deliverability problems vanish before you ever touch warmup or copy.

In this article
- What each record does
- Alignment, the bit everyone gets wrong
- Common mistakes outbound teams make
- The SPF lookup budget, counted by hand
- A worked diagnosis: SPF passes but DMARC fails
- Common fixes, by symptom
- Reading DMARC reports
- Reading DMARC reports
- What to look for in your first aggregate report
- A sensible deployment plan
- A sensible deployment plan
- Frequently asked questions
Authentication is the layer underneath everything else in deliverability. Warmup, copy, list hygiene, and pacing all matter, but they matter less if SPF, DKIM, and DMARC are misconfigured. This guide explains what each record actually does, how alignment works, the mistakes that bite outbound teams hardest, and how to read the reports DMARC sends you.
What each record does
SPF authorises sending sources. It is a TXT record at the apex of your domain that lists IPs and includes for every system permitted to send mail using your domain in the envelope-from (also called Return-Path or MAIL FROM). Receivers check the envelope-from against the SPF record and pass, soft-fail, hard-fail, or neutral depending on the result and your qualifier.
DKIM signs messages. The sending system generates a cryptographic signature over selected headers and (usually) the body, then publishes the public key as a TXT record at <selector>._domainkey.yourdomain.com. Receivers fetch the key, verify the signature, and conclude whether the message was tampered with in transit and whether it was actually signed by the claimed domain.
DMARC ties the two together. It tells receivers what to do when neither SPF nor DKIM passes with alignment, and it asks them to send you reports. The policy lives at _dmarc.yourdomain.com. The three policy values are p=none (monitor only), p=quarantine (junk it), and p=reject (refuse delivery).

Alignment, the bit everyone gets wrong
Passing SPF or DKIM is not enough for DMARC. The passing record must also align with the From header, which is the address recipients actually see. SPF alignment compares the envelope-from domain to the From header domain. DKIM alignment compares the d= tag in the DKIM signature to the From header domain.
Alignment has two modes, relaxed (the default) and strict. Relaxed permits an organisational match, so mail.yourdomain.com aligns with yourdomain.com. Strict requires an exact match, so mail.yourdomain.com would fail strict alignment against yourdomain.com. For cold outreach, relaxed is almost always the right choice. Configure it explicitly with aspf=r and adkim=r in your DMARC record so future-you knows what was intended.
The trap: many outbound vendors set the envelope-from to their own bounce domain, which means SPF passes but does not align. If DKIM is also misconfigured, DMARC fails despite SPF showing PASS in the headers. Always check alignment, not just the underlying pass result.
Common mistakes outbound teams make
- Multiple SPF records on the same domain. Receivers must treat this as a permerror, which is a hard fail. Always consolidate to one.
- More than 10 DNS lookups in the SPF chain. Each include and a, mx, ptr counts. Tools like dmarcian's SPF surveyor will count for you.
- 1024-bit DKIM keys. Considered weak in 2026. Regenerate at 2048-bit and rotate annually.
- Same DKIM selector across multiple providers. Each vendor must use a unique selector so key rotation does not break anyone else.
- p=reject from day one. Always start at p=none and watch reports for at least 30 days before tightening.
- Treating DMARC PASS in the headers as proof of alignment. Read the aggregate reports, they show alignment explicitly.
- Forgetting that the bounce vendor in your campaign tool needs to be listed in SPF too.

The SPF lookup budget, counted by hand
The 10-lookup limit surprises teams because every vendor you add quietly spends some of it. Each include: mechanism costs one lookup, and every include inside that include costs more. The a, mx, ptr and exists mechanisms and the redirect modifier each cost one as well. Plain ip4 and ip6 entries cost nothing, which is why flattening a record to raw IP ranges is a common fix, at the price of having to refresh it when a vendor changes its ranges.
Here is a typical outbound domain that looks innocent: Google Workspace for the team's mailboxes, a campaign tool, a CRM that sends meeting invites, a support desk and a billing system. Five includes on the surface. Once you expand them, the chain can easily pass ten, and the receiver returns a permerror. The failure is silent for you, because mail still flows, it just stops authenticating through SPF on the receivers that enforce the limit.
- Write down every system that sends as your domain. Be ruthless: if nobody can name an owner, find out whether it still sends.
- Expand each include with a free SPF surveyor and note its lookup cost.
- Remove vendors that no longer send, and move transactional or support mail to a subdomain with its own SPF record.
- If you are still over ten, flatten the heaviest include to ip4 ranges, and put a monthly reminder in the calendar to re-check them.
- Re-test, then confirm in an aggregate report that SPF is passing for each real source.
A worked diagnosis: SPF passes but DMARC fails
A common ticket reads: "Our headers show spf=pass, but DMARC says fail and replies have dried up." The walkthrough takes five minutes. Open the raw headers of a message that reached a seed mailbox and look at three lines in the Authentication-Results header.
| Line to find | What you see | What it means |
|---|---|---|
| spf= | pass, smtp.mailfrom=bounce.vendor-example.net | SPF passed, but for the vendor's bounce domain, not yours. It does not align with your From domain. |
| dkim= | pass, header.d=vendor-example.net | DKIM passed for the vendor's own domain. Also not aligned. |
| dmarc= | fail, header.from=yourdomain.com | Neither passing check matches the From domain, so DMARC fails. |
The fix is to make one of the two align. The cheaper route is almost always DKIM: in the vendor's dashboard, add your own domain as a custom signing domain, publish the CNAME or TXT record it gives you, and wait for the tool to show it as verified. Send a new test and confirm header.d now equals your domain. You do not need SPF alignment as well, since DMARC needs only one aligned pass, though having both is sturdier because forwarding breaks SPF and leaves DKIM to carry the message.
Common fixes, by symptom
| Symptom | Likely cause | Fix |
|---|---|---|
| SPF shows permerror | Two SPF records, or more than 10 lookups | Merge into one record, then trim or flatten includes. |
| DKIM shows none for one tool | Selector not published, or CNAME proxied by your DNS host | Re-publish the record and turn off any proxy setting on it. |
| DMARC fail only on one vendor | Vendor signs with its own domain | Enable custom domain signing in that vendor. |
| Reports show unknown IPs with both fail | Spoofing, or a forgotten legacy system | Identify the owner. If nobody claims it, p=reject will block it. |
| Everything passes but mail still lands in spam | Authentication is not the problem | Look at reputation, content and list quality instead. |
That last row matters. Authentication is a gate, not a guarantee. Passing all three records means receivers can trust who you are. It does not mean they will like what you send, and it does not repair a domain whose reputation is already damaged.
Reading DMARC reports
Reading DMARC reports
DMARC reports come in two flavours. Aggregate reports (RUA) are XML files sent daily by major receivers. Forensic reports (RUF) are individual failure samples and are rarely sent by major providers because of privacy concerns. Most useful intelligence comes from RUA.
An aggregate report includes, per sending source IP, the volume of messages, the SPF result, the DKIM result, and the alignment result. If you see significant volume from an IP you do not recognise with both checks failing, somebody is spoofing your domain. If you see volume from your own vendor with one of the checks failing, your configuration with that vendor is wrong.
Reading raw XML is painful. Use a free tool like dmarcian, EasyDMARC, or Postmark's DMARC Digests to convert reports into a dashboard. The investment is two minutes, the payoff is months of clearer diagnostics.
What to look for in your first aggregate report
The first report is usually humbling. Sort the rows by volume and ask three questions in order. Is the top source one you recognize? Does it show an aligned pass on at least one check? Is the long tail made of IPs belonging to your own vendors under different hostnames? Most teams find one forgotten tool, such as an old newsletter service or a form plugin, sending a few hundred messages a week as their domain with no signature. That is the system you fix before you tighten the policy, because p=reject would start refusing its mail the day you enable it.
Keep a simple inventory sheet with one row per sending source: the owner, the SPF mechanism, the DKIM selector, whether it aligns, and the date you last verified it. Review it whenever someone adds a tool. It turns the aggregate report from a mystery into a checklist.
A sensible deployment plan
A sensible deployment plan
- Publish SPF and DKIM. Send a test message and verify both pass with alignment.
- Publish DMARC at p=none with rua reporting to a monitored mailbox.
- Watch reports for 30 days. Identify every legitimate sending source and bring each one into compliance.
- Move to p=quarantine with pct=10, increasing the percentage weekly as reports stay clean.
- Move to p=reject once quarantine at 100% has run cleanly for 14 days.
- Once at p=reject, publish a BIMI record if you have a Verified Mark Certificate. Gmail and Yahoo display the logo, and it contributes a small positive signal.
Frequently asked questions
Do I need SPF, DKIM and DMARC for cold email?
Yes. Google and Yahoo require SPF, DKIM and DMARC for bulk senders, along with one-click unsubscribe and a spam rate under 0.3%. Even below bulk volumes, unauthenticated cold email is far more likely to be filtered, so set all three up on every sending domain before the first message goes out.
Why does DMARC fail when SPF shows pass?
Because DMARC requires alignment. SPF may pass for a vendor's bounce domain while your From address uses a different domain. Neither check then aligns with the From domain, and DMARC fails. Fix it by enabling custom domain signing (DKIM) in the vendor, or by using a custom return-path domain.
What is the SPF 10-lookup limit?
SPF evaluation may trigger at most 10 DNS lookups across includes, a, mx, ptr, exists and redirect. Going over returns a permerror, which receivers treat as a failure. Remove unused vendors, move other mail to a subdomain, or flatten heavy includes to IP ranges.
How long should I stay on p=none?
At least 30 days, and until every legitimate sending source shows an aligned pass in your aggregate reports. Then move to quarantine at a low percentage, raise it weekly, and go to reject after a clean stretch at 100%.
Do I need a separate DMARC record for each subdomain?
Not necessarily. A policy at the organizational domain applies to subdomains unless you publish an sp= tag or a record at the subdomain. Many teams send cold email from a dedicated domain with its own records so that outreach reputation stays separate from the main business domain.


