Skip to main content
(Updated July 27, 2026 ) by Meysam Azad
11 min read

DMARC Subdomain Policy: How sp= and np= Protect Every Subdomain

A p=reject policy on your root domain does nothing for mail.example.com — unless you tell DMARC what to do with subdomains.

A DMARC subdomain policy is the rule a domain owner publishes for mail sent from subdomains of an organizational domain. It is controlled by two tags: sp= (for existing subdomains) and np= (for non-existent subdomains, added in DMARCbis / RFC 9989). When you set neither, subdomains inherit the parent domain’s p= policy.

This post assumes you already know the basics. If you do not, start with our DMARC fundamentals guide and come back. Most subdomain spoofing succeeds because the parent domain left sp= and np= unset, so a do-nothing p=none quietly covers every subdomain too.

Here is what to publish, and why: how a subdomain policy resolves, sp= versus np=, the DMARCbis DNS tree walk, whether receivers actually honor these tags, and the exact record to set.

What is the DMARC sp tag (subdomain policy)?

The sp= tag sets the DMARC policy for mail from existing subdomains of your organizational domain. It takes the same three values as p=none, quarantine, or reject — and lives in the parent domain’s _dmarc record. If you omit sp=, subdomains use whatever p= is set to.

Two details matter. First, the organizational domain is the registrable domain at the top of your namespace — example.com, not mail.example.com. Second, sp= is only meaningful on the organizational domain’s record. RFC 9989 §4.7 states that sp= “will be ignored for DMARC Policy Records published on subdomains,” so putting sp= on _dmarc.mail.example.com does nothing — set it on the parent.

Here is how the three policy tags relate:

TagApplies toValuesDefault when unset
p=the organizational domain itselfnone / quarantine / rejecttreated as none if missing
sp=existing subdomainsnone / quarantine / rejectfalls back to p=
np=non-existent subdomainsnone / quarantine / rejectfalls back to sp=, then p=

For the full DMARC tag grammar and how to publish the record itself, see the full DMARC tag reference and how to publish the record. The rest of this guide is about behavior: how those tags resolve and how to use them to close a spoofing gap.

How subdomains inherit the DMARC policy

Subdomains do not need their own DMARC record. A receiver applies the most specific policy it finds, in this order: (1) the subdomain’s own _dmarc record if one exists, otherwise (2) the parent’s sp= value, otherwise (3) the parent’s p= value. RFC 9989 §4.10.1 spells out exactly this precedence.

Walk it through with example.com. Suppose the parent publishes v=DMARC1; p=reject; sp=quarantine. Mail from news.example.com, which has no record of its own, is quarantined on failure (the sp= value). Mail from shop.example.com, which publishes its own _dmarc record with p=none, is governed by that record — the subdomain’s own policy wins.

This inheritance is also why a permissive parent leaves subdomains exposed. If p=none is in place and sp= is unset, no subdomain is protected either.

Key finding

57.9% of DMARC-protected domains sit at p=none — and with no sp= set, every subdomain inherits that do-nothing policy

Source: State of Email Authentication 2026 — 5,499,028 Tranco domains, scan February 27, 2026

sp=none vs sp=reject — subdomain policy examples

Use sp=reject when no subdomains send legitimate mail (the common case). Use sp=none only when a subdomain sends mail that is not yet DMARC-aligned and you are still in monitoring mode. The two configurations below look similar and behave very differently:

DNS TXT record — _dmarc.example.com dns
# Root protected, subdomains WIDE OPEN — the exposed combination
v=DMARC1; p=reject; sp=none

# Root in monitoring, subdomains locked down — protect inactive
# subdomains while you still test the parent policy
v=DMARC1; p=none; sp=reject

The first record protects the root and leaves subdomains wide open — the exposed one, and the exact gap attackers look for. The second puts the root in monitoring while locking down subdomains, which is useful when you want to protect inactive subdomains before the parent reaches enforcement.

