cloudflare / cloudflare/workerd

Email Routing → Worker delivery: Authentication-Results header missing, ARC- Authentication-Results contains no SPF/DKIM/DMARC verdicts

Open
#6,740 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
C++
Stars
8.7k
Forks
739
Avg merge
2d 20h
Merged PRs (30d)
174

Description

On Email Routing → Worker delivery (catch-all rule for *@domain.com routed to a Worker via 'Send
to a Worker' action), inbound mail arrives at the Worker with NO 'Authentication-Results' header
and an 'ARC-Authentication-Results' header that contains only 'arc=none' — no spf=, dkim=, or
dmarc= verdicts. This makes it impossible for a Worker to apply SPF/DKIM/DMARC-based spam
filtering on inbound mail.

Expected behavior:

Per Cloudflare Email Routing documentation, the receiving MX should perform SPF/DKIM/DMARC checks
and stamp an 'Authentication-Results' header on the message before it is delivered to the Worker.
At minimum, the ARC-Authentication-Results header (RFC 8617) should preserve verdicts from
upstream authenticators when the message has been forwarded through one (e.g. Gmail).

Actual behavior:

For mail forwarded through Gmail (Substack newsletter → Gmail user → forwarded to alias on
domain.com), the Worker observes:

message.headers.get('Authentication-Results') // returns null message.headers.get('ARC-
Authentication-Results') // returns 'i=1; mx.google.com; arc=none'

Note 'mx.google.com' as the authority — this is Gmail's own ARC seal, NOT a Cloudflare-stamped
header, and Gmail provided only 'arc=none' (meaning 'no upstream ARC chain') without any
SPF/DKIM/DMARC verdicts. There is no header in the message containing those verdicts.

Full list of headers present on the ForwardableEmailMessage (from a diagnostic console.log in the
Worker):

arc-authentication-results, content-type, date, from, in-reply-to, message-id, mime-version,
references, reply-to, subject, to, x-cf-spamh-score, x-gm-features

Notably absent: Authentication-Results, Received-SPF, Received, DKIM-Signature.

Reproduction steps:

1. Configure Email Routing for a domain with a catch-all rule routing *@ to a Worker via 'Send to a
Worker'.
2. Deploy a Worker that logs both 'Authentication-Results' and 'ARC-Authentication-Results' headers
from message.headers.
3. From a Gmail account, forward an email (e.g. a Substack newsletter that originally passed
SPF/DKIM/DMARC at Gmail) to @.
4. Observe in 'wrangler tail' that Authentication-Results is null and ARC-Authentication-Results
contains only 'arc=none'.

Diagnostic Worker code used:

console.log(JSON.stringify({ auth_raw: message.headers.get('Authentication-Results'), arc_raw:
message.headers.get('ARC-Authentication-Results'), header_names:
Array.from(message.headers).map(([k]) => k), }));

Impact:

Workers on Email Routing cannot rely on SPF/DKIM/DMARC for inbound spam/spoof filtering, even
though Cloudflare's MX has the data needed to populate the header. Forced workaround is to either
(a) disable auth-based filtering entirely, (b) parse the raw RFC 5322 message ourselves with a
DKIM verifier (heavy lift in a Worker), or (c) trust HMAC envelope authentication only and hope
the upstream mail isn't a forgery.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.