Get OAuth credentials from Google for a WordPress SMTP plugin

A WordPress SMTP plugin that authenticates to Gmail or Google Workspace by OAuth needs three things from the Google Cloud Console: a Client ID, a Client Secret, and an authorized redirect URI that matches what the plugin emits. Everything else in the setup flow exists to make those three values issuable and trustworthy. The Cloud Console UI has been redesigned several times since Less Secure App (LSA) access was Google's name for the third-party authentication path that used a plain account password against Gmail's SMTP, IMAP, and POP endpoints. Google shut it down for consumer accounts on 30 May 2022 and for Workspace accounts on 1 May 2025; OAuth, App Passwords, or a different sending provider replace it. Read full reference → was removed in 2022, and it will be redesigned again; the credential set, the OAuth consent screen, and the publishing-status system do not change with it. This guide names the durable objects rather than walking through current button positions.

The credential set

A WordPress mailer plugin using Gmail OAuth presents these fields:

  • Client ID is the public identifier for the WordPress site as a registered OAuth client. It travels in the browser, embedded in the authorization URL the plugin redirects the user to. It is safe to expose in logs or DOM inspection.
  • Client Secret is the confidential half of the credential. It stays on the WordPress server, in the plugin’s options, and is sent server-to-server when exchanging the authorization code for an access token and refresh token. Anyone with the secret can impersonate the WordPress client.
  • Authorized redirect URI is the address Google sends the user back to after they consent. The plugin shows this in its connector setup and expects to receive the authorization code at it. It is registered on the Google side and must match what the plugin sends, character for character.

Two fields the wizard offers that mailer plugins do not use:

  • Authorized JavaScript origins is for OAuth flows that complete in the browser. WordPress mailer plugins run the web server flow, where the redirect URI is the field that matters and JavaScript origins is unused. Leave it empty unless a specific plugin asks for it.
  • Scopes, configured on the OAuth consent screen rather than on the credential, name the permissions the plugin will request. For SMTP-style sending the relevant scope is https://www.googleapis.com/auth/gmail.send, classified as a sensitive scope in the Gmail API documentation. (Restricted Gmail scopes, which carry stricter verification requirements, are the read/compose/modify family. gmail.send is not among them.) The sensitive classification matters for verification; see the publishing-status section below.

Before opening the Cloud Console

Two things are needed before the Cloud Console is useful. The first is a Gmail or Google Workspace account that will own the project and the credentials. The owning account does not have to be the mailbox the WordPress site will send from, though for a single-mailbox setup they are usually the same.

The second is the redirect URI the WordPress plugin emits. Every mailer plugin shows this on the connector configuration screen: FluentSMTP, WP Mail SMTP, Post SMTP, and Gmail SMTP all display it before authorization. Copy it. Do not retype it. A trailing slash, a missing s in https, or an unexpected path segment produces Error 400: redirect_uri_mismatch at consent time, and the fix is always on the Google side.

Three objects in a Cloud project

Three Cloud Console objects have to exist before the credential becomes usable, in this order.

The first is a Google Cloud project. It is the container: quota, billing, API enablement, and OAuth credentials are all scoped to it. A single WordPress site maps cleanly to a single project; an agency managing many sites can run one project per client, which keeps consent screens, branding, and any future verification submissions separate. The Gmail API itself has no per-call billing under quota; the project only incurs charges when paid APIs are enabled.

The second is the Gmail API, enabled on the project. Enabling makes the API callable from credentials issued in the project. The Gmail API quota is published at 80,000,000 quota units per day per project, and a messages.send call costs 100 units, putting the per-project ceiling at 800,000 sends per day. A typical WordPress site does not approach it.

The third is an OAuth consent screen, configured on the project. This is the user-facing screen Google shows when the WordPress plugin redirects the mailbox owner to authorize the application. The text reads roughly “WordPress for example.com wants to send email on your behalf.” The consent screen carries the app name, the support email, the developer contact, the scopes the app will request, and the list of test users where applicable. The project must have a consent screen configured before any OAuth client created in the project will work.

User type and publishing status

This is the part of the setup that determines whether the credential keeps working in production, and the part the original wizard-driven setup guides routinely skipped.

The consent screen has two axes that interact: user type and publishing status.

User type is set once. Internal restricts the credential to accounts inside the same Google Workspace organisation; the unverified-app screen and brand verification do not apply to Internal apps. (Workspace admins can still gate access through admin-console scope policies; Internal removes Google-side friction, not organisation-side policy.) External allows any Gmail or Workspace account to consent and is the only option available to a Gmail account that is not part of a Workspace. Most independent WordPress sites have to pick External.

