Blog · Dmarc
How to Validate DMARC Record Syntax Before Publishing
A DMARC record that looks fine can still break your email. Copy a template, miss a semicolon, publish it, and three days later your marketing emails start bouncing. The fix is not complicated. The validation step is what most admins skip.
This guide covers how to check your DMARC record for syntax errors before it goes live. You will see which tools to use, what the commands do, and exactly what to fix when something is wrong.
Why DMARC Syntax Validation Matters
An invalid DMARC record does not produce a friendly error message. Receivers either ignore it silently or fall back to no DMARC protection. Your aggregate reports show nothing useful. Legitimate mail keeps flowing, or it does not, depending on receiver implementation. There is no DNS error for a bad DMARC record the way there is for a missing MX record.
The consequences of a bad publish include:
- Silent mail rejection at receivers that process your domain's mail
- Spurious DKIM and SPF failures in aggregate reports that are caused by syntax, not by actual authentication problems
- Total DMARC non-compliance at major receivers that cannot parse your record
Most of these cases are avoidable with ten minutes of validation before you publish.
What a DMARC Record Looks Like
A DMARC record is a single TXT record published at _dmarc.yourdomain.com. It uses tag=value pairs separated by semicolons. Here is the minimal valid record:
v=DMARC1; p=none;
Here is a fully configured record with the most common optional tags:
v=DMARC1; p=quarantine; rua=mailto:dmarc@example.com; ruf=mailto:dmarc@example.com; fo=1; pct=100; sp=quarantine; aspf=relaxed;
Each tag does something specific:
| Tag | Required | What it does |
|-----|----------|--------------|
| v | Yes | Protocol version. Must be DMARC1. Must appear first. |
| p | Yes | Policy. none, quarantine, or reject. |
| rua | No | Aggregate report destination (email address). |
| ruf | No | Forensic report destination (email address). |
| fo | No | Forensic report options. Default is 0 (only report failures). 1 reports everything. |
| pct | No | Percentage of mail subject to the policy. Range 0-100. Default is 100. |
| sp | No | Subdomain policy. Inherits from p if omitted. |
| aspf | No | SPF alignment mode. relaxed (default) or strict. |
| adkim | No | DKIM alignment mode. relaxed (default) or strict. |
A valid record needs v=DMARC1 and p= at minimum. Everything else is optional. But each omission changes behaviour. Know what you are leaving out.
Common Syntax Errors and How to Spot Them
These are the mistakes that appear most often in published DMARC records:
Duplicate tags. Some DNS providers append values rather than replace them. Two p= lines means the second one wins, silently. If you switched from p=none to p=reject without changing anything, check for a duplicate.
Wrong policy value. p=disabled, p=off, and p=no are not valid. The only accepted values are none, quarantine, and reject. Any other value is ignored.
Missing or misplaced v=DMARC1. This tag must be first. If you paste a record starting with p=none; v=DMARC1;, receivers may parse it as v=none and reject the entire record.
Publishing at the wrong name. The record belongs at _dmarc.example.com, not example.com. Many administrators confuse the two. The underscore is required.
Non-TXT record type. DMARC must be a TXT record. Publishing it as an A, AAAA, or CNAME record means receivers cannot find it.
pct values outside 0-100. A record with pct=150 or pct=-1 is silently ignored by most receivers.
Unknown tags. Tags not in RFC 7489 are ignored. This is not catastrophic but may indicate a copy-paste error from a misinformed guide.
Spaces in mailto URIs. rua=mailto: dmarc@example.com (space after the colon) is a malformed URI. Special characters in mailto addresses should be percent-encoded or removed.
How to Validate Using Online Tools
Two free tools handle this well.
MXToolbox DMARC Lookup (mxtoolbox.com)
Enter your domain prefixed with _dmarc. (for example, _dmarc.example.com). The tool resolves the TXT record and shows a parsed breakdown of every tag it finds. If anything is wrong, it flags the specific tag and explains the issue.
Google Admin Toolbox (toolbox.googleapps.com)
Enter the full _dmarc.example.com domain. Google resolves it against their DNS infrastructure and shows what a receiver would see. This is useful because it shows what Google's mail servers would actually process.
Both tools show the raw TXT value and the parsed version side by side. Check the parsed version against the tag table above. If any tag is missing, unexpected, or flagged, investigate before publishing.
A third option is DMARCLY (dmarcly.com), which validates the record and also shows what your aggregate reports would look like once the record is live.
How to Validate Using DNS Lookup Commands
If you prefer the terminal, resolve the record directly:
bash
dig TXT _dmarc.example.com +short
bash
host -t TXT _dmarc.example.com
bash
nslookup -type=TXT _dmarc.example.com
Each command returns the raw TXT value. An empty result means the record does not exist at that name.
Once you have the raw TXT string, feed it to MXToolbox or DMARCLY's raw record parser. Paste the string and see which tags are detected.
For example, if dig returns:
"v=DMARC1; p=quarantine; rua=mailto:dmarc-reports@example.com"
A parser shows this as valid: v and p are correct, rua is present and syntactically sound. If you see a tag missing from the parsed output, check your spelling.
What to Do If Your Record Is Invalid
Record not found. Confirm you are querying _dmarc.yourdomain.com with the underscore. If that returns empty, check your DNS provider interface for the correct subdomain. Some providers use a different UI label for subdomain records.
Duplicate tags. Remove the duplicate line from your DNS record. Keep the value you actually want applied.
Invalid or unknown tags. Remove unknown tags. Cross-reference remaining tags against RFC 7489. If a tag value looks wrong, check the allowed values in the tag table above.
pct out of range. Remove the pct tag entirely to use the default of 100, or set it to an integer between 0 and 100.
Using aspf=strict. Before using strict SPF alignment, confirm every legitimate sending source for your domain passes SPF under a domain-aligned envelope-from. Most organisations use relaxed (the default). Switching to strict without a full audit will break legitimate mail.
Syntax is fine but mail still fails. A valid record that specifies p=reject will reject mail from any source that fails SPF or DKIM alignment. That is correct behaviour. If you are seeing unexpected rejections after publishing a valid record, the issue is alignment, not syntax. Parse your aggregate reports to see which IPs are failing. This is also where ongoing monitoring matters: DMARCFlow parses those aggregate reports automatically, so you can spot alignment failures within hours rather than waiting for manual review.
Frequently Asked Questions
Does DMARC have to be a TXT record?
Yes. All current receivers look for a TXT record at _dmarc.yourdomain.com. While RFC 9091 defined a separate DMARC DNS record type, receiver adoption is not universal. Publishing as TXT is the safe choice.
Can I have multiple DMARC records for the same domain?
No. RFC 7489 specifies exactly one DMARC record per domain. Multiple records produce undefined behaviour. Some receivers ignore all of them, some process the first, some process the last. None of these outcomes are predictable.
What happens if my DMARC record has a syntax error?
Most receivers ignore the malformed record entirely and apply no DMARC protection. Your mail flows as if DMARC were not published. Your aggregate reports may show parsing errors or stop arriving. There is no DNS error. The record just silently does nothing.
Should I publish DMARC before SPF and DKIM are configured?
Yes. Starting with p=none while you configure SPF and DKIM is the correct approach. Collect aggregate reports, confirm your legitimate sending sources pass alignment, then move to p=quarantine or p=reject on your own timeline. Just validate the syntax before you publish the initial p=none record.
TL;DR Syntax Checklist
Before you publish any DMARC record, run through each of these:
- [ ] Record is a TXT record at
_dmarc.yourdomain.com(with underscore) - [ ]
v=DMARC1is the first tag in the record - [ ]
p=has one of three values:none,quarantine, orreject - [ ]
pct=(if present) is an integer from 0 to 100 - [ ] No duplicate tag names
- [ ] No unknown tag names
- [ ]
ruaandrufmailto addresses are correctly formatted - [ ]
aspf=andadkim=(if present) are set torelaxedorstrict
Run your record through MXToolbox or Google Admin Toolbox before publishing. Fix what they flag. Then monitor your aggregate reports within 48 hours of going live.
Once your record is validated and published, ongoing monitoring ensures it stays correct. DMARCFlow watches your deployed DMARC record and alerts you when DNS changes affect your email authentication configuration, so a syntax problem or accidental removal does not catch you off guard.