Free tool

DMARC Checker

Look up any domain's DMARC record, see what its policy really does, and find out what to change.

By Ahmet Karaca · Updated · Checked against RFC 9989 (DMARC, May 2026), RFC 9990 (DMARC aggregate reports), RFC 7489 (DMARC), Google's email sender guidelines, Yahoo Sender Hub best practices and Microsoft's Outlook.com requirements for high-volume senders on

What your DMARC record tells receivers

DMARC connects the two technical checks, SPF and DKIM, to the address people actually see in the From line. A message passes DMARC when at least one of them passes and is aligned with the From domain. Your record then tells receivers what to do with mail that fails, and where to send reports about it. What is DMARC? explains the whole decision step by step.

How a DMARC record is written

A DMARC record is a TXT record at _dmarc under the domain in your From address. It is a list of tag=value pairs separated by semicolons:

_dmarc.example.com.  TXT  "v=DMARC1; p=quarantine; rua=mailto:dmarc@example.com"

RFC 9989, which replaced RFC 7489 in May 2026, defines these tags. Tags it doesn't know are ignored.

TagMeaningIf left out
vVersion. Must be the first tag, and its value exactly DMARC1, or receivers ignore the whole record.Required
pPolicy for mail that fails: none, quarantine or reject.none if rua is valid, else no DMARC
spPolicy for existing subdomains that have no record of their own.Same as p
npPolicy for subdomains that don't exist in DNS. Part of the core standard since RFC 9989, which took it from RFC 9091.Same as sp, then p
tTesting. t=y asks receivers to apply one level less than the policy. New in RFC 9989.n
ruaWhere to send aggregate reports, as mailto: addresses separated by commas.No reports
rufWhere to send reports about single messages that failed.No reports
adkimDKIM alignment: r (relaxed) or s (strict).r
aspfSPF alignment: r (relaxed) or s (strict).r
foWhich failures trigger a ruf report. Ignored without ruf.0
psdy marks a public suffix, published by its operator; n marks the domain as the organizational domain for itself and its subdomains.u

RFC 9989 removed three tags. pct asked receivers to apply the policy to a share of failing mail; its job now belongs to t. rf, the format of failure reports, and ri, the interval between aggregate reports, are gone too. A record that still carries them keeps working, because receivers ignore tags they don't process.

What each part of the result means

  • Policy. The p= value with what it does: monitoring only, failing mail to spam, or failing mail blocked.
  • Enforcement. Whether receivers apply that policy today. Not enforced means p=none. Testing means t=y or pct=0, so receivers hold back. Enforced means the policy applies to all failing mail. A percentage appears only for an old record with a pct between 0 and 100.
  • Reports go to. How many rua addresses the record lists, and which ones. "Nobody" means you get no reports.
  • The record. The TXT record and the name it was found at. If that name is higher up the tree than the domain you entered, the domain has no record of its own and inherits that one. For an existing subdomain, receivers then take the policy from sp= when the record has one, not from p=. If receivers would ignore the record, because a tag is repeated, or its policy tag is missing or invalid and no valid rua= URI is listed, we show its text without the policy boxes.
  • Findings. Problems first, then warnings, then notes, many with a link to the fix. With no findings you see "No problems found".

Common errors and how to fix them

These are the findings the checker can report, with the message you see in the result. Domains and values below are examples. Mistakes in the record itself come first:

  • Problem: "example.com has no DMARC record. Anyone can send mail that claims to be from your domain." Publish a record at _dmarc, starting with p=none and a report address. The DMARC generator writes one.
  • Problem: "_dmarc.example.com has more than one DMARC record, so receivers ignore all of them." Keep one record and delete the rest. If a DNS host or email service created one for you, edit that record instead of adding another.
  • Problem: "A DMARC record must start with v=DMARC1." The version tag must come first, say exactly DMARC1 and be separated from the next tag by a semicolon, so receivers ignore records like v=dmarc1; p=reject or v=DMARC1 p=reject. We show this when the record at your _dmarc name looks like DMARC but its version tag is broken.
  • Problem: "'p reject' is not a valid tag=value pair." Separate tags with semicolons and give each one an equals sign.
  • Problem: "The 'rua' tag appears more than once. DMARC uses the DKIM tag syntax (RFC 6376 §3.2), where a repeated tag makes the whole record invalid, so receivers following it ignore the record." Until you fix it, your domain has no DMARC policy at all, and the checker shows the record without its policy boxes. Merge the values into one tag; several addresses go in one rua=, separated by commas.
  • Problem: "The record has no p= tag and no valid rua= URI, so receivers ignore it completely. Your domain has no DMARC protection or reporting." RFC 9989 tells receivers to skip DMARC for a record like this. Add p=none and a rua= address to start monitoring, or a stronger policy once your reports are clean.
  • Warning: "The record has no p= tag. Because its rua= tag holds a valid report URI, receivers treat it as p=none: they may send reports, but nothing is protected." Add p=none explicitly, then tighten it as your reports allow.
  • Problem: "p=rejected is not valid. Use none, quarantine or reject. Until you fix it, receivers treat the whole record as p=none." That is the message when rua= holds a valid report URI. Without one it ends "With no valid rua= URI either, receivers ignore the whole record.", because RFC 9989 then tells receivers to skip DMARC. The same rule applies to sp= and np=.
  • Problem: "pct=150 must be a whole number from 0 to 100." Better still, remove pct and use t=y while you test.
  • Problem: "adkim=relaxed must be r (relaxed) or s (strict)." Use the single letter, or leave the tag out for relaxed.
  • Problem: "'dmarc@example.com' in rua= is not a valid URI. Use a mailto: address." Each address needs the mailto: prefix. A mailto: URI whose address is broken gets its own message: "'mailto:dmarc@' in rua= is not a valid mailto: address, so no reports reach it."