Publishing status moves between Testing and In Production. Testing is the default. While in Testing, the consent screen lists up to 100 explicit test users (added by email address); only those users can complete the consent flow. The condition that bites operators a week later: External apps in Testing issue refresh tokens that expire after 7 days, regardless of which scopes are requested. Moving to In Production removes the 100-user cap and the 7-day refresh expiry, but it requires Google to verify the app. For a gmail.send-only app (sensitive scope) verification is Google review of the OAuth consent screen plus a homepage, a privacy policy, and a demonstrated use case. For an app requesting restricted Gmail scopes, verification additionally requires an annual third-party security assessment (CASA). Sensitive-only apps do not need CASA.

The practical pattern that comes out of this:

  • Workspace mailbox, served by a Workspace admin. Set user type to Internal. Verification does not apply. The credential is stable.
  • Gmail (non-Workspace) mailbox. User type is forced to External. Leave publishing status as Testing and add the sending mailbox as a test user. The credential works. It also requires re-authorization once a week, because the refresh token expires after seven days. This is the silent foot-gun in the consumer-Gmail path, and it is the reason a configuration that worked on day one stops working on day eight.
  • Workspace mailbox, no admin access. Treat it as the Gmail case: External user type, Testing publishing status, sending mailbox added as a test user, weekly re-authorization. The alternative is publishing the consent screen and completing sensitive-scope verification, which is reasonable for an organisation that can carry a homepage and a privacy policy and unreasonable for most independent sites.

A consumer-Gmail account that cannot tolerate weekly re-authorization is a candidate for App Password authentication instead of OAuth, or for moving the sending mailbox to Workspace. The choice between OAuth and App Passwords is laid out separately in Gmail OAuth vs App Passwords.

Creating the OAuth client

The Credentials surface in the Cloud Console is the destination. Create an OAuth client ID. Choose Web application as the application type; the web server flow is what the plugin runs. Name the client something descriptive (the project name plus the WordPress hostname is a workable convention). Paste the redirect URI from the plugin into the Authorized redirect URIs field. Save.

Google displays the Client ID and Client Secret immediately and offers both for download as a JSON file. Either copy the two values into the plugin’s connector configuration, or download the JSON and paste from there. Both fields are retrievable later from the same Credentials screen; the secret can also be rotated there if it leaks.

The two rules that survive UI redesigns

These are the two pieces of the setup that fail most often and are the most common subject of support requests on every SMTP plugin’s forum.

Redirect URI matching is exact. https://example.com/wp-admin/admin.php?page=fluent-smtp and https://example.com/wp-admin/admin.php?page=fluent-smtp/ are different URIs as far as Google is concerned, and so are the same URLs with http instead of https. A redirect_uri_mismatch error at consent time is almost always this. The fix is never on the WordPress side. Copy what the plugin shows, paste without editing, and save the Google credential again. One detail worth knowing: edits to an OAuth client’s authorized URIs can take from 5 minutes to a few hours to propagate, per Google’s documentation. If a corrected redirect URI still produces the same error immediately after saving, wait before chasing other causes.

External + Testing = 7-day refresh token. A WordPress site that sent email correctly for the first week and started failing on day eight is almost certainly hitting this. The trigger is the External user type combined with Testing publishing status; the scope requested does not change the rule. For gmail.send the practical effect is the same regardless: either move the credential to a Workspace organisation and set user type to Internal, or publish the consent screen and complete Google’s sensitive-scope verification. There is no third option for a long-lived OAuth credential in this configuration.

Service accounts and domain-wide delegation

A complete alternative for Google Workspace: a service account credential with domain-wide delegation granted by a Workspace super-admin. With delegation, the WordPress site can send as any mailbox in the Workspace domain without a per-user consent flow, and the credential does not expire on the consumer-Gmail schedule. This is the right path for a multisite estate that needs to send from many mailboxes in the same Workspace, or for transactional sending that should not depend on a single user staying authorized.

Service-account setup is its own procedure and does not use the OAuth consent screen at all. A separate nanoPost guide covers it; the short answer for the OAuth-credential reader is that domain-wide delegation exists, it is only available to Workspace, and it removes most of the consent and verification complexity at the cost of needing a super-admin to enable it.

The plugin holds the refresh token from the first authorization and mints fresh access tokens (typically about an hour each, returned in the expires_in field) transparently as needed. Google’s Cloud Console will move things around again. The credential set will not.