See if your domain meets Gmail, Yahoo, and Microsoft sender requirements. Check free →

Email authentication

DMARC Enforcement Rollout: Staged Quarantine to Reject in 30 Days [2026]

TL;DR: You ramp DMARC enforcement in stages, p=none to p=quarantine to p=reject, using the t=y testing flag to hold each step one level softer while you watch reports. The pct= percentage tag these rollouts used to lean on was removed in RFC 9989 (DMARCbis) in May 2026; the enforcement stage plus the binary t= flag replaced it. Gate every advance on alignment-rate evidence. Plan on a 30-day rollout in the best case; expect to pause for two to four weeks at one of the stages while a misaligned sender gets fixed.

What the t= flag actually does

The t= tag is DMARC's policy test mode, defined in RFC 9989 (DMARCbis). It is optional, and its default is t=n. It signals to the receiver whether you want the policy in your p=, sp=, and np= tags applied as written, or held one level softer while you test:

At t=y, a receiver applies the policy one level below what you published. p=quarantine; t=y is treated as p=none; p=reject; t=y is treated as p=quarantine. At t=n (the default), the policy is applied exactly as specified.

In plainer English: p=reject; t=y tells receivers “my policy is reject, but while I test, quarantine failing mail instead of bouncing it.” You publish your target policy and get a recoverable dry run of it in production, without the hard failures. When the evidence says you're ready, you drop the flag and the policy applies for real.

A few details that get lost in the typical explainer:

  • t= only softens p=quarantine and p=reject. At p=none there's nothing to soften; the policy is already monitor-only. Don't bother with t= until you're publishing p=quarantine or higher.
  • It steps down one level. It is not a percentage. This is the deliberate change from the old pct= tag. Every failing message is treated the same way (one level softer), instead of a fraction getting the full policy and the rest getting a weaker one. The behavior is now predictable across receivers.
  • Receivers report what they actually did. Aggregate reports include both policy_published (what you said, including t=) and policy_evaluated (what the receiver applied, including any local override). When you read rua= reports during a staged ramp, you'll see both. That's how you measure whether the test rung is behaving as expected.
  • Default is t=n. If you don't specify t=, the receiver applies the policy exactly as published. Omitting the tag and setting t=n are equivalent.

The whole point of t=y is to give you a soft rung at each enforcement level. Used well, it lets you observe a full slice of enforcement consequences in production, one notch below the real disposition, before it lands for real. Used badly (set once and forgotten) it's just a misleading way to publish a policy you never actually enforce.

What happened to pct=? The original DMARC spec (RFC 7489) had a pct= tag that asked receivers to apply your policy to a percentage of failing mail, so operators ramped 10, 25, 50, 75, 100. RFC 9989 removed it. Over eleven years of deployment, receivers applied those intermediate percentages inconsistently, so the same record produced different enforcement at different mailbox providers. Treat pct= as legacy: the DMARCit generator no longer emits it, the checker flags it obsolete, and any receiver you care about may ignore it. The t= flag is the binary replacement.

The enforcement-stage ladder

With pct= gone, the ramp is no longer a percentage climb. It's a walk through enforcement stages, with the t=y testing flag giving you a soft rung before each real one:

p=none                 (inventory only)
   ↓  (≥30 days; complete sender inventory)
p=quarantine; t=y       (quarantine on record, applied as none)
   ↓  (≥7 days; alignment rate ≥ 99% on legitimate volume)
p=quarantine            (full quarantine; t=n is the default)
   ↓  (≥7 days; clean)
p=reject; t=y           (reject on record, applied as quarantine)
   ↓  (≥7 days; clean)
p=reject                (full enforcement)

Why each rung matters:

  • p=none is inventory. You take no action on failing mail and read aggregate reports until you can name every legitimate sender. Thirty days is a reasonable floor. You cannot gate an advance on evidence you haven't collected yet.
  • p=quarantine; t=y commits your target policy to the record while receivers still treat failing mail as p=none. Be honest about what this rung is: the disposition applied is identical to p=none, so its value is publishing the policy, validating your tooling and reports, and confirming nothing about the record itself breaks. The meaningful dry run comes later, at the reject rung.
  • p=quarantine is full quarantine. Every failing message is junked. This is where hidden senders you missed surface as real quarantined volume. If you were going to discover a misaligned source through enforcement, you discover it here.
  • p=reject; t=y is the real test rung. Failing mail is quarantined instead of bounced, so you see exactly what full reject will do without the hard failures. A clean week here is the strongest pre-publish signal that p=reject will be uneventful.
  • p=reject is full enforcement. Spoofed mail dies at the receiving server. From here, maintenance is watching rua= for drift and new senders.

