Back to the guides · Fundamentals · 18 min read
SPF, DKIM and DMARC explained: why alignment matters
The three records, what each one is for, and the fault almost no tool names: SPF and DKIM green with DMARC failing one hundred per cent of the time.
Updated in August 2026
SPF says which servers may send on behalf of your domain. DKIM signs the message cryptographically so the receiver can confirm nobody has tampered with it. DMARC checks neither of those things: it checks that at least one of them passes and is also aligned with the domain the user sees in the From. That last word, aligned, is what explains how a domain can show SPF and DKIM green in every checker and still fail DMARC on one hundred per cent of its mail.
All three are TXT records in your domain's DNS. They are public: anyone can read them, you included, with one command in a terminal. This guide explains what each one does, where they break in practice, and how to check alignment by looking at a real message.
SPF: who is allowed to send for you
An SPF record is a list of authorised servers. The receiver looks at the IP the message came from and checks whether it is on the list. A healthy SPF record looks like this:
; corporate mail (Google Workspace) empresa.es. TXT "v=spf1 include:_spf.google.com -all" ; transactional (Amazon SES) mail.empresa.es. TXT "v=spf1 include:amazonses.com -all" ; campaigns (SMTP2GO) news.empresa.es. TXT "v=spf1 include:spf.smtp2go.com -all"
Each subdomain gets its own ten-lookup limit and its own reputation. This is the structural answer to the problem below.
SPF has two limits that sink more domains than anything else. The first is the ten DNS lookups: RFC 7208 requires that no more than ten terms resolving names be evaluated. include, a, mx, ptr, exists and the redirect modifier all count. ip4, ip6, all and exp do not. Every marketing tool you add usually brings its own include, and the day you go past ten the result is permerror, which most receivers treat as an SPF failure. It is the number one cause of "it suddenly stopped arriving".
The second is void lookups. The same RFC says implementations should limit void lookups, meaning queries that return nothing or NXDOMAIN, to two. Two includes pointing at services that no longer exist are enough to bring the whole SPF record down. That is why an audit starts by pruning: on a domain five years old it is normal to find three or four fossil includes. The record should also fit in 512 octets, with each TXT string under 255 bytes.
On how the record ends: ~all (softfail) is the right choice while you are rolling out and while there are forwarders without ARC. The target is -all (hardfail), but it only adds real security once DMARC is at enforcement, because with DMARC at reject it is DMARC that decides. Our recommendation: -all on controlled sending subdomains, ~all on the corporate domain where people forward mail to their own Gmail.
DKIM: the signature that travels with the message
DKIM signs a specific set of headers plus the body with a private key held only by your outbound server. The public key is published in DNS under a selector, and the receiver fetches it there to verify. Unlike SPF, the signature survives forwarding as long as nobody modifies the message.
sel2026a._domainkey.empresa.es. IN TXT ( "v=DKIM1; k=rsa; t=s; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA..."
"...IDAQAB" )A 2048-bit RSA key does not fit in a single 255-byte TXT string. Many Spanish hosting DNS panels split the record badly and the key ends up unreadable: a silent failure, and a very common one.
- Key length
- RFC 8301 requires a minimum of 1024 bits and recommends 2048. Google requires the minimum and recommends the same; Yahoo also sets 1024 as its floor. The sensible decision today is 2048, always.
- Algorithm
- RFC 8301 is unambiguous: sign with rsa-sha256, and rsa-sha1 must not be used either for signing or for verification. A selector still active with sha1 is a finding, not a detail.
- Selector naming
- M3AAWG recommends that the selector say which flow it belongs to, when it entered service and how many bits it is, and strongly advises against reusing names. A convention that works: camp-202608-2048, txn-202608-2048.
- Which headers to sign (the h= tag)
- At minimum From, To, Subject, Date, Message-ID, MIME-Version, Content-Type and Reply-To. And, if you send commercial mail, List-Unsubscribe and List-Unsubscribe-Post are mandatory: RFC 8058 requires them, and if they are not covered by the signature Gmail will not show its native unsubscribe button.
- Canonicalisation
- relaxed/relaxed. simple/simple breaks the moment anything along the path rewrites a header, which is the normal state of affairs.
Key rotation has a clear reference: the M3AAWG best practices document, whose 2019 update moved the recommendation from quarterly to twice a year and proposes April and October as sensible months. The procedure matters as much as the calendar: keep two key pairs published at all times, one signing and one waiting; to rotate, publish the next one, wait for propagation, and only then switch the signing server over. The previous key stays in DNS for between seven and thirty days and is then retired by emptying the p field, without deleting the selector entry.
DMARC: what it actually checks
Here is the misunderstanding that half the industry rests on. DMARC does not check SPF and DKIM. DMARC checks that at least one of the two passes and is aligned with the domain in the From header, which is the only one the recipient sees. If both pass but neither aligns, DMARC fails.
- SPF alignment
- Compares the Return-Path domain (the envelope sender, MAIL FROM) with the From domain. They are two different things, and almost nobody looks at the first.
- DKIM alignment
- Compares the domain in the signature's d= tag with the From domain. A perfectly valid signature carrying the provider's d= does not align with your domain.
- Relaxed versus strict
- Alignment is relaxed by default (aspf=r, adkim=r) and sharing the organisational domain is enough: news.empresa.es aligns with empresa.es. In strict mode (s) the match has to be exact.
«The domain in the sender’s From: header must be aligned with either the SPF domain or the DKIM domain.»
Yahoo says it in the same words, and Microsoft requires valid DMARC plus alignment through SPF or DKIM in order not to reject with 550 5.7.515. All three ask for the same thing, which is why alignment is not a purist's footnote: it is the requirement.
The classic failure: green, green, and DMARC at zero
The pattern repeats in almost every audit of a Spanish SME. The company signs up for a campaign tool. The tool sets its own Return-Path (something like bounces.proveedor.com) so it can handle bounces, so SPF passes, but it passes for the provider's domain: no alignment. And if on top of that the provider signs with DKIM using d=proveedor.com rather than the client's domain, there is no alignment on that side either. Result: SPF green, DKIM green, DMARC failing on one hundred per cent of messages.
| Where to look | What it contains | What has to be true |
|---|---|---|
| Return-Path | bounces.proveedor.com | Shares the organisational domain with the From, or SPF does not align |
| DKIM-Signature, d= tag | proveedor.com | It is the client's domain, or DKIM does not align |
| From: | hola@empresa.es | The only thing the recipient sees, and the reference for everything else |
How to actually read a DMARC report
Once you publish a rua, receivers send you a compressed XML file every day summarising, per source IP, how many messages they saw and what happened to them. They contain no content and no recipients. This is the fragment you need to be able to read:
<record>
<row>
<source_ip>203.0.113.10</source_ip>
<count>1420</count>
<policy_evaluated>
<disposition>none</disposition> <!-- what was done with the message -->
<dkim>fail</dkim> <!-- ALIGNMENT, not validity -->
<spf>pass</spf>
</policy_evaluated>
</row>
<identifiers><header_from>empresa.es</header_from></identifiers>
<auth_results>
<dkim><domain>proveedor.com</domain><result>pass</result></dkim> <!-- valid signature... -->
<spf><domain>empresa.es</domain><result>pass</result></spf>
</auth_results>
</record>DKIM pass in auth_results and fail in policy_evaluated means exactly one thing: the signature is valid but it does not align. That single pattern explains half of all real diagnostics.
With the reports in front of you, every IP sending in your name falls into one of four buckets: legitimate and aligned (nothing to do), legitimate and not aligned (needs fixing), forwarders (low volume, many different IPs, SPF fail with DKIM pass: normal behaviour, mitigated by ARC) and spoofing (no authentication of any kind, which is the reason you eventually move to reject). The golden rule: you do not move up a step while the second bucket still carries material volume.
Check it yourself in three minutes
dig +short TXT empresa.es | grep spf1 dig +short TXT _dmarc.empresa.es dig +short TXT sel2026a._domainkey.empresa.es dig +short MX empresa.es
The DKIM selector cannot be guessed from outside: you have to take it from the DKIM-Signature header of one of your own emails. That is why an honest tool leaves DKIM grey instead of calling it broken.
Alignment is not visible in DNS, it is visible in a message. Open an email you sent in Gmail, use "Show original" and look for the Authentication-Results header. That is where the verdict on all three lives, and the one that counts is the last:
Authentication-Results: mx.google.com;
dkim=pass header.i=@proveedor.com header.s=sel1;
spf=pass (google.com: domain of bounces.proveedor.com designates 203.0.113.10) smtp.mailfrom=bounces.proveedor.com;
dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=empresa.esThe first two say pass and the third says fail. It is the case this guide is about, written out by Gmail itself.
The right order of work
- Inventory of senders: who sends in the domain's name today. There are usually three or four more than the company remembers.
- One SPF record per flow: short, no fossils, under ten lookups. If it does not fit, split it by subdomain rather than flattening it by hand.
- 2048-bit DKIM signing with the client's domain at every provider, with h= covering the unsubscribe headers.
- DMARC at p=none with rua pointing at a mailbox somebody actually reads. Publishing a rua nobody processes is the same as having no DMARC.
- Read reports for weeks, close out the legitimate-but-unaligned bucket, and only then start raising the policy.
That last step is a whole guide of its own, because since May 2026 it is done differently: the DMARC revision removed the pct tag, and with it the classic runbook of ramping up by percentage. How you get to p=reject today without losing legitimate mail is covered in the guide to raising DMARC without breaking anything.
Questions that always come up
Do I need DMARC if I send very little mail?
Google, Yahoo and Microsoft require it above 5,000 messages a day to consumer accounts, and p=none satisfies them. Below that threshold it is not compulsory, but without DMARC you get no reports, and without reports you do not know who is sending in your name.
Is having all three records enough?
No. Having all three and aligning none is the most common scenario of the lot, and a cheap checker will show it green. The valid check is the Authentication-Results header of a real message from each flow.
Can I flatten SPF to stay under ten lookups?
You can, but only with automatic re-flattening and daily verification. If the provider changes its IPs and you do not notice, you stop authenticating overnight. Splitting by subdomain solves the same problem and does not break.
What about ARC, do I need to sign it?
If you only send, no. ARC is added by intermediaries: mailing lists, forwarders and anti-spam gateways. It applies to you if you operate one of those, not if you are the original sender.
Sources
Everything stated here comes from one of these places. If something carries no source, it is an opinion and is said as such.
- IETF. RFC 7208: Sender Policy Framework (SPF) · Consulted on 26 August 2026
- IETF. RFC 8301: DKIM security update (key sizes and algorithms) · Consulted on 26 August 2026
- IETF. RFC 8058: one-click unsubscribe · Consulted on 26 August 2026
- IETF. RFC 9989: DMARC (obsoletes RFC 7489) · Consulted on 26 August 2026
- IETF. RFC 8617: Authenticated Received Chain (ARC) · Consulted on 26 August 2026
- M3AAWG. DKIM Key Rotation Best Common Practices (2019 update) · Consulted on 26 August 2026
- Google. Email sender guidelines · Consulted on 26 August 2026
- Yahoo. Sender best practices · Consulted on 26 August 2026
- Microsoft. Fix NDR error 550 5.7.515 in Outlook.com · Consulted on 26 August 2026
This guide explains how things work and cites the rules with a link, but it is not legal advice.