Skip to main content

Gmail API Scopes Reference

When using EmailEngine with Gmail, you must choose which OAuth2 scopes to request. Google requires applications to follow the principle of least privilege - request only the scopes your application actually needs. The scope selection also determines what Google verification process your application must pass.

This page covers all Gmail scope configurations supported by EmailEngine, what each enables, and how to set them up.

Prerequisites

This page assumes you have already created a Google Cloud project and OAuth2 credentials. If not, see Setting Up Gmail API or Setting Up Gmail with OAuth2 (IMAP/SMTP) first.

Quick Reference

ConfigurationScopesReadSendModify/Move/TrashManage LabelsPub/Sub WebhooksGoogle Classification
Full Accesshttps://mail.google.com/YesYesYes (+ permanent delete)YesIMAP onlyRestricted
Gmail API Full Accessgmail.modifyYesYesYesYesYesRestricted
Read + Sendgmail.readonly + gmail.send + gmail.labelsYesYesNoYesYesRestricted
Read-Onlygmail.readonly + gmail.labelsYesNoNoYesYesRestricted
Send-Onlygmail.sendNoYesNoNoNoSensitive

Manage Labels refers to creating, renaming, and deleting labels (folders). The gmail.labels scope is also required for EmailEngine to list labels properly.

Google's Scope Classifications

Google classifies OAuth2 scopes into three tiers. The classification determines what verification your application needs before it can be published:

ClassificationVerification RequiredGmail Scopes in This Tier
RestrictedSecurity audit (CASA assessment)https://mail.google.com/, gmail.modify, gmail.readonly, gmail.compose, gmail.metadata
SensitiveBrand verification onlygmail.send
Non-sensitiveNo verificationgmail.labels

The overall classification of your application is determined by its most restrictive scope. For example, if you request both gmail.send (Sensitive) and gmail.readonly (Restricted), your application is classified as Restricted.

Send-Only is the easiest to verify

The Send-Only configuration using gmail.send is the only Gmail scope combination that avoids the Restricted tier. It requires only brand verification (Sensitive), which is significantly faster and cheaper than a full security audit.

How Scope Configuration Works in EmailEngine

EmailEngine uses three fields to determine which scopes are requested during OAuth2 authentication:

FieldPurposeAPI ParameterWeb UI Field
Base ScopesSelects the default scope setbaseScopes"Base scopes" radio buttons
Additional ScopesAdds scopes on top of the defaultsextraScopes"Additional scopes" textarea
Disabled ScopesRemoves scopes from the defaultsskipScopes"Disabled scopes" textarea

How they combine:

  1. Start with the default scope for the selected base ("imap" = https://mail.google.com/, "api" = gmail.modify)
  2. Add any scopes from Additional Scopes that are not already included
  3. Remove any scopes that match Disabled Scopes

EmailEngine also automatically adds the OpenID Connect scopes openid, email, and profile to all user-facing OAuth2 flows. These provide basic user identity information and do not need to be configured manually.

Web UI Preset Buttons

When the base scope is set to Gmail API, the OAuth2 application configuration page shows four preset buttons that auto-populate the Additional and Disabled scopes fields:

  • Normal (Full Access) - uses gmail.modify as-is
  • Read-Only - adds gmail.readonly + gmail.labels, disables gmail.modify
  • Read-Only + Send - adds gmail.readonly + gmail.send + gmail.labels, disables gmail.modify
  • Send-Only - adds gmail.send, disables gmail.modify

These presets preserve any third-party scopes you may have added manually (such as Google Calendar or Drive scopes).


Full Access

Scope: https://mail.google.com/

This is the broadest Gmail scope. It grants full access to all Gmail operations, including permanent message deletion, which no other scope allows. This scope is accepted by every Gmail API endpoint and also enables IMAP and SMTP protocol access.

In EmailEngine, this scope is used with the IMAP/SMTP backend (baseScopes: "imap"). EmailEngine connects via IMAP for reading and SMTP for sending, providing raw protocol-level access.

What this enables

OperationSupported
List and read messagesYes
Send messages (with full SMTP envelope control)Yes
Modify message labels/flagsYes
Move messages between labelsYes
Trash messagesYes
Permanently delete messagesYes
List, create, rename, delete labelsYes
Raw SMTP features (custom envelope-from, etc.)Yes

What this does not enable

  • Cloud Pub/Sub push notifications (EmailEngine uses IMAP IDLE for real-time updates instead)

When to use

  • You need permanent message deletion (not just trash)
  • You need raw SMTP features (custom envelope-from, direct SMTP control)
  • You want to use EmailEngine's IMAP/SMTP proxy, which lets legacy clients and scripts connect with password authentication while EmailEngine handles OAuth2 behind the scenes
  • You are migrating from an existing IMAP-based integration
  • Your organization restricts Cloud Pub/Sub permissions
  • You can justify the full scope to Google during verification

Google classification

Restricted - requires a security audit (CASA assessment) for public applications.

Setup via Web UI

  1. Go to Configuration > OAuth2 > Add new OAuth2 app
  2. Select Gmail as the provider
  3. Upload your Google credentials JSON file or enter Client ID and Client Secret manually
  4. For Base scope, select IMAP and SMTP
  5. No additional or disabled scopes needed
  6. Click Register app

Setup via API

curl -X POST "https://emailengine.example.com/v1/oauth2" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"provider": "gmail",
"name": "Gmail IMAP/SMTP",
"baseScopes": "imap",
"clientId": "YOUR_CLIENT_ID.apps.googleusercontent.com",
"clientSecret": "YOUR_CLIENT_SECRET",
"redirectUrl": "https://emailengine.example.com/oauth"
}'