The stages aren't yours to invent anymore; RFC 9989 fixed them as the two policy levels plus the binary test flag. What's yours is the gating between them: the dwell time at each rung and the alignment-rate threshold you require before you climb. The one-level-below behavior of t=y is specified in RFC 9989, so it behaves the same at every conforming receiver, which is the whole reason it replaced the percentage tag.

Diagram 1 (designer flag): “DMARC enforcement-stage ladder”: horizontal staircase with five rungs (none, quarantine;t=y, quarantine, reject;t=y, reject), each rung annotated with the dwell-time gate and the alignment-rate threshold to advance.

The alignment-rate gate (the differentiator)

It's tempting to advance on a calendar. You set a reminder for “go to full quarantine next Monday,” and when Monday rolls around you publish the next stage, whether or not the evidence supports the advance. That's a policy-toggle workflow.

The right approach is alignment-evidence-gated: advance only when alignment rate clears a threshold over a configurable lookback window. Same outcome, different rigor.

What “alignment rate” means in practice: the percentage of legitimate volume from your domain in the lookback window where SPF or DKIM passed and aligned with the From: header domain, divided by the total legitimate volume. A typical advance threshold is 99% or higher over a 7-day lookback window. (See /enforcement-readiness for the readiness-evaluator UX that surfaces this.)

A few things to internalize about alignment rate as a gate:

  • It's not real-time. DMARC aggregate reports arrive on a daily cadence at best. Receivers batch across a 24-hour window, and delivery can lag another day. Any “real-time alignment-rate dashboard” is overstating the input data. The honest framing is at-best next-day evidence: a lookback over discrete daily data, not a live signal.
  • It's measured on legitimate volume only. Including unauthorized volume (spoofing, sources you've classified as “ignore”) in the denominator pushes the rate down for reasons unrelated to readiness. The DMARCit readiness evaluator excludes flagged-unauthorized sources from the gate; if you're computing this manually, do the same.
  • It accounts for policy_evaluated overrides. If a receiver applied a local override (forwarded, mailing_list, local_policy) and didn't enforce, that's not a failure of your alignment. Strip overrides from the gate calculation, or you'll under-count alignment.
  • One bad day shouldn't reset the clock. A flaky DKIM key on Tuesday that got fixed Wednesday isn't a reason to back off, but it should pause the advance until the next clean lookback window.

Most “stuck at p=none” stories reduce to one of two failures: the ramp had no gate, or it had a tool that toggled policy on a calendar with no evidence check. The cure in both cases is the same: make the evidence visible at every rung, and only advance when it clears.

Worked example: 30-day staged rollout

