Whether you are building a brand-new SMTP-based application for sending email or maintaining a legacy system, you’ve likely heard the news: Google and Microsoft are officially putting an end to Basic Authentication. This means the days of simply using an app password to connect to servers such as smtp.gmail.com are over! To continue using applications that send email on behalf of users, organizations must adopt OAuth 2.0, the recommended and supported authorization mechanism for secure access.
This article focuses on migrating classic SMTP authentication to OAuth2 at the protocol level, explaining what happens on the wire. While Google’s OAuth2 infrastructure is used as a concrete reference, the flows described are based on publicly published standards rather than provider-specific behaviour, making them equally relevant to developers integrating SMTP with other OAuth2-compliant identity providers.
Why SMTP Authentication Is Changing
Traditional SMTP authentication relies on long-lived usernames and passwords that are broadly scoped and difficult to rotate safely. Once compromised, these credentials often provide unrestricted access until manually revoked.
OAuth2 replaces this model with short-lived, scoped access tokens, eliminating the need for applications to store mailbox passwords. For SMTP clients, this significantly reduces the impact of credential leakage and allows access to be revoked server-side without redeploying applications. As a result, OAuth2 is no longer an optional enhancement—it is the baseline security requirement for modern mail providers.
OAuth2 in the Context of SMTP
In the SMTP world, OAuth2 does not change message submission semantics or delivery behaviour. Instead, it replaces the password-based authentication step with a token-based mechanism defined through SASL extensions.
From the server’s perspective, the SMTP session still follows the same state machine defined by RFC 5321 (Simple Mail Transfer Protocol ). OAuth2 only affects how the client proves its identity during the authentication phase.
Choosing the Right OAuth2 Strategy
Google offers several scenarios depending on your application type. For classic SMTP clients, you will generally choose one of these two:
- The Service Account (Silent/Server-to-Server): Ideal for automated background applications that send mail on behalf of many users in a Google Workspace domain. It requires a one-time setup by an administrator, after which the application works silently without user intervention.
- User Consent (The 3-Legged Path): Best for applications where an actual person is present to explicitly grant permission via a login screen, such as a desktop or web app.
The remainder of this article elaborates on the Service Account–based approach, as it most closely aligns with how classic SMTP clients are typically deployed in server-side applications.
The Service Account Flow : High-Level Implementation Overview
At a high level, OAuth2 replaces the SMTP password with a temporary access token obtained using a signed JSON Web Token (JWT). From an SMTP client’s perspective, the process involves the following steps:
- Load service account credentials
- Construct and sign a JWT
- Exchange the JWT for an OAuth2 access token
- Authenticate to the SMTP server using the OAUTHBEARER mechanism
Service Account Credentials
Service Account credentials are created in the Google Cloud Console and downloaded as a JSON key file. This file contains the only copy of the private key used to sign JWTs.
A typical key file contains fields similar to the following :
{
"type": "service_account",
"project_id": "example-project",
"client_email": "smtp-sa@example-project.iam.gserviceaccount.com",
"private_key_id": "abcdef123456",
"private_key": "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n"
} Constructing the JWT
The JWT is how the application proves its identity to Google’s OAuth2 token endpoint. The JWT consists of a header and a payload. For Google, the header must use the RS256 algorithm. The payload contains your “Claims”—the rules of your request:
JWT Claims
The payload includes a small set of required claims:
{
"iss": "smtp-sa@example-project.iam.gserviceaccount.com",
"sub": "sender@your-domain.com",
"scope": "https://mail.google.com/",
"aud": "https://oauth2.googleapis.com/token",
"iat": 1700000000,
"exp": 1700003600
} For readers new to OAuth2:
- iss (The Issuer): identifies the service account making the request. In Gmail case, it is your Service Account’s email address.
- sub (The Subject) specifies the mailbox being impersonated via domain-wide delegation. It will be same as the sender’s email address.
- scope defines what access is being requested. For Gmail SMTP, use https://mail.google.com/.
- aud (audience) indicates the intended recipient of the JWT. Use https://oauth2.googleapis.com/token.
Required Google Cloud Setup
Before the logic above can work, you must complete these administrative steps in the Google Cloud and Google Workspace environments:
- Create the Service Account: Generate the account in your project and download the JSON key file from the IAM & Admin > Service Accounts page.
- Enable the Gmail API: You must explicitly enable the Gmail API in the API Library for your Google Cloud project.
- Set Up Domain-Wide Delegation: To use the sub claim for impersonation, a Workspace Super Admin must manually authorize your Service Account’s Client ID in the Google Admin Console under Security > Access and data control > API Controls.
Please refer to https://developers.google.com/identity/protocols/oauth2/service-account for official documentation on this setup.
OAuth2 Token Acquisition
Before issuing the SMTP AUTH command, the client exchanges a signed JWT for an OAuth2 access token using the JWT Bearer grant:
grant_type = urn:ietf:params:oauth:grant-type:jwt-bearer
assertion = <signed JWT>
A successful exchange returns an HTTP 200 OK response containing a short-lived access token.
Note: JWT structure is defined by RFC 7519 (JSON Web Token (JWT)) , and the JWT Bearer exchange by RFC 7523 (JSON Web Token (JWT) Profile for OAuth 2.0 Client Authentication) .
Authenticating to SMTP with OAUTHBEARER
With a valid access token available, legacy mechanisms such as AUTH LOGIN are replaced by AUTH OAUTHBEARER.
Conceptually, the authentication payload contains:
- the user identity being asserted
- the SMTP host and port
- the OAuth2 access token
n,a=<user_email>,
\x01host=<smtp_host>
\x01port=<smtp_port>
\x01auth=Bearer <access_token>
\x01\x01
The entire string is Base64-encoded and transmitted as:
AUTH OAUTHBEARER <base64-encoded-response>
Please note that Base64 encoding is mandated by RFC 4954 (SMTP Service Extension for Authentication)
Complete SMTP Session Flow with OAuth2
OAuth2 does not alter SMTP’s state machine—it only replaces the authentication mechanism. The session still follows the same high-level phases as any standard ESMTP exchange.
At a conceptual level, the flow consists of three stages:
- Capability discovery
The client issues EHLO to determine which extensions the server supports, including STARTTLS and SASL authentication mechanisms.
- Transport security
If STARTTLS is advertised, the connection is upgraded to TLS. Because SMTP extensions apply only to the current transport context, the client must reissue EHLO after the TLS handshake.
- Authentication
Once a secure channel is established and AUTH OAUTHBEARER is advertised, the client authenticates using an OAuth2 access token instead of a password.
The complete back-and-forth message exchange for these steps is illustrated in the diagram below.
Handling the 334 Response Common Failure Modes & Debugging Tips
This section is particularly helpful when migrating existing SMTP clients.
- 530 Authentication required
- STARTTLS not issued before AUTH
- EHLO not re-sent after TLS
- 535 Authentication failed
- Incorrect sub claim
- Missing domain-wide delegation
- Expired token or incorrect scope
- EHLO succeeds but AUTH is not advertised
- Gmail API not enabled
- OAuth2 not enabled for the tenant
- Repeated 334 response
- Client incorrectly re-sending credentials instead of CRLF
Here, as specified in RFC 7628, (Simple Authentication and Security Layer (SASL) Mechanisms for OAuth ) if the server returns a 334 intermediate response, the client must acknowledge it by sending an empty response (CRLF).
Ensuring a Secure and Reliable Implementation
Given the significant security implications of getting the implementation correct, Google strongly encourages the use of OAuth 2.0 client libraries when interacting with their endpoints. Using well-debugged, standard libraries helps protect your application and your users from subtle implementation errors that could lead to security vulnerabilities.
- Official Client Libraries: Google provides various libraries for languages like Java, Python, and Node.js that handle the complex tasks of JWT signing and token refreshing automatically. (Please refer to: https://developers.google.com/identity/protocols/oauth2#libraries)
- Third-Party Solutions: For developers who prefer a modular approach, I personally suggest third-party libraries such as Chilkat (www.chilkatsoft.com) are excellent for streamlining the entire OAuth2 flow.
















