Skip to main content

Overview

Use the Gmail integration after the shared GCP setup to ingest Google Workspace mailboxes for the domain you want Asymptote to track. The current Gmail integration enumerates Workspace users through the Admin SDK Directory API, runs an initial mailbox backfill, processes ongoing Gmail history notifications through Pub/Sub, normalizes mailbox data, and renews mailbox watches on a schedule.

Before you start

  • Run the shared GCP setup first with ./cloud-providers/gcp/scripts/init.sh.
  • Install Terraform >= 1.9, gcloud, jq, and curl.
  • Make sure you have a Google Workspace super admin who can grant domain-wide delegation in the Google Workspace Admin Console.
  • Make sure the Workspace domain and admin subject email you plan to use belong to the Google Workspace tenant you want to ingest.
  • If you have more than one generated GCP install under generated/gcp/, decide which install-state.json you want to use and pass it with --install-state PATH.
  • Use a GCP identity that can create Gmail integration resources and deploy the Gmail workloads.
The Gmail installer prints a delegated service account OAuth client ID. A Google Workspace super admin must add that client ID in the Admin Console before the installer can validate mailbox access and start the backfill.

Fill install.yaml

The Gmail installer reads cloud-providers/gcp/scripts/integrations/gmail/install.yaml by default. Gmail inherits the hosting mode, project ID, region, and other shared values from the base install-state.json. You do not set those again here. Fill in these fields:
  • gmail.workspace_domain: required. Use the Google Workspace domain whose mailboxes you want to ingest.
  • gmail.admin_subject_email: required. Use a Google Workspace admin email in that same tenant. The installer uses this subject for Admin SDK Directory listing and delegation validation.
  • gmail.included_labels: optional. If you leave it blank, the installer defaults to INBOX, SENT, and DRAFT. In v1, only INBOX, SENT, and DRAFT are supported.
  • gmail.mailbox_quota_units_per_minute: optional. Defaults to 12000.
  • gmail.api_max_retries: optional. Defaults to 5.
  • gmail.api_initial_backoff_seconds: optional. Defaults to 1.0.
  • gmail.api_max_backoff_seconds: optional. Defaults to 30.0.
  • gmail.draft_refresh_interval_seconds: optional. Defaults to 300.
  • gmail.ingest_max_instances: optional. Defaults to 10.
  • gmail.normalization.filters.max_event_age_days: optional. Use 0 or leave it unset for no age filter.
  • gmail.watch_renewal_schedule: optional. Defaults to 0 4 * * *.
  • gmail.watch_renewal_time_zone: optional. Defaults to Etc/UTC.
Config shape:
gmail:
  workspace_domain: "example.com"
  admin_subject_email: "admin@example.com"
  included_labels:
    - "INBOX"
    - "SENT"
    - "DRAFT"
  mailbox_quota_units_per_minute:
  api_max_retries:
  api_initial_backoff_seconds:
  api_max_backoff_seconds:
  draft_refresh_interval_seconds:
  ingest_max_instances:
  normalization:
    filters:
      max_event_age_days:
  watch_renewal_schedule: ""
  watch_renewal_time_zone: ""

Hosting modes

Gmail uses the same Google Workspace domain-wide delegation flow in both base modes.
  • self-hosting: the Gmail installer creates the Gmail-specific infrastructure in your project and then waits for a Workspace super admin to authorize the delegated service account client ID.
  • cloud-hosting: the shared GCP foundation still comes from your base mode, but the Gmail integration itself uses the same delegated service account grant flow as self-hosting.

Run the installer

1

Update `cloud-providers/gcp/scripts/integrations/gmail/install.yaml`

Fill in the Workspace domain, admin subject email, labels, and any quota, retry, normalization, or watch-renewal settings you want to override.
2

Run the script

From the repository root, run:
./cloud-providers/gcp/scripts/integrations/install-integration.sh gmail
3

Approve the planned changes

Review the planned changes and approve them to continue.
4

Add the delegated OAuth client ID in Google Workspace Admin Console

After Terraform finishes, the installer prints the Gmail delegated service account email and its OAuth client ID, and writes the same instructions to:
generated/gcp/<project-id>/gmail-domain-wide-delegation.txt
Sign in to Google Workspace Admin Console as a super admin, then open:
Security > Access and data control > API controls > Manage Domain Wide Delegation
Add the printed client ID and authorize these scopes:
https://www.googleapis.com/auth/gmail.readonly
https://www.googleapis.com/auth/admin.directory.user.readonly
5

Resume the installer after the admin grant if needed

In an interactive shell, you can confirm the prompt after the Workspace grant is complete.If the installer already paused or you want to resume explicitly, rerun:
./cloud-providers/gcp/scripts/integrations/install-integration.sh gmail --resume-after-admin-grant
If you want to use a different config file, target a specific base install, or skip confirmation prompts:
./cloud-providers/gcp/scripts/integrations/install-integration.sh gmail --config /path/to/install.yaml
./cloud-providers/gcp/scripts/integrations/install-integration.sh gmail --install-state /path/to/install-state.json
./cloud-providers/gcp/scripts/integrations/install-integration.sh gmail --auto-approve
./cloud-providers/gcp/scripts/integrations/install-integration.sh gmail --resume-after-admin-grant --config /path/to/install.yaml --install-state /path/to/install-state.json
When the script finishes, it prints the project ID, Gmail ingest function URL, Gmail normalization service URL, Gmail backfill job name, Gmail watch renewal job name, the raw events bucket, the path to the domain-wide delegation instructions file, the validation execution ID, and the live-bootstrap and initial backfill execution IDs when available.

Update the integration later

If Gmail is already connected and you want to change the synced labels, admin subject email, throttling behavior, or watch-renewal settings, update the existing Gmail integration instead of rerunning the base GCP setup.
1

Update the Gmail settings

Edit cloud-providers/gcp/scripts/integrations/gmail/install.yaml and keep the full set of labels you want synced in gmail.included_labels, along with any updated workspace_domain, admin_subject_email, quota, retry, normalization, or watch-renewal values.
2

Confirm the Workspace admin grant still matches the generated client ID

If you rerun against the same base install, the delegated client ID should stay the same. If you target a different base install or project and the installer prints a new client ID, add that new client ID in Google Workspace Admin Console before resuming.
3

Rerun only the Gmail installer

Run:
./cloud-providers/gcp/scripts/integrations/install-integration.sh gmail
If needed, pass --install-state /path/to/install-state.json to target the existing base setup you want to update. If the installer pauses after printing the Workspace instructions, complete the grant and rerun with --resume-after-admin-grant.
After that rerun, the existing Gmail connection stays in place and the installer updates the stored config, validation, and runtime resources to match the YAML.

Troubleshooting

  • If the installer cannot find the base setup you want, pass --install-state /path/to/install-state.json.
  • If the installer says gmail.workspace_domain is required, fill in gmail.workspace_domain.
  • If the installer says gmail.admin_subject_email is required, fill in gmail.admin_subject_email with a Google Workspace admin email in the same tenant.
  • If the installer says gmail.included_labels must contain at least one supported label, add at least one label to gmail.included_labels. In v1, the supported values are only INBOX, SENT, and DRAFT.
  • If the installer fails while validating Workspace delegation after you added the client ID, wait a few minutes for the Google Workspace Admin Console grant to propagate, then rerun with --resume-after-admin-grant.
  • If Terraform apply fails while creating IAM bindings for Gmail-specific principals, check whether the legacy domain-restricted-sharing constraint iam.allowedPolicyMemberDomains is blocking Google-managed principals such as gmail-api-push@system.gserviceaccount.com.