Skip to content
praneeth.me

praneeth@website:~$ dmarc --check

DMARC rollout plan and record checker

That record is where you are heading — full protection against anyone sending mail as your domain. Publishing it today would bounce your own invoices. Below is the staged route there, where every step that can affect real mail comes after one that cannot.

checked against
RFC 9989
stages
7
typical duration
2–4 months
what we collect
nothing

Nothing you type or paste is ever sent to this site — there is no server involved and no analytics. Looking up a domain is the one exception: that query goes straight from your browser to a public DNS resolver, asking the same public question any mail server does, and only when you press the button.

  1. 0 audit
  2. 1 monitor
  3. 2 fix
  4. 3 quarantine
  5. 4 reject

Before you start. This is a staged plan, not a checklist to do in one sitting. Getting from nothing to full protection normally takes months, and every stage that can affect real mail is deliberately preceded by one that cannot. Read the whole thing before publishing anything.

Phase 0 — Where are you now?

What this is. Find out what your domain already says before changing anything. Most domains have something — often set years ago by someone who has left, or added automatically by a mail provider.

What you do. Look up your domain, or paste a record you already have. Either way it is checked against RFC 9989 right here.

Prefer to look it up yourself
dig +short TXT _dmarc.yourdomain.com

  # Windows
  nslookup -type=TXT _dmarc.yourdomain.com

No record change in this phase.

Before moving on. You can state what your domain currently does with failing mail: nothing, quarantine, or reject. If the record contains pct=, rf= or ri=, note them — they were removed from the spec and no longer do anything.

Phase 1 — Start watching, and close the doors that don't exist

What this is. Two things, neither of which can break your mail.

The first is asking mail providers to report to you — a daily summary of who is sending as your domain, including senders you have forgotten and anyone impersonating you. Nothing about how your mail is treated changes.

The second is shutting down subdomains that do not exist. If payroll.yourdomain.com has never existed, nothing legitimate can come from it — a name with no DNS record cannot have SPF or DKIM. Technically these are names that return NXDOMAIN: the DNS answer meaning "no such name". Phishing uses invented subdomains precisely because they have historically been unprotected. This is the safest change in the whole process, which is why it happens now rather than at the end.

v=DMARC1; p=none; np=reject; rua=mailto:[email protected]
tag what it does
p=none don't change how my mail is treated
np=reject reject mail claiming to come from subdomains that don't exist in DNS (names returning NXDOMAIN)
rua= send daily summary reports here

Existing subdomains are untouched. sp= stays out of the record entirely. Subdomains that do exist follow p=none and are left alone until reports show what actually sends from them.

What you do

  1. Decide where reports go. Two paths:
    • A reporting service (most people). They give you an address for rua= and handle the rest — follow their setup steps, not ours. dmarcian, Postmark DMARC and URIports all have free tiers that suit a single domain. Listed because “use a service” is useless advice on its own — not as endorsements, and none is affiliated with this site.
    • Your own mailbox. You will get XML attachments daily from dozens of providers. Workable for one domain with light mail; unreadable at volume.
  2. Publish as a TXT record at _dmarc.yourdomain.com.
  3. Wait and read.

Before moving on.

  • Reports are actually arriving.
  • You can name every legitimate system sending as you — not just your mail provider, but the invoicing system, the CRM, monitoring alerts, the marketing platform, the printer.
  • At least 2–4 weeks, and one full billing cycle. If you bill monthly and skip this, you will discover your invoices were failing on the day you start rejecting mail.
Reports aren't arriving

Give it a week. Some providers send once a day; a few take longer to start.

Check the obvious first. The record must be at _dmarc.yourdomain.com, not on the domain itself. A typo in rua= fails silently.

If you're using a reporting service and still see nothing, ask them — they publish the authorisation record on their side and can confirm it is in place.

If you pointed rua= at an address on a different domain yourself — a personal address, or a mailbox on another domain you own — that domain has to grant permission. Nothing tells you it is missing; providers simply don't send:

yourdomain.com._report._dmarc.otherdomain.com TXT "v=DMARC1"

Not needed when rua= points at the same domain you are protecting.

Phase 2 — Fix what's failing

What this is. Reports now show legitimate senders failing. This phase fixes them. Your DMARC record doesn't change — you stay in watch-only mode while the real work happens elsewhere. This is usually the longest phase, and the record sits still throughout.

unchanged from Phase 1
v=DMARC1; p=none; np=reject; rua=mailto:[email protected]

