Back to blog
Threat Intel
Phishing Forensics

Postmortem: How We Blocked Our Own CRM with a `p=reject` DMARC Policy

We flipped the switch to DMARC `p=reject` to stop spoofing and ended up blocking our own customer invoices.

MailSleuth Research
Email Security Team
August 6, 20268 min read
An illustration of a line of falling dominoes being stopped by one mismatched domino, symbolizing a DMARC p=reject polic

The DMARC `p=reject` rollout was smooth. Too smooth. For about six hours, the world was quiet. Aggregate reports looked clean, our monitoring was green, and the team celebrated a milestone we'd been working toward for a year. Then the first ticket landed in the high-priority queue. It was from our Head of Finance. 'Customer X is asking for their invoice from this morning. Can you check if it sent?'

That single ticket was the leading edge of a business-critical outage. Within an hour, it was clear: no invoices, no password resets, and no support ticket confirmations had been delivered since we made the change. We had successfully locked down our domain against spoofing. In the process, we had also managed to block thousands of legitimate, automated emails from our own systems.

This is the story of how a well-intentioned security control, implemented to thwart BEC and CEO fraud, brought a core business function to a halt. It’s a technical postmortem, but it’s also a cautionary tale about the gap between RFCs and the messy reality of third-party SaaS.

The Plan: Full Enforcement to Shut Down Spoofing

The project's goal was simple and noble: get our primary domain to DMARC `p=reject`. We were responding to a string of sophisticated spear-phishing attempts targeting our executives. The pressure was on to make it impossible for an attacker to spoof an email from our CEO's address and have it land in an employee's inbox.

We had done our homework. Or so we thought. We spent six months at `p=none` collecting data, then another three at `p=quarantine`. We meticulously configured SPF (RFC 7208) for our Google Workspace mail exchangers and DKIM (RFC 6376) signing was enabled for all outbound mail. Our DMARC aggregate reports showed that nearly all mail originating from our own infrastructure was passing authentication and alignment checks. The small percentage of failures appeared to be from benign sources like mailing list forwarders, which ARC (RFC 8617) is slowly helping to solve, but which we accepted as a known issue. The path seemed clear.

The final DMARC record, defined in RFC 7489, was set to be the gold standard: `v=DMARC1; p=reject; rua=mailto:aggrep@dmarc.mycompany.com;`. The `p=reject` tag is an unambiguous instruction to receiving mail servers: if an email claiming to be from our domain fails the DMARC check, drop it. Don't deliver it, don't put it in spam, just reject it outright. We were confident we had identified all legitimate senders and were ready to close the door.

The Sound of Silence: When 'No News' Is Bad News

The morning after flipping the switch, the security channel was quiet. The calm before the storm. The first sign of trouble wasn't a security alert, but a confused message from the sales team. A lead was complaining they never received their welcome email. Then another from Finance about invoices. Then a flood of tickets into the support queue from users unable to reset their passwords.

A pattern emerged quickly. The failures were all tied to automated systems: our CRM, our billing platform, our main application. Human-to-human emails sent from our employees' mailboxes were flowing perfectly. My first reaction was denial. 'It can't be DMARC. Our reports were clean. Everything was aligned.' This is a classic incident response trap—trusting your past analysis in the face of contradictory live data.

We scrambled to find a common thread. All the failing systems were SaaS platforms. They were all configured to send mail on behalf of `mycompany.com`. And they were all, until about 8 hours prior, working flawlessly. The only variable that had changed was our DMARC policy. The evidence was pointing to a conclusion we didn't want to believe: we had just DDoSed our own customer communications.

Root Cause: A Fatal Mismatch in DMARC Alignment

Authentication vs. Alignment: The Critical Difference

Here's where many DMARC projects go off the rails. It’s easy to look at a report and see SPF `pass` and DKIM `pass` and assume you're good to go. But DMARC doesn't just care about authentication; it demands *alignment*. An email can have a perfectly valid SPF record and a cryptographically sound DKIM signature and still fail DMARC.

For SPF alignment, the domain in the `MAIL FROM` address (the envelope sender, used for bounces) must match the domain in the `From:` header (what the user sees). For DKIM alignment, the domain in the DKIM signature's `d=` tag must match the `From:` header domain. A mismatch in both means DMARC failure, regardless of whether SPF and DKIM passed for their respective domains.

Deconstructing the Failed Header

Once we got our hands on the raw headers of a rejected email from a friendly partner who pulled it from their MTA logs, the root cause became painfully obvious. The `Authentication-Results` header told the whole story.

Authentication-Results: mx.some-receiver.com;
dkim=pass header.d=crm-vendor.net header.s=selector1 ...
spf=pass (receiver.com: domain of bounces-xyz@crm-vendor.net designates 203.0.113.42 as permitted sender) smtp.mailfrom=bounces-xyz@crm-vendor.net;
dmarc=fail (p=REJECT sp=REJECT dis=REJECT) header.from=mycompany.com