If you have no legitimate subdomain senders, the strongest posture is sp=reject paired with np=reject (covered next). Getting subdomains to enforcement is part of reaching a domain-wide p=reject — the same journey as moving from p=none to enforcement on the parent.

The np= tag — policy for non-existent subdomains (DMARCbis, RFC 9989)

The np= tag, introduced in DMARCbis (RFC 9989 §4.7), sets the DMARC policy for mail claiming to come from subdomains that do not exist in DNS. It takes none, quarantine, or reject. If np= is unset, the receiver falls back to sp=, then to p=.

Here is the attack it closes. A spoofer invents a subdomain that was never created — random-invoice.brand.com, payroll.brand.com — that has no _dmarc record. Under the original 2015 DMARC specification there was no dedicated control for this, and receiver fallback behavior diverged — DMARCbis (RFC 9989 §4.7) added the np= tag. A 2021 peer-reviewed study (Maroofi et al., IEEE Transactions on Network and Service Management) showed attackers could spoof every tested provider from non-existent subdomains when the organizational domain set no subdomain policy. np=reject is the IETF’s purpose-built answer.

The clearest real-world demonstration is gov.uk. As documented by Hexiosec (formerly Red Maple) in 2022, _dmarc.gov.uk publishes p=reject; sp=none; np=reject; adkim=s; aspf=s; fo=1, while _dmarc.data.gov.uk does not exist. The np=reject blocks the non-existent-subdomain spoof that the permissive sp=none would otherwise have let through.

One thing np= does not fix: hijacked subdomains that genuinely exist. In the February 2024 SubdoMailing campaign (Guardio Labs), attackers re-registered abandoned domains behind dangling CNAME and stale SPF records of real brands, so their mail passed SPF, DKIM, and DMARC from existing, hijacked subdomains. np= addresses only non-existent subdomains; the fix for that class is DNS hygiene — removing dangling records and stale include: entries.

How the DMARCbis DNS tree walk finds your subdomain policy

To decide which policy applies, a DMARCbis receiver performs a DNS tree walk: it starts at the sending subdomain and queries progressively higher labels — up to a maximum of eight lookups — until it finds a DMARC record (RFC 9989 §4.10). This replaces the deprecated Public Suffix List (PSL) two-query method that older guides still teach. A “non-existent” subdomain is defined precisely: a DNS query that returns NXDOMAIN (RFC 9989 §3.2.13). One honest caveat: the tree walk and the PSL can resolve a different organizational domain for some TLDs, so the spec’s own mitigation is explicit records plus strict alignment at every sending domain.

For the wider DMARCbis picture, see the full DMARCbis breakdown (RFC 9989, 9990, 9991).

Do receivers actually honor sp= and np=?

As of June 2026, the major receivers honor sp= inheritance, but none publicly documents support for np= or the DMARCbis tree walk. Treat sp= as enforced and np= as defense-in-depth: safe to publish, but not yet something you can rely on a receiver enforcing.

On sp=, the documentation is clear. Google states that subdomains inherit the parent policy and that sp= overrides it, with an explicit subdomain record winning over both. Microsoft documents that the parent record “automatically covers all subdomains (including nonexistent subdomains)” unless a subdomain publishes its own record. Apple’s Branded Mail guide requires sp=quarantine or sp=reject when registering subdomains under a parent record. Yahoo urges a policy per sending domain but does not document sp= semantics, so its behavior is unverified.

On np= and the tree walk, the absence is the finding: no major receiver documents either. OpenDMARC is frozen at version 1.4.2 (December 2021) and remains PSL-based; Rspamd 4.1.1 implements neither. Only checker and library tooling — checkdmarc and Mail::DMARC — has shipped np= parsing and the tree walk. DMARCguard’s own checker runs the DMARCbis tree walk, so it shows which policy a receiver should resolve for a subdomain. A second caveat: not all authoritative nameservers return NXDOMAIN for an empty subdomain, so even where np= is read, enforcement can be inconsistent.

