Gmail Postmaster Tools
Connect Gmail Postmaster Tools to Sendry to pull spam-rate, IP and domain reputation, SPF/DKIM/DMARC pass rates, and delivery errors directly into your deliverability dashboard.
Gmail Postmaster Tools
Sendry can pull your domain's Gmail Postmaster Tools metrics once a day and surface them on the Deliverability dashboard. There are two ways to connect:
- Connect with Google — the in-product OAuth flow. Recommended for most users.
- Manual paste — paste a refresh token from your own Google Cloud project. Use this if your Sendry instance hasn't enabled the OAuth flow, or if you need fine-grained control over which Google account is used.
Either way, only the read-only Postmaster scope is requested
(https://www.googleapis.com/auth/postmaster.readonly). Sendry never asks for Gmail mailbox
access.
Prerequisites
- Your sending domain must already be verified in Gmail Postmaster Tools. Sign in at postmaster.google.com, add the domain, and complete the DNS TXT verification before connecting to Sendry. Without verification, the daily sync will return no data for the domain.
- You must sign in to Sendry with an account that has
full_accessto the organization.
Option 1 — Connect with Google (recommended)
- In the Sendry dashboard, go to Deliverability → Connect Gmail Postmaster.
- Click Connect with Google.
- Sign in to the Google account that owns your Postmaster Tools verifications and approve the read-only scope.
- You'll be redirected back to Sendry. The page now shows the connected Google account and the last sync timestamp.
Behind the scenes, the dashboard:
- Calls
GET /v1/postmaster/oauth/startto get a Google consent URL with a 10-minute state token bound to your org. - Redirects to Google. After consent, Google redirects back to
GET /v1/postmaster/oauth/callback?code=…&state=…. - Sendry exchanges the code, stores the refresh token, and 302's back to
/deliverability/postmaster-connect?connected=1.
The postmaster-sync worker runs daily at 02:00 UTC and refreshes the access token from
the stored refresh token each run. You can also trigger a one-off sync via
POST /v1/postmaster/sync.
Disconnecting
Click Disconnect on the connect page (or call POST /v1/postmaster/oauth/disconnect).
This clears only the OAuth tokens; any manually-pasted credentials remain untouched.
When the dashboard button is greyed out
If you see an "OAuth not configured on this Sendry instance" alert, the API server hasn't been provisioned with Google OAuth credentials. Ask your admin to set the following environment variables on the API process:
GOOGLE_OAUTH_CLIENT_ID=... # Google Cloud OAuth 2.0 Client ID
GOOGLE_OAUTH_CLIENT_SECRET=... # Google Cloud OAuth 2.0 Client Secret
GOOGLE_OAUTH_REDIRECT_URI=... # e.g. https://app.sendry.online/v1/postmaster/oauth/callback
The redirect URI must be added to Authorized redirect URIs in the Google Cloud Console
for the OAuth client, and the https://www.googleapis.com/auth/postmaster.readonly scope
must be added to the OAuth consent screen's allowed scopes.
Until those env vars are set, fall back to Option 2 — Manual paste.
Option 2 — Manual paste
If you'd rather use your own Google Cloud project (or your Sendry instance hasn't enabled
the in-product OAuth flow), POST a refresh token directly:
curl -X POST https://api.sendry.online/v1/postmaster/credentials \
-H "Authorization: Bearer $SENDRY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"google_oauth_client_id": "...apps.googleusercontent.com",
"google_oauth_client_secret": "...",
"google_oauth_refresh_token": "1//0g..."
}'
To obtain a refresh token from your own GCP project:
- Create a Web Application OAuth 2.0 client in Google Cloud Console.
- Add
https://www.googleapis.com/auth/postmaster.readonlyto the consent screen scopes. - Run the OAuth playground or your preferred tool to complete the consent flow with
access_type=offline+prompt=consentto get a refresh token.
The worker will use these per-org credentials instead of Sendry's shared OAuth client.
What metrics get pulled?
For each verified domain in your Sendry org, the daily sync pulls the previous day's
Postmaster traffic stats and writes one row to postmaster_metrics:
| Column | Source |
|---|---|
spam_rate | userReportedSpamRatio |
ip_reputation | bucket with the highest ipCount |
domain_reputation | domainReputation |
dkim_success_rate | dkimSuccessRatio |
spf_success_rate | spfSuccessRatio |
dmarc_success_rate | dmarcSuccessRatio |
feedback_loop_identifier_rate | average of spammyFeedbackLoops[].spamRatio |
inbound_encryption_ratio | inboundEncryptionRatio |
outbound_encryption_ratio | outboundEncryptionRatio |
delivery_errors | raw deliveryErrors[] array (JSONB) |
You can read these back via GET /v1/postmaster/metrics?domain_id=&from=&to=, or view them
under Deliverability → Reputation.
Troubleshooting
Google returns access_denied on the callback.
You clicked "Cancel" on the consent screen, or your Google account doesn't have access to
the Postmaster verifications. Retry with the correct account.
Callback fails with state_org_mismatch.
You switched orgs in another browser tab between starting and finishing the flow. Restart
the connect flow from the Sendry tab where you want the credential bound.
Callback fails with missing_refresh_token.
Google only returns a refresh token on first consent. If you previously granted Sendry
access without using our prompt=consent flag, revoke Sendry's access in your
Google account permissions and retry.
Daily sync logs Failed to refresh OAuth token for an org.
The refresh token has been revoked (user-initiated, password change, or 6-month inactivity).
Reconnect via the dashboard.
No metrics appear after 24 hours.
Confirm the domain is verified at postmaster.google.com. The sync skips 404s silently —
they just mean Postmaster has no data for that domain on the requested date.
AI in the Editor
Generate subject lines, preview text, and image alt-text in multiple languages, and reference existing broadcasts or templates with @mentions.
DMARC Analyzer
Upload DMARC aggregate XML reports (or pipe them in via a DMARC mailbox) and see a pass/fail digest per source IP for the last 7-30 days.