What you do. For each failing sender, get SPF or DKIM passing and aligned. Aligned means the domain that authenticated matches the domain in the From: address. A sender can pass SPF and still fail DMARC by passing for the wrong domain — the most common source of confusion here.

You only need one of them

DMARC passes if SPF passes and aligns, or DKIM passes and aligns. Both is not required.

SPF DKIM DMARC
pass, alignedfail pass
failpass, aligned pass
pass, not alignedfail fail
pass, not aligned pass, not alignedfail

Chase DKIM first. When mail is forwarded, SPF breaks — the forwarding server isn't in your SPF record, and nothing you publish fixes that. DKIM survives forwarding. A sender passing only SPF will fail intermittently in ways you can't resolve, so DKIM is where limited vendor-wrangling time is best spent. Keep SPF correct too; just don't rely on it alone.

Optional, for diagnosis

v=DMARC1; p=none; np=reject; rua=mailto:[email protected]; ruf=mailto:[email protected]; fo=1

ruf= requests individual failure reports; fo=1 asks for one whenever either check fails rather than only when both do. These can contain message headers and sometimes body content belonging to other people, and many providers won't send them at all for that reason. Turn it off when you're done diagnosing.

Before moving on. A high, stable pass rate. Every remaining failure is one you have identified and are content to have blocked. No unexplained sources.

Phase 3 — Quarantine

What this is. Failing mail goes to spam instead of the inbox. Recoverable, which is why it comes before rejection.

What replaced the old percentage ramp. Previously you ramped with pct=10, then 25, 50, 100. pct= was removed and does nothing — leaving it in doesn't slow anything down; receivers ignore it and apply your policy in full immediately.

The replacement is t=y, and its behaviour is easy to misread: it applies the policy one level below the one you published. It is not an off switch.

record what actually happens to failing mail
p=quarantine; t=y nothing — treated as p=none
p=quarantine quarantined
p=reject; t=y quarantined
p=reject rejected
Step 3a — quarantine in testing mode
v=DMARC1; p=quarantine; t=y; np=reject; rua=mailto:[email protected]

Nothing happens to your mail. Reports show exactly what would be quarantined. This is the only genuinely zero-impact step in the ramp. Sit here 1–2 weeks.

Step 3b — quarantine for real
v=DMARC1; p=quarantine; np=reject; rua=mailto:[email protected]

Dropping t=y is the moment real mail is first affected.

Holding subdomains back

If Phase 1's reports showed an existing subdomain still failing, it would otherwise be dragged to quarantine alongside the parent. sp=none holds it:

v=DMARC1; p=quarantine; sp=none; np=reject; rua=mailto:[email protected]

Only use this if reports showed a subdomain sending. Don't set it because one might.

Before moving on. 2–4 weeks at full quarantine, no legitimate mail affected, no new failing sources.

Phase 4 — Reject

What this is. Failing mail is refused outright rather than spam-foldered. Nobody can retrieve it.

Step 4a — reject in testing mode
v=DMARC1; p=reject; t=y; np=reject; rua=mailto:[email protected]

Failing mail is quarantined — the same disposition as Phase 3b. Because the effect on mail is identical, moving from 3b to 4a carries no new risk; what changes is what you are signalling and what the reports show you about rejection impact. Sit here 1–2 weeks.

Step 4b — reject for real
v=DMARC1; p=reject; np=reject; rua=mailto:[email protected]

Bringing subdomains along

Once reports show existing subdomains are clean, drop sp= so they inherit p=reject, or state it explicitly:

v=DMARC1; p=reject; sp=reject; np=reject; rua=mailto:[email protected]

What this does and doesn't give you. This is the strongest protection against someone sending mail directly as your domain. It does not fix indirect flows — mailing lists and forwarding services — which must be understood before you get here, not after. See the scenarios below.

Before moving on. There is no moving on. Keep reading reports; new senders get added over time and each will fail until aligned.

Refinements

Optional. You can run a fully protected domain without any of these.

adkim= / aspf= — how exact alignment must be

Default r (relaxed): mail.yourdomain.com counts as matching yourdomain.com. s (strict) requires an exact match.

v=DMARC1; p=reject; adkim=s; aspf=s; np=reject; rua=mailto:[email protected]

Strict alignment most often breaks SaaS vendors, because they sign with their own subdomain:

From:  alerts@yourdomain.com
DKIM:  d=mailer.yourdomain.com

relaxed → matches, passes
strict  → doesn't match, fails

Only pursue strict if you specifically need to stop subdomains authenticating for the parent. Review every vendor first, and introduce it back at p=none and watch — never as an edit to a live p=reject record.