The action that follows: publish np=reject now as defense-in-depth, keep sp= set, and neutralize the tree-walk-versus-PSL gap with explicit records and strict alignment (adkim=s; aspf=s) at every sending domain.

When should a subdomain have its own DMARC record?

Most subdomains should inherit the parent policy. Publish a separate _dmarc record on a subdomain only when you need one of four things:

  1. A different policy than the parent — for example, a subdomain still in monitoring while the parent enforces.
  2. A separate rua/ruf reporting destination — the chief practical effect of a subdomain record is redirecting where reports go, not “adding protection.”
  3. Delegated ownership — a contractor- or team-managed subdomain that needs to control its own record.
  4. A staged enforcement rollout scoped to that one subdomain.

There is a governance trap here. A subdomain owner who publishes p=none on a delegated subdomain re-opens a spoofing hole the parent had already closed. At scale, decide deliberately who can publish subdomain records.

Parked and non-sending domains need the least deliberation: with no mail expected anywhere, the strongest posture is p=reject; sp=reject; np=reject. Creating the record itself is no different from any DMARC record — the TXT host is _dmarc.<subdomain> and the syntax is identical. This page stays on behavior and policy.

How to set a DMARC subdomain policy with sp= and np=

  1. Look up your current DMARC record. Run dig +short TXT _dmarc.example.com (replace example.com with your domain). Note whether sp= and np= are present and what p= is. A bare p=reject already behaves as sp=reject.
  2. Choose your subdomain policy (sp=). Set sp=reject if no subdomains send legitimate mail; use sp=none only while a subdomain is mid-rollout and not yet DMARC-aligned.
  3. Add np= for non-existent subdomains. Append np=reject as defense-in-depth. Receivers that ignore it fall back to sp=, then p=, so there is no downside to publishing it.
  4. Publish and verify. Update the single _dmarc TXT record on the organizational domain — not on a subdomain — then confirm it is live.

A hardened end-state record reads: v=DMARC1; p=reject; sp=reject; np=reject; rua=mailto:[email protected]; adkim=s; aspf=s. You can build one with our DMARC generator with sp= and np=.

Frequently Asked Questions

How does DMARC work with subdomains?

Subdomains inherit the organizational domain’s DMARC policy unless overridden. A receiver applies the subdomain’s own _dmarc record if one exists, otherwise the parent’s sp= value, otherwise the parent’s p=. No separate record is required for inheritance to work (RFC 9989, Section 4.10.1).

What is the DMARC sp tag (subdomain policy)?

The sp= tag sets the DMARC policy for existing subdomains of the organizational domain, using the same none, quarantine, or reject values as p=. It is published on the parent’s _dmarc record and, when omitted, defaults to the p= value (RFC 9989, Section 4.7).

Are DMARC records inherited by subdomains?

Yes. If a subdomain has no _dmarc record, receivers apply the parent’s sp= policy, or the parent’s p= if sp= is unset. A bare p=reject therefore also rejects unsigned subdomain mail, so set sp= intentionally to avoid surprising your own senders.

What is the DMARC np tag for non-existent subdomains?

np=, added in DMARCbis (RFC 9989), sets the policy for mail from subdomains that do not exist in DNS — a common spoofing vector. It takes none, quarantine, or reject and defaults to sp=, then p=. Major receivers do not yet document np=, so treat it as defense-in-depth.

Should sp= be none or reject?

Use sp=reject when no subdomains send legitimate mail — the strongest and most common posture. Use sp=none only while a subdomain’s mail is not yet DMARC-aligned and you are monitoring. Pair sp=reject with np=reject on parked domains that have no subdomain senders.

Conclusion

Subdomains inherit p= unless sp=, np=, or an explicit record overrides it. np=reject is the DMARCbis (RFC 9989) fix for non-existent-subdomain spoofing, but it is not yet enforced at major receivers — publish it as defense-in-depth, not as a control to rely on. The durable posture is explicit records plus strict alignment at every sending domain.

Set your DMARC subdomain policy deliberately, then verify it. Check what policy a receiver resolves for your subdomains — free, no signup required.