| Tag | Value | Meaning |
|---|---|---|
| {{ row.tag }} | {{ row.value }} | {{ row.meaning }} |
| Check | Status | Notes |
|---|---|---|
| {{ row.label }} | {{ row.status }} | {{ row.note }} |
DMARC is the DNS policy layer that tells receiving mail systems what to do when messages claiming to come from your domain fail authentication alignment. It matters because spoofed mail is often a domain reputation problem before it is a mailbox problem, and a weak or incomplete policy can leave gaps even when SPF and DKIM exist on paper.
This validator reads the published _dmarc TXT record for a domain, parses the visible tag set, and turns the result into a summary you can inspect quickly. The package fits the common practical moment after a DNS change, a sender migration, or a report that a domain still appears to be running in monitor-only mode when the team thought enforcement was already active.
The first screen is not just raw DNS text. The summary box pulls out the requested policy, subdomain policy view, percentage, TTL, and lookup time, then the tabs split the result into a tag table, a package-specific checklist, a score gauge, and a JSON snapshot. That makes the page useful both for a fast human review and for a small evidence bundle you may want to copy into a ticket or handoff note.
The value of that workflow is clarity, not authority. DMARC itself is a published policy and reporting mechanism, not a guarantee that every message from the domain will land successfully. This tool likewise shows the published policy posture and compares it with its own stricter checklist; it does not test live mail flow, inspect SPF or DKIM on real messages, or predict inbox placement.
That boundary matters when the score looks lower than expected. A domain can be intentionally staged with p=none, partial rollout through pct, or inherited subdomain behavior while a deployment is still being cleaned up. The result is best treated as a configuration review and a conversation starter, not as the final word on whether the entire mail program is healthy.
The everyday workflow is simple. Enter the base domain, run the lookup, and read the published DMARC record as the package found it. If no record is returned, the tool stops there with an explicit error instead of inventing defaults. If a record is found, the page normalizes quoted TXT fragments, joins them into one string, and starts showing the policy in several different views.
The Tags tab is the best place to confirm what is actually published. It lists each parsed tag and value, and it renders reporting destinations from rua and ruf as clickable links when they use mailto:, http:, or https:. That is useful when the question is “what exactly is in DNS right now?” rather than “how strict is this record?”
The Validation Checks tab answers the second question. Instead of exposing only the final score, it shows which expectations passed and which failed, so you can tell the difference between a monitoring policy, a missing reporting address, relaxed alignment, or an omitted sp tag. Because the checks are visible line by line, the page is more useful than a single red-or-green headline.
The Score tab is the shortest summary. It compresses the checklist into a semicircular gauge and supports image or CSV export. That is convenient for status notes, but the gauge is still just a visualization of this package's own pass-count logic. If you need the raw data for another system, the JSON tab exposes the queried host name, lookup timing, record text, parsed tags, checks, and score in one structured block.
All four result views are export-friendly. The tag and check tables can be copied or downloaded as CSV or DOCX, the score chart can be saved as PNG, WebP, JPEG, or CSV, and the JSON block can be copied or downloaded directly. That makes the tool practical for small operational reviews where the next step is often a ticket, a change request, or a comparison after DNS propagation.
DMARC records are published as DNS TXT records at _dmarc.<domain>. The code sends a single DNS-over-HTTPS request to Cloudflare's resolver endpoint with the query name set to that host and the record type set to TXT. The response is measured for elapsed time in milliseconds, and the first answer's TTL is surfaced as the freshness cue in the summary box.
The parser is intentionally lightweight. It trims the record, joins quoted TXT fragments when a DNS answer is split across multiple strings, then breaks the result on semicolons and stores one value per tag. That works well for ordinary DMARC records and makes the result easy to read, but it is not a full RFC-grade linter for every malformed edge case or every advanced reporting nuance.
The package score is calculated from eleven checklist rows. Each passing row counts equally, and the total is rounded to the nearest whole percent. Higher scores therefore mean closer agreement with the opinionated profile embedded in this package, not with an official industry certification.
| Check | What counts as a pass here |
|---|---|
| Record present | The queried host returns record text. |
| Version tag | v is present and equals DMARC1. |
| Policy defined | p is present. |
| Enforcement posture | p is quarantine or reject. |
| Rollout percentage | pct is absent or equals 100. |
| Aggregate reporting | rua is present. |
| Failure reporting row | The row is displayed for ruf, but the implementation treats it as informational and does not lower the score when ruf is missing. |
| DKIM alignment | adkim=s. |
| SPF alignment | aspf=s. |
| Subdomain policy | sp is explicitly present. |
| Failure options | fo is present. |
That scoring model leads to a few important interpretation quirks. A record that uses p=none for observation, relaxed alignment, or staged rollout through pct will lose points even if that posture is deliberate. Likewise, the summary badge will display sp as the explicit value when present or echo p when it is absent, but the checklist still rewards only an explicit sp tag.
The input validator accepts ordinary ASCII-style domain labels, requires at least two labels, and rejects overly long names. Internationalized domains need to be entered in punycode form if you want them to match that pattern. URI rendering is similarly conservative: only mailto, http, and https are linkified, while other schemes stay as plain text.
From a privacy standpoint, the package is straightforward. The browser performs the live DNS query, and the page itself does not write cookies or local storage for the result. The exported CSV, DOCX, image, and JSON files are generated from the fetched record and the computed checklist already visible on the page.
_dmarc host for a TXT record.A high score usually means the domain is publishing a stricter DMARC posture: enforcement rather than observation, explicit reporting, explicit subdomain handling, and strict alignment settings. For many teams that is the desired destination, because DMARC was built to let receivers apply increasingly strict handling to mail that does not authenticate and align with the visible sender domain.
A middling score does not automatically mean the record is wrong. It often means the domain is still in transition. Common examples are p=none during initial monitoring, no sp tag because subdomains follow the organizational policy implicitly, or a deliberate pct rollout below 100 while a sender inventory is still being cleaned up.
A low score is the strongest signal that the published record is still very light on enforcement detail. Missing reporting addresses, relaxed alignment, or a missing fo tag will all pull the result down. That is useful when you are trying to harden a policy, but it should not be confused with proof that real mail is failing in production. The package never sees message headers, aligned identifiers, or receiver-specific delivery decisions.
TTL and lookup time help with timing, not correctness. TTL tells you how long a resolver may reasonably keep an answer cached, so it is the right clue when a recent DNS edit does not appear yet. Lookup time is just the elapsed request time for that fetch. It does not grade policy quality, and a fast response does not mean the record is strong.
Suppose the record is v=DMARC1; p=reject; pct=100; rua=mailto:dmarc@example.com; adkim=s; aspf=s; sp=reject; fo=1. In this package that passes every scoring row. The result is a 100% score, a green policy badge, explicit subdomain handling, and a checklist with no obvious hardening gaps left to investigate.
Now take v=DMARC1; p=none; rua=mailto:dmarc@example.com. The record is present, the version is valid, the base policy exists, and aggregate reporting is configured, but the package will still mark enforcement, strict alignment, explicit subdomain policy, and failure options as missing. The result is a lower score that reflects the package's hardening bias, even though p=none may be an intentional staging choice.
If a record omits sp, the summary badge will still display the main policy as the visible fallback for subdomains, because that is the effective view many readers expect. The checklist can still show Subdomain policy set as failed at the same time. That is not a contradiction in the code. It is the difference between showing the practical fallback and rewarding only an explicit sp tag in the score.
No. It reads the published DMARC policy record only. It does not inspect live message headers, SPF evaluations, DKIM signatures, or real receiver decisions.
p=none still be valid?Because p=none is commonly used during the monitoring phase of a rollout. The package scores it lower because the checklist prefers stronger enforcement, not because the syntax is automatically wrong.
sp even when my record does not contain it?The summary badge falls back to the main policy for readability. The validation row still checks whether sp was explicitly published.
Not usually. The implementation joins quoted TXT fragments into one string before it parses the tag list, which is how ordinary split DNS TXT answers are handled.
The record is fetched live in the browser and the page exposes export options for you to keep a copy. The package code itself does not use cookies or local storage for the lookup result.
psprua and ruf