← Blog
Monitor showing a DNS tree where real subdomains glow teal and dashed non-existent subdomains end in red shields blocking email

By DMARCdrift Team

DMARC np= Explained: Policy for Subdomains That Don't Exist

5 min readdmarcrfcspoofingdns

The DMARC np tag sets the policy for subdomains of your domain that don't exist in DNS. If someone sends mail as ceo@payroll.example.com and payroll.example.com returns NXDOMAIN, receivers apply your np policy instead of sp or p. Legitimate mail almost never comes from a name that doesn't exist, so np=reject is one of the few DMARC changes you can make before your main domain is anywhere near enforcement.

What counts as a non-existent subdomain

RFC 9989 §4.7 defines np as the policy "for non-existent subdomains of the given Organizational Domain." The tag started life in RFC 9091 (the experimental PSD DMARC spec) and is now part of the core standard.

"Non-existent" has a precise meaning. §3.2.13 ties it to RFC 8020: "if the response code received for a query for a domain name is NXDOMAIN, then the domain name and any possible subdomains do not exist."

So the test is the DNS response code, not whether the name has an A or MX record. A few consequences:

  • A name with any record exists. If mail.example.com has only a TXT record, a query for its A record returns NOERROR with no answers. That is not NXDOMAIN, so np doesn't apply.
  • Names with children exist. If you publish s1._domainkey.news.example.com, then news.example.com is an empty non-terminal. It returns NOERROR, not NXDOMAIN.
  • Wildcards make everything exist. With *.example.com in your zone, every subdomain resolves, nothing returns NXDOMAIN, and np never fires. Your sp (or p) covers all of it.

Precedence: np, sp, and p

np only matters when a receiver falls back to your Organizational Domain's record. If the From domain has its own _dmarc record, that record's p applies. A non-existent name can't have one.

When the policy comes from the Organizational Domain (or a public suffix domain) and the From domain is a subdomain, §4.10.1 decides: the policy "is taken from the "sp" tag (if any) if the Author Domain exists or the "np" tag (if any) if the Author Domain does not exist." The fallbacks are in §4.7: "If the "np" tag is absent, the policy specified by the "sp" tag (if the "sp" tag is present) or the policy specified by the "p" tag (if the "sp" tag is not present) MUST be applied for non-existent subdomains."

From domain Tags published Policy applied
example.com any p
app.example.com (exists) sp present sp
app.example.com (exists) no sp p
zzz.example.com (NXDOMAIN) np present np
zzz.example.com (NXDOMAIN) no np, sp present sp
zzz.example.com (NXDOMAIN) no np, no sp p

The order is np, then sp, then p. If you set sp=none to protect a messy set of subdomains and skip np, non-existent subdomains inherit that none.

Why np=reject is a cheap win

Spoofing a subdomain is attractive because it looks plausible. security@alerts.example.com reads like something your company would send, and most domains at p=none do nothing to stop it.

np=reject closes that for every name that isn't in your zone, and it costs you almost nothing:

  • It doesn't touch mail from example.com. That still gets p.
  • It doesn't touch mail from any subdomain that exists. That still gets sp or p.
  • Subdomains you actually send from almost always exist. Setting one up with an ESP usually means publishing SPF, DKIM, or bounce records at or below that name.

That last point is where to check before you publish. Like p, np only applies to mail that fails DMARC, so aligned mail is unaffected. The one real risk is legitimate mail that uses a From subdomain with no DNS records at all and doesn't pass DMARC. Under p=none it's delivered today. With np=reject it gets rejected. Your aggregate reports show every From domain receivers saw. Resolve each subdomain in them before you add the tag.

A useful consequence: you can reject spoofed made-up subdomains while your real mail is still under p=none or p=quarantine. The work on the main domain (getting every sender aligned) takes weeks. This part doesn't have to wait for it.

Example records

Monitoring the main domain, rejecting made-up subdomains:

v=DMARC1; p=none; np=reject; rua=mailto:reports@example.com

Quarantine on real mail, reject on non-existent subdomains:

v=DMARC1; p=quarantine; np=reject; rua=mailto:reports@example.com

Loose policy on existing subdomains, strict on the rest:

v=DMARC1; p=reject; sp=none; np=reject; rua=mailto:reports@example.com

Here np=reject is doing real work. Without it, non-existent subdomains inherit sp=none.

Full enforcement:

v=DMARC1; p=reject; rua=mailto:reports@example.com

With no sp and no np, non-existent subdomains fall back to p=reject. Adding np=reject changes nothing at a DMARCbis receiver, though it documents intent.

Watch out for t=y

If you're using DMARCbis test mode during a rollout, it softens np too. RFC 9989 §4.7 says the t tag covers the policy "declared in the "p", "sp", and/or "np" tags." With p=none; np=reject; t=y, the p=none is untouched, but np=reject is treated as quarantine. See how t=y works for the full mapping.

Receivers that don't implement np

np is new to many receivers. A receiver still running RFC 7489 logic treats np as an unknown tag and ignores it (RFC 7489 §6.3). It then applies sp, or p if sp is absent, to all subdomains, existing or not.

That means np can't make anything worse at an older receiver. At worst it has no effect, and you get the same behavior as before you added it. At a DMARCbis receiver, it does exactly what you asked. RFC 9990 aggregate reports also include an np element in policy_published, so you can see which reporters picked it up.

Check your record

Run your domain through the DMARC record checker to see your current p, sp, and np, and what a spoofed non-existent subdomain would inherit.