Many organisations publish a DMARC record and then leave it at p=none for years, so anyone can still send mail that claims to come from their domain. Reaching p=reject is mostly an inventory and ownership problem: finding every system and supplier that sends as you, making each one authenticate with an aligned identifier, then tightening policy without losing real mail. This guide covers SPF, DKIM and DMARC at record level, the changes in RFC 9989 (DMARC on the Standards Track since May 2026), aggregate reports, a phased rollout with rollback points, and the mailbox provider rules that make authentication a delivery requirement. It is for email administrators, DNS owners and security engineers. Gateways, filtering and transport security are covered in the Email Security Guide.
Key takeaways
- Alignment is the whole game. DMARC passes only when SPF or DKIM passes for a domain matching the visible From: domain, so a supplier passing SPF with its own bounce domain still fails DMARC for you.
- DKIM is the identifier to rely on. It survives forwarding where SPF breaks, and RFC 9989 says domains publishing p=reject must not rely on SPF alone.
- The pct tag is gone. RFC 9989 removed pct and added
t=y(test mode, apply one level lower) andnpfor non-existent subdomains, so staged rollouts need rethinking. - DKIM private keys are machine secrets. They need an owner, a store, rotation at least every six months (M3AAWG) and revocation when a supplier leaves.
- DMARC does not stop abuse of your own senders. A stolen email service API key sends mail that passes SPF, DKIM and DMARC, so sending credentials need the controls of any other non-human identity.
How SPF, DKIM and DMARC fit together
SPF (RFC 7208) authorises IP addresses for the envelope sender (RFC 5321 MAIL FROM, also called Return-Path). DKIM (RFC 6376) verifies a signature tied to the domain in the d= tag. Neither looks at the RFC 5322 From: header users see. DMARC asks whether at least one of them passed for a domain aligned with that header.
| Mechanism | Identifier checked | Published at | Survives forwarding? | Typical failure cause |
|---|---|---|---|---|
| SPF | Envelope from and HELO | TXT at the domain, v=spf1 ... | No: the forwarder's IP is not in your record | Missing sender, over 10 DNS-querying terms, two SPF records |
| DKIM | d= domain in DKIM-Signature | TXT at <selector>._domainkey.<domain> | Usually, unless body or signed headers change (list footers, subject tags) | Supplier signs with its own domain, key not published |
| DMARC | Header From, compared with SPF and DKIM domains | TXT at _dmarc.<domain> | Yes, if DKIM still verifies and aligns | Neither SPF nor DKIM aligned |
Alignment is set by aspf and adkim. Relaxed (r, the default) accepts the same organisational domain, so d=mail.example.com aligns with From: [email protected]. Strict (s) needs an exact match.
SPF: authorising senders within the 10-lookup limit
A minimal record: v=spf1 ip4:192.0.2.0/24 include:_spf.example.net ~all. Most production failures come from RFC 7208 section 4.6.4 and related rules:
- Ten DNS-querying terms:
include,a,mx,ptr,existsandredirectcount; "SPF implementations MUST limit the total number of those terms to 10", and exceeding it returns permerror. Nested includes count, so one supplier can use four or five.ip4,ip6andalldo not. - Void lookups: lookups returning no answer should be limited to two, so stale includes for retired services cause permerror.
- One record only: two
v=spf1records is a permerror, often caused by following a supplier's onboarding steps literally. - Size: the record "SHOULD remain small enough" to fit a 512-octet answer; under 450 octets ought to fit UDP.
- Hardfail versus softfail:
-allis "an explicit statement" that other hosts are unauthorised,~all"a weak statement". RFC 9989 section 7.1 warns that-allcan trigger SMTP-time rejection before DMARC runs, losing mail that would have passed on aligned DKIM. UK government guidance sets "a minimum soft fail (~all) qualifier".
Flattening versus delegation
Flattening replaces include terms with the IP ranges they resolve to. The risk is drift: when a supplier changes ranges, the flattened record silently stops matching, so regenerate it automatically and alert on change. The durable fix is a subdomain per high-volume supplier (news.example.com, billing.example.com) with its own SPF and DKIM. Relaxed alignment still works, each subdomain gets its own 10-lookup budget, and one supplier's reputation problem stays on its subdomain.
DKIM: selectors, key length and rotation
DKIM signs a body hash plus listed headers. "To support multiple concurrent public keys per signing domain, the key namespace is subdivided using "selectors"" (RFC 6376 section 3.1), which is what makes rotation and per-supplier keys possible.
| Decision | Minimum | Recommended practice | Source |
|---|---|---|---|
| Algorithm | rsa-sha256; rsa-sha1 must not be used | rsa-sha256; Ed25519 (RFC 8463) only as a second signature, since verifier support varies | RFC 8301, RFC 8463 |
| RSA key length | 1024 bits (Gmail and Yahoo minimum) | 2048 bits, split into 255-character TXT strings; 4096-bit keys may not fit a 512-byte UDP response | RFC 8301, Google, RFC 6376 |
| Rotation | Not set by the RFC | "at least every six months"; keep the old public key seven to 30 days, then publish an empty p= | M3AAWG |
| Selector naming | Any label | Stream and date, such as mkt-202610; "The reuse of selector names is strongly discouraged" | M3AAWG |
| Revocation | Empty p= "means that this public key has been revoked" | Revoke rather than delete the selector | RFC 6376, M3AAWG |
Rotation: publish the new public key under a new selector, switch signing, keep the old key published for seven to 30 days so mail in transit still verifies, then set the old selector to v=DKIM1; p=. For suppliers, M3AAWG describes delegating selectors by CNAME (key1, key2, key3) to records the supplier controls so it can rotate without DNS changes on your side. The cost is that the supplier holds your signing key.
DKIM replay
An IETF problem statement (an expired draft) defines it: "In a Replay Attack, a recipient of a DKIM-signed message re-posts the message to other recipients, while retaining the original, validating signature, and thereby leveraging the reputation of the original signer." RFC 6376 says x= "is not intended as an anti-replay defense". Mitigate on the sending side: stop platforms you control from signing arbitrary user-supplied content (free trials, open forms), sign and oversign From, To, Subject and Date, and keep streams on separate selectors so one can be revoked fast.
DMARC policy and alignment under RFC 9989
DMARC was first published in 2015 as RFC 7489, an Informational, Independent Submission. RFC 9989, a Proposed Standard published in May 2026, obsoletes RFC 7489 and RFC 9091; aggregate reporting moved to RFC 9990 and failure reporting to RFC 9991. A starting record is v=DMARC1; p=none; rua=mailto:[email protected].
| Tag | Meaning | Default if absent | Practical note |
|---|---|---|---|
p | none, quarantine or reject | none | Enforcement means any policy other than none |
sp | Existing subdomains | Inherits p | Set explicitly once the parent enforces |
np | Non-existent subdomains (new) | sp, else p | Set np=reject early: nothing legitimate sends from names that do not exist |
t | Test mode, y or n (new) | n | With t=y failing mail should get "one level below the specified policy" |
adkim, aspf | Alignment, r or s | r | Strict only where every sender uses the exact domain |
rua | Aggregate report URIs | No reports | Always set; external destinations need authorisation |
ruf, fo | Failure reports and options | None; fo=0 | Optional; may contain personal data |
psd | Public suffix domain flag (new) | u | For registries and large multi-tenant suffixes |
pct | Removed (RFC 7489 sampling percentage) | Unknown tags are ignored | Stage with t=y or per-subdomain policy |
RFC 9989 also finds the organisational domain with a DNS tree walk capped at eight queries rather than relying only on the Public Suffix List. Most domains resolve the same way, but deep or private suffix structures may not, so check the discovery_method field in reports.
Policy is a request. RFC 9989 section 5.4 says "Mail Receivers SHOULD NOT reject messages solely because of a published policy of "reject"", and section 7.4 says domains whose users post to mailing lists "SHOULD NOT publish Domain Owner Assessment Policies of "p=reject"". That is a real choice for organisations whose staff use open source or standards lists.
Reading aggregate and failure reports
Aggregate reports (RFC 9990) are XML, normally gzip-compressed, sent "daily (or more frequent)". Each record gives a source IP, message count, disposition, SPF and DKIM results and whether each aligned. If rua points outside your organisational domain, the receiver looks for a TXT record beginning v=DMARC1 at <your-domain>._report._dmarc.<destination-host>; without it reports are dropped. RFC 9990 warns reports can be forged and parsers face zip and XML bomb risks, so treat them as untrusted input.
- SPF pass, not aligned, no DKIM: a supplier using its own bounce domain. Enable DKIM with your domain or a custom return-path.
- DKIM pass with the supplier's
d=: the platform signs as itself. Configure custom DKIM before enforcement. - Aligned DKIM pass, SPF fail, unfamiliar IPs: usually forwarding or lists. DMARC still passes.
- Both fail from unknown IPs: spoofing or an unregistered shadow sender. Investigate before assuming either.
- Both fail from your own ranges: scanners, printers or applications sending direct to the internet.
Failure reports (RFC 9991) "may include PII and non-public information (NPI)", and "many large-scale providers limit or entirely disable the generation of failure reports". Send them to a restricted mailbox with a retention rule, and never plan a rollout around them.
Rolling out: from p=none to p=reject
RFC 9989 notes it "may take many months of consuming DMARC aggregate reports" to be ready, and suggests at least a month at none, then as long at quarantine. Lower TTLs on _dmarc records before each step so rollback is quick.
- Inventory every domain. Include subdomains with MX or A records and parked or defensive domains. Lock down non-sending domains at once with the record set in the Email Security Guide (SPF
-all, DMARC reject, empty DKIM key, null MX). - Publish monitoring records.
p=nonewithruaon every sending domain. Confirm reports arrive within 48 hours. - Build the sender register. From four to six weeks of reports and from finance, HR, marketing and IT, record each platform: owner, volume, SPF method, DKIM selector, return-path and contract owner.
- Fix each sender. Custom DKIM with your domain everywhere, bulk senders on subdomains, stale includes removed, SPF under 10 lookups. Retire senders nobody claims.
- Test quarantine. Publish
p=quarantine; t=y; np=reject; failing mail still gets none handling while reports show what quarantine would catch. After two to four clean weeks, removet=y. - Test reject. Publish
p=reject; t=y, which asks for quarantine. Watch help desk tickets and supplier bounces for two to four weeks, then removet=yand setsp=reject, giving any problem subdomain its own record at quarantine. - Hold the line. Make aligned DKIM a gate in supplier onboarding and review the register quarterly.
Rollback: step back one level (to p=reject; t=y or p=quarantine; t=y), fix the sender and repeat. Dropping to none removes protection from every other stream.
Choosing the right approach
| Decision | Option A | Option B | Choose B when |
|---|---|---|---|
| SPF ending | ~all | -all | The domain never sends mail |
| Alignment | Relaxed | Strict | A high-value domain (payments, executive mail) where every sender uses the exact domain |
| Supplier SPF | Include or flatten in the main record | Subdomain per supplier | More than three or four bulk suppliers, or close to 10 lookups |
| DKIM key custody | Supplier-held via CNAME | You generate and upload the key | The platform sends payment or security notices and you want rotation and revocation under your control |
| Corporate domain policy | p=reject | p=quarantine | Many staff post to mailing lists that break DKIM (RFC 9989 section 7.4) |
Small organisations with one mail platform and a few suppliers can reach reject in a quarter, using a report-processing service rather than parsing XML. Large organisations with hundreds of domains hit an ownership problem first: assign a DMARC owner per domain family and make suppliers prove aligned DKIM before go-live.
Mailbox provider requirements
Since February 2024, authentication has been a condition of bulk delivery to consumer mailboxes. The core rules confirmed on each provider's pages:
| Provider | Scope | Authentication | DMARC | If not met |
|---|---|---|---|---|
| Gmail | All senders from 1 February 2024; more rules above 5,000 messages a day to personal accounts | Bulk: SPF and DKIM; key 1024 bits or longer, 2048 recommended | Bulk: record required, may be p=none; From aligned with SPF or DKIM domain | Google says mail from senders your SPF does not cover is more likely to be marked as spam |
| Yahoo | Bulk senders (no volume figure published) | "Implement both SPF & DKIM" | "at least p=none - DMARC must pass"; aligned From | Enforcement rolled out through the first half of 2024 |
| Outlook.com, Hotmail, Live.com, MSN | "5,000 or more email messages" to Microsoft consumer services from one From domain | SPF and DKIM both pass | Published, and passing with SPF or DKIM aligned | Rejected with 550 5.7.515: "Access denied, sending domain <domain> does not meet the required authentication level." |
These are floors. A p=none record satisfies all three and stops no spoofing.
Beyond DMARC: ARC, BIMI, MTA-STS and TLS-RPT
- Authenticated Received Chain (ARC, RFC 8617, Experimental): intermediaries record the results they saw in ARC-Authentication-Results, ARC-Message-Signature and ARC-Seal headers, helping receivers accept forwarded mail that broke DKIM. But "ARC is not a trust framework", and recipients should "treat every Sealer of the ARC Chain with suspicion". Yahoo recommends ARC for forwarders; if your gateways modify mail, seal it and register the sealer as trusted on your mail platform.
- BIMI: shows a brand logo in supporting clients. The BIMI Group requires DMARC "at enforcement on the organizational domain and subdomains", a record such as
default._bimi TXT "v=BIMI1; l=https://example.com/logo.svg; a=", an SVG Tiny PS logo and, for most providers, a Verified Mark or Common Mark Certificate. It is a brand feature, but often the reason enforcement gets funded. - MTA-STS (RFC 8461) and TLS-RPT (RFC 8460): protect inbound mail in transit. MTA-STS serves a policy from
https://mta-sts.<domain>/.well-known/mta-sts.txt; TLS-RPT at_smtp._tlsreports failures. Start in testing mode. See the DNS Security Guide for protecting the zones these records live in.
Where identity fits: senders and keys are non-human identities
Every platform allowed to send as your domain holds a credential that makes its mail authentic: an SMTP relay password, an email service API key, an OAuth grant to send through Microsoft Graph or the Gmail API, or the DKIM private key itself. DMARC verifies the domain, not who used the credential.
- Register senders as NHIs: owner, purpose, selectors, API keys and review date for each platform. See the NHI Ownership Guide.
- Treat DKIM private keys as secrets: generate them in a key management service, restrict export, rotate and revoke on supplier exit. See the Cryptographic Key Management Guide.
- Scope and monitor sending API keys: send-only permissions, IP restrictions where offered, alerts on volume spikes and new sending identities. See the API Key Management Guide. The TruffleNet campaign used stolen AWS keys to abuse Amazon SES for business email compromise, and the Gravity SMTP vulnerability exposed email API keys on WordPress sites to mass scanners.
- Close the supplier exit: remove the SPF include, revoke the selector or CNAME and rotate shared credentials. See the Third-Party Access Guide.
Detection and measurement
Feed parsed aggregate reports into the SIEM and alert on new source IPs sending above a threshold as your domain, SPF permerror, DKIM failures on a known selector, and any change to _dmarc, _domainkey or SPF records outside change control. Metrics:
- Enforcement coverage: owned domains (sending and parked) at quarantine or reject with
spandnpset. - Aligned pass rate: legitimate volume passing DMARC, per sender.
- DKIM-aligned share: legitimate volume passing on aligned DKIM, since SPF-only streams break on forwarding.
- Unregistered senders: sources sending as your domain that are missing from the register, per month.
- Key hygiene: selectors older than six months or shorter than 2048 bits.
- SPF headroom: DNS-querying terms per domain against the limit of 10.
Framework mapping
| Framework | Reference | Coverage |
|---|---|---|
| CIS Controls v8.1 | Safeguard 9.5 Implement DMARC | DMARC with SPF and DKIM on all domains |
| NIST SP 800-53 Rev. 5 | SI-8 Spam Protection; SC-8 Transmission Confidentiality and Integrity; SC-12 Cryptographic Key Establishment and Management | Sender authentication, MTA-STS, DKIM key lifecycle |
| NIST CSF 2.0 | PR.DS-02 data in transit; DE.CM continuous monitoring | Transport protection, report monitoring |
| ISO/IEC 27001:2022 Annex A | 5.14 Information transfer; 8.24 Use of cryptography | Messaging rules, DKIM key management |
| MITRE ATT&CK | T1566 Phishing (Initial Access) | Removes exact-domain spoofing; does not address look-alike domains |
Common failure patterns
- Permanent p=none: the record exists, nobody reads the reports, and the domain stays spoofable. Mailbox provider rules are met, which removes the pressure to move on.
- SPF permerror from include sprawl: each supplier adds an include until the record passes 10 lookups and SPF fails for everyone. Stale flattened records fail the same way when a supplier changes IPs.
- Suppliers signing as themselves: a CRM or ticketing tool looks fine at p=none and is rejected the day you enforce. Reports show it weeks earlier if someone looks.
- Open subdomains and parked domains: the main domain rejects while
sp=noneor an unprotected owned look-alike is used instead. - Sending credentials treated as configuration: API keys in web plugins or code, never rotated. When the Mailchimp support tool was hijacked, customer data and API keys were exposed, and mail sent through a legitimate platform authenticates perfectly.
- Reports going nowhere:
ruato a processor without the_report._dmarcrecord, or to a retired service. The NCSC says "Mail Check and Web Check were retired on 31st March 2026", yet GOV.UK setup examples still show Mail Check addresses.
Practitioner checklist
- Lock down every non-sending domain with SPF
-all, DMARC reject, an empty DKIM key and null MX. - Publish DMARC with
ruaon every sending domain and confirm reports arrive, including the_report._dmarcrecord for external processors. - Build a sender register with an owner and credential record for each platform.
- Require aligned DKIM with your domain from every supplier before go-live; put bulk senders on subdomains.
- Keep SPF to one record, under 10 DNS-querying terms and 450 octets.
- Use 2048-bit RSA keys, dated selectors and rotation at least every six months; revoke with an empty
p=. - Replace
pctstaging witht=yand setnp=rejectearly. - Step through quarantine and reject with
t=ytests, lowered TTLs and a one-level rollback plan. - Alert on changes to SPF, DKIM and DMARC records and on unregistered sending sources.
- Scope, monitor and rotate email API keys and SMTP credentials as non-human identities.
Standards and references
- IETF: RFC 9989 Domain-Based Message Authentication, Reporting, and Conformance (DMARC)
- IETF: RFC 9990 DMARC Aggregate Reporting
- IETF: RFC 7208 Sender Policy Framework (SPF)
- IETF: RFC 6376 DomainKeys Identified Mail (DKIM) Signatures
- M3AAWG: DKIM Key Rotation Best Common Practices
- Google: Email sender guidelines
- Yahoo: Sender Best Practices
- Microsoft: Fix NDR error 550 5.7.515 in Outlook.com
Related NHI Mgmt Group resources: Email Security Guide · Phishing Guide · AiTM Phishing Guide · Email Identity and BEC Guide · DNS Security Guide