What p=reject actually does

A DMARC policy is an instruction to receiving mail servers about what to do with a message that uses your domain in the visible From header and fails DMARC. p=none says do nothing beyond reporting. p=quarantine says treat it as suspicious, which in practice means the spam folder. p=reject says refuse it.

Most receivers that honour p=reject do so at the SMTP transaction with a permanent 5xx response, so the sending server does not queue and retry — the message is gone on the first attempt. Some receivers accept the message and discard it afterwards, in which case there is not even a bounce for the sender to notice. Either way the mailbox owner never sees it, and you, the domain owner, get no real-time signal. What you get is a row in the next aggregate report:

<row>
  <source_ip>203.0.113.27</source_ip>
  <count>142</count>
  <policy_evaluated>
    <disposition>reject</disposition>
    <dkim>fail</dkim>
    <spf>fail</spf>
  </policy_evaluated>
</row>

That is the crux of the risk. Reject is a policy applied by other people’s servers to mail you may not know you are sending, and the feedback loop runs a day behind, at best.

“Fails DMARC” means “not aligned”, not “not yours”

It is worth being precise about which mail gets rejected. DMARC does not reject mail that is fraudulent; it rejects mail that is not aligned with your domain. A message passes DMARC if SPF or DKIM passes and the domain that passed matches the From domain. A perfectly legitimate invoice sent by your billing platform, authenticated cleanly against the platform’s own domain, fails alignment against yours — and under p=reject that invoice is refused exactly as if it were a phish. The worked example in how SPF and DKIM can both pass while DMARC fails shows the headers this produces.

So the question before moving to reject is not “is anyone spoofing us?” It is “does every system that puts our domain in a From header authenticate in a way that aligns with it?” Every sender you have not found is a sender you have not aligned, and every sender you have not aligned is a sender you are about to block.

The senders that get missed

Ask an IT team to list what sends mail as their domain and the answer is usually the mail platform, the marketing ESP, and one or two SaaS products. The aggregate reports almost always show more. The categories that reliably turn up late:

  • Transactional SaaS with a “send as your domain” setting. CRM, helpdesk, HR and payroll, billing and invoicing, e-signature, project management, recruiting, booking and scheduling. Each of these was configured by whichever team bought it, often years ago, and each sends from From addresses on your domain unless it was told otherwise.
  • Devices. Multifunction printers doing scan-to-email, alarm and building-management systems, UPS and network hardware sending alerts. These relay through whatever SMTP host was reachable when they were installed, frequently with no authentication at all.
  • Servers and cron jobs. Application error mail, backup reports, monitoring alerts, anything that calls sendmail on a box that has been running since before anyone on the current team joined.
  • Vendors sending on your behalf. An outsourced payroll provider, a survey vendor, a debt-collection agency, a print-and-post service — anyone contracted to email your customers “from” you. See sending DMARC-compliant mail on behalf of others for how that is supposed to be set up, and why it often isn’t.
  • Subsidiaries, acquisitions and regional offices running their own mail platform, often on a subdomain (below).
  • Low-frequency senders. Quarterly statements, annual renewal notices, end-of-financial-year mail, an awards programme that sends once a year. A month of clean reports says nothing about a system that sends in March.

The report data is the inventory, and it only counts what has actually sent during the observation window. That is why the advice in publishing a DMARC record is to sit at p=none for a full business cycle rather than a couple of weeks: the sender you are worried about is the one that has not sent yet.

Subdomains inherit the policy

A p=reject on example.com applies to every subdomain that does not publish its own DMARC record, unless the organisational record sets a different sp (policy for existing subdomains). Under DMARCbis it also applies to non-existent subdomains unless np is set. So the moment example.com goes to reject, mail from alerts.example.com, crm.example.com and mail.au.example.com is subject to the same policy — whether or not anyone knew those hostnames were sending.

This is where an incomplete inventory does the most damage, because subdomain senders are exactly the ones that were set up outside the main mail platform. Two defensive options while the inventory is still running:

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

Enforce on the organisational domain, quarantine rather than reject on existing subdomains until their senders are aligned, and reject outright on subdomains that do not exist (nothing legitimate sends from those). Or publish a separate _dmarc.alerts.example.com record with its own policy for any subdomain whose senders are still being worked out.

The DMARC Inspector shows the p and sp a published record resolves to, including the inherited default.

The SPF trap: fixing one sender can break every sender

