Setting Up Gmail API
This guide shows you how to configure EmailEngine to use Gmail REST API as the email backend instead of IMAP/SMTP. With this setup, EmailEngine uses direct Gmail API calls for all operations and receives change notifications via Google Cloud Pub/Sub.
In a previous guide, we showed how to configure EmailEngine to access Gmail over OAuth2 using IMAP and SMTP. That setup uses Gmail OAuth2 only for generating access tokens to authenticate IMAP/SMTP sessions.
This guide covers using Gmail REST API directly as the email backend. EmailEngine does not open IMAP or SMTP sessions and instead performs all operations via Gmail REST API calls.
Why Use Gmail API Instead of IMAP?
Use Gmail API when:
- You want better Gmail category handling
- Google's verification process requires limited OAuth2 scopes
- You want to avoid IMAP connection limits
Use IMAP/SMTP when:
- You need the full
https://mail.google.com/scope and can justify it to Google - Your organization restricts Cloud Pub/Sub permissions
- You need raw SMTP features (e.g., custom envelope-from)
- You want to avoid additional GCP setup complexity
- You're migrating existing IMAP-based integrations
IMAP/SMTP requires the full https://mail.google.com/ scope. Gmail API can use more granular scopes:
| Scope | Access Level | Use Case |
|---|---|---|
gmail.readonly | Read-only | Applications that only need to read emails |
gmail.modify | Read, send, modify | Full email access except permanent deletion |
gmail.send | Send only | Applications that only send emails |
Google's Principle of Least Privilege: For public production apps, Google requires you to request only the minimum scopes needed for your use case. If your application only reads emails, you will not be granted gmail.modify. If you only send emails, you will not be granted read access.
EmailEngine can be configured to work with these limited scopes - select the appropriate Base Scopes setting when creating your Gmail OAuth2 application in EmailEngine.
Overview of Setup Steps
Setting up Gmail API requires more steps than IMAP because you need:
- A regular OAuth2 app for user authentication
- A service account for managing Cloud Pub/Sub
- Cloud Pub/Sub API enabled for webhook notifications
Step 1: Create a Google Cloud Project
Go to Google Cloud Console and open the project menu in the top navbar.

Click the "New project" button to start.

Name your project (e.g., "EmailEngine Gmail API").

Wait for the project to be created, then select it from the project menu.
Step 2: Enable Required APIs
Click the hamburger menu (top-left) → APIs & Services → Enabled APIs & Services.

Enable Gmail API
Find and enable Gmail API for your project.

This allows EmailEngine to perform Gmail REST API requests.
Enable Cloud Pub/Sub API
Also find and enable Cloud Pub/Sub API.

Gmail pushes change notifications (new messages, flag changes, etc.) to Google's Pub/Sub system, not directly to EmailEngine. EmailEngine sets up a Pub/Sub topic and subscription to receive these notifications and convert them into webhooks for your application.
Without Pub/Sub, EmailEngine would not know when changes occur on the email account and couldn't send real-time webhook notifications.
Step 3: Configure OAuth Consent Screen
The consent screen is shown to users when they authorize EmailEngine.
Click hamburger menu → APIs & Services → OAuth consent screen.

Choose User Type

Internal:
- Only accounts from your Google Workspace organization
- No verification process required
- Best for testing and enterprise apps
External:
- Any Gmail user can authenticate
- Requires verification for production
- Best for public applications
For this tutorial, we'll use Internal. For production, select External and complete Google's verification process.
Fill in App Information

Provide:
- App name: "EmailEngine" (or your application name)
- User support email: Your email address
- Developer contact information: Your email address
- Application home page: Your EmailEngine instance URL
Click Save and continue.
Configure Scopes
Click Add or remove scopes and find gmail.modify from the list.

Check gmail.modify and click Update.
The gmail.modify scope is required for Gmail API access. This is different from the https://mail.google.com/ scope used for IMAP/SMTP.
If Google's verification process determines you need different scopes (e.g., gmail.readonly, gmail.send, gmail.labels), see the Custom Scopes section below.

