External reputation feedback
Connect Google Postmaster Tools and enroll in Microsoft SNDS and JMRP.
External reputation feedback
Owlat's Delivery health page compares its own complaint signal with reputation data reported by mailbox providers. Provider data is delayed and sampled; use it as evidence alongside SMTP outcomes, not as a real-time delivery guarantee.
Google Postmaster Tools
Google's API requires OAuth 2.0 authorization from a user who can read the
authentication domain. A DNS check performed by Owlat does not grant that
Google account access. Register and verify the DKIM d= domain or SPF
Return-Path domain in Postmaster Tools, then
create an OAuth client with the Postmaster Tools API enabled.
Request only these read scopes:
https://www.googleapis.com/auth/postmaster.domainhttps://www.googleapis.com/auth/postmaster.traffic.readonly
Generate an offline refresh token for the Google user and configure all three MTA variables together:
GOOGLE_POSTMASTER_CLIENT_ID=...
GOOGLE_POSTMASTER_CLIENT_SECRET=...
GOOGLE_POSTMASTER_REFRESH_TOKEN=...
Restart the MTA. The leader queries the v2 domainStats resource for the
preceding seven UTC dates hourly because Google commonly publishes data after a
delay. A persisted, bounded domain cursor eventually covers accounts with more
domains without allowing one run to grow without limit. The collector also has
a distributed overlap lease, a wall-clock budget, one refresh-on-401 attempt,
and bounded Retry-After/transient-error retries.
The refresh token stays in the MTA environment, the access token stays in Redis
for less than its provider-declared lifetime, and neither is sent to Convex,
logs, Prometheus, or the browser. Before querying statistics or creating any
per-domain cursor or receipt, the MTA asks the signed Convex endpoint whether
that exact domain is currently verified in Owlat. The response contains only
accepted_authorized or ignored_unowned; it exposes no tenant record.
Authorization probes and observations bypass generic raw-webhook audit storage,
and the MTA never puts them in its generic dead-letter queue. A failed delivery
leaves the domain page uncheckpointed, so the next bounded sweep safely retries
it. Only an accepted_authorized observation creates a receipt. A persistent
generation index lets each completed discovery cycle remove cursor and receipt
state for domains Google no longer lists, including across MTA restarts; cleanup
is capped per run and never scans the Redis keyspace. No per-domain Postmaster
metric is exported: the dashboard consumes the structured Convex aggregate.
Owlat retains that daily aggregate for 90 days and deletes it when the sending
domain is removed; an unverified or deleted domain replay is acknowledged
without retaining its name or payload.
Owlat collects, per verified domain per UTC day:
SPAM_RATE— the share of delivered mail Gmail users reported as spam.SPF_SUCCESS_RATE,DKIM_SUCCESS_RATE,DMARC_SUCCESS_RATE— the share of traffic that authenticated, as Google measured it rather than as our own DNS check predicts.DELIVERY_ERROR_RATEplus a best-effort per-category breakdown (rate limiting, suspected spam, bad DMARC policy, and so on).- The v2 Compliance Status verdict: each check's pass/fail, stored with the check name Google reported. A check name Owlat has no guidance for is kept and rendered generically rather than dropped.
Google may omit a metric when traffic is too low. No data is not a zero spam
rate, and a partial day is normal — a metric that is missing is simply absent
from the stored row. The current v2 StandardMetric contract does
not expose the v1 domain-reputation, IP-reputation, sample-IP, or spam-rate
confidence-bound fields. Owlat marks those reputation details unavailable; it
does not call v1 with incompatible v2 scopes or infer ratings from another
metric. If Google adds reputation metrics to v2, Owlat can add them against
that published contract.
Postmaster Tools is additive only. A deployment with no Google account connected sends exactly the same mail: the collector returns early, nothing is written, nothing errors, and the Delivery page shows a "not connected" affordance explaining that connecting raises measurement confidence. Failing compliance checks surface as actionable cards on the Delivery page that name the check and the remedy, never as a raw API field.
Sources: Google API setup and OAuth scopes, authentication-domain setup, the v1-to-v2 migration guide, v2 domain statistics query, and v2 standard metrics.
Microsoft SNDS and JMRP
Microsoft's Smart Network Data Services is IP-oriented. Sign in with a Microsoft account, request access to every public outbound IP you control, and complete the portal's authorization process. Then use View Data and View IP Status to monitor unusual behavior and reputation.
In the same portal, enroll those IPs in the Junk Mail Reporting Program and
send reports to a monitored abuse mailbox. JMRP reports are complaint evidence:
process them promptly through the existing feedback/suppression flow and never
re-mail a complaining recipient. Owlat needs no new plumbing for them — JMRP
reports are RFC 5965 ARF, so they land in the same feedback processor as every
other ISP's complaints, attributed to the original send by its signed VERP
return path. Microsoft frequently omits the standard recipient fields and
carries the complaining address only in X-HmXmrOriginalRecipient on the
re-attached original, which the processor reads as a last resort.
Importing the SNDS data feed
Microsoft's July 2026 portal announcement replaced the legacy
sendersupport.olc.protection.outlook.com/snds/ links with per-account
Automated Data Access URLs. Generate one per registered IP range and set
them as SNDS_DATA_FEED_URLS (comma- or whitespace-separated, https only).
Keep them secret: each URL is a bearer capability to your SNDS data.
Owlat polls those feeds every six hours and stores one row per sending IP per UTC day — the complaint-rate band, the filter result, spam-trap hits and the day's volume counters — with 90-day retention. The feed reports activity in sub-day windows; a day folds them together, summing counters and keeping the worst band and filter result of the day. Registered ranges overlap, so a day reported by two of your feeds folds into that same single row instead of two competing ones.
SNDS reports a complaint-rate band, not a rate, so Owlat stores and reasons
about the band. 0.1% - < 0.2% is never turned into 0.0015: that would invent
a precision Microsoft never published, and every downstream decision would then
compare a fabricated number. A band spelling Owlat does not recognise is stored
as unknown, which holds the ramp rather than moving it. The parser matches the
column against Microsoft's documented spellings whole — < 0.1%, > 0.9% and
one-band-wide ranges such as 0.3% - < 0.4% — and never reads a number out of
text it does not otherwise recognise. So a bound that is not a band edge
(< 0.5% spans five bands), a widened range (0% - < 0.9% spans nine), a
localized decimal separator and a prose rewording are all unknown rather than
guessed at. The feed is internet-supplied, < 0.1% is the only band that can
justify speeding the ramp up, and the one direction the parser must never fail
is towards "cleaner than measured".
The gate breaches from 0.1% - < 0.2% upwards, matching the complaint gate it
sits beside, and also on any red filter result or any spam-trap hit. Each poll
and each gate read is bounded — the feed body is capped while it streams, the
number of (IP, day) observations per poll is capped, and both the ingest and the
gate work newest-day-first so a same-day breach can never fall off the end of a
cap — a day that was never stored would otherwise read later as a day with
nothing wrong in it.
A read that hits its cap is marked low-confidence, so a partial window can slow
the ramp but never justify speeding it up.
Enrollment is optional, and its absence is a supported configuration rather than
an incomplete setup. With no feed configured the poller returns immediately —
no request, no row, no error — and the Microsoft ramp leans on the outcomes of
its own sends instead (bounce, deferral and complaint rates, plus seed placement
at Outlook), dwelling twice as long before it advances and capping one phase
lower. If you declare
your sending addresses in MTA_IP_POOLS, feed rows for any other address are
dropped, since an SNDS key can cover a whole registered range.
MTA_IP_POOLS also scopes the gate's read, not just the ingest. With a pool
declared the gate reads only the days recorded against those addresses. With no
pool declared it reads the window whole but marks it unattributed: a clean
band in a shared registered range may belong to another sender, so it stays
usable for slowing the ramp and can never speed it up. Concretely: a clean
unattributed window holds rather than passing, because a pass is what grows
the clean streak an increase is spent from — and a spam-trap hit that is the
only breaching evidence in such a window holds too. Evidence that may be a
neighbour's moves the ramp in neither direction. Breaches are unchanged: a red
filter result or a band at or above the breach band still fails the gate whether
or not the window is attributed, because a problem inside our own registered
range is still ours to answer. Every verdict derived from an unattributed window
says so in its reason and names the remedy. Declaring your pool is
therefore the cheapest way to raise the Microsoft cell's measurement confidence
— and, like every other external signal here, not declaring it slows the ramp
and does nothing else.
Microsoft sources: SNDS portal and enrollment and Outlook.com sender troubleshooting.