dmarc_rua_summary
Summarize DMARC aggregate reports to show pass/fail per domain and identify top IPs that a p=reject policy would block.
Instructions
Summarize DMARC aggregate (RUA) reports: pass/fail per domain, top reject-candidate IPs.
Impersonates the domain's configured dmarc_rua_mailbox (a real user --
domain-wide delegation cannot act as a group or alias; config default
postmaster@<domain>), searches it for mail addressed to
dmarc_rua_recipient (the rua=mailto: address published in DNS,
e.g. the postmaster+rua@ plus-subaddress; default: same as the
mailbox), reads the aggregate reports those messages carry, and answers "how much of this domain's mail volume is
passing DMARC, and if we moved the policy to p=reject, what would
actually get blocked?"
A record counts as PASS when either its aligned DKIM or SPF check reads
"pass" (DMARC's own OR semantics) — NOT when both do. A record counts as
a reject candidate when it is already quarantined or rejected (a tenant
already running p=quarantine/p=reject enforces this today), or when
BOTH checks fail with disposition="none" (what a stricter policy would
newly start blocking); everything else is a pass. This distinction
matters a lot in practice: a large share of legitimate mail (mailing-list
forwards, some relays) passes DMARC via SPF alignment alone with DKIM
unaligned, so counting on DKIM alone overstates the failure rate
severalfold.
reject_candidate_ips (the top top per domain by volume) is where
to actually look before flipping a policy to p=reject: a header_from
that names a SUBDOMAIN of the audited domain is governed by that
subdomain's own sp= policy, not the parent's p=, so it is not
necessarily what a p=reject change on the parent would affect.
Requires the gmail.readonly DWD scope — the same one
gmail_message_trace needs, granted PER SERVICE ACCOUNT CLIENT ID in
the Admin console (Security > API controls > Domain-wide delegation),
separately from the admin.directory.* / admin.reports.* scopes
the rest of this server uses.
Read-only: only messages().list/messages().get/
attachments().get against the one configured mailbox are issued —
see DomainClient.fetch_dmarc_rua_records.
Args:
hours: Lookback window. Default 72 (3 days): RUA reports typically
arrive roughly daily per sending source, so a single day's
window risks missing infrequent senders entirely.
domain: Configured [domain.*] section to report on. Default: all
configured domains.
mailbox: Override the configured dmarc_rua_mailbox (the user to
impersonate) for every selected domain. Set this only for an
ad-hoc check against a different inbox than the one in config;
unless recipient is also given, that inbox's own address is
searched. Also re-enables a domain configured with
dmarc_rua_mailbox = none for the duration of the call.
Validated as an email-shaped address (rejected otherwise).
recipient: Override the address searched for (to:) for every
selected domain -- the rua=mailto: value in DNS when it is
not the mailbox itself. Validated as an email-shaped address
(rejected otherwise) before use, since it is interpolated into
a Gmail search query.
max_pages: Gmail messages().list pages (100 messages each) to
walk per domain. capped=true in the result means more pages
existed — a capped fetch UNDER-counts real report volume, not
just a lower bound on some other total, since every matching
message must be walked (there is no server-side aggregate to
fall back on).
top: How many reject-candidate source IPs to return per domain
(highest volume first). The per-domain pass/quarantined/
rejected/undisposed_fail totals themselves are never truncated.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| top | No | ||
| hours | No | ||
| domain | No | ||
| mailbox | No | ||
| max_pages | No | ||
| recipient | No |