Scroll down and click Save and continue to finish consent screen setup.
Step 4: Create OAuth Credentials for User Authentication
Navigate to APIs & Services → Credentials.

Click Create credentials → OAuth client ID.

Configure OAuth Client

Application type: Web application
Authorized JavaScript origins: Add your EmailEngine URL:
http://127.0.0.1:3000(for local testing)https://your-emailengine-domain.com(for production)
Authorized redirect URIs:
Add your EmailEngine URL with /oauth:
http://127.0.0.1:3000/oauthhttps://your-emailengine-domain.com/oauth
Click Create.
Download User Credentials

Click the Download button. Save this file - you'll need it to configure EmailEngine.
- User OAuth credentials: Filename starts with
client_secret_ - Service account credentials: Uses service account name prefix
Keep these separate - you'll need both!
Step 5: Create Service Account for Pub/Sub Management
EmailEngine needs a service account with permissions to manage Pub/Sub topics and subscriptions.
On the Credentials page, navigate to the Service Account management page.

Click Create Service Account.
Configure Service Account

Service account name: Choose any name (e.g., "EmailEngine Pub/Sub Manager")
Role: Select Pub/Sub Admin (or a compatible role that allows managing Pub/Sub queues, topics, and IAM policies)
The service account must have permissions to:
- Create and delete Pub/Sub topics
- Create and delete Pub/Sub subscriptions
- Manage IAM policies for Pub/Sub resources
The "Pub/Sub Admin" role provides all necessary permissions.
Click Create to finish.
Generate Service Account Keys
Once created, select the service account and navigate to Manage Keys.

Click Add key → Create new key → JSON format.
The key file will automatically download. Store it securely - you cannot download it again.
Step 6: Configure EmailEngine - Service Account
Now configure EmailEngine to use the service account for managing webhooks.
Add Gmail Service Account Application

- Open EmailEngine dashboard
- Navigate to Configuration → OAuth2
- Click Add application
- Select Gmail Service Accounts
Configure Service Account Settings

Application name: Give it a descriptive name (e.g., "Gmail Pub/Sub Manager")
Credentials file: Select the service account JSON file (not the user OAuth credentials!)
Base scope: Select Cloud Pub/Sub
Make sure you're uploading the service account credentials file, not the user OAuth credentials file. You can tell them apart:
- Service account: Filename uses service account name prefix
- User OAuth: Filename starts with
client_secret_
Click Register app to save.
Step 7: Configure EmailEngine - User OAuth
Now configure the user OAuth application that will authenticate Gmail accounts.
Add Gmail OAuth2 Application

- Navigate to Configuration → OAuth2
- Click Add application
- Select Gmail
Configure OAuth2 Settings

Application name: Give it a descriptive name (e.g., "Gmail API OAuth2")
Enable this app: Check this box
Credentials file: Select the user OAuth credentials file (client_secret_...json)
Redirect URL: Verify this matches exactly what you entered in Google Cloud Console
Base scope: Select Gmail API
Service Account for managing webhook Pub/Sub: Select the service account app you created earlier
You must select the service account application you created in Step 6. This tells EmailEngine which credentials to use for managing Pub/Sub resources.
Configuring Limited Scopes
If Google requires you to use limited scopes during verification, you can configure EmailEngine to request only the scopes you need.
Default scope: By default, Gmail API mode requests gmail.modify which provides read, send, and modify access (but not permanent deletion).
Using more limited scopes: To use scopes other than gmail.modify, you need to:
- Add the required scopes to Additional scopes
- Add
gmail.modifyto Disabled scopes (to skip the default scope)
| Your Use Case | Additional Scopes | Disabled Scopes | Resulting Access |
|---|---|---|---|
| Read and send (default) | (none) | (none) | Full gmail.modify access |
| Read only | gmail.readonly, gmail.labels | gmail.modify | Read-only access with folder listing |
| Send only | gmail.send | gmail.modify | Send-only access |
| Read and send (granular) | gmail.readonly, gmail.send, gmail.labels | gmail.modify | Read and send with separate scopes |
When using gmail.readonly instead of gmail.modify, you should also add gmail.labels to see the folder/label structure. Without it, EmailEngine cannot list mailboxes properly.
Click Register app to save.
Step 8: Test the Setup
Add a Gmail account to test the complete flow.
Via Hosted Authentication Form

