Subdomain Policy — the sp Tag

Subdomain policy — the sp tag

DMARC has one policy that applies to the organizational domain and an optional separate policy that applies to subdomains. The second one is the sp= tag. When sp is absent, subdomains inherit p. When sp is set, it overrides for subdomains.

This is the field that surfaces during a DMARC ramp because marketing and notification subdomains are almost always where the first breakage shows up.

How the policy tree works

A receiver evaluating a message from news@marketing.isidoregroup.com looks up DMARC in this order:

  1. Try _dmarc.marketing.isidoregroup.com first. If a DMARC record exists there, use it.
  2. If not, fall back to _dmarc.isidoregroup.com — the organizational domain.
  3. From that record, read sp= if present. That is the policy for the subdomain.
  4. If sp is absent, use p=.

The practical consequence: a domain with only _dmarc.isidoregroup.com published and p=reject will reject failing mail from any subdomain too, unless sp= says otherwise.

A typical record using sp

v=DMARC1; p=reject; sp=quarantine; rua=mailto:dmarc@isidoregroup.com

This says: enforce p=reject on mail claiming to be from isidoregroup.com, but only p=quarantine on mail from any subdomain. A reasonable posture during a ramp where the organizational domain has been validated but subdomains have not.

The inverse is also valid:

v=DMARC1; p=quarantine; sp=reject; rua=mailto:dmarc@isidoregroup.com

This says: be looser on the apex (where third-party tools commonly send) and stricter on subdomains (where nothing legitimately sends). The asymmetry is useful when you have one or two known unaligned third-party senders on the apex you cannot yet fix but you know your subdomains have no legitimate traffic.

Why marketing and notification subdomains break first

Most enterprise marketing platforms — Marketo, HubSpot, Mailchimp, Constant Contact, Pardot — recommend or require their clients send from a subdomain rather than the apex. Common patterns:

  • email.{client}.com
  • news.{client}.com
  • marketing.{client}.com
  • notifications.{client}.com

The platform’s recommendation is to delegate that subdomain (NS records pointing to the platform) or at least to publish SPF, DKIM, and a From: configuration that the platform manages.

When you publish DMARC at the apex with p=reject and no sp=, the platform’s mail from news.{client}.com is subject to that policy. If the platform did not align correctly — either because it sends from its own envelope domain and never published a DKIM key under your subdomain, or because the client never finished the delegation — the marketing send fails DMARC the moment you flip to enforcement.

This is the call you will get: “we sent our monthly newsletter this morning and nobody got it.” The aggregate report will show 30,000 messages with <source_ip> belonging to the marketing platform and <policy_evaluated> showing disposition=reject.

sp=quarantine (when the rest is at p=reject) is a way to soften that landing while you fix the platform’s alignment. It is not a permanent answer.

When to use sp vs. publish a subdomain DMARC record

Two options when a specific subdomain needs different handling:

Option A — use sp= at the apex. Affects every subdomain uniformly. Simple. Used when subdomains as a class need a different posture than the apex.

Option B — publish a separate DMARC record at _dmarc.subdomain.{domain}. Affects only that one subdomain. Used when one subdomain (marketing, say) needs different treatment but other subdomains should follow the apex policy.

_dmarc.marketing.isidoregroup.com  TXT  "v=DMARC1; p=none; rua=mailto:dmarc@isidoregroup.com"

This puts marketing.isidoregroup.com at observe-only while the apex stays at p=reject. The receiver looks up _dmarc.marketing.isidoregroup.com first, finds it, and stops there.

Option B is finer-grained. Use it when you have one specific subdomain you need to handle differently — typically because you are mid-onboarding a marketing platform and have not finished its DKIM setup.

The trap to avoid

sp= is sometimes mistakenly used to mean “send-policy” or “subdomain pattern.” It is neither. It is subdomain policy — and only the policy. It takes the same three values as p: none, quarantine, reject. Anything else is ignored.

It also does not stack. There is no “subdomain of a subdomain” handling. _dmarc.isidoregroup.com controls every subdomain of isidoregroup.com (via p or sp), and a published _dmarc.x.isidoregroup.com controls exactly that subdomain. There is no _dmarc.y.x.isidoregroup.com cascading rule.

Where Cathedra sits

DmarcRecordCheck.php parses sp along with the other tags but does not produce a separate finding on its value. The check focuses on p, pct, and rua. Your job is to read the record, recognize when sp is present and how it differs from p, and predict which subdomain traffic will be affected.

When troubleshooting a “newsletter didn’t deliver” call, the DMARC record’s sp (or the presence/absence of a subdomain DMARC record) is one of the first three things you check, alongside the aggregate report from that day.

What you should remember

  • sp= sets the policy for subdomains. If absent, subdomains inherit p=.
  • A separate _dmarc.subdomain.{domain} record overrides both. The receiver checks subdomain DMARC first, then falls back to the apex.
  • Marketing and notification subdomains break first during a DMARC ramp. Plan for them before you flip the apex to enforcement.
  • sp=quarantine on a record with p=reject softens the landing for unaligned subdomain senders while you fix them.
  • Cathedra parses sp but does not produce a separate finding. Read it manually from the record.

Cathedra alignment: DmarcRecordCheck.php — sp is parsed by the tag parser but not the source of a distinct finding; understanding it explains where subdomain-related alignment failures fall in the policy tree