# DMARC p=none vs quarantine vs reject: a safe rollout

> What p=none, p=quarantine and p=reject do, the sp, np, pct and t tags, how to read an aggregate report and when to move up without losing legitimate email.

Source: https://couryo.com/en/blog/dmarc-none-quarantine-reject · Published 2026-10-20

Someone on the team read that `p=reject` protects the brand, changed the DMARC record on a Friday, and by Monday the invoices from the billing system had stopped reaching customers. Nobody connected the two for days. DMARC is the best protection against people spoofing your domain, but raising the policy without reading the reports takes legitimate mail down with it. This guide walks through the safe path, based on the current rules.

## What each policy does

DMARC is a TXT record at `_dmarc.yourdomain.com`. It checks whether a message passed SPF or DKIM **with a domain aligned to the `From`**, and tells the receiver what to do when it didn't:

| Policy | What happens to failing mail | What it's for |
|---|---|---|
| `p=none` | nothing; delivery as usual | monitoring and reports |
| `p=quarantine` | treated as suspicious, usually sent to spam | the middle step, still recoverable |
| `p=reject` | refused at the door | full protection against spoofing |

Two common misunderstandings:

- **DMARC doesn't look at content.** It only answers "is this message really from the `From` domain?". A legitimate, authenticated email can still land in spam for other reasons; a spoofed email can still arrive under `p=none`.
- **`p=none` already counts.** Gmail and Yahoo require DMARC from senders above 5,000 messages a day, and `p=none` is accepted ([Gmail's sender guidelines](https://support.google.com/a/answer/81126)); Microsoft asks for at least `p=none` at Outlook.com ([2025 announcement](https://techcommunity.microsoft.com/blog/microsoftdefenderforoffice365blog/strengthening-email-ecosystem-outlook%E2%80%99s-new-requirements-for-high%E2%80%90volume-senders/4399730)). Moving to `reject` is protection, not one of their requirements.

## The tags that matter

```text title="TXT at _dmarc.example.com"
v=DMARC1; p=none; rua=mailto:dmarc@example.com; adkim=r; aspf=r
```

| Tag | What it does |
|---|---|
| `p` | the domain's policy: `none`, `quarantine` or `reject` |
| `rua` | where receivers send aggregate reports (XML, usually daily) |
| `sp` | policy for **existing subdomains** (`shop.example.com`); without it, `p` applies |
| `np` | policy for **non-existent subdomains** (`anything.example.com`); without it, `sp` or `p` applies |
| `adkim`, `aspf` | alignment mode: `r` (relaxed, subdomains count as the same domain) or `s` (strict, exact match only) |
| `pct` | applied the policy to a share of messages; **removed from the spec in 2026** (see below) |
| `t` | `t=y` asks receivers to apply one level below the published policy, for testing; the default is `t=n` |

### What changed in 2026: pct out, t in

In May 2026, DMARC got a Standards Track specification from the IETF, [RFC 9989](https://www.rfc-editor.org/rfc/rfc9989), replacing RFC 7489 (which was only informational). Two changes affect your rollout:

- **The `pct` tag was removed.** The RFC explains that, in practice, values other than 0 and 100 were never applied accurately, and each receiver did it differently.
- **A `t` (testing) tag was added.** With `t=y`, receivers apply one level lower: `p=quarantine; t=y` is treated as `none`, and `p=reject; t=y` as `quarantine`. It's the successor to the old `pct=0`.

Receivers take time to change, and [Google's recommended rollout guide](https://knowledge.workspace.google.com/admin/security/recommended-dmarc-rollout) still shows `pct` examples (verified on 10/20/2026). Since the spec says unknown tags must be ignored, adding `t=y` breaks nothing for receivers that don't know it yet. Just don't count on `pct=10` enforcing on exactly 10% of your mail.

## How to read an aggregate report

Reports arrive at the `rua` address as XML (sometimes compressed). An excerpt in the [RFC 9990](https://www.rfc-editor.org/rfc/rfc9990) format:

```text title="Aggregate report (excerpt)"
<policy_published>
  <domain>example.com</domain>
  <p>none</p>
</policy_published>
<record>
  <row>
    <source_ip>203.0.113.25</source_ip>
    <count>1840</count>
    <policy_evaluated>
      <disposition>none</disposition>
      <dkim>pass</dkim>
      <spf>pass</spf>
    </policy_evaluated>
  </row>
  <identifiers>
    <header_from>example.com</header_from>
  </identifiers>
  <auth_results>
    <dkim><domain>example.com</domain><selector>s1</selector><result>pass</result></dkim>
    <spf><domain>bounces.example.com</domain><result>pass</result></spf>
  </auth_results>
</record>
<record>
  <row>
    <source_ip>198.51.100.7</source_ip>
    <count>212</count>
    <policy_evaluated>
      <disposition>none</disposition>
      <dkim>fail</dkim>
      <spf>fail</spf>
    </policy_evaluated>
  </row>
  <identifiers>
    <header_from>example.com</header_from>
  </identifiers>
  <auth_results>
    <spf><domain>mail.billing-vendor.example</domain><result>pass</result></spf>
  </auth_results>
</record>
```

How to read it:

- **`source_ip` and `count`:** which server sent, and how many messages.
- **`policy_evaluated`:** the **aligned** result, which is what DMARC uses. `pass` here means it passed and was aligned with the `From`.
- **`auth_results`:** the raw result, with the signing domain or envelope domain.
- **`disposition`:** what the receiver did with the message. Under `p=none`, nothing is blocked.

In the example, the first block is your sending service, all good. The second is the classic problem: 212 messages from a billing vendor, with SPF passing **for the vendor's domain**, not yours, and no DKIM. To DMARC that's a failure. Under `p=reject`, those 212 invoices would be refused.

Reading XML by hand every day doesn't scale. Use a tool that groups reports by source and shows who fails.

## Step-by-step rollout

**1. Inventory.** List everything that sends with your domain in the `From`: company mailboxes (Google Workspace, Microsoft 365), your app, your store, billing and invoicing, CRM, help desk, marketing platform. Each needs DKIM with **your** domain, or an envelope on a domain of yours.

**2. `p=none` with `rua`.** Publish it and collect. Google suggests at least a week; if you have monthly sends (invoices, statements, monthly reports), wait a full cycle so they show up.

**3. Fix every failing source.** For each IP with `fail` under `policy_evaluated`: find out who it is, set up DKIM with your domain in that service or move its envelope to a subdomain of yours. A source you don't recognize may be spoofing, which is exactly what `reject` will stop.

**4. `p=quarantine` in test mode, then for real.**

```text title="Test (applies none where RFC 9989 is in effect)"
v=DMARC1; p=quarantine; t=y; rua=mailto:dmarc@example.com
```

```text title="Quarantine enforced"
v=DMARC1; p=quarantine; rua=mailto:dmarc@example.com
```

**5. `p=reject`.** Once quarantine runs with no legitimate source failing:

```text title="Reject"
v=DMARC1; p=reject; rua=mailto:dmarc@example.com
```

### When to move up

Move up a level when, over the whole observation period:

- every legitimate source shows an aligned `pass`;
- the remaining failures come from sources you don't recognize (spoofing) or from forwarding;
- no new service started sending without DKIM;
- you know how to roll back quickly (see below).

**Forwarding:** when someone forwards your email, SPF breaks because the forwarding server isn't in your SPF record. DKIM usually survives. That's why **every legitimate service should pass with aligned DKIM**, not SPF alone. Microsoft also points to ARC as the mechanism that preserves authentication through forwarding and mailing lists.

## Subdomains

- **Without `sp`, subdomains inherit `p`.** Move the root to `reject` and `shop.example.com` goes to `reject` too, unless it has its own `_dmarc` record.
- **A subdomain with its own record governs itself.** `_dmarc.marketing.example.com` applies to `marketing.example.com`, and an `sp` tag published on a subdomain is ignored.
- **Roll out subdomains separately** when each has a different sender. A common path: `p=reject; sp=quarantine` while subdomains are still being watched.
- **Use `np=reject`** so made-up names (`account-security.example.com`) can't be used in phishing.
- **Domains that never send** (the `.net` that only redirects to your `.com`): publish `v=spf1 -all` and `v=DMARC1; p=reject;` right away.

## How to roll back if mail goes missing

If legitimate email stops after a change, drop the policy one level (from `reject` to `quarantine`, or to `p=none`) and fix the source. The change only reaches everyone once the record's TTL expires, so a short TTL on `_dmarc` (a few minutes) helps during the rollout. Messages already rejected don't come back; the sender has to resend them.

## Where Couryo fits

In Couryo, each domain's DMARC starts at `p=none` with `rua=mailto:reports@dmarc.couryo.com`, and Couryo parses every report (XML, zip or gzip). The domain's **DMARC** tab shows sending sources, how many messages each sent and whether they passed SPF, DKIM and DMARC, with a "someone is sending as you without authenticating" alert when a source fails. The deliverability agent only recommends moving up when the domain has had its current policy for 30 days, at least 99% of messages passed DMARC and no source failed, and it hands you the new record ready to copy. You change the record yourself: the agent reads and recommends, it doesn't touch your DNS. See [Deliverability agent](https://couryo.com/en/docs/deliverability.md#dmarc-reports) and [Domains and DNS](https://couryo.com/en/docs/domains.md).

## FAQ

### How long should I stay at p=none?

Google suggests at least a week of reports. In practice, wait for at least one full cycle of your sending: if invoices go out monthly, they only appear in reports after the first run. Couryo's agent waits for 30 clean days before recommending a move.

### Does p=quarantine send all my email to spam?

No. Only messages that **fail** DMARC (no aligned SPF or DKIM). Legitimate, authenticated mail is delivered as usual. The risk is legitimate sources you haven't configured yet, which is why the reports come first.

### Can I still use pct=25 to ramp up?

You can publish it, but don't rely on it. RFC 9989 removed `pct` in 2026 because values other than 0 and 100 were never applied consistently. To test a policy without enforcing it, use `t=y`; to enforce, move from one level to the next.

### Does DMARC alone keep my email out of spam?

No. It proves the message comes from your domain, which the big providers require and which helps reputation. Complaints, bad lists and scam-like content still send mail to spam. See [Why your emails go to spam](https://couryo.com/en/guides/emails-going-to-spam.md).

### Do I need p=reject to meet Gmail's and Microsoft's rules?

No. Gmail, Yahoo and Microsoft accept `p=none` for bulk senders. `p=reject` is about protecting your domain from spoofing, and it's worth getting there carefully.