These are about the policy and reports rather than syntax:

  • Warning: "p=none only monitors. Spoofed mail using your domain is still delivered." Fine while you collect reports; then move on. Moving from p=none to p=reject covers each stage.
  • Warning: "No rua= address, so you receive no reports about who sends mail as your domain." Add rua=mailto: with an address you read, or a monitoring service's address.
  • Warning: "Reports to reports.example.net may be dropped: it hasn't published authorization to receive reports for example.com." The receiving domain must publish example.com._report._dmarc.reports.example.net with v=DMARC1. Ask the service to add it, or check that you copied its address correctly.
  • Warning: "'https://reports.example.net/dmarc' in rua= is a valid URI, but most receivers only send reports to mailto: addresses, so it likely gets none." RFC 9989 allows any URI, but requires receivers that send reports to support only mailto: and to ignore schemes they don't support. Use a mailto: address.
  • Warning: "t=yes is not valid. Use t=y to test the policy or leave t out; receivers treat anything else as t=n and apply the policy." Write t=y exactly.
  • Warning: "psd=y declares example.com a public suffix, like a TLD registry. Receivers then treat the name one label below as the organizational domain, which changes alignment for its subdomains. Remove it unless you operate a public suffix." Delete psd=y. If you want a boundary inside your own DNS, psd=n is the value for that; the psd tag section explains both.
  • Warning: "psd=yes is not valid. Use y, n or u, or leave it out. Receivers fall back to psd=u." Most domains leave psd out entirely.
  • Warning: "fo=0:1 is not valid. Use 0, 1, d or s, joined with colons (for example fo=1:d), and not 0 and 1 together. Receivers fall back to fo=0." Separate values with colons, not commas. The fo tag section lists what each value asks for.
  • Warning: "'policy' is not a DMARC tag and will be ignored." Usually a typo for a real tag; compare it with the table above.
  • Note: "fo= only shapes failure reports, and the record has no ruf= address, so receivers ignore it. You can delete it." Keep fo only next to a ruf address you actually read.
  • Note: "Your policy is in testing mode: receivers are expected to treat it one level lower, so p=reject acts like quarantine and p=quarantine like none. Reports still arrive and show what enforcement would change." Remove t=y and pct=0 when the reports show every legitimate sender passing.
  • Note: "Receivers that still follow RFC 7489 don't know t=y and apply the full policy. Add pct=0 next to t=y so they hold back too." Publish t=y; pct=0 together during testing.
  • Note: "pct=50 asks receivers to apply the policy to part of your failing mail. RFC 9989 removed pct: receivers following it ignore the tag and apply the full policy, while older RFC 7489 receivers may still apply part. Use t=y while you test, then the full policy." Replace the partial pct with t=y, or remove it to enforce.
  • Note: "RFC 9989 removed the ri= tag, so it has no effect. You can delete it." The same note covers rf=.
  • Note: "Subdomains use a weaker policy (sp=none) than the main domain." Intended while subdomains are still being set up; raise sp when they are ready.
  • Note: "mail.example.com has no DMARC record of its own, so receivers use the one on example.com." Nothing to fix unless the subdomain needs a different policy; then publish a record at its own _dmarc.

And these mean DNS didn't give us a full answer:

  • Problem: "We couldn't query DNS for _dmarc.example.com. Try again in a minute." DNS failed before we found any record, so we can't say what applies. We don't keep this result.
  • Warning: "We couldn't finish the DMARC lookup at _dmarc.com, so the policy shown may not be the final one. Try again in a minute." We found a record, but a later query failed; a record at a shorter name could still change the outcome.
  • Warning: "We couldn't verify whether reports.example.net may receive your reports. Try again in a minute." The authorization lookup timed out or failed; it says nothing about the address itself.

