deniz.in

Markets

Weather

Loading weather

· via dev.to (home feed)

DMARC's RFC 9989 update drops pct, so deleting the tag silently tightens records

RFC 9989 moved DMARC onto the IETF Standards Track in May and removed the pct tag, so tidying old records can quietly push them to full enforcement. Here is what changed and what to check.

DMARC's RFC 9989 update drops pct, so deleting the tag silently tightens records

DMARC was published as RFC 9989 on 19 May 2026, ending its roughly ten-year run as a merely informational specification and placing it on the IETF Standards Track. According to a dev.to post by Steven Browning, the new document replaces RFC 7489 and RFC 9091, spins reporting out into two companions (RFC 9990 for aggregate reports, RFC 9991 for per-message failure reports), and removes the pct tag entirely. That last change is the trap: plenty of deployed records still carry pct, and editing them to remove a now-dead tag quietly changes what they do.

Removing pct is not a neutral edit

The pct tag was the classic tool for staged rollouts: publish p=quarantine alongside pct=25 and only a quarter of failing messages get quarantined while you watch the reports and raise the number. RFC 9989 drops the tag, citing how inconsistently receivers interpreted it, and documents the removal in a dedicated appendix.

The subtlety is what cleanup does. As Browning explains, receivers that never recognised pct were already applying the published policy to all failing mail, so deleting pct=25 does not restore some remembered quarter-sampling behaviour. It makes full enforcement explicit: a domain that quarantined a sample of failures now quarantines every one of them. That may be the intended destination, but the post argues it is better chosen deliberately than discovered through bounced mail.

A testing mode replaces the percentage ramp

The replacement is a t tag. With t=y, receivers are asked to act one notch gentler than the published policy — p=reject is treated as quarantine, p=quarantine as none — while aggregate reports keep arriving. It is a cleaner mechanism than statistical sampling, but the gradual percentage ramp no longer exists; the choices are now a testing mode or the policy itself.

When p=reject is the wrong destination

RFC 9989 also pushes back on the assumption that p=reject is the end goal. Section 7.4 says domains whose users post to mailing lists should not publish p=reject. Mailing lists and forwarders relay and rewrite messages in ways that break the original authentication, so a reject policy bounces legitimate mail from your own users, and list software often responds to those bounces by unsubscribing them. A purely transactional domain can sensibly end at reject; a domain used by humans may want to stop at quarantine.

Three smaller spec changes

Organisational domain discovery no longer consults the Public Suffix List. RFC 9989 defines a series of DNS queries it calls the DNS Tree Walk — a name worth remembering when something behaves oddly on a multi-level domain. The np tag, carried over from RFC 9091, lets you publish a policy for subdomains that do not exist at all, useful because non-existent subdomains are commonly abused for spoofing; without np they inherit sp, or failing that p. And sp is now ignored on records published below the organisational domain level, which explains subdomain sp settings that never appeared to do anything.

SPF and DKIM traps in the same records

An SPF record can look short yet sit close to RFC 7208's ceiling of ten DNS-querying terms per evaluation, since every include: pulls in whatever the provider publishes, recursively. Exceeding it returns a permerror — a hard failure that only shows up in reports — and the spec also recommends at most two void lookups, a reason to drop includes for long-abandoned services. Separately, a record ending in a bare all authorises every sender, because an unqualified mechanism defaults to +; ~all or -all was almost certainly intended. Two SPF records at the same name is also a permerror, fixed by merging them into one.

On the DKIM side, a checker reporting a missing key often just means it guessed at common selectors and missed yours, since no standard lookup enumerates them. A real signed message settles it: in the DKIM-Signature header, s= is the selector and d= the signing domain, which frequently belongs to a sending platform rather than matching the From address. A key record with an empty p= value means the key was revoked, not that it is absent.

What to check before touching anything

The post suggests three steps: inspect a real message header from your own domain sent to an external recipient, which hands you the DKIM selector and signing domain; read the end of your SPF record and count the includes; and review a week of aggregate reports before tightening anything, because there is nearly always a legitimate sender nobody remembered.

Why it matters

Email authentication records are configured once and then left alone for years, and DNS raises no alarm when a spec revision retires something a record still references. The pct removal turns routine hygiene into a policy change: a well-meaning cleanup expands enforcement from a sampled share to every failing message, with no error message anywhere. The damage lands on legitimate mail — mailing-list posts, forwarded messages — that suddenly gets quarantined or rejected. Reading reports before editing is the cheap insurance. One boundary worth noting: these records stop others sending as your domain; they do not filter inbound mail and cannot prevent lookalike domains.

  • #dmarc
  • #email-authentication
  • #dns
  • #spf
  • #dkim