- In EmailEngine, click Add account
- Click Sign in with Google
- Complete the OAuth2 consent flow
- EmailEngine will:
- Store OAuth2 tokens
- Create a Pub/Sub topic and subscription
- Start receiving webhook notifications
Via API
Generate an authentication form URL:
curl -X POST https://your-ee.com/v1/authentication/form \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"account": "user123",
"email": "user@gmail.com",
"redirectUrl": "https://myapp.com/settings"
}'
Direct the user to the returned URL.
Verify Setup
Check the account status in EmailEngine:
- Account should enter "connected" state
- In Google Cloud Console → Pub/Sub, you should see:
- A new topic (created by EmailEngine)
- A new subscription (created by EmailEngine)
Using Custom Scopes
If you have a public OAuth2 application and Google requires narrower scopes than gmail.modify, you can configure custom scopes.
Configure Custom Scopes in EmailEngine
In the Gmail OAuth2 application configuration in EmailEngine, scroll to the bottom to find the Additional scopes and Disabled scopes fields.
Example: Read-only access
If Google only grants gmail.readonly and gmail.labels:
Additional scopes:
https://www.googleapis.com/auth/gmail.readonly
https://www.googleapis.com/auth/gmail.labels
Disabled scopes:
https://www.googleapis.com/auth/gmail.modify
Example: Read and send with granular scopes
If Google requires separate read and send scopes instead of gmail.modify:
Additional scopes:
https://www.googleapis.com/auth/gmail.readonly
https://www.googleapis.com/auth/gmail.send
https://www.googleapis.com/auth/gmail.labels
Disabled scopes:
https://www.googleapis.com/auth/gmail.modify
Example: Send-only access
If your application only sends emails:
Additional scopes:
https://www.googleapis.com/auth/gmail.send
Disabled scopes:
https://www.googleapis.com/auth/gmail.modify
You must add gmail.modify to Disabled scopes when using custom scopes. Otherwise, EmailEngine will request both gmail.modify AND your additional scopes, which defeats the purpose of using limited scopes.
When users authenticate, the Google permissions screen will only show the scopes you configured.
Production Considerations
Security Audit for Public Apps
If you need a public app for any Gmail user:
Requirements:
- Security audit: OWASP compliance, penetration testing
- Use case validation: Google may reject certain use cases
- Minimum scopes: Google may require narrower scopes
Process:
- Expensive and time-consuming
- May require custom scope configuration
- Not all email use cases will be approved
Alternatives:
- Use Internal apps (Google Workspace only)
- Use IMAP/SMTP with app passwords
- Consider if narrower scopes work for your use case
Managing Pub/Sub Resources
EmailEngine automatically:
- Creates Pub/Sub topics for each account
- Creates subscriptions to receive notifications
- Cleans up resources when accounts are deleted
- Renews subscriptions before expiration (7 days)
You can:
- Monitor Pub/Sub usage in Google Cloud Console
- Set up billing alerts for Pub/Sub costs
- View subscription status in EmailEngine
Token Management
EmailEngine automatically:
- Refreshes access tokens when they expire during API requests
- Makes regular API requests (at least daily) even for idle accounts, keeping refresh tokens active
- Stores refresh tokens securely
- Re-authenticates on token failures
You can:
- Retrieve current access tokens for other Google API calls
- Monitor token status via account state
- Revoke access by deleting the account
Google refresh tokens can expire under certain conditions:
- 6 months of inactivity - If not used to obtain new access tokens
- 7 days - If your OAuth app is in "Testing" mode (not published to production)
- User revokes access - Via Google account settings
- Password change - When Gmail scopes are present
- Token limit exceeded - Google allows ~50 refresh tokens per user/client; oldest tokens are invalidated
EmailEngine keeps tokens active by making regular API requests, but if an account is deleted from EmailEngine and re-added later, a new consent flow is required.