SPF, DKIM, DMARC and ARC
DMARC explained
DMARC is the check that links authentication to the visible From domain. The record and its tags, how receivers evaluate and apply it, the five results, and what a fail under p=none means for you.
DMARC (Domain-based Message Authentication, Reporting and Conformance) is the check that connects email authentication to the domain in the From: line you actually see. SPF and DKIM can both pass for domains that have nothing to do with the visible sender. DMARC passes only when at least one of them passes for a domain that matches the From domain. The domain owner also publishes a policy saying what receivers should do with mail that fails: nothing, treat it as suspicious, or refuse it.
In the RFC: DMARC was first published in 2015 as RFC 7489, an Informational document. In May 2026 the IETF published the revised standard (the work known as DMARCbis) as RFC 9989, which obsoletes RFC 7489, with reporting split into RFC 9990 (aggregate) and RFC 9991 (failure). This page follows RFC 9989 and notes where older software still behaves the RFC 7489 way.
The DMARC record
A domain opts in by publishing a TXT record at _dmarc. plus the domain:
_dmarc.example.com. TXT "v=DMARC1; p=quarantine; sp=reject; adkim=r; aspf=r; rua=mailto:dmarc-reports@example.com"
The tags you are likely to meet (RFC 9989 §4.7):
| Tag | Meaning |
|---|---|
v=DMARC1 |
Required, must come first. |
p= |
Policy for the domain: none, quarantine or reject. |
sp= |
Policy for existing subdomains, if different from p. |
np= |
Policy for subdomains that do not exist at all (new in RFC 9989). |
adkim=, aspf= |
Alignment mode for DKIM and SPF: r relaxed (default) or s strict. |
rua= |
Where to send daily aggregate reports (counts by source IP and result). |
ruf= |
Where to send per-message failure reports; many large receivers do not send these. |
t= |
Test mode: t=y asks receivers to apply one level less than the stated policy. |
psd= |
Marks a public suffix domain; used by registries, not ordinary senders. |
You will still see pct= in a lot of records. It came from RFC 7489 §6.3 and asked receivers to apply the policy to only a percentage of failing mail. RFC 9989 removed it because, in practice, only 0 and 100 were applied consistently; t=y replaces the pct=0 use (RFC 9989 Appendix A.6). Receivers running older software may still honor pct.
The three policies
p=noneis monitoring mode. The owner asks for reports and expresses no handling preference. RFC 9989 §5.4 says anonepolicy must not change how the receiver would otherwise handle the message.p=quarantinesays failing mail is suspicious. In practice that usually means the spam or junk folder.p=rejectsays failing mail is not legitimate use of the domain. Receivers that honor it usually refuse the message during the SMTP conversation, so it never reaches any folder and the sender gets a bounce.
The policy is found by looking first at _dmarc.<From domain>, then, if nothing is there, walking up towards the organizational domain (RFC 9989 §4.10.1). That is why sp= matters: mail from news.example.com with no record of its own is governed by example.com's record.
How a receiver evaluates a message
The steps in RFC 9989 §5.3, in plain terms:
- Take the domain from the
From:header. If there is none, or several, DMARC cannot run normally. - Find the DMARC record. No record means result
none, and DMARC stops. - Run SPF on the envelope sender and verify every DKIM signature, noting the domain each one covers.
- Check whether any passing identifier is aligned with the From domain, strictly or relaxed as the record says. The details are in DMARC alignment.
- One aligned pass is enough for DMARC to pass. Otherwise it fails.
- Apply local policy, taking the domain's requested policy into account.
The five results
These are the values that appear as dmarc= in Authentication-Results, as registered in RFC 9989 §9.2:
| Result | Meaning |
|---|---|
| pass | A record exists and an aligned SPF or DKIM pass exists. |
| fail | A record exists but nothing aligned passed. |
| none | The From domain publishes no DMARC record. |
| temperror | A transient error, typically DNS, stopped evaluation. |
| permerror | A permanent error, such as a malformed record. |
Receivers often add the policy they found and what they did with it:
Authentication-Results: mx.example.net;
dkim=pass header.d=mailer.example.org;
spf=pass smtp.mailfrom=bounces.example.org;
dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=example.com
The format of that parenthetical varies by provider. Some write p=REJECT dis=NONE, meaning the domain asked for rejection but the receiver delivered anyway.
Receivers can override the policy
The domain's policy is a request. RFC 9989 §5.4 says final handling is always the receiver's decision. A receiver may reject or quarantine mail that passes DMARC, because a pass says nothing about whether the mail is wanted. It may also accept mail that fails under p=reject, and the RFC says receivers should not reject on a reject policy alone, because legitimate forwarded and mailing-list mail often fails. When a receiver overrides, it should still record the result in Authentication-Results and report the override back to the domain owner. A common reason for an override is a trusted ARC chain showing the message passed before a mailing list modified it.
What dmarc=fail with p=none means for you
This combination is common and easy to misread. It means:
- The message's authentication did not connect to the From domain.
- The domain owner has asked receivers not to act on that, so your provider delivered it normally.
Possible explanations, roughly from most to least common: the domain is still rolling out DMARC and some legitimate service (a CRM, a ticketing tool) sends unaligned mail; the message went through a forwarder or mailing list that broke DKIM; or someone is spoofing a domain that has not enforced DMARC yet. The headers alone cannot tell the first and last apart for certain. Look at who actually signed (header.d) and sent (smtp.mailfrom), whether they are services you would expect, and the other signals in our phishing checklist.
A dmarc=pass is the strongest header evidence you get that the visible From domain authorized the message. It still says nothing about whether the sender is honest. A scammer who owns example-billing.example can pass DMARC for that domain. Check the domain itself with the look-alike domains guide.
To see all of this for a real message, paste its headers into the analyser. It shows the dmarc result your provider recorded, the policy if the receiver noted it, and which SPF and DKIM domains did or did not align.
Got a suspicious email?
Paste its headers into the analyser. It runs on your device and explains every result on this page.
Open the analyser