fo= — which failures generate a report

Only does anything when ruf= is set. 0 (default) both must fail; 1 either fails; d DKIM failed; s SPF failed. Combine with a colon: fo=d:s. fo=1 is the useful one.

ruf= — failure reports

Covered in Phase 2. A diagnostic tool, not a permanent setting.

psd= — public suffix domains

Only relevant if other organisations register names under your domain — a registry, or something like co.uk. Values y, n, u (default). If you are not a registry, ignore it.

Multiple report destinations

Comma-separated; every external domain needs its own authorisation record (see “Reports aren't arriving” above):

rua=mailto:[email protected],mailto:[email protected]

Tags that no longer exist

pct=, rf=, ri=. Remove them. pct= especially, because it implies a gradual rollout that isn't happening.

Scenarios

A domain that sends no mail at all

Tempting to jump straight to reject, but “we don't use this domain” is exactly the belief that turns out wrong — usually a campaign someone ran years ago. Run a shortened Phase 1 (two weeks) to confirm, then go straight to reject:

v=DMARC1; p=reject; sp=reject; np=reject; rua=mailto:[email protected]

Pair it with an SPF record authorising nothing, and a null MX:

yourdomain.com. TXT "v=spf1 -all"
yourdomain.com. MX 0 .

A subdomain with its own DMARC record

_dmarc.news.yourdomain.com overrides the parent completely — your sp= is ignored for it. Check for these before assuming the parent is in charge.

Mailing lists

Lists that modify the subject or add a footer break DKIM, and mail arrives from the list server so SPF doesn't align. At p=reject, your posts to those lists may be rejected. Nothing on your side fixes it; well-run lists rewrite the From: address to handle it.

Third-party senders you can't configure

If a vendor can't do aligned DKIM for your domain: have them send from their own domain, give them a subdomain with its own DMARC record set to none, or replace them. No tag makes unaligned mail pass.

The whole path

phase record effect on mail duration
0no change noneone sitting
1 p=none; np=reject; rua=… none 2–4 wks, min. 1 billing cycle
2unchanged noneweeks to months
3a p=quarantine; t=y; np=reject; rua=… none1–2 weeks
3b p=quarantine; np=reject; rua=… quarantined2–4 weeks
4a p=reject; t=y; np=reject; rua=… quarantined1–2 weeks
4b p=reject; np=reject; rua=… rejectedongoing

Before you rely on any of this

This is guidance, not professional advice. It is provided as-is, with no warranty of any kind. You are responsible for your own mail flow and for every DNS change you publish. If mail matters to your organisation commercially, legally or operationally, involve someone accountable for it before enforcing.

Rejection cannot be undone. At p=reject, mail that fails is refused at the receiving server and is gone — not in a spam folder, not recoverable. Every phase before it exists to make sure that only mail you intend to block gets blocked.

What is checked, and what isn't. The checker in Phase 0 reads one DMARC record — looked up or pasted — and reports what RFC 9989 makes of it, including which phase that record sits at. That is the whole of it. It does not inspect your mail flow, verify your senders, read your aggregate reports, or know whether the work behind a published policy was ever done. The phases are the same for everyone; only the findings are about you.

The durations are convention, not specification. Nothing in RFC 9989 mandates a timeline. The week counts here reflect common practice; the “one full billing cycle” rule is the one worth treating as a hard minimum, because monthly and quarterly senders are what people miss.

DNS changes are not instant. Existing TTLs mean receivers may act on your previous record for hours after you publish a new one. Lower the TTL before a change if you need it to take effect predictably, and never assume an edit is live because it resolves for you.

np= may silently not apply. It relies on receivers seeing NXDOMAIN for a non-existent subdomain. Some DNSSEC-signed providers — Cloudflare, AWS Route 53, NS1 and Azure DNS among them — answer with compact denial of existence (RFC 9824) instead, returning NOERROR with an NXNAME-bearing NSEC record. A receiver checking strictly for NXDOMAIN concludes the subdomain exists and skips your policy. Setting np=reject still costs nothing; just don't treat it as airtight.

Your provider's instructions win. If a reporting service, mail platform or registrar tells you something different about their own setup, follow them. This plan cannot know how your specific vendors behave, and no vendor named anywhere on this page is affiliated with or endorsed by this site.

Written against RFC 9989 (May 2026), which replaced RFC 7489, together with RFC 9990, RFC 9991 and RFC 9824. Specifications change and receiver behaviour lags them. Check the current RFC before treating any statement here as authoritative.