A DMARC record with a syntax error is ignored or only partly applied, so receivers may treat your domain as having no DMARC policy at all. Open the DMARC checker, read the red line, and match it to the list below. The most frequent causes are a missing p= tag, something before v=DMARC1, a comma where a semicolon belongs, a bad rua address, and two DMARC records on _dmarc.
A correct record for comparison:
_dmarc.example.com. 3600 IN TXT "v=DMARC1; p=none; rua=mailto:[email protected]"
Errors the checker reports
| Checker message | Cause | Fix |
|---|---|---|
| Record must start with “v=DMARC1” | Something precedes the version tag, it is misspelled, or the quotes were pasted into the value | Make v=DMARC1 the very first characters |
| Missing required “p=” policy tag | Policy omitted, or tags in the wrong order | Add p=none, p=quarantine or p=reject right after v |
| Invalid policy “p=…” | Typo such as p=rejected, p=quarentine, p=block | Use exactly none, quarantine or reject |
| Malformed tag ”…” | A piece without =, often from a wrong separator | Use tag=value; tag=value |
| Report URI must be mailto: | [email protected] without mailto: | Write rua=mailto:[email protected] |
| pct must be 0-100 | pct=105, pct=50% | Use an integer without the percent sign |
| adkim / aspf must be r or s | adkim=relaxed | Use the single letter r or s |
| fo must be 0, 1, d, s or a colon list | fo=1,d | Use fo=1:d |
The rules behind them
RFC 7489 §6.3 says the v tag is required and “MUST be the first tag in the list”; if its value does not match DMARC1 exactly, the entire record is ignored. The p tag follows it and is required for a policy record. A record that fails these rules does not just lose a tag: receivers discard the whole record (§6.6.3 step 2 discards records not starting with a v= tag that identifies DMARC).
Tags are separated by a semicolon with optional spaces around it (the ABNF in §6.4 allows whitespace on both sides). Commas, colons and plain spaces between tags do not work, although a comma is correct inside a tag whose value is a list, such as two rua addresses. A trailing semicolon is allowed.
Unknown tags are ignored (§6.3). So a misspelled optional tag such as rau= or pcts= produces no error from a receiver. It simply does nothing, and you lose reporting without noticing. Re-read tag names against the DMARC setup guide.
Report URIs
rua and ruf take a comma-separated list of URIs. Receivers must support mailto: (§6.2), so use it:
Wrong: [email protected]
Wrong: rua=mailto:[email protected]; mailto:[email protected]
Right: rua=mailto:[email protected],mailto:[email protected]
A size limit can follow an address after !, for example mailto:[email protected]!10m (§6.2). Without the mailto: prefix, or with a space in the list, the address is unusable. If the address belongs to a different domain, the other domain must publish an authorization record (§7.1), or reports will not arrive; see How to set up a DMARC record.
Multiple records
If a query for _dmarc.example.com returns more than one DMARC record, discovery ends and DMARC is not applied to the message (§6.6.3 step 5). This usually happens when a second service asks you to “add” a DMARC record and you do so instead of editing the existing one. Fix it by deleting all but one and merging the tags, typically your rua and its p value. Use the DNS lookup for TXT at _dmarc.example.com to see what is actually published; some DNS panels show records you cannot see in the registrar’s own interface.
Common typos
- Smart quotes or a stray quote copied from a document: the record then starts with
"and fails thev=DMARC1test. v=DMARC 1orv=dmarc1: the version value is compared as published; useDMARC1.- Record placed at
example.cominstead of_dmarc.example.com. - A TXT string split in the middle of a tag by hand. Panels join strings, but a space added at the split ends up inside the value.
p=none;;rua=...empty tags: remove the extra semicolon.
FAQ
Which part of the record is checked first?
The v=DMARC1 tag, because a mismatch there discards the entire record before any other tag is read.
The checker shows a warning, not an error. Is the record broken?
No. Warnings, for example pct below 100, describe policy choices rather than invalid syntax.
I fixed the record but the checker still shows the old one. Resolvers cache the answer for the TTL. Wait for it to expire, or compare several resolvers with the DNS lookup.
Sources
- RFC 7489, §6.3 General record format: https://www.rfc-editor.org/rfc/rfc7489#section-6.3
- RFC 7489, §6.2 DMARC URIs: https://www.rfc-editor.org/rfc/rfc7489#section-6.2
- RFC 7489, §6.4 Formal definition: https://www.rfc-editor.org/rfc/rfc7489#section-6.4
- RFC 7489, §6.6.3 Policy discovery: https://www.rfc-editor.org/rfc/rfc7489#section-6.6.3
- RFC 7489, §7.1 Verifying external destinations: https://www.rfc-editor.org/rfc/rfc7489#section-7.1