Your DMARC is set to reject — but attackers are phishing from your subdomains

You did the work. SPF configured, DKIM keys published, DMARC policy at p=reject. Your DMARC reports show clean passes. You’re done.

Except your subdomains are probably unprotected, and attackers know it.

Phishing emails landing in your customers’ inboxes right now — signed “from: billing.yourcompany.com” or “no-reply.mail.yourcompany.com” — pass every email filter because your DMARC policy says nothing about those subdomains. The p=reject rule you spent three months rolling out only protects yourcompany.com exactly. Not one level below it.

This is the subdomain DMARC gap. It’s not obscure. Attackers enumerate it deliberately.

Why subdomains aren’t covered by your root DMARC policy

Your DMARC record lives at _dmarc.yourcompany.com. The policy there applies to email from yourcompany.com — the organizational domain — and nothing else, by default.

An email from billing.yourcompany.com triggers a DMARC lookup at _dmarc.billing.yourcompany.com first. If that record doesn’t exist (which it doesn’t, for almost every subdomain you’ve never explicitly configured), the lookup falls back to _dmarc.yourcompany.com. But the fallback behavior isn’t to apply p=reject. It’s to apply whatever the sp= tag says — and if sp= is absent, the fallback is p=none.

So the attack scenario looks like this:

  1. Attacker sends email with From: billing.yourcompany.com
  2. Receiving server looks up _dmarc.billing.yourcompany.com — record doesn’t exist
  3. Falls back to _dmarc.yourcompany.com — finds your record
  4. Your record says p=reject but doesn’t have sp=
  5. Fallback policy is p=none — no action taken
  6. Email lands in the inbox

Your DMARC aggregate reports show this as passing with no issues. Because from the root domain’s perspective, nothing failed.

The sp= tag and what it does

RFC 7489 defines the sp= tag to specify the policy applied to subdomains of the organizational domain when no subdomain-specific DMARC record exists.

Your current DMARC record probably looks something like:

v=DMARC1; p=reject; rua=mailto:...

With sp= added:

v=DMARC1; p=reject; sp=reject; rua=mailto:...

That one addition tells receiving mail servers: if you’re evaluating mail from any subdomain of this domain and there’s no subdomain-specific record, apply reject. No exceptions.

The three values mirror the main p= tag: none (no action, monitor only), quarantine (spam folder), reject (block delivery).

Why sp=reject is the right default for most organizations

If your subdomains don’t send email — and most of them don’t — sp=reject is the correct setting. You’re not rejecting legitimate mail. You’re rejecting all mail, which is exactly right for subdomains that have no business sending email in the first place.

The domains that need consideration are the ones that legitimately send email from a subdomain:

  • mail.yourcompany.com — sometimes used as a return-path domain by sending services
  • em.yourcompany.com or sends.yourcompany.com — common SendGrid and Mailchimp tracking domains
  • helpdesk.yourcompany.com — Zendesk, Freshdesk, or similar

For these, you have two options. The cleaner approach is to publish a full DMARC record at _dmarc.mail.yourcompany.com with the appropriate policy for that specific subdomain. The subdomain-specific record takes precedence over the fallback, so it won’t inherit sp=reject from the root. The messier approach is to set sp=quarantine at the root — slightly softer than reject — to give yourself room for subdomains that aren’t cleanly configured.

The practical recommendation: set sp=reject at the root, then audit which subdomains actually send email and give them their own records.

How to find your sending subdomains

Before touching your DMARC record, you need to know which subdomains send email. There are three places to look.

Your sending service dashboards. SendGrid, Amazon SES, Postmark, and similar services show you the domains and subdomains they’re authorized to send from. Check the verified sender domain list in each service you use.

Your DNS records. Look for CNAME entries pointing to third-party sending infrastructure. em.yourcompany.com CNAME something related to SendGrid or Salesforce Marketing Cloud is a sign that subdomain sends email. Look for SPF records on subdomains too — if mail.yourcompany.com has its own v=spf1 record, it’s sending email.

Your DMARC aggregate reports. If you’re receiving aggregate report XML, look for records where the header_from shows a subdomain. If billing.yourcompany.com is appearing in reports with pass results, that subdomain is in use. If it’s appearing with no results, it might be a spoofing target.

DMARC Guardian’s domain overview shows subdomain activity alongside your root domain — if any of your subdomains have appeared in aggregate reports, they show up in the sources view.

The wildcard subdomain problem

Even with sp=reject in place, there’s a related attack vector worth understanding: wildcard subdomains that your DNS legitimately resolves.

If your DNS has a wildcard A record (*.yourcompany.com → some IP), every possible subdomain resolves. That doesn’t enable phishing directly — DMARC is about email authentication, not DNS resolution — but it does mean that any service you spin up under a subdomain will inherit sp=reject protection automatically, without you needing to remember to configure DMARC for it. Which is exactly the behavior you want.

What you’re protecting against with sp=reject is an attacker using a non-resolving subdomain (billing.yourcompany.com with no DNS record at all) in the From: header of a phishing email. Receiving mail servers don’t require the subdomain to resolve in DNS. They evaluate the DMARC policy based on the organizational domain alone. sp=reject tells them: reject that mail regardless.

The fix is one DNS change

If you’ve confirmed which subdomains legitimately send email and given them their own DMARC records, the root fix is straightforward:

_dmarc.yourcompany.com  TXT  "v=DMARC1; p=reject; sp=reject; rua=mailto:your-rua-address"

If you’re not sure yet and want to audit first, add sp=quarantine as an intermediate step:

_dmarc.yourcompany.com  TXT  "v=DMARC1; p=reject; sp=quarantine; rua=mailto:your-rua-address"

This won’t block subdomain-spoofed mail outright, but it will push it to spam — which generates signals you can monitor while you identify whether any legitimate subdomain mail starts getting flagged.

After publishing the change, wait 48 hours for DMARC aggregate reports to reflect the new policy. Review for any unexpected quarantine increases that might indicate a legitimate subdomain you missed. If you see nothing new in quarantine, move to sp=reject.

What this looks like in DMARC reports

The signal you’re looking for after adding sp=reject is subdomain mail appearing in aggregate reports with a reject disposition rather than none. If that mail was legitimate — a sending service you forgot about — it will appear with a volume spike in failing sources.

The riskier outcome is that nothing appears: the attacker-sent mail was being delivered without appearing in DMARC reports because the policy was none and receivers weren’t reporting it. After adding sp=reject, the legitimate concern shifts from monitoring to confirmation — you want to verify that nothing got newly blocked that shouldn’t have been.

DMARC Guardian’s reports view shows disposition breakdowns per source. After applying sp=reject, the none disposition for subdomain sources should drop to zero. Any remaining volume with reject disposition indicates mail that got blocked — review the IP sources to confirm it’s not a misconfigured legitimate sender.

sp= is one line. Deploy it today.

Most teams skip sp= because nothing prompts them to add it. The DMARC deployment guides focus on the root domain. The monitoring dashboards show root domain health. The subdomains sit unprotected in the background until someone points it out.

Adding sp=reject to your existing DMARC record takes five minutes. If your subdomains don’t send email — and you’ve checked — it’s zero risk. If they do send email, finding that out now, in your own audit, is significantly better than finding it out because a customer got a convincing fake invoice.


DMARC Guardian’s DNS tab shows subdomain DMARC coverage for every domain you’re monitoring. If your root domain has p=reject but sp= is missing, the setup guide flags it as an open gap.