Look closely. The email claimed to be from `finance@mycompany.com`. The SPF check `pass`ed, but for `crm-vendor.net`, the CRM's own domain used in the `smtp.mailfrom` path. The DKIM check also `pass`ed, but the signature was from `header.d=crm-vendor.net`. Neither of these passing results *aligned* with `mycompany.com`, the domain in the `From:` header. Therefore, the DMARC result was a hard `fail`. With our policy set to `reject`, the receiving server did exactly what we asked it to do and discarded the message.

Lesson 1: The `pct` Tag Is Your Safety Valve, Not an Optional Step

Our biggest mistake was impatience. We jumped directly from `p=quarantine` at 100% to `p=reject` at 100%. We completely skipped a phased rollout using the `pct` (percent) tag.

The `pct` tag is one of the most powerful and underutilized features of DMARC. It tells receivers to apply the policy (`quarantine` or `reject`) to only a certain percentage of emails that fail the DMARC check. For example, `p=reject; pct=5;` means 'reject only 5% of failing mail and let the other 95% through.' This is not a suggestion; it's a core part of the RFC 7489 specification designed for exactly this kind of incremental deployment.

Had we started with `pct=5`, we wouldn't have had a total outage. We would have seen a small number of rejections in our forensic (RUF) reports or a small number of support tickets. It would have been a warning shot, not a cannonball through the hull. We could have identified the CRM issue, rolled back the change, and fixed the problem without impacting every single customer. The rollout path should always be a slow ramp: `pct=5`, `pct=10`, `pct=25`, `pct=50`, and finally, after weeks of monitoring, `pct=100`.

Lesson 2: You Must Audit Every Single Third-Party Sender

DMARC aggregate reports tell you *what* IPs are sending on behalf of your domain, but they don't tell you *who* they are or *why* they're sending. This incident taught us that a technical audit is insufficient. You need an organizational one.

Creating Your Sender Inventory

The real work is mapping sending IPs and domains back to the business services that use them. This means getting leaders from Marketing, Sales, Finance, HR, and Engineering into a room and building a comprehensive inventory. For every service that sends email, you must ask:

Does it send from our main corporate domain? Does it support custom DKIM signing, allowing it to sign with a key we control under our domain? If not, does it at least sign with its own domain and provide a stable `MAIL FROM` for SPF alignment? The answers determine if a service is compatible with a `p=reject` policy on your main domain. Our CRM was not.

The Subdomain Strategy for Non-Compliant Senders

So what do you do with a critical service that can't achieve DMARC alignment on your organizational domain? You don't weaken your core security posture. You move the service to a dedicated subdomain.

For example, instead of our CRM sending from `finance@mycompany.com`, it should send from `finance@billing.mycompany.com`. This isolates its email stream. You can then create a separate, tailored set of SPF, DKIM, and DMARC records for `billing.mycompany.com`. This allows that service to operate correctly without diluting the high-trust status of `mycompany.com`, which should be reserved for employee communications and fully compliant services.

Recovery: Rollback, Isolate, and Relaunch

The immediate fix was simple: we reverted the DMARC record in DNS back to `p=quarantine`. Within the hour (our TTL), emails from the CRM started flowing again. The outage was over, but the real work was just beginning.

Our investigation confirmed that our CRM vendor did not support custom DKIM alignment on our subscription tier. The long-term solution was exactly the subdomain strategy we had neglected to consider. We provisioned the subdomain `billing.mycompany.com` specifically for this service. We worked with the vendor to reconfigure their platform to send from `invoices@billing.mycompany.com`. We published new SPF and DKIM records for this subdomain and a separate `p=quarantine` DMARC policy to monitor it.

With the non-compliant CRM traffic successfully isolated, we were finally able to restart the `p=reject` rollout for our primary `mycompany.com` domain. This time, we followed the `pct` ramp-up religiously. It took an extra month, but it was successful and, more importantly, completely silent.

The takeaway

Moving to `p=reject` isn't a finish line you cross; it's a new operational state you must constantly maintain. It transforms DMARC from a passive reporting tool into an active enforcement mechanism, and it will ruthlessly expose any shortcuts you took in your sender audit. Every new SaaS tool your marketing or sales team onboards is a potential new source of DMARC failure.

A full sender inventory isn't a 'nice-to-have' for `p=reject`—it's the non-negotiable price of admission. The good news is that the process itself, while tedious, forces a level of visibility and control that benefits the entire organization. Tools that parse DMARC reports and help map infrastructure to known senders, like MailSleuth.AI, can turn this daunting audit into a manageable, repeatable process. Don't let your next successful security implementation become your next production outage.

#dmarc#email-security#p-reject#spf#dkim#postmortem
MailSleuth Research
Email Security Team

We dissect phishing campaigns and email infrastructure so you don't have to.