Here's a defensible 30-day rollout plan, assuming you've already completed sender inventory at p=none and SPF is healthy. (If you haven't, read /learn/p-quarantine-vs-p-reject first, and fix /learn/spf-permerror before you touch enforcement.)

DayActionWhat you check
Day 0Publish v=DMARC1; p=quarantine; t=y; rua=mailto:agg@yourdomain.com (preserving any existing rua= / ruf= / sp=).DNS poll confirms the record landed. Validators clean. Reports show policy_published quarantine with t=y; failing mail is still dispositioned none.
Day 1-6Aggregate reports flow in.Daily reports show your quarantine policy on record with disposition=none applied. Sender inventory stays stable; no new unclassified sources of meaningful volume.
Day 7Review week-1 evidence. If alignment rate ≥ 99% on legitimate volume over the 7-day lookback, drop t=y and publish p=quarantine (full).New record published. DNS poll confirms. Failing mail is now junked for real. Watch for a bump in spam-folder complaints.
Day 8-13Reports flow at full quarantine.Alignment rate holds. This is where hidden senders that survived none and testing surface as real quarantined volume; expect to find one or two.
Day 14Hold at full quarantine. Classify anything new.If alignment dipped, don't advance: re-add t=y or drop back to p=none, classify the source that broke, fix it, then re-advance.
Day 15-20Continued reports at full quarantine.Alignment rate holds above threshold. No new unclassified sources. Quarantine bounce-back complaints, if any, show up here.
Day 21If clean, publish p=reject; t=y. Failing mail is now quarantined, not bounced.DNS poll confirms. This is the real dry run of reject: reports show exactly what full reject will do, without the bounces.
Day 22-27Reports flow at reject with t=y.The week should look like full reject minus the bounces. Confirm no legitimate volume is sitting in the would-be-rejected set.
Day 28If clean, drop t=y and publish p=reject (full).DNS poll confirms. Bounces start appearing for spoofed traffic; legitimate mail unaffected.

That's the optimistic case. Real rollouts often pause for two to four weeks at one of the stages while a misaligned sender gets fixed, or while a stakeholder team negotiates with a vendor whose DKIM signing is broken. A 30-day rollout that takes 60 days because you held at full quarantine for three weeks is a successful rollout. A 14-day rollout that finished on time but rolled back two weeks later because the gate was wrong is a failed rollout dressed in the costume of a fast one.

Diagram 2 (designer flag): “30-day rollout calendar”: horizontal timeline with the four advance points (Day 0, 7, 21, 28) and the daily-report cadence underneath, showing where the gate is checked and where pauses commonly happen.

When to pause and back off

The whole point of staged rollout is that you can stop and reverse. Failure modes that justify pausing or backing off:

  • Alignment rate drops mid-ramp. A previously-aligned sender broke: an ESP rotated DKIM keys without telling you, marketing migrated a vendor over the weekend, an internal flow got rerouted through a forwarder. Aggregate reports will show the drop within 24-48 hours. Back-off action: step back one stage, re-add t=y (or drop to p=none if the breakage is severe), publish, confirm via DNS poll, then investigate.
  • A new sender appeared and isn't yet aligned. Sometime between rungs, a new sending source showed up, usually a vendor someone signed up for without telling IT. Hold at the current rung. Don't advance until the new source is either aligned or explicitly classified.
  • Quarantine bounce-back complaints. A customer or internal user reports a legitimate email landed in spam. Shouldn't happen if your alignment rate is genuinely above 99%, but the long tail is real. More than a couple per week: step back a rung and investigate.
  • Aggregate reports stop arriving. If rua= mail stops, you've lost the gate. Fix the report flow before you advance.

The back-off sequence is the same in every case: step down a stage (re-add t=y, or drop p=reject back to p=quarantine), confirm via DNS, investigate, fix or classify, then re-advance from where you were. You don't lose all your evidence by backing off one rung.

Revert isn't free. DNS caching and report delays mean the revert doesn't take effect instantly at all receivers. Plan on a 24-48 hour window. If the breakage needs to be gone now, that's an argument for republishing p=none outright, not a reason to skip the revert.

The DMARCit approach

Treating the enforcement ladder as a calendar event (pick a date, click a button, the record updates) is a policy-toggle workflow. We think it's the wrong shape. The ladder isn't the hard part, the gate is.

DMARCit's enforcement-readiness flow is alignment-evidence-gated, not policy-toggle. The product surface tracks each sending source on your domain, lets you mark it legitimate, unauthorized, forwarded, or needs-review, computes alignment rate over a configurable lookback window with overrides excluded, and gates the advance CTA on the rate clearing the threshold for the configured dwell time. The CTA isn't “go to full quarantine because Monday.” It's “alignment rate is 99.4% over the last 7 days; dropping t=y to full quarantine is unblocked”. Or, more often, “alignment rate dipped to 97.8% on Tuesday; advance is blocked, here's the source that broke.”

We don't auto-write your DNS. The tool generates the new TXT record value for you to apply yourself, sets or clears the t= flag for the right rung, and shows the rollback value pre-computed alongside it. Existing rua=, ruf=, and sp= tags are preserved in the diff (losing them is a customer incident, and we won't risk it). After you publish, we poll DNS to confirm the change landed and warn about the report-lag window before you check the next gate.