How we check

We find the record the way RFC 9989 tells receivers to. First we ask for the TXT records at _dmarc under the domain you entered and keep only those whose first tag is v=DMARC1. If exactly one is left, that is the record. If more than one is left, receivers ignore them all, and so do we.

If the domain has no usable record of its own, we walk up the DNS tree: we remove the leftmost label and ask again, one level at a time, until a record with a psd= tag stops the walk or no labels remain. Finding a record doesn't end the walk, because a record at a shorter name can still change which domain counts as the organizational one. A walk makes at most 8 queries; for a name with more labels than that, the second query jumps straight to the last 7 labels. For news.mail.example.com it looks like this:

_dmarc.news.mail.example.com   no record
_dmarc.mail.example.com        no record
_dmarc.example.com             v=DMARC1; p=reject; sp=quarantine
_dmarc.com                     no record
→ example.com is the organizational domain; its sp=quarantine applies

From the records found, we pick the organizational domain using the rules in section 4.10.2 of the RFC: a psd=n record marks it, a psd=y record means the name one label below it, and otherwise it is the record with the fewest labels. The record that applies is the organizational domain's; only if that has none do we fall back to a public suffix's psd=y record. When the record comes from a name higher up the tree, the result says the domain inherits it.

One case gets special care. If no valid record exists but one of the names we asked has a record whose version tag is broken, such as v=dmarc1, we show that record with the version error instead of reporting "no DMARC record", because its owner clearly meant to publish one.

Report addresses

For each rua address on a different organizational domain from the record, we check that the receiving domain agreed to take your reports, as RFC 9990 requires: a TXT record at yourdomain._report._dmarc.theirdomain starting with v=DMARC1. We work out both organizational domains with the same tree walk. We look at up to 3 distinct report domains per record; one that shares your organizational domain needs no authorization.

DNS problems and timing

If DNS fails before any record is found, we say so rather than guess. If it fails after a record was found, we show that record with a warning that a shorter name we couldn't reach might have changed the outcome. A check has 10 seconds to finish. This public checker reads DNS through a caching resolver, and we reuse a finished result for 5 minutes unless something failed, so a record you just changed can take a few minutes, or until its TTL runs out, to show here.

What it doesn't check

  • Whether your mail passes DMARC. That depends on SPF and DKIM results for each message; the reports show it.
  • Your SPF and DKIM records, which have their own checkers, or all three together in the domain health check.
  • Whether report mailboxes accept mail; we only check that an outside domain authorized them.

The safe path to p=reject

Jumping straight to p=reject can block your own invoices or newsletters if a service you use isn't set up yet. Start with p=none and a report address, read the reports until every legitimate sender passes, then test quarantine with t=y before enforcing it, and do the same with reject. Moving from p=none to p=reject walks through every stage.

Need a record? Build one with the DMARC generator, or run a full domain health check to see SPF, DKIM and DMARC together.

Related tools and guides

Frequently asked questions

+What does a DMARC checker do?

It reads the TXT record published at _dmarc.yourdomain.com, parses each tag, and tells you whether receivers will actually enforce it. It also flags syntax mistakes, missing report addresses and report destinations that haven't authorized your domain.

+Is p=none enough to meet Google, Yahoo and Microsoft requirements?

For bulk senders the minimum requirement is a DMARC record, and p=none satisfies it. But p=none only monitors: spoofed mail using your domain is still delivered. Use it to collect reports, then move to quarantine and reject.

+Why does my subdomain show the DMARC record of my main domain?

If a subdomain has no DMARC record of its own, receivers use the record of its organizational domain, and for an existing subdomain the sp= tag, when present, decides the policy. The checker shows the name the record came from and says the subdomain inherits it.

+What does 'report destination not authorized' mean?

When DMARC reports go to a different organization's domain, that domain must publish a TXT record like yourdomain.com._report._dmarc.theirdomain.com containing v=DMARC1. RFC 9990 tells receivers to ignore a report address without it, so your reports never arrive.

+What is the difference between t=y and pct?

Both hold a policy back while you test. pct came from RFC 7489 and asked receivers to apply the policy to a share of failing mail; RFC 9989 removed it and added t=y, which asks receivers to apply one level less. Until every receiver follows RFC 9989, publish t=y; pct=0 together.

+I changed my record. Why does the checker still show the old one?

DNS answers are cached for the record's TTL, and we reuse a finished result for a few minutes. Wait a little and check again; if the old record persists for hours, look for a second copy of the record at your DNS host.

We use Google Analytics cookies only if you accept. Privacy policy