DMARC Checker: How to Read, Test, and Fix Your DMARC Record

DMARC is the policy layer that sits on top of SPF and DKIM. Without it, those two checks produce results that no one acts on. With it, you tell every receiving mail server exactly what to do when a message claims to be from your domain but fails authentication.

This page explains how DMARC works, how to read what your record actually says, and how to move from the default p=none (monitoring only) to real enforcement.


What DMARC Is — and What It Actually Does

SPF and DKIM are authentication mechanisms. SPF checks whether the sending server is authorized for your domain. DKIM checks whether the message was signed by a key published in your DNS. Both are useful. Neither, on its own, tells a receiving server what to do when a check fails.

DMARC is the policy record that answers that question.

You publish it as a DNS TXT record at _dmarc.yourdomain.com. A minimal record looks like:

v=DMARC1; p=none; rua=mailto:dmarc-reports@yourdomain.com

When a message arrives claiming to be from your domain, the receiving server looks up that record and applies the policy in p=.

The alignment requirement — why DMARC can fail even when SPF and DKIM pass

DMARC does not just check whether SPF or DKIM passed. It checks whether a passing result is aligned with the domain in the visible From: header — the address your recipient actually sees.

  • Relaxed alignment (the default): The organizational domain must match. mail.example.com aligns with example.com.
  • Strict alignment: The domains must match exactly. mail.example.com does not align with example.com under strict.

A message can pass raw SPF and DKIM and still fail DMARC if neither passing result aligns with the From: domain. This is the most common source of unexpected DMARC failures from legitimate senders like ESPs and CRMs.


How to Read Your DMARC Record

A full DMARC record looks like this:

v=DMARC1; p=quarantine; sp=none; pct=25; rua=mailto:agg@yourdomain.com; ruf=mailto:forensic@yourdomain.com; adkim=r; aspf=r

Here is what each tag means:

Tag What it does
v=DMARC1 Required. Identifies this as a DMARC record.
p= The policy for the domain. See the next section.
sp= A separate policy for subdomains. If omitted, p= applies to subdomains too.
pct= The percentage of failing mail the policy applies to (1–100). Useful during rollout. Defaults to 100.
rua= Where to send aggregate (daily summary) reports.
ruf= Where to send forensic (per-message failure) reports. Less widely sent due to privacy concerns; often omitted.
adkim= DKIM alignment mode: r (relaxed, default) or s (strict).
aspf= SPF alignment mode: r (relaxed, default) or s (strict).

If your record has no rua= tag, you have no visibility into who is sending mail as your domain — legitimate or otherwise. You cannot safely tighten policy without that data.


The Policy Ladder: p=none → p=quarantine → p=reject

The p= tag is the heart of DMARC. It has three possible values, and they are not interchangeable.

p=none — Monitoring only. No enforcement.

Failing mail is still delivered normally, straight to the inbox. Nothing is blocked, nothing is flagged. You receive reports (if rua= is set), but the receiving server takes no action based on DMARC.

p=none is the right starting point. It is not protection. Most domains stall here indefinitely because moving feels risky — but staying here means the policy does nothing at enforcement time.

p=quarantine — Failing mail goes to spam/junk

The receiving server routes mail that fails DMARC authentication to the spam or junk folder instead of the inbox. Some servers may flag it instead. Mail is not lost, but it is treated with suspicion.

This is the right intermediate step. It surfaces problems (your recipients or their mail admins notice quarantined legitimate mail) without causing outright delivery failures.

p=reject — Failing mail is blocked outright

The receiving server refuses the message at the SMTP level. It does not reach the inbox, and it does not reach junk. This is full enforcement.

p=reject is the goal for any domain that sends mail. It is also the policy that Gmail and Yahoo now require for bulk senders as part of their 2024–2025 enforcement updates — misconfigured email auth now results in permanent 5xx rejections for qualifying senders, not temporary delays.


How to Fix p=none: The Safe Path to p=reject

Moving from p=none to p=reject takes time if you do it correctly. Skipping steps causes legitimate mail to be blocked.

Step 1: Fix SPF and DKIM first. Confirm that every system sending mail as your domain — your mail server, your CRM, your ESP, your support platform — has a valid SPF authorization and a working DKIM signature, and that both align with your From: domain. Do not move forward until legitimate mail is passing and aligning.

Step 2: Add rua= and collect aggregate reports. Publish a record with p=none and a valid rua= address. Watch the daily XML reports for two to four weeks. You are looking for: all known senders passing, no unexpected sources showing up at volume. These reports are the evidence base for the next step.