The usual way to align a newly discovered sender is to add it to SPF. SPF is limited to ten DNS lookups per evaluation, and every include: for a SaaS platform costs one or more of them. Adding the fifth or sixth vendor is regularly what pushes a record over the limit, at which point SPF returns permerror — for every message, from every sender, not just the one you added.

Under p=none that is an inconvenience visible in reports. Under p=reject, any sender that relied on SPF for alignment (which is most of them, because DKIM alignment through a third party takes a custom selector that many were never given) now fails DMARC and is refused. One DNS edit, made to fix a sender, has rejected all of them.

The SPF Check tool counts lookups against the limit for the record as it is actually published. Run it before and after every SPF change once you are at enforcement, and prefer DKIM alignment for every sender that can support it, so that SPF’s fragility stops being the thing your mail depends on.

Aligned today is not aligned permanently

Identifying a sender and aligning it once is not the end. Senders drift:

  • A vendor rotates its DKIM keys and expects you to update the CNAMEs it gave you. If they were TXT copies of the key rather than CNAMEs to the vendor’s own records, the signature stops validating.
  • A platform changes its sending IP ranges and its include: no longer covers them.
  • Someone in another team enables a new “send from our domain” feature in a tool that was previously sending from the vendor’s domain.
  • A subdomain’s dedicated DKIM selector is cleaned up by someone tidying the DNS zone.

At p=none or p=quarantine, each of these shows up as a dip in alignment for a source you recognise, and you have time to fix it. At p=reject the same event is an outage for that sender, and the first report of it is usually a customer asking why the invoices stopped. Enforcement is the point at which monitoring has to become continuous rather than a project with an end date.

Indirect mail flows fail on purpose

Two flows break under p=reject even when every sender you control is perfectly aligned, and it is better to decide about them deliberately than to discover them afterwards.

Forwarding. A message forwarded by the recipient’s own mailbox rule (or an alumni address, or a role account that redirects elsewhere) breaks SPF, because the forwarding host is not in your SPF record. DKIM survives if the forwarder did not touch the signed content. A sender aligned only by SPF therefore fails DMARC after forwarding; the same sender aligned by DKIM passes. This is the strongest practical argument for getting DKIM alignment on every sender before enforcing, not just SPF.

Mailing lists. Lists commonly add a subject tag or a footer, which invalidates the original DKIM signature, and they resend from their own server, which breaks SPF. Under p=reject, posts from your users to lists that do not rewrite the From header are rejected by every subscriber’s mailbox provider that honours your policy. Well-run lists detect a reject policy and rewrite From to work around it; older ones do not. DMARCbis is explicit that domains whose users post to mailing lists should think hard before publishing p=reject, and that a subdomain or separate domain for those users is the usual answer.

What a safe move to reject looks like

The stages are the ones in how to publish a DMARC record; the point here is what has to be true before each step.

  1. At p=none, until the inventory is complete. Every source in the aggregate reports is identified — named, owned by a team, and either aligned or explicitly decided against. There are no rows you cannot explain. The window has covered at least one full billing and reporting cycle of your business, so the quarterly and annual senders have had a chance to appear.
  2. At p=quarantine; t=y, for at least a month. Quarantine is the rehearsal: a sender you missed lands in spam rather than disappearing, which means someone tells you about it. t=y is the DMARCbis testing flag that signals to receivers you are in a trial phase. Watch the reports for any recognised source whose alignment slips. (pct was the older way to phase this in; DMARCbis removed it, and the wizard no longer offers it.)
  3. At p=reject, without t=y, only when quarantine has run clean. Lower the DNS TTL on the _dmarc record before the change so a rollback takes minutes, not a day. Keep watching the reports with the same attention as before: the enforcement stage is where a new unknown source is a problem to solve within hours, not a curiosity.

If a disposition=reject row appears for a source you recognise, the fix is usually to drop back to p=quarantine, align that sender, and return — not to stay at reject and hope the volume is small. Mail that was refused while you decided is not recoverable.

Reading your own reports for the unknowns

The report data is where the unidentified senders are. If you are not yet using a monitoring service, the XML-to-human Converter turns a raw aggregate report into a table of sources with their alignment results and dispositions, in the browser, without uploading it. Sort by source and look for the rows you cannot name; those are the senders that a move to p=reject would cut off. DMARCLoop does the same thing continuously, resolves each source to a named service where it can (see how DMARCLoop identifies sources), and tells you when the evidence says the next step is safe rather than leaving that judgement to a calendar.