OAuth Email API: Authenticate User Mailboxes the Right Way
Stop storing passwords. An OAuth email API lets your app access user inboxes securely - using revocable, scope-limited tokens from Gmail, Outlook, and IMAP providers. This guide covers every OAuth flow, every scope, every pitfall, and how to ship in 5 minutes with a unified hosted auth layer.
// Connect any user mailbox via OAuth - 1 API call
const response = await fetch(
'https://api6.unipile.com:13226/api/v1/hosted/accounts/link',
{
method: 'POST',
headers: {
'X-API-KEY': 'YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
type: 'GOOGLE', // or MICROSOFT, IMAP
name: 'user_123'
})
}
);
const { url } = await response.json();
// Redirect user to url - OAuth handled by UnipileWhat is an OAuth Email API?
An OAuth email API is a programmatic interface that grants your application access to user mailboxes using OAuth 2.0 tokens - without ever handling or storing the user's password. Instead of asking users for credentials, you redirect them through the provider's consent screen, receive a short-lived access token, and use it to read, send, or sync emails on their behalf. The distinction matters: this is about accessing user-owned mailboxes (Gmail, Outlook, personal email), not sending transactional emails via SMTP relay services like SendGrid.
An OAuth email API is a combination of an OAuth 2.0 authorization flow (to authenticate a user and obtain delegated access) and an email API (to read, send, search, or sync that user's mailbox). The OAuth layer generates a cryptographically signed, revocable, scope-limited access token. The email API consumes that token to interact with Gmail, Outlook, or any IMAP-compatible mailbox - all without ever knowing the user's password.
- Stores plaintext or encrypted passwords in your DB
- Full mailbox access - no scope control
- Blocked by Google/Microsoft since 2026
- GDPR/SOC2 liability for credential storage
- Zero password storage - only short-lived tokens
- Granular scopes - read-only, send-only, or full
- Revocable at any time by the user
- Compliant with GDPR, SOC2
Why OAuth Replaced Password-Based Email Access
Using IMAP with a username and password used to be the standard way to access user email programmatically. That era is over. Google deprecated basic authentication for Gmail in 2022, and Microsoft completed its shutdown of basic auth for Exchange Online in October 2022, with the final sweep for remaining protocols in 2026. If your application still relies on password-based IMAP access, it is either already broken or will break soon.
OAuth tokens are short-lived (typically 1 hour) and scope-limited. Even if leaked, they cannot be used to log in as the user, change their password, or access other services. You never touch the user's credential.
Microsoft completed its retirement of basic authentication for Exchange Online and legacy IMAP in 2026. Any app still using username+password to access Outlook or Microsoft 365 mailboxes will receive 401 Unauthorized errors.
Storing user passwords - even hashed - creates a compliance liability. GDPR's data minimization principle requires you to not collect what you do not need. SOC2 auditors flag credential storage.
Critical: Google App Passwords and Microsoft legacy protocols are no longer sufficient for production applications. If you are building a product that accesses user mailboxes, an OAuth email API is not optional - it is the only compliant path forward in 2026.
How OAuth Works for Email APIs (Step-by-Step)
The authorization code flow is the standard OAuth 2.0 flow for server-side applications that need to access user email. Understanding it end-to-end helps you implement it correctly, debug token failures, and explain the flow to your security team.
You construct a URL with your client_id, a redirect_uri, the requested scope, a random state parameter (CSRF protection), and response_type=code. The user is sent to Google's or Microsoft's consent screen.
The consent screen shows your app name, logo, and the exact permissions you requested. The user either approves (grants consent) or denies. Requesting too many scopes at this step is the most common cause of consent rejection.
After consent, the provider redirects to your redirect_uri with a short-lived code parameter (valid for ~10 minutes). Verify the state parameter matches what you sent to prevent CSRF attacks.
Server-to-server POST to the token endpoint with your client_id, client_secret, the code, and grant_type=authorization_code. You receive an access_token and (if you requested offline access) a refresh_token.
Pass the access token in the Authorization: Bearer header on every API request. When it expires (typically after 1 hour), use the refresh token to obtain a new access token without user interaction.
Access tokens vs refresh tokens: lifecycle
Valid for 1 hour (Google) or 1 hour (Microsoft). Passed in the Authorization header on every API call. When it expires, your OAuth email API call returns a 401 error - the signal to refresh.
Valid until revoked (Google) or 90 days of inactivity (Microsoft). Never sent to API endpoints - only used server-to-server to get new access tokens. Must be encrypted at rest.
Build a unified OAuth flow in minutes
Skip the per-provider authorization plumbing. One Unipile API call replaces three OAuth integrations.
OAuth Flows by Provider: Google and Microsoft
Google and Microsoft each implement OAuth 2.0 differently - different authorization endpoints, different scopes, different token endpoints, and different verification processes. IMAP is the credential-based fallback for providers without standardized OAuth. Here is what you need to know for each case.
Google's OAuth implementation uses the standard authorization code flow. The token endpoint is https://oauth2.googleapis.com/token. The critical complexity is Google CASA (Cloud Application Security Assessment): once your app exceeds 100 users, you must pass a security review. For sensitive scopes like gmail.modify or gmail.readonly, App Verification is required before production use. For a complete Gmail API integration deep-dive, see our dedicated guide. Implementation details are in the Unipile Google OAuth docs.
# Exchange authorization code for Gmail access + refresh tokens
curl -X POST https://oauth2.googleapis.com/token \
-d "code=AUTH_CODE" \
-d "client_id=YOUR_CLIENT_ID" \
-d "client_secret=YOUR_CLIENT_SECRET" \
-d "redirect_uri=https://yourapp.com/callback" \
-d "grant_type=authorization_code"
# Response: { "access_token": "...", "refresh_token": "...", "expires_in": 3600 }Microsoft uses its Identity Platform (formerly Azure AD v2). The token endpoint is https://login.microsoftonline.com/{tenant}/oauth2/v2.0/token. Publisher Verification is required before your OAuth email API app can request sensitive mail scopes in production. Microsoft deprecated basic auth for all Exchange Online protocols - OAuth is mandatory. See our complete Microsoft Graph email guide for full details, and the Unipile Microsoft OAuth docs for implementation reference.
# Exchange code for Microsoft OAuth tokens
curl -X POST https://login.microsoftonline.com/common/oauth2/v2.0/token \
-d "code=AUTH_CODE" \
-d "client_id=YOUR_CLIENT_ID" \
-d "client_secret=YOUR_CLIENT_SECRET" \
-d "redirect_uri=https://yourapp.com/callback" \
-d "grant_type=authorization_code" \
-d "scope=https://graph.microsoft.com/Mail.Read offline_access"
# Response: { "access_token": "...", "refresh_token": "...", "expires_in": 3600 }IMAP is not an OAuth provider: it is a protocol that authenticates with username/password, or app passwords (such as a Google App Password or iCloud-generated password). It is the fallback for custom mail servers, corporate domains not on Microsoft 365, and any provider without a standardized OAuth flow. XOAUTH2 existed as an IMAP SASL extension for a small number of providers, but it has been largely abandoned - Yahoo discontinued its first-party implementation in 2022. For most IMAP deployments, Unipile authenticates with credentials directly. See the full IMAP integration guide for server configuration and authentication details.
import base64, imaplib
# Build XOAUTH2 string from OAuth access token
def build_xoauth2(user_email, access_token):
auth_str = f"user={user_email}\x01auth=Bearer {access_token}\x01\x01"
return base64.b64encode(auth_str.encode()).decode()
# Connect via IMAP with XOAUTH2
conn = imaplib.IMAP4_SSL("imap.mail.yahoo.com")
auth_str = build_xoauth2("user@yahoo.com", access_token)
conn.authenticate("XOAUTH2", lambda x: auth_str)The Hidden Complexity of Multi-Provider OAuth
Implementing an OAuth email API for one provider takes a few days. Implementing it correctly for Gmail, Outlook, and IMAP - with production-grade token management, error handling, and compliance - typically takes 4 to 8 weeks of engineering time. Here is why.
Google Cloud Console, Azure Portal, and Yahoo Developer Network are 3 entirely different dashboards with different UX, different app registration flows, and different verification requirements. Any credential rotation touches all 3.
Gmail's sensitive scopes (including gmail.readonly) are blocked at 100 users until you pass a CASA Tier 2 assessment. This involves a CASA-authorized lab, a penetration test, and a formal security review - typically 6-12 weeks and $10,000-$25,000.
Microsoft requires Publisher Verification for apps requesting sensitive Mail scopes. Without it, users see a red "unverified publisher" warning on the consent screen. The verification process requires an active Microsoft Partner Network account with a verified domain.
Google refresh tokens expire after 6 months of inactivity (or immediately if the user revokes). Microsoft tokens expire after 90 days of inactivity. Yahoo/IMAP XOAUTH2 tokens have provider-specific lifetimes. Your token management layer must handle all 3 differently.
Google, Microsoft, and Yahoo each render consent screens differently - different branding, different scope descriptions, different UI patterns. Your users see 3 different flows depending on their email provider, creating inconsistent UX and higher drop-off rates.
OAuth endpoints change. Scope names get deprecated. New security requirements are added. Each provider announces breaking changes on different timelines. Someone on your team must track 3 provider blogs, 3 changelogs, and 3 compliance calendars - indefinitely.
Skip the OAuth complexity entirely
Hosted auth, scope management, refresh handling. Unipile handles all of it so you can focus on your product.
OAuth Email API Architecture: 3 Approaches Compared
There are 3 architectures for building an OAuth email API layer. Each has a fundamentally different cost-to-ship, maintenance burden, and security profile. The right choice depends on whether email connectivity is your core product or a feature you are shipping alongside your main product.
| Dimension | Direct Provider OAuth (x3) | Self-hosted OAuth Gateway | Unified Hosted OAuth (Unipile) Recommended |
|---|---|---|---|
| Time to first mailbox linked | 3-7 days (per provider) | 2-4 weeks | 5 minutes |
| OAuth flows to implement | 3 separate flows | 3 flows + routing logic | 1 hosted link endpoint |
| Google CASA review | You handle it (6-12 weeks, $10k+) | You handle it | Handled by Unipile |
| Microsoft Publisher Verification | You handle it | You handle it | Handled by Unipile |
| Token refresh management | 3 strategies to build | Custom per provider | Automatic, transparent |
| Email read/send API | 3 different APIs | Abstraction layer required | 1 unified REST API |
| Webhook on new emails | Push/pull per provider | Custom | Unified webhook events |
| SOC2 / GDPR compliance | Your responsibility | Your responsibility | Unipile is SOC2 certified |
| Ongoing maintenance | High (3 provider changelogs) | High | Zero - handled by Unipile |
| Best for | Single-provider, email-native products | Large teams with dedicated infra | Any team shipping fast |
Build vs Buy: Hosted OAuth Email API in 5 Minutes
Instead of building 3 separate OAuth flows, Unipile provides a hosted authentication link that handles Google OAuth, Microsoft Identity, and IMAP OAuth for you. Your app generates a link, redirects the user, and receives a webhook when the mailbox is linked. The OAuth email API is then immediately usable - no console setup, no CASA review, no token refresh logic to build.
Step 1: Generate a hosted auth link
One API call to create a hosted authentication session. Specify the provider type and a name for the account. Unipile returns a URL to redirect your user to the OAuth consent screen.
// Connect Gmail user via Unipile hosted OAuth email API
const response = await fetch(
'https://api6.unipile.com:13226/api/v1/hosted/accounts/link',
{
method: 'POST',
headers: {
'X-API-KEY': 'YOUR_UNIPILE_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
type: 'GOOGLE',
name: 'user_alice_123',
success_redirect_url: 'https://yourapp.com/connected',
failure_redirect_url: 'https://yourapp.com/error'
})
}
);
const { url, object } = await response.json();
// Redirect user to url - Unipile handles OAuth consent
window.location.href = url;Step 2: Connect an Outlook user
Same endpoint, same pattern. Change type to MICROSOFT. No Azure Portal, no Publisher Verification to manage on your side.
import requests
# Connect Outlook user via Unipile OAuth email API
response = requests.post(
"https://api6.unipile.com:13226/api/v1/hosted/accounts/link",
headers={"X-API-KEY": "YOUR_UNIPILE_API_KEY"},
json={
"type": "MICROSOFT",
"name": "user_bob_456",
"success_redirect_url": "https://yourapp.com/connected"
}
)
auth_url = response.json()["url"]
# Redirect to auth_url - Microsoft Identity flow handled by UnipileStep 3: Receive the webhook on account.connected
After OAuth consent, Unipile fires a webhook to your endpoint. The event payload includes the new account_id - which you store and use for all subsequent read email API and send email API calls.
Webhook event: When a user completes OAuth, Unipile sends a account.connected event to your webhook URL. The payload contains the account_id (store this), the provider (GOOGLE / MICROSOFT / IMAP), and the linked email address. This is the only state you need to persist - Unipile manages all OAuth tokens internally.
Skip the 8-week OAuth implementation. Connect mailboxes in minutes.
Unipile's hosted OAuth email API handles Google CASA, Microsoft Publisher Verification, XOAUTH2, and token refresh for all providers. Your users link their mailbox via a single hosted flow - you get a unified API to read, send, and sync.
Managing OAuth Tokens: Refresh, Revoke, Rotate
Token management is the most operationally demanding part of building an OAuth email API. Access tokens expire, refresh tokens get revoked by users, and your system must handle all of this gracefully - or risk your users losing access to their mailboxes silently.
Best practices for token storage
- Encrypt refresh tokens at rest using AES-256 or a cloud KMS (AWS KMS, GCP Cloud KMS, Azure Key Vault). Never store them in plaintext in your database.
- Never log access tokens or refresh tokens. Structured logging systems like Datadog or Splunk should have token fields masked or redacted.
- Store tokens in a dedicated secrets store (Vault, AWS Secrets Manager) rather than in your main application database, to minimize blast radius if the DB is compromised.
- Implement token rotation: when you get a new refresh token on a refresh call (some providers issue new refresh tokens on each use), invalidate the old one immediately.
Handling refresh failures gracefully
When a refresh token expires or is revoked, your refresh call returns a 400 or 401 error. Your OAuth email API must catch this and trigger a re-authentication flow for the user - not silently fail. The worst outcome is a user who thinks emails are being read, but the token has been revoked for weeks. Build an explicit account health check and alert users when re-auth is needed.
OAuth Scopes: What to Ask For (and What Not To)
Scope minimization is both a security best practice and a consent optimization strategy. Requesting more scopes than you need causes users to hesitate (or reject) at the consent screen, and triggers elevated scrutiny during Google CASA and Microsoft Publisher reviews.
| Scope | Provider | Use case | Sensitivity | CASA review? |
|---|---|---|---|---|
| gmail.readonly | Gmail | Read all emails and metadata | High | Yes - Tier 2 |
| gmail.send | Gmail | Send email as the user | High | Yes - Tier 2 |
| gmail.modify | Gmail | Read, send, delete, label | High | Yes - Tier 2 |
| gmail.labels | Gmail | Read and manage labels only | Low | No |
| Mail.Read | Outlook | Read all mail | Medium | Publisher Verification |
| Mail.Send | Outlook | Send mail as user | Medium | Publisher Verification |
| Mail.ReadWrite | Outlook | Read, send, delete, folder mgmt | High | Publisher Verification |
| offline_access | Outlook | Obtain refresh tokens | Low | No |
| mail-r | IMAP (Yahoo) | Read email via IMAP/XOAUTH2 | Medium | Yahoo dev review |
Tokens refreshed and rotated for you
Stop writing token-lifecycle code. Connect a mailbox once, Unipile keeps the access alive across all providers.
Compliance: SOC2, GDPR, CASA
An OAuth email API that handles user mailboxes sits at the intersection of security and privacy compliance. Here are the four frameworks most enterprise buyers will ask about - and what OAuth's token model means for each.
SOC2 auditors look at token handling as part of the Availability and Confidentiality criteria. OAuth tokens must be encrypted at rest (AES-256 or KMS), access-logged, and subject to a formal rotation policy. Storing refresh tokens in plaintext is an automatic finding. Using a hosted OAuth email API like Unipile (which is SOC2 certified) shifts this responsibility.
Under GDPR, your app is a data processor when it accesses user email content. You need a DPA (Data Processing Agreement) with your OAuth email API infrastructure provider. OAuth's revocability directly satisfies Article 17 (right to erasure) - when a user revokes, your access ends immediately. Document your lawful basis for accessing email data (typically consent via OAuth flow).
Once your Gmail OAuth email API app exceeds 100 users with sensitive scopes, Google blocks further user additions until you pass CASA Tier 2. This requires a pentest by a CASA-authorized lab, a security questionnaire, and a formal assessment report submitted to Google. Timeline: 8-16 weeks. Cost: $10,000-$25,000. Verified apps get the "Verified by Google" badge on their consent screen.
OAuth Email API: Pricing and Cost Models
The "free" provider APIs from Google and Microsoft hide significant real costs. Here is a realistic cost model for implementing an OAuth email API at scale - covering the direct provider route vs unified APIs.
Google and Microsoft APIs are technically free at the API call level. But: Google CASA Tier 2 costs $10k-$25k and 3+ months of engineering time. Publisher Verification for Microsoft requires a Partner Network account and legal domain verification. Engineering time to build 3 flows, token management, and error handling: 6-10 weeks. Annual maintenance: 2-4 weeks/year per provider.
Unipile's OAuth email API includes all provider compliance (CASA, Publisher Verification), token management, and a unified email API under a single subscription. For teams shipping email connectivity as a feature (not a product), the ROI calculus is straightforward: weeks of engineering time saved vs a monthly API cost. See the compare email API providers guide for a full cost breakdown.
Common Pitfalls When Implementing OAuth Email
These are the most common mistakes developers make when building an OAuth email API for the first time - and what to do instead.
Google invalidates refresh tokens if the user has not used your app for 6 months. Your token refresh call returns invalid_grant. Fix: implement a periodic "token health check" that makes a lightweight Gmail API call for each linked account at least once every 30 days to prevent inactivity-based expiry.
Requesting gmail.modify when you only need gmail.readonly inflates your consent screen and causes users to abandon the OAuth flow. It also escalates your CASA tier requirement. Always request the minimum scope needed. You can request additional scopes incrementally later.
Gmail's sensitive scope cap at 100 users is the most common growth blocker for OAuth email API implementations. Plan for the CASA review before you hit 50 users - the review takes 8-16 weeks, and your user growth will be blocked while it is pending.
Verbose request logging that captures Authorization headers will log your access tokens in plaintext. Implement log scrubbing middleware that redacts Bearer [TOKEN] patterns before logs are written to any persistent storage.
Some corporate email servers run behind custom IMAP configurations that do not support OAuth. Your OAuth email API must have a graceful fallback path for IMAP-only providers. Build this into your account connection flow from day one, or you will exclude a significant segment of B2B users. See our IMAP integration guide for the full fallback pattern.
Build instead of stitching providers together
Get a working OAuth email integration today. Free tier, no credit card, full Gmail and Microsoft scopes available.
Frequently Asked Questions
The most common questions developers ask when building an OAuth email API integration - answered precisely.
https://oauth2.googleapis.com/token, scopes in the gmail.* namespace. For Outlook (covering Outlook.com, Microsoft 365, and Exchange Online): Microsoft Identity Platform, token endpoint https://login.microsoftonline.com/common/oauth2/v2.0/token, scopes under https://graph.microsoft.com/. For IMAP: IMAP is not an OAuth provider. It uses username/password or app password credentials. XOAUTH2 existed as a SASL extension for a small number of providers but has largely been deprecated.grant_type=refresh_token. For Google: POST to https://oauth2.googleapis.com/token. For Microsoft: POST to https://login.microsoftonline.com/common/oauth2/v2.0/token. If you receive invalid_grant, the refresh token has expired or been revoked - prompt the user to re-authenticate.gmail.readonly to read, gmail.send to send, gmail.modify for full read/write/delete. For Outlook: Mail.Read to read, Mail.Send to send, Mail.ReadWrite for full access - plus offline_access to get refresh tokens. Always request the minimum scope your use case requires. See the email API page for use-case-specific scope recommendations.gmail.labels (not subject to CASA), start the CASA process before you hit 50 users (it takes 8-16 weeks), or use a hosted OAuth email API like Unipile whose infrastructure has already passed CASA review - eliminating this requirement for your application entirely./api/v1/hosted/accounts/link. You pass a type (GOOGLE, MICROSOFT, or IMAP) and Unipile generates a hosted auth URL. The user completes OAuth consent on Unipile's infrastructure - which has passed Google CASA and Microsoft Publisher Verification. After consent, Unipile sends a webhook with the account_id. All token management and refresh is handled internally.invalid_grant. Your OAuth email API must catch this, mark the linked account as disconnected, and notify the user with a re-authentication link. With Unipile, a revocation webhook fires automatically so your system is notified in real time - no polling required.