• v0.48.0 d252416be5

    joeyr released this 2026-08-25 20:32:51 -05:00 | 68 commits to main since this release

    The DMARC policy was there the whole time, in the same header the "could not
    be read" note was printed beside.
    0.47.0 split absent from p=none, which
    was right, and then explained the absence as a property of the provider —
    "iCloud stamps one, Gmail does not". Gmail stamps it inside the dmarc=
    clause. The parser was not reading that shape, and the note turned a parsing
    gap into a documented fact about Google, which is the kind of wrong answer that
    stops anyone looking again.

    Fixed

    • dmarc_policy was empty on every Gmail message, and the policy was in the
      clause.
      Google writes it as an RFC 8601 comment on its own verdict:

      dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=example.org
      

      _PROPERTY matches ptype.property=value and excludes parens, so nothing
      ever looked inside one. dmarc_policy_unknown therefore fired on 100% of
      that tenant's decisions — the replacement warning landing exactly where the
      one it replaced had, for a different reason.

      Measured 2026-08-25, probes/probe_dmarc_policy.py, over the 4,602-message
      Gmail archive: 1,147 messages carry a trusted dmarc= verdict and 1,147 of
      them carry the policy
      — 501 p=none, 422 p=quarantine, 224 p=reject.
      So on 56% of them the honest answer was a policy stronger than the weak
      case a reader supplies for themselves, and on the other 44% it was the weak
      case, stated. X-DMARC-Policy was present on 0 of 1,147, which is the fact
      0.47.0 had and the one it generalised from.

      _dmarc_comment_tags reads p, sp and dis out of the comment, and
      lowercases them: Google writes p=QUARANTINE, _POLICY_NOTE keys on the RFC
      spelling, and a straight pass-through would have fallen through to
      "Unrecognised published DMARC policy" across the whole tenant while looking
      like it had read the value.

    • The two records now have a precedence rule, and it is the one that cannot
      be forged.
      The clause comment wins over X-DMARC-Policy: it sits inside a
      header is_trusted has already ruled on, so it carries the same boundary
      check as the verdict it qualifies, while X-DMARC-Policy has no authserv-id
      and nothing here can distinguish Apple's from one a sender wrote. 0 of 1,168
      messages across both tenants carry both, so this is a rule against a future
      provider rather than a resolution of an observed conflict.
      dmarc_policy_source reports which record answered.

    • A reported policy now names the domain it belongs to. This is the one new
      way populating the field could mislead, and it is closed in the change that
      populates it. The policy is the evaluated domain's, and under a relay that
      is the forwarder: all 258 relayed messages on the archive report
      SimpleLogin's p=quarantine, and not one of them says anything about
      whoever wrote the message. A bare policy: quarantine beside a forwarded
      message reads as the sender's defences. policy_domain and a sentence on
      policy_note say whose it is.

      summarise's relayed branch has existed since 0.45.0 and had never fired
      on Gmail
      , because the value it guards was always empty there. It fires now.

    • sp= is reported, never substituted. 128 of 1,147 publish p=none sp=quarantine. Which applies depends on whether the From domain is the
      organisational domain or a subdomain of it, which needs the public suffix
      list — a dependency and a periodic data update this module does not carry —
      so both are reported and neither is chosen. dis= is reported separately as
      what the server actually did, which is not what the domain asked for.

    • The legacy bare d= DMARC domain was unreadable. Google's older clauses
      name the evaluated domain d=paypal.com rather than header.from=, and 11
      of 1,147 still arrive that way. Unread, evaluated_from is empty and
      evaluated_from_matches_header comes back False — which is the signature
      of a message carrying two From headers, asserted about ordinary mail from a
      bank. Read on dmarc only, and with comments stripped first: a bare-tag scan
      across every clause would start lifting values out of the free text in an SPF
      comment, which the sending domain's own name shapes.

    • _POLICY_UNKNOWN_NOTE no longer names the wrong cause. It described the
      parser's blind spot as something Gmail does not do. Both providers report the
      policy now, so the branch is left for the cases that are honestly unknown:
      nothing evaluated DMARC, or it was evaluated without a policy recorded.

    Verified

    • probes/probe_dmarc_policy.py, read-only, both tenants, 2026-08-25 — the
      counts above. Like every probe here it is gitignored, so they are a dated
      record against a named sample rather than something re-derivable from this
      repo.
    • probes/probe_policy_live.py on real Gmail mail: a direct message reports
      policy: quarantine, policy_source: authentication-results,
      policy_domain: duck.com; a relayed one reports policy_domain: simplelogin.co with the assessment naming the policy as the relay's.
      dmarc_policy_unknown is gone from both.
    Downloads