Gravity SMTP 2.3.3 fixes several related OAuth connection defects for Google, Microsoft, and Zoho. Refreshing a callback could replay the authorization flow, a missing state value was not validated correctly, stale errors could persist, and failed or abandoned connections could appear active or primary. These defects can leave the admin screen disagreeing with the provider and the actual mail path.
Use this for WordPress sites that send through Google Workspace, Microsoft 365, Outlook, Zoho Mail, shared mailboxes, agency-managed OAuth applications, multisite, and any environment with separate staging and production redirect URIs.
Quick answer
Update to Gravity SMTP 2.3.3 or later, remove only known failed test connections, and run a clean authorization with a dedicated test mailbox. Capture the state value, callback URL, site URL, provider tenant, connection ID, and primary status without recording tokens. Refresh the completed callback, submit it without state, abandon a second flow, deny provider consent, and expire or revoke the token. One clean flow should create one active connection. Replays, missing state, denied consent, and abandoned flows must not become active or primary.
Test scenarios to run
Run the same controlled fixture across these branches. Write down the expected result before testing so a surprising response is easy to identify.
| Scenario | Fixture | Expected result |
| Clean callback | Valid state once | One active connection |
| Browser refresh | Used callback | No duplicate connection |
| Missing state | Callback without state | Rejected |
| Denied consent | Provider error | Inactive, not primary |
Diagnostic table
Use this table to connect the observed behavior to evidence and a verification step.
| Action | Evidence | Verification |
| Update and snapshot connections | Record plugin version, provider, OAuth application, redirect URI, WordPress home and site URL, proxy headers, multisite blog, initiating user, connection ID, and primary connection before testing. | Refreshing or reusing a callback cannot create, activate, or promote a second connection. |
| Authorize one clean mailbox | Run successful authorization, callback refresh, callback reuse in another browser, missing state, altered state, denied consent, abandoned tab, provider error, and expired nonce branches. | Missing or altered state is rejected without storing a usable token or exposing sensitive callback values. |
| Exercise callback failures | Compare the plugin connection list, active and primary flags, provider consent screen, token record metadata, test email result, email log, and outbound provider log. | The plugin, provider, email log, and delivered message agree on the active sending identity. |
| Revoke and reauthorize | Revoke the provider grant and confirm the connection fails clearly, does not silently switch identities, and can be reauthorized without duplicate active rows. | Token revocation produces a clear failure and one controlled reauthorization restores delivery. |
What to check first
- Record plugin version, provider, OAuth application, redirect URI, WordPress home and site URL, proxy headers, multisite blog, initiating user, connection ID, and primary connection before testing.
- Run successful authorization, callback refresh, callback reuse in another browser, missing state, altered state, denied consent, abandoned tab, provider error, and expired nonce branches.
- Compare the plugin connection list, active and primary flags, provider consent screen, token record metadata, test email result, email log, and outbound provider log.
- Revoke the provider grant and confirm the connection fails clearly, does not silently switch identities, and can be reauthorized without duplicate active rows.
- Verify staging and production use separate approved redirect URIs and that copying the database cannot make a staging token the production primary connection.
Field notes
- Write the pass condition before changing anything and keep one repeatable synthetic fixture for the full test window.
- Record exact versions and UTC timestamps because deployments, caches, retries, scheduled actions, and background jobs can change the evidence.
- Test the public path and the stored server-side result, not only an admin preview, isolated command, or API response.
- Repeat verification after the relevant cache, queue, cron, webhook, and observation window has completed.
Useful command or data shape
Adapt paths, IDs, and privacy handling to the site before running commands or storing data on production.
curl -sS -I --max-time 10 'https://example.com/wp-admin/admin.php?page=gravity-smtp'
wp option get gravitysmtp_version
Why this usually happens
- The callback is treated as repeatable even though the authorization code is single use.
- A connection row is created before state and provider success are fully validated.
- An old error message survives after a later successful authorization.
- A copied database retains primary flags that do not match the destination environment.
Decision rule
Approve the mail connection only when one authorization creates one active record, state failures are rejected, stale errors clear, abandoned flows stay inactive, and revocation has a tested recovery path.
Production verification checklist
- Refreshing or reusing a callback cannot create, activate, or promote a second connection.
- Missing or altered state is rejected without storing a usable token or exposing sensitive callback values.
- The plugin, provider, email log, and delivered message agree on the active sending identity.
- Token revocation produces a clear failure and one controlled reauthorization restores delivery.
Safe fix order
Use a sequence that makes each result easy to prove. Stop when new evidence changes the scope or owner of the problem.
- Update and snapshot connections
- Authorize one clean mailbox
- Exercise callback failures
- Revoke and reauthorize
- Separate environment credentials
Mistakes to avoid
- Changing production before recording exact versions, UTC timestamps, a stable fixture, the expected result, and a tested rollback point.
- Treating one successful screen as proof while stored records, logs, queues, caches, emails, APIs, and downstream systems remain unchecked.
- Testing only as an administrator instead of using the role, device, locale, cache state, payment state, and failure branch that customers reach.
- Leaving temporary exclusions, debug output, test accounts, broad permissions, or one-off repair code active after verification.
Questions teams ask during testing
Can I run this directly in production?
Begin with read-only evidence and use staging for package, database, checkout, form, permission, or security changes. If a production canary is necessary, make it identifiable, reversible, monitored, and unable to expose personal data or charge a customer.
How do I avoid a false positive?
Repeat the same fixture with the same versions, role, URL, locale, cache state, and integrations. Compare browser, stored, API, and log evidence instead of relying on one screen.
What should the evidence packet contain?
Keep UTC time, exact versions, synthetic record ID, expected result, actual result, relevant log lines, change made, rollback point, owner, and final verification. Redact secrets and personal data.
When is the test complete?
Close the work when the primary path passes, failure branches are understood, stored and downstream records reconcile, temporary changes are removed, and monitoring covers the next update.
What to tell the client or owner
Give the owner a concise packet with the affected workflow, exact versions, UTC test time, fixture ID, expected result, actual result, key logs, change made, rollback point, final result, unresolved risks, owner, and next review date. Remove credentials and personal data before sharing it.
When HandL WP should help
Bring in help when this affects leads, checkout, search visibility, security, paid media reporting, or a client production site. HandL WP can trace the issue through WordPress, hosting, cache, tracking, and Search Console, then verify the workflow after the technical fix.
If this is active on a production site, have HandL WP test SMTP OAuth delivery.
Related HandL WP guides
Use these related guides when the same issue touches tracking, security, checkout, or crawler visibility.
Test provider refresh and connector removal states
Zoho sites should add the Gravity SMTP Zoho expired-token refresh recovery test. Teams replacing providers should also run the removed connector stale-option test so delayed callbacks, stale tabs, and direct requests cannot reactivate an invalid route.
Helpful references