Skip to main content

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.

IMAP vs Gmail API

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
OAuth2 Scope Requirements

IMAP/SMTP requires the full https://mail.google.com/ scope. Gmail API can use more granular scopes:

ScopeAccess LevelUse Case
gmail.readonlyRead-onlyApplications that only need to read emails
gmail.modifyRead, send, modifyFull email access except permanent deletion
gmail.sendSend onlyApplications 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:

  1. A regular OAuth2 app for user authentication
  2. A service account for managing Cloud Pub/Sub
  3. 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.

Creating a new Google Cloud project

Click the "New project" button to start.

Naming your project

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

Waiting for project creation

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 & ServicesEnabled APIs & Services.

Navigating to APIs & Services

Enable Gmail API

Find and enable Gmail API for your project.

Enabling Gmail API

This allows EmailEngine to perform Gmail REST API requests.

Enable Cloud Pub/Sub API

Also find and enable Cloud Pub/Sub API.

Enabling Cloud Pub/Sub API

Why Cloud Pub/Sub?

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.

The consent screen is shown to users when they authorize EmailEngine.

Click hamburger menu → APIs & ServicesOAuth consent screen.

Navigating to consent screen

Choose User Type

Selecting 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

Configuring consent screen details

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.

Adding required scope

Check gmail.modify and click Update.

Required Scope

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.

Saving consent screen configuration

Scroll down and click Save and continue to finish consent screen setup.

Step 4: Create OAuth Credentials for User Authentication

Navigate to APIs & ServicesCredentials.

Navigating to credentials page

Click Create credentialsOAuth client ID.

Creating OAuth client ID

Configure OAuth Client

Configuring OAuth client details

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/oauth
  • https://your-emailengine-domain.com/oauth

Click Create.

Download User Credentials

Downloading OAuth credentials

Click the Download button. Save this file - you'll need it to configure EmailEngine.

Credential File Names
  • 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.

Navigating to service accounts

Click Create Service Account.

Configure Service Account

Creating 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)

Required Permissions

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.

Generating service account keys

Click Add keyCreate new keyJSON 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

Creating service account app in EmailEngine

  1. Open EmailEngine dashboard
  2. Navigate to ConfigurationOAuth2
  3. Click Add application
  4. Select Gmail Service Accounts

Configure Service Account Settings

Configuring service account

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

Use Correct Credentials File

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

Creating Gmail OAuth2 app

  1. Navigate to ConfigurationOAuth2
  2. Click Add application
  3. Select Gmail

Configure OAuth2 Settings

Configuring Gmail 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

Link Service Account

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:

  1. Add the required scopes to Additional scopes
  2. Add gmail.modify to Disabled scopes (to skip the default scope)
Your Use CaseAdditional ScopesDisabled ScopesResulting Access
Read and send (default)(none)(none)Full gmail.modify access
Read onlygmail.readonly, gmail.labelsgmail.modifyRead-only access with folder listing
Send onlygmail.sendgmail.modifySend-only access
Read and send (granular)gmail.readonly, gmail.send, gmail.labelsgmail.modifyRead and send with separate scopes
Why gmail.labels?

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

Testing with hosted authentication

  1. In EmailEngine, click Add account
  2. Click Sign in with Google
  3. Complete the OAuth2 consent flow
  4. 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
Important

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:

  1. Security audit: OWASP compliance, penetration testing
  2. Use case validation: Google may reject certain use cases
  3. 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
Refresh Token Expiration

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.

Learn more about OAuth2 token management →