We automate the mechanics. You still own the call to advance. That's the honest framing: alignment-evidence-gated isn't enforcement-by-autopilot. It's a tool that surfaces the evidence and the rollback in the same place as the advance CTA, so the decision is informed.

For the full guided walkthrough (the staged-quarantine UX with source-marking and the enforcement ladder integrated with alignment-rate evidence at each step) see /enforcement-readiness. For pricing, /pricing.

Common rollout pitfalls

The most common mistakes we see:

  • Still publishing pct=. RFC 9989 removed it. Modern validators flag it as obsolete, and receivers may ignore it entirely, so a record that leans on pct= for its ramp isn't enforcing the way you think. Drop it and use t=y for the test rungs.
  • Advancing too fast. Skipping the alignment-rate gate is the version of “moving fast” that ends in a customer-incident retrospective. If you advance on a calendar and not on evidence, you've published the stage but not earned it.
  • Leaving t=y on forever. The operator publishes p=quarantine; t=y to satisfy an auditor and then never drops the flag. Six months later the record still says t=y and every failing message is being treated as p=none. That's not enforcement; that's enforcement cosplay. Set a calendar reminder plus an evidence gate.
  • Interaction with subdomain policies. The t= flag applies to the whole record. The subdomain's effective policy is whatever sp= says (or p= if sp= is absent), and a bare subdomain policy is governed by np=. If you want staged rollout scoped differently for subdomains, plan it explicitly.
  • Misunderstanding what t=y does. At p=reject; t=y, failing mail is quarantined, not delivered normally. At p=quarantine; t=y, it's treated as p=none. It steps down one level; it does not turn enforcement off. RFC 9989 has the receipt.
  • Treating t=y as a long-term posture. It's a testing flag, not an end-state. Living at t=y indefinitely means the gate isn't being checked or it's broken. Either drop the flag and enforce, or fall back to a defensible p=quarantine end state.

The path to full reject

p=quarantine is not the same as p=reject. Quarantine sends failing mail to spam; reject bounces it. The mail still gets to the recipient at quarantine: it might rot in junk, but a determined human can rescue it. At reject, the mail is gone, and the only artifact is a bounce notification at the sender.

The path from full p=quarantine to p=reject looks like:

  1. Hold at full p=quarantine for at least the configured lookback window (typically 7-14 days). Alignment rate ≥ 99% on legitimate volume, no new unclassified sources, no overrides driving the rate down.
  2. Publish p=reject; t=y (preserving all other tags). Failing mail is quarantined, not bounced, so you get a recoverable dry run of reject. DNS poll confirms.
  3. Hold the test rung until the evidence is clean, then drop t=y to publish p=reject for real, gated on the same alignment-rate evidence.
  4. At p=reject (with t=n), you're done. Maintenance mode is monitoring rua= for drift and watching for new senders that need to be aligned or classified.

For the full quarantine-vs-reject framing (when reject is the right end-state and when quarantine forever is fine) see /learn/p-quarantine-vs-p-reject. The short version: if you're a phishing target, a bulk sender meeting Gmail/Yahoo 2024 requirements, or under a regulatory regime that names p=reject explicitly, finish the ladder. Otherwise, p=quarantine is a defensible end-state for many domains.

What to do next

If you're planning a staged DMARC rollout:

  1. Check that your SPF is healthy (no permerror, no temperror, lookup count well under 10). Run a free SPF check before you publish enforcement.
  2. Confirm you have at least 30 days of rua= aggregate reports and a complete sender inventory. (See /learn/dmarc-monitoring for the signal set.)
  3. Read /learn/p-quarantine-vs-p-reject for the policy-value framing if you haven't.
  4. Publish p=quarantine; t=y, then walk the stage ladder (full quarantine, then p=reject; t=y, then full reject), gated on alignment rate ≥ 99% over a 7-day lookback at each step.
  5. Hold at full p=quarantine for at least the configured lookback window before you test p=reject.

Check your DMARC posture in 60 seconds

Free DMARC checker pulls your current record, identifies every sending source, computes alignment rate, and tells you which enforcement stage is the right next move. Want to see the staged rollout before you touch DNS? Click through the live demo: it walks the same t=y test rungs and alignment-rate gates on sample data.

Related reading

Learn more