Step 3: Move to p=quarantine, optionally with pct=. Change p=none to p=quarantine. If you are cautious, add pct=25 to apply the quarantine policy to only 25% of failing mail while you continue watching reports. Ramp pct= upward as confidence grows.

Step 4: Move to p=reject. Once aggregate reports show no legitimate mail failing DMARC, remove pct= (or set it to 100) and change the policy to p=reject. Failing mail is now blocked at the server.

A practical record at the p=quarantine ramp stage:

v=DMARC1; p=quarantine; pct=25; rua=mailto:dmarc-reports@yourdomain.com

A final record at full enforcement:

v=DMARC1; p=reject; rua=mailto:dmarc-reports@yourdomain.com

What Lumira's DMARC Check Returns

Lumira's email-authentication API checks your DMARC record on demand. For the DMARC component, the response surfaces:

  • policy — the value of p= (none, quarantine, or reject)
  • subdomain_policy — the value of sp=, if set
  • pct — the percentage the policy applies to
  • rua — the list of aggregate report destinations
  • record — the raw TXT record as published in DNS
  • A letter grade (A–F) — based on the combination of policy, alignment configuration, and reporting setup

The engine flags p=none as monitoring-only (not enforcement) and flags a missing rua= as a visibility gap. See the real API response example below this section for what the output looks like against a live domain.

How to call the API

GET https://api.lumirallc.com/v1/email-auth/{your-domain}

Include your API key in the request header:

X-API-Key: your-key-here

or

Authorization: Bearer your-key-here

Replace {your-domain} with your actual domain — for example, example.com. No request body. The domain goes in the URL path.

[PLACEHOLDER: lumirallc.com/check — public one-click scanner not yet live.] A no-signup web version is coming soon. For now, the API is the way to check your domain.

Continuous monitoring and change alerts — watching your DMARC record over time and notifying you when it changes — are coming soon. The live product today is the on-demand API check described above.


FAQ

Is p=none safe to leave permanently?

No — but it is not dangerous in the way that p=reject with broken SPF/DKIM is dangerous. p=none means the DMARC record exists and is collecting reports, but the receiving server takes no enforcement action. Failing mail is delivered normally. It is the right place to start; it is not a destination.

What does p=reject actually do?

When a message claiming to be from your domain fails DMARC authentication — meaning neither SPF nor DKIM passes in alignment with your From: domain — the receiving server refuses the message at the SMTP level. A 5xx rejection code is issued. The message is not delivered. This applies to all mail that fails, including misconfigured legitimate senders if you move to p=reject before your setup is clean.

What is the difference between rua and ruf?

rua= receives aggregate reports: daily XML summaries listing every source that sent mail as your domain, and whether it passed or failed. These are the reports you read to understand your sending ecosystem before tightening policy.

ruf= receives forensic reports: samples of individual messages that failed, intended to help diagnose specific failures. Forensic reports are less widely sent by receiving mail servers — many providers do not send them at all due to privacy concerns. Omitting ruf= is common and usually fine; rua= is the essential one.

Can DMARC fail even if SPF and DKIM both pass?

Yes. DMARC requires that a passing SPF or DKIM result is aligned with the domain in the From: header. A service that passes SPF for its own domain (sendgrid.net) but sends mail with your From: address (yourcompany.com) will fail DMARC alignment unless you have authorized it correctly — typically by configuring a custom domain in the ESP so DKIM signs under your domain.


Check Your DMARC Record

The Lumira email-authentication API checks your DMARC record — policy, alignment settings, reporting configuration, and grade — against your live DNS, on demand.

GET https://api.lumirallc.com/v1/email-auth/{your-domain}

Get an API key at lumirallc.com and run your first check in under a minute. No agents to install, no subscription required to start.

[PLACEHOLDER: lumirallc.com/check — public one-click scanner coming soon] for a no-code version.

A real DMARC result (captured live, not hand-written)

This is the dmarc section of a real /v1/email-auth/google.com response — a domain at the DMARC goal state: a reject policy with aggregate (rua) reporting (DMARC check score 100/100):

{
  "check": "dmarc",
  "title": "DMARC",
  "severity": "ok",
  "score": 100,
  "summary": "DMARC is published and enforced with a reject policy.",
  "findings": [],
  "data": {
    "record": "v=DMARC1; p=reject; rua=mailto:mailauth-reports@google.com",
    "policy": "reject",
    "subdomain_policy": null,
    "pct": 100,
    "rua": [
      "mailto:mailauth-reports@google.com"
    ]
  },
  "provider": null,
  "latency_ms": 109.5
}

Get your domain's real DMARC grade

Lumira's API returns it with the findings behind it.

Request API access