DMARC checker

Check a DMARC policy

See how a domain tells receivers to handle mail that fails authentication, and whether it's collecting the reports that show who sends as you.

A DMARC record is a DNS TXT record at _dmarc.yourdomain telling receivers what to do when a message fails both SPF and DKIM alignment: nothing, quarantine, or reject. It also nominates an address to receive aggregate reports, which are the only practical way to see who is sending as your domain.

How to read your result

The record is one line of tag-value pairs. The checker splits out the tags that change behaviour and ignores the ones that do not.

  • Published record. The raw value at _dmarc plus the domain. If it says inherited from another domain, this subdomain has no record of its own and is governed by its parent — which is usually fine, and occasionally a surprise.
  • p — the policy for the domain itself: none, quarantine or reject. This is the single most important value on the page.
  • sp — the policy for subdomains, when it differs from p. Absent means subdomains follow p.
  • pct — the percentage of failing mail the policy applies to. Anything under 100 means the policy is partially enforced.
  • alignmentrelaxed or strict, separately for SPF and DKIM. Explained below, because it is the part that trips people up.
  • rua — where aggregate reports go. none here means you have a policy and no visibility into whether it is hurting you.

Alignment is the part people miss

DMARC does not ask whether SPF or DKIM passed. It asks whether either passed for the domain the recipient can see — the one in the From: header. A message can pass SPF perfectly for a bulk sender's own domain and still fail DMARC, because that domain is not yours.

Relaxed alignment accepts a match at the organizational domain, so mail.example.com aligns with example.com. Strict requires an exact match. Relaxed is the sane default; strict breaks the moment a vendor signs with a subdomain you did not anticipate.

The policy ladder

p=none asks receivers to do nothing and send reports. It is a monitoring mode, not protection — a domain on p=none is exactly as spoofable as one with no DMARC at all. Its purpose is to tell you who sends as you before you start rejecting.

p=quarantine sends failing mail to spam. p=reject refuses it at the SMTP conversation, so it never reaches a folder. Reject is the goal, and moving there before you have read a few weeks of reports is how legitimate mail gets destroyed.

The five most common failures

Sitting on p=none forever

By far the most common state, and the most misleading: the record exists, the checker shows a policy, and nothing is actually protected. p=none is a stage, not a destination. If it has been there a year, the project stalled.

No rua address

Without a reporting address you are flying blind. Aggregate reports are the only mechanism that tells you which senders are failing alignment, and you need that list before enforcement is safe. A policy with no reports is a policy you cannot tighten with any confidence.

Using pct as a safety blanket

pct was designed for a gradual rollout, and it is often left at a low value permanently because it feels cautious. It is not caution, it is a coin flip: identical messages get different treatment. Use it to ramp, then remove it.

Forgetting sp on the parent domain

Subdomains inherit the parent's policy, which means an unused subdomain is covered — good — but also that a subdomain you do send from is governed by a policy written without it in mind. If your marketing platform sends from a subdomain, check it explicitly rather than assuming the parent's record fits.

The record at the wrong name

DMARC lives at _dmarc.example.com, not at example.com. A correct record published at the apex does nothing at all, and it is an easy mistake because SPF does live at the apex. If the checker reports nothing found, look there first.

What the reports actually contain

Aggregate reports arrive as compressed XML, once a day, from every receiver that processes your mail. Each one is a tally rather than a copy of anything: for a given source IP and a given sending domain, how many messages arrived, and whether SPF and DKIM aligned. No message content, no recipient addresses, no subject lines.

That structure is why they answer the one question you cannot otherwise answer — who is sending as your domain — and also why they are tedious to read by hand. A mid-sized domain generates dozens of files a day from a dozen providers, each with its own quirks, and the signal you want is a pattern across all of them rather than anything in one.

Two things to look for before you tighten a policy. First, sources you do not recognise that are passing alignment: those are usually a forgotten vendor, occasionally something worse. Second, sources you do recognise that are failing: those are the ones that break when you move to reject, and every one needs fixing or removing first.

If reading the XML yourself stops being practical, that is what our DMARC aggregation does — it collects the reports, groups them by sender, and shows which sources would be affected by a stricter policy.

A worked example

A domain at full enforcement, reporting to two addresses:

v=DMARC1; p=reject; sp=reject; adkim=r; aspf=r; pct=100; rua=mailto:[email protected]
  • v=DMARC1 — version; must be first.
  • p=reject — failing mail is refused outright.
  • sp=reject — stated explicitly rather than inherited, so intent is unambiguous.
  • adkim=r; aspf=r — relaxed alignment on both, so subdomain signing still aligns.
  • pct=100 — the whole stream, not a sample.
  • rua= — aggregate reports keep arriving after enforcement, which is how you catch a new sender breaking.

Related checks

  • SPF checker — one of the two mechanisms DMARC evaluates.
  • DKIM checker — the other, and the one that survives forwarding.
  • BIMI checker — requires DMARC at quarantine or reject before a logo displays.
  • TXT lookup — read the raw record, or check for a duplicate at the same name.
  • Full domain check — SPF, DKIM, DMARC and MX in one pass.

Every tag, with defaults and alignment examples →