See also

Setting Up Gmail with OAuth2 (IMAP/SMTP) - complete step-by-step setup guide.


Gmail API Full Access

Scope: https://www.googleapis.com/auth/gmail.modify

This is the default scope when using the Gmail API backend. It provides full read, send, and modify access through Google's REST API, with Cloud Pub/Sub for real-time push notifications.

What this enables

OperationGmail API EndpointSupported
List and read messagesmessages.list, messages.getYes
Send messagesmessages.sendYes
Modify message labels/flagsmessages.modifyYes
Move messages between labelsmessages.modifyYes
Trash messagesmessages.trashYes
List labelslabels.listYes
Create, rename, delete labelslabels.create, labels.patch, labels.deleteYes
Cloud Pub/Sub push notificationsusers.watchYes
Reply and forward (with reference)via messages.send + messages.getYes

What this does not enable

  • Permanent message deletion (only trash). Requires https://mail.google.com/ scope.
  • Raw SMTP features (custom envelope-from). Requires IMAP/SMTP mode.

EmailEngine behavior

  • Full Pub/Sub watch for real-time webhook notifications
  • History tracking for incremental sync
  • Fallback polling in case Pub/Sub notifications are missed
  • Locale detection for the account
  • After sending, fetches back the actual Message-ID from Gmail

When to use

  • Default choice for Gmail API integration
  • You need full email operations (read, send, modify, move, trash)
  • You want Cloud Pub/Sub push notifications for real-time updates

Google classification

Restricted - requires a security audit (CASA assessment) for public applications.

Setup via Web UI

  1. Go to Configuration > OAuth2 > Add new OAuth2 app
  2. Select Gmail as the provider
  3. Upload your Google credentials JSON file or enter Client ID and Client Secret manually
  4. For Base scope, select Gmail API
  5. Click the Normal (Full Access) preset button (or leave Additional and Disabled scopes empty)
  6. Click Register app

Setup via API

curl -X POST "https://emailengine.example.com/v1/oauth2" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"provider": "gmail",
"name": "Gmail API - Full Access",
"baseScopes": "api",
"clientId": "YOUR_CLIENT_ID.apps.googleusercontent.com",
"clientSecret": "YOUR_CLIENT_SECRET",
"redirectUrl": "https://emailengine.example.com/oauth"
}'

No extraScopes or skipScopes needed - gmail.modify is the default for the "api" base scope.

See also

Setting Up Gmail API - complete step-by-step setup guide including Cloud Pub/Sub configuration.


Read + Send

Scopes:

  • https://www.googleapis.com/auth/gmail.readonly
  • https://www.googleapis.com/auth/gmail.send
  • https://www.googleapis.com/auth/gmail.labels

Uses three separate scopes instead of the broader gmail.modify. This provides read and send access but cannot modify existing messages (flags, labels, moves, or trash).

What this enables

OperationGmail API EndpointSupported
List and read messagesmessages.list, messages.getYes
Send messagesmessages.sendYes
Modify message labels/flagsmessages.modifyNo
Move messages between labelsmessages.modifyNo
Trash messagesmessages.trashNo
List labelslabels.listYes
Create, rename, delete labelslabels.create, labels.patch, labels.deleteYes
Cloud Pub/Sub push notificationsusers.watchYes
Reply and forward (with reference)via messages.send + messages.getYes

What this does not enable

  • Modifying labels on existing messages (marking as read/unread, starring, categorizing)
  • Moving messages between folders/labels
  • Trashing or deleting messages
  • These operations require gmail.modify and will return a scope error from Google's API

EmailEngine behavior

  • Full Pub/Sub watch for real-time webhook notifications
  • History tracking for incremental sync
  • Fallback polling for missed notifications
  • Locale detection
  • After sending, fetches back the actual Message-ID from Gmail
  • Webhook notifications for incoming messages work normally
Operations that will fail

With this scope combination, EmailEngine API calls that attempt to modify, move, or trash messages will fail with a 403 Insufficient Permission error from Google. This includes:

  • PUT /v1/account/{account}/message/{message} (updating flags)
  • PUT /v1/account/{account}/message/{message}/move (moving messages)
  • DELETE /v1/account/{account}/message/{message} (trashing messages)

When to use

  • Google's verification process requires you to justify each scope separately
  • Your application reads emails and sends responses but does not need to modify or organize them
  • You want the narrowest scopes that still allow both reading and sending

Google classification

Restricted - the gmail.readonly scope is Restricted, which sets the overall classification. The gmail.send scope alone is Sensitive and gmail.labels is Non-sensitive, but the combination is Restricted.

Setup via Web UI

  1. Go to Configuration > OAuth2 > Add new OAuth2 app (or edit an existing one)

  2. Select Gmail as the provider

  3. For Base scope, select Gmail API

  4. Click the Read-Only + Send preset button

    This automatically sets:

    • 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
  5. Click Register app

Setup via API

curl -X POST "https://emailengine.example.com/v1/oauth2" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"provider": "gmail",
"name": "Gmail API - Read + Send",
"baseScopes": "api",
"clientId": "YOUR_CLIENT_ID.apps.googleusercontent.com",
"clientSecret": "YOUR_CLIENT_SECRET",
"redirectUrl": "https://emailengine.example.com/oauth",
"extraScopes": [
"https://www.googleapis.com/auth/gmail.readonly",
"https://www.googleapis.com/auth/gmail.send",
"https://www.googleapis.com/auth/gmail.labels"
],
"skipScopes": [
"https://www.googleapis.com/auth/gmail.modify"
]
}'

Read-Only

Scopes:

  • https://www.googleapis.com/auth/gmail.readonly
  • https://www.googleapis.com/auth/gmail.labels

Provides read access to messages and labels. Cannot send, modify, or delete messages.

What this enables

OperationGmail API EndpointSupported
List and read messagesmessages.list, messages.getYes
Send messagesmessages.sendNo
Modify message labels/flagsmessages.modifyNo
Move messages between labelsmessages.modifyNo
Trash messagesmessages.trashNo
List labelslabels.listYes
Create, rename, delete labelslabels.create, labels.patch, labels.deleteYes
Cloud Pub/Sub push notificationsusers.watchYes
Reply and forward (with reference)-No

What this does not enable

  • Sending emails (the submit API endpoint will fail)
  • Modifying labels on existing messages
  • Moving or trashing messages

EmailEngine behavior

  • Full Pub/Sub watch for real-time webhook notifications
  • History tracking for incremental sync
  • Fallback polling for missed notifications
  • Webhook notifications for incoming messages (e.g., messageNew) work normally
  • Locale detection
gmail.labels is required

The gmail.labels scope is required for EmailEngine to list labels (mailboxes) properly. Always include it alongside gmail.readonly. Without it, EmailEngine cannot function correctly even for read-only use cases.

When to use

  • Email monitoring or archival applications
  • Helpdesk systems that only need to read incoming emails
  • Analytics that process email content without modifying it
  • You do not need to send, modify, or organize emails through EmailEngine

Google classification

Restricted - the gmail.readonly scope is Restricted. The gmail.labels scope is Non-sensitive, but the combination is Restricted.

Setup via Web UI

  1. Go to Configuration > OAuth2 > Add new OAuth2 app (or edit an existing one)

  2. Select Gmail as the provider

  3. For Base scope, select Gmail API

  4. Click the Read-Only preset button

    This automatically sets:

    • 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
  5. Click Register app

Setup via API

curl -X POST "https://emailengine.example.com/v1/oauth2" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"provider": "gmail",
"name": "Gmail API - Read Only",
"baseScopes": "api",
"clientId": "YOUR_CLIENT_ID.apps.googleusercontent.com",
"clientSecret": "YOUR_CLIENT_SECRET",
"redirectUrl": "https://emailengine.example.com/oauth",
"extraScopes": [
"https://www.googleapis.com/auth/gmail.readonly",
"https://www.googleapis.com/auth/gmail.labels"
],
"skipScopes": [
"https://www.googleapis.com/auth/gmail.modify"
]
}'

Send-Only

Scope: https://www.googleapis.com/auth/gmail.send

The most restrictive configuration. Can only send emails - no access to read messages, list labels, or modify anything.

What this enables

OperationGmail API EndpointSupported
List and read messagesmessages.list, messages.getNo
Send messagesmessages.sendYes
Modify message labels/flagsmessages.modifyNo
Move messages between labelsmessages.modifyNo
Trash messagesmessages.trashNo
List labelslabels.listNo
Create, rename, delete labelslabels.create, labels.patch, labels.deleteNo
Cloud Pub/Sub push notificationsusers.watchNo
Reply and forward (with reference)-No

What this does not enable

  • Reading any email content
  • Listing mailboxes or labels
  • Any modification or deletion of messages
  • Receiving webhook notifications for incoming emails
  • Reply/forward with reference.action (returns ReferenceNotSupported error because EmailEngine cannot read the original message)

EmailEngine behavior

EmailEngine activates a special send-only mode for accounts with only the gmail.send scope:

  • No Pub/Sub watch - push notifications are not set up since there is nothing to monitor
  • No history tracking - incremental sync is disabled
  • No fallback polling - no periodic checks for new messages
  • No locale detection - user locale is not resolved
  • No incoming email webhooks - messageNew, messageUpdated, and similar webhook events are not fired
  • Email detection - uses the Google UserInfo endpoint (/oauth2/v2/userinfo) instead of the Gmail profile endpoint to determine the user's email address
  • After sending - cannot fetch back the Gmail-assigned Message-ID because that requires read access. Uses the original Message-ID from the email headers instead
  • Reply/forward - attempting to use reference.action in the submit API throws a 400 ReferenceNotSupported error, since EmailEngine cannot read the referenced message to build the reply chain

When to use

  • Transactional email (order confirmations, password resets, notifications)
  • Applications that only need to send emails and have no need to read or manage the user's mailbox
  • You want the easiest Google verification path (Sensitive instead of Restricted)

Google classification

Sensitive - this is the only Gmail scope configuration that avoids the Restricted tier. Sensitive scopes require brand verification but not a full security audit (CASA assessment). This makes the verification process significantly faster and less expensive.

Setup via Web UI

  1. Go to Configuration > OAuth2 > Add new OAuth2 app (or edit an existing one)

  2. Select Gmail as the provider

  3. For Base scope, select Gmail API

  4. Click the Send-Only preset button

    This automatically sets:

    • Additional scopes:
      https://www.googleapis.com/auth/gmail.send
    • Disabled scopes:
      https://www.googleapis.com/auth/gmail.modify
  5. Click Register app

Setup via API

curl -X POST "https://emailengine.example.com/v1/oauth2" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"provider": "gmail",
"name": "Gmail API - Send Only",
"baseScopes": "api",
"clientId": "YOUR_CLIENT_ID.apps.googleusercontent.com",
"clientSecret": "YOUR_CLIENT_SECRET",
"redirectUrl": "https://emailengine.example.com/oauth",
"extraScopes": [
"https://www.googleapis.com/auth/gmail.send"
],
"skipScopes": [
"https://www.googleapis.com/auth/gmail.modify"
]
}'

Updating an Existing OAuth2 Application

To change scopes on an existing OAuth2 application, use the PUT /v1/oauth2/{app} endpoint:

curl -X PUT "https://emailengine.example.com/v1/oauth2/YOUR_APP_ID" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"extraScopes": [
"https://www.googleapis.com/auth/gmail.readonly",
"https://www.googleapis.com/auth/gmail.labels"
],
"skipScopes": [
"https://www.googleapis.com/auth/gmail.modify"
]
}'
Scope changes require re-authentication

Changing scopes on the OAuth2 application only affects new account authentications. Existing accounts keep their original scopes until the user re-authenticates. To apply new scopes to existing accounts, generate a new authentication link and have users complete the OAuth2 flow again.

Gmail API Endpoint Scope Requirements

For reference, here is which scopes are accepted by the Gmail API endpoints that EmailEngine uses:

Gmail API Endpointmail.google.comgmail.modifygmail.readonlygmail.sendgmail.labels
messages.listYesYesYes--
messages.getYesYesYes--
messages.sendYesYes-Yes-
messages.modifyYesYes---
messages.trashYesYes---
messages.delete (permanent)Yes----
messages.batchModifyYesYes---
labels.listYesYesYes-Yes
labels.getYesYesYes-Yes
labels.createYesYes--Yes
labels.patchYesYes--Yes
labels.deleteYesYes--Yes
users.watch (Pub/Sub)YesYesYes--

Source: Gmail API Reference

See Also