You bought a domain, pointed its mail somewhere, and the setup page handed you three lines of DNS text. One begins `v=spf1`. One is a long unbroken string published under a name containing `_domainkey`. One begins `v=DMARC1`. The instructions told you to paste them into your registrar's control panel and save. They did not tell you what any of them were, and nothing on the page suggested it mattered.
It matters, because the three fail in different ways and you will eventually have to work out which one has gone wrong. All three exist to patch the same hole. The protocol that carries mail across the internet was never built to check that a sender is entitled to the name in the From line, as Microsoft's own authentication documentation says plainly. Anyone running a mail server can put your domain there. SPF, DKIM and DMARC are the retrofit.
The short version: SPF is about which servers may send, DKIM is about whether the message arrived unaltered, and DMARC is the only one of the three that concerns itself with the address your recipient actually reads. Here is what each really checks, and why forwarding breaks one of them and not the others.
SPF authorises servers, not people
SPF is a list, published as a TXT record on your domain, of the machines allowed to send mail using that domain. RFC 7208 frames it as a way for the administrators of a domain to explicitly authorise the hosts permitted to use their domain names. A receiving server sees the IP address that connected to it, fetches your record, walks through its mechanisms, and decides whether that address is on the list.
The mechanisms are the parts you paste. `ip4:` and `ip6:` for literal addresses, `a` and `mx` for whatever your domain's own records point at, and `include:` to pull in another domain's list, which is how a hosted mail provider or a mailing platform gets covered. The record ends with an `all` mechanism carrying a qualifier: `-all` for a hard fail, `~all` for a soft fail, `?all` for neutral. RFC 7208 defines seven possible outcomes in total: none, neutral, pass, fail, softfail, temperror and permerror.
There is a limit that catches people out. RFC 7208 requires an implementation to stop after ten terms that cause DNS queries, counting `include`, `a`, `mx`, `ptr`, `exists` and `redirect`, and to return permerror beyond that. Every supplier you add consumes at least one, and some includes expand into more inside. A record that grew one tool at a time can quietly stop working.
The address SPF checks is not the one you see
This is the most misunderstood thing about SPF, and it explains most of the confusion that follows. An SMTP conversation carries two different sender addresses. The envelope sender is given in the `MAIL FROM` command, before any of the message itself is transmitted, and is usually recorded in the `Return-Path` header. It is where bounces go. The From header is part of the message content, and it is the only one your mail client displays.
SPF checks the envelope. RFC 7208 evaluates the RFC5321.MailFrom identity, recommends that verifiers separately check the HELO identity as well, and says that checking any other identity against an SPF version 1 record is not recommended without the publishing domain's explicit approval. The From header is a different identity. SPF has no opinion about it.
The consequence is uncomfortable. Someone can register a domain of their own, publish a correct SPF record for it, send from a server that record authorises, and put your address in the From line. SPF passes. Microsoft's documentation describes exactly this sequence as a way to send mail that passes SPF while displaying a domain the sender does not control. The recipient never sees the envelope, so nothing in front of them contradicts the forgery.
DKIM signs the message itself
DKIM takes a different approach. Your outgoing server computes a hash of the message body and of a chosen list of header fields, signs that with a private key, and inserts the result as a `DKIM-Signature` header. RFC 6376 specifies the tags it carries, including `d` for the signing domain, `s` for the selector, `h` for the headers that were signed, `bh` for the body hash, `b` for the signature itself, and `c` for canonicalisation.
The public half of the key lives in DNS. Given a signature with `d=example.com` and `s=foo.bar`, RFC 6376 says the verifier queries `foo.bar._domainkey.example.com`. The selector is what lets a domain hold several keys at once, which is how rotation happens without an outage, and how a provider can sign on your behalf under a name you publish.
Because the signature covers the message rather than the connection, it survives being passed along. RFC 6376 notes that transit is normally through relays that make no substantive change and therefore preserve the signature. The word doing the work there is normally. Canonicalisation sets the tolerance: `simple` permits almost no modification, `relaxed` absorbs common changes such as whitespace and rewrapped header lines. RFC 7960 records the classic offenders, a mailing list that prepends a tag to the subject or appends a footer to the body.
DMARC ties both of them to the From line
SPF authenticates a domain in the envelope. DKIM authenticates a domain in a signature. Neither is required to have any relationship to the domain your recipient reads. DMARC's contribution is to insist that one of them does, and RFC 9989 gives that requirement a name: Identifier Alignment. Relaxed alignment holds when the Author Domain has the same Organizational Domain as an authenticated identifier; strict alignment requires the two to be identical.
Alignment comes in two strictnesses, set by the `aspf` and `adkim` tags. Relaxed, the default, requires the organisational domains to match, so a From address at contoso.com aligns with an envelope at bounces.contoso.com. Strict requires the fully qualified names to be identical, and the same pair fails. A message passes DMARC if at least one of the two checks produces a pass on an aligned identifier, and fails only when both fail.
That is why an otherwise baffling result is so common. A marketing platform sends on your behalf using its own bounce domain in the envelope. SPF passes, for the platform's domain. Your From address is your own domain. The two do not align, so SPF contributes nothing to DMARC, and unless the platform also signs with `d=` set to your domain, DMARC fails on a message that passed SPF perfectly. Microsoft's troubleshooting guidance lists this as the classic alignment problem.
The record is a TXT record at `_dmarc` on your domain. `p=` carries the policy, `sp=` overrides it for subdomains that exist, `np=` covers subdomains that do not, `rua=` names an address for aggregate reports and `ruf=` for per-failure reports. RFC 9989, which replaced RFC 7489 in May 2026, dropped the old `pct=` sampling tag and tells receivers to ignore it where it still appears. Subdomains inherit the parent's DMARC record unless they publish their own, which is not true of SPF or DKIM.
| Record | What it authenticates | Where it lives | What breaks it |
|---|---|---|---|
| SPF | The connecting IP, against the envelope sender | TXT on the domain | Forwarding, an unlisted new sender, over ten DNS lookups |
| DKIM | The body and signed headers, against the `d=` domain | TXT at `selector._domainkey` | Anything that edits the signed parts in transit |
| DMARC | Alignment with the visible From domain | TXT at `_dmarc` | SPF and DKIM both failing or both unaligned |
Forwarding is where SPF gives up
If you forward mail from your domain to a mailbox elsewhere, this section is the one that concerns you. SPF is evaluated against the address of the server that made the connection. RFC 7208 covers this under mediators: when a forwarder keeps the original envelope sender, the check runs against the forwarder's IP, which is not in the original domain's record, and SPF fails. Nothing is wrong. The message is genuine. The record was simply never written to authorise somebody else's server.
The usual answer is the Sender Rewriting Scheme. Microsoft's documentation on SRS describes it as rewriting the MAIL FROM address on messages forwarded to external recipients, added specifically because autoforwarding is incompatible with SPF. The rewritten address sits on the forwarder's own domain and encodes the original sender's domain and local part with a hash and a timestamp, so bounces still find their way back. The From header is untouched, and the recipient still sees the original author.
SRS repairs SPF and stops there. Microsoft states directly that it does not resolve forwarded messages failing DMARC, because after the rewrite the domain SPF passed for is the forwarder's, which does not align with the From address. The only reliable route through a forward is a DKIM signature made with the From domain and left intact to the far end. That is the practical reason DKIM matters more than its reputation suggests, and why ARC exists for services that must modify messages on the way through. If your domain forwards to a mailbox elsewhere, this is the machinery you are relying on.
The reason this stopped being optional
Publishing all three used to be good practice. It is now an entry requirement at Gmail and Yahoo. Google's sender guidelines state that from 1 February 2024, senders of more than 5,000 messages a day to Gmail accounts must set up both SPF and DKIM, must have DMARC configured with the From domain aligned to either the SPF or the DKIM domain, and must keep their spam rate below 0.3% as reported by Postmaster Tools. The DMARC policy itself may be `p=none`. Marketing and subscribed messages must also support one-click unsubscribe.
Yahoo's Sender Hub sets out the same shape from February 2024: every sender should have SPF or DKIM at minimum, bulk senders need both plus a valid DMARC policy of at least `p=none` that passes, relaxed alignment is acceptable, spam rates stay below 0.3%, and unsubscribes are honoured within two days. Yahoo's page does not name a volume threshold. Microsoft's guidance for its own platform treats the three as interdependent building blocks and says anything less than all of them gives substandard protection.
What to publish, and in what order
The order matters more than the contents, because a strict policy published before you know what sends as your domain is a self-inflicted outage.
- Publish an SPF record listing every source you already know about, ending in `~all` rather than `-all`. Microsoft's guidance recommends exactly this, starting at soft fail, discovering the remaining sources, then tightening once the list is complete.
- Turn on DKIM signing and publish the public key under a selector. Google's guidelines set a minimum of 1024 bits and recommend 2048. Check that the `d=` value is your own domain, or the signature will pass and still not align.
- Publish a DMARC record at `_dmarc` with `p=none` and a working `rua=` address. Send the reports to a shared mailbox, not to a person's inbox.
- Read the aggregate reports for several weeks. They arrive as gzipped XML, roughly daily from each reporting receiver, and the thing to look for is the gap between a source that passed SPF and a source that aligned.
- Move to `p=quarantine`, then to `p=reject`, one domain or subdomain at a time, starting with whichever carries the least mail and saving the parent domain for last. Do not try to stage the rollout with the old `pct=` tag: RFC 9989 removed it in May 2026 and tells receivers to disregard it, so a record reading `p=reject; pct=10` is now enforced against everything.
`p=none` is worth being precise about, because it is often described as protection and it is not. RFC 9989 defines it as the domain owner offering no expression of preference. It changes nothing about how a receiver treats a failing message. Its entire function is to switch on reporting, so you can see who sends as you before you decide to block anything. Microsoft's documentation calls it the value used for testing and tuning.
The failure this sequence prevents is publishing `p=reject` on day one. Almost every organisation sends more mail than it remembers: the invoicing system, the CRM, the helpdesk, appointment reminders, the payroll provider, a contact form, a survey tool somebody set up three years ago. Microsoft's documentation observes that many companies never publish SPF at all because they do not know all their own sending sources. Go straight to reject and you find out the expensive way, from customers who did not receive things. Note that all of this concerns outbound mail only; a catch-all address governs what arrives and has no bearing on these records. Domains you own but never send from should carry `p=reject`.
What these records do not do
They authenticate a domain. They do not authenticate a person, an intention or a claim. RFC 9989 is explicit that DMARC can only combat exact-domain spoofing, and in particular does not address "visually similar domain names" or abuse of the human-readable display name in the From header.
So a scammer registers something that reads like your company with an extra word in it, publishes flawless SPF, DKIM and DMARC on that domain, and sends an invoice from it. Every check passes, and every check is telling the truth: the message really did come from a server the domain's owner authorised. The domain simply is not yours, and no amount of authentication on your side prevents it. The same holds for a genuine account that has been compromised, which authenticates perfectly because it is genuine.
DKIM is narrower than it sounds too. RFC 6376 says that verifying the signature asserts the hashed content has not changed since it was signed, and asserts nothing else about protecting the end-to-end integrity of the message. It is a signature, not encryption, and the body stays readable to every machine that handles the message. Authentication raises the cost of pretending to be you. It does nothing about the more ordinary problem of your address being in circulation.
If you take one thing from this, take the shape of the failures. SPF fails when a new server starts sending, or when mail is forwarded. DKIM fails when something rewrites the message. DMARC fails when neither of the other two lines up with the name in the From field, which can happen while both are technically passing. Reading the reports for a month before tightening the policy costs nothing and avoids the only genuinely expensive mistake available here.