---
title: "Your AI-built app connects to Gmail. Six things that have to hold before launch (2026)"
description: "Six checks before launching a Gmail-connected AI-built app: scopes, token storage, per-user isolation, Google verification and CASA, watch renewals, deletion."
url: https://systemtrails.com/resources/gmail-connected-ai-built-app-before-launch/
markdown: https://systemtrails.com/resources/gmail-connected-ai-built-app-before-launch/index.md
type: resources
date: 2026-08-28
lastmod: 2026-09-01
tags: ["gmail","oauth","ai-mvp","security","launch-readiness"]
---

# Your AI-built app connects to Gmail. Six things that have to hold before launch (2026)

> Six checks before launching a Gmail-connected AI-built app: scopes, token storage, per-user isolation, Google verification and CASA, watch renewals, deletion.

A Gmail-connected app built with Cursor, Claude Code, Lovable, Replit, or Bolt is ready to launch when six things hold: the scope list is the narrowest that works, refresh tokens are encrypted server-side and bound to one user, no code path can use one user's token for another, the OAuth consent screen is published and verified (with CASA scheduled if a scope is restricted), the `watch()` subscription is renewed at least every 7 days, and disconnecting a user leaves nothing behind. Until the consent screen is verified, Google caps you at 100 test users and every token dies 7 days after consent. None of it needs a rewrite.

**TL;DR**

Gmail-connected apps built with AI coding tools fail in six predictable places. Check these before launch, in this order:

1. **Scopes**: ask for the narrowest Gmail scope, not full access
2. **Token storage**: refresh tokens encrypted, server-side, per user, revocable
3. **Per-user isolation**: one user can never read another user's messages, even through a bug
4. **Google verification and CASA**: without it you are capped at 100 test users and 7-day tokens
5. **Watch renewals and quotas**: push notifications expire after 7 days; new projects have per-user quota ceilings since May 2026
6. **Deletion and data policy**: delete means delete, including Google's Limited Use rules

## The path from scope to launch

The scope the AI picked decides everything downstream: whether you need verification at all, whether you need a CASA assessment, and how long the calendar is. This is the path, from Google's own scope classification (updated July 22, 2026).

```mermaid
flowchart LR
  S["Which Gmail scope<br/>does the app request?"] --> N["Non-sensitive<br/>gmail.labels, add-on scopes"]
  S --> SE["Sensitive<br/>gmail.send"]
  S --> R["Restricted<br/>gmail.readonly, gmail.modify,<br/>gmail.metadata, mail.google.com"]
  N --> P1["Publish"]
  SE --> V1["Brand + scope<br/>verification"] --> P2["Publish"]
  R --> V2["Brand + scope<br/>verification"] --> C["CASA, AL1 or AL2,<br/>revalidated every 12 months"] --> P3["Publish"]
  S -. "consent screen<br/>still in Testing" .-> T["100 test users,<br/>every token dies after 7 days"]
```

The six checks below follow that path. Each one names the symptom you will see in an AI-built app and the one thing to verify.


### 1. Scopes

Full access requested because it made every feature work. **Check:** the scope list in code and in the OAuth client match, and neither contains `mail.google.com` unless you delete mail.
### 2. Token storage

Refresh tokens in a plain-text column, in logs, or in the browser. **Check:** every read of `refresh_token`, traced to its destination.
### 3. Per-user isolation

The Gmail client is built from a request parameter or a shared variable. **Check:** a two-user test proves no call for user A carries user B's token.
### 4. Verification and CASA

Consent screen still in Testing at launch. **Check:** publishing status in Cloud Console, and a CASA lab booked if any scope is restricted.
### 5. Watch renewals and quotas

`watch()` called once at setup. **Check:** a daily renewal job, `historyId` reconciliation, and a backfill that respects 6,000 units per user per minute.
### 6. Deletion and Limited Use

Message bodies cached and kept after disconnect. **Check:** disconnect a test account, then query the database.


## 1. Scopes: the AI asked for more than you need

Gmail's API has a ladder of OAuth scopes, and Google classifies each rung. The classification, not the feature, decides your verification path.

| Scope | What it allows | Google's class | What launch requires |
|---|---|---|---|
| `gmail.labels` | Read and edit labels | Non-sensitive | Publish |
| `gmail.send` | Send mail as the user | Sensitive | Brand and scope verification |
| `gmail.readonly` | Read messages and settings | Restricted | Verification plus CASA |
| `gmail.modify` | Read, compose, send, label, archive (no permanent delete) | Restricted | Verification plus CASA |
| `gmail.metadata` | Headers and labels, no bodies | Restricted | Verification plus CASA |
| `mail.google.com` | Everything, including permanent deletion | Restricted | Verification plus CASA, and the hardest review |

AI coding tools tend to request `mail.google.com` because every feature works on the first try. Three problems follow. Users see a scarier consent screen and drop off. Google's reviewers ask you to justify every scope, and "the AI picked it" is not a justification. And a breach of a full-access token is a breach of the whole mailbox.

**The check:** open your OAuth client configuration and your code's scope list. If `mail.google.com` is there and you do not delete messages, remove it. If the app only sends, `gmail.send` alone keeps you out of CASA entirely. Expect to re-verify after any scope change.

## 2. Token storage: where the refresh tokens actually live

A Gmail refresh token is a standing key to someone's inbox. The pattern in AI-built apps, seen repeatedly: the token is written to a database column in plain text, sometimes logged on every request, occasionally shipped to the browser so the frontend can "call Gmail directly."

**What has to hold:** tokens stored server-side only, encrypted at rest with a key from a KMS or vault, not a constant in the code. Each token bound to exactly one user record, looked up by the authenticated session, never by a client-supplied user id. Logs redact tokens and message bodies. Deleting the account revokes the token at Google (`oauth2.revoke`) and destroys the stored copy.

**The check:** search the repo and the database schema for `refresh_token`. Trace every read of that column. If any path returns it to the client or writes it to a log, that is finding number one of your teardown.

## 3. Per-user isolation: the bug that leaks someone else's inbox

Every Gmail-connected app has a place where it decides *whose* token to use. In AI-built code that decision is often made from a parameter in the request (`?userId=`), from a cached "current user" variable that survives across requests, or from a background job that iterates users and reuses one client object.

This is the failure mode that turns a bug into a breach: user A's sync job runs with user B's token, or a shared client retains the last user's credentials. It is invisible in single-user testing, and it is the first thing a [technical due diligence reviewer](/resources/technical-due-diligence-ai-built-codebase/) looks for.

**The check:** find every construction of the Gmail client. Confirm it is built from the token of the authenticated user in that request or that job, and destroyed after. Then write the one test that matters: two users, two inboxes, assert that no call for user A ever carries user B's token.

## 4. Google verification and the CASA assessment

Until your OAuth consent screen is published and verified, the project stays in **Testing**: a maximum of **100 test users**, and every authorization, refresh token included, **expires 7 days after consent**. Founders hit this the week after launch, when the first cohort's connections silently die.

Any restricted Gmail scope requires more than brand verification: a **CASA (Cloud Application Security Assessment)** by a Google-authorized lab, and Google states that apps must be revalidated **at least every 12 months** after the assessor's letter date. CASA now assigns one of two assurance levels: **AL1**, where the lab validates evidence and scan results you submit, and **AL2**, where the lab tests the running application, its infrastructure, and every place user data is stored. Google, not you, picks the level, based on scopes, user volume, and risk signals. Google's own guidance is that restricted-scope verification "potentially takes several weeks."

**The one thing to check today**

Open Google Cloud Console, then **APIs and Services, OAuth consent screen (Audience)**. If the publishing status says **Testing**, your launch has a 100-user ceiling and a 7-day token lifetime right now, whatever the code does. Start the verification this week; the calendar, not the engineering, is the long pole.

## 5. Watch renewals and the 2026 quota tiers

If the app reacts to new mail, it uses `users.watch()` to get push notifications through Pub/Sub. Google's documentation is direct: call `watch` **at least once every 7 days** or updates stop, and the recommendation is **once per day**. Expiry is silent; there is no error and no email. After any gap, catch up with `history.list` from the last stored `historyId`.

**How the AI wired it:** `watch()` is called once, in the onboarding handler. Nothing renews it. The demo works for a week, then every user goes quiet on day 8 and nobody knows why. The last `historyId` was never stored, so there is nothing to reconcile from.

**What a product does:** A daily job calls `watch()` for every connected user and stores the returned `expiration`. Each notification's `historyId` is persisted. On restart or after any gap, `history.list(startHistoryId)` replays what was missed. An alert fires if a user's watch is within 24 hours of expiry.

There is a second, newer ceiling. On **May 1, 2026** Google rolled out a tiering model for Gmail API usage. Cloud projects created on or after that date get **1,200,000 quota units per minute per project** and **6,000 per minute per user**, with an 80,000,000-unit daily threshold. `messages.get` costs 20 units, `threads.get` 40, `users.watch` 100, `messages.send` 100. Projects that used the API between November 2025 and April 2026 keep their earlier quotas.

That per-user number matters for a common AI-built pattern: on connect, fetch every message in the inbox. At 20 units each, 300 `messages.get` calls fill a user's minute. A 10,000-message inbox backfilled that way takes 33 minutes of quota errors unless the job batches, paces, and resumes.

**The check:** search for `watch(`. If there is no scheduled renewal and no reconciliation on `historyId`, the integration is a demo, not a product. Then look at the first sync: does it page, back off on 429s, and prefer `messages.list` plus `history.list` over fetching every body?

## 6. Deletion, retention, and Google's Limited Use rules

Gmail data falls under Google's API Services User Data Policy and the Workspace API user data policy (updated July 22, 2026). The **Limited Use** requirements: use the data only to provide or improve user-facing features prominent in your app, do not sell or transfer it, do not use it for ads or credit decisions, do not let humans read it except with the user's specific agreement, and do not use it to create, train, or improve an AI or ML model beyond that one user's personalized feature. Your privacy policy has to say this, and the app has to do it.

AI-built apps commonly cache message bodies "for performance," keep them after the user disconnects, and feed them to a third-party model without a word in the privacy policy.

**The check:** disconnect a test account and look at the database. Anything left is a policy problem and, for employment or health data, a legal one. Then read the privacy policy against the code: every data flow the code performs must be disclosed.

## What "ready" looks like

A Gmail-connected app is launch-ready when: the scope list is minimal and justified; tokens are encrypted, server-side, per user, and revoked on deletion; the two-user isolation test passes; the consent screen is verified, with the CASA lab booked if a scope is restricted; watches renew daily and the first sync respects the per-user quota; and disconnect leaves nothing behind.

None of this requires a rewrite. In most AI-built apps it is a fixed-scope hardening pass of one to two weeks, done once, with the trail left behind: the isolation test, the renewal job, the runbook for the day Google emails you about your revalidation.

If you want senior eyes on your actual code first, that is what the [free teardown](/free-teardown/) is: three findings and a verdict, recorded, within 72 hours.

## Sources

- Google, [Choose Gmail API scopes](https://developers.google.com/workspace/gmail/api/auth/scopes), scope classification table, updated 2026-07-22
- Google, [Manage app audience](https://support.google.com/cloud/answer/15549945) (Testing status: 100 test users, authorizations expire 7 days from consent)
- Google, [Restricted scope verification](https://developers.google.com/identity/protocols/oauth2/production-readiness/restricted-scope-verification), updated 2026-08-19
- Google, [Security assessment](https://support.google.com/cloud/answer/13465431) and App Defense Alliance, [CASA assurance levels](https://appdefensealliance.dev/casa/casa-tiering), updated 2026-06-27
- Google, [Configure push notifications in Gmail API](https://developers.google.com/workspace/gmail/api/guides/push), updated 2026-07-22
- Google, [Gmail API usage limits](https://developers.google.com/workspace/gmail/api/reference/quota), updated 2026-07-31, and [Workspace developer release notes](https://developers.google.com/workspace/release-notes), 2026-05-01
- Google Workspace Updates, [Agent tools and security updates for Workspace developers](https://workspaceupdates.googleblog.com/2026/05/agent-tools-and-security-updates-for-workspace-developers.html), 2026-05-01
- Google, [API Services User Data Policy](https://developers.google.com/terms/api-services-user-data-policy) and [Workspace API user data and developer policy](https://developers.google.com/workspace/workspace-api-user-data-developer-policy), updated 2026-07-22

## FAQ

**Do I need Google's OAuth verification to launch a Gmail-connected app?**

Yes, for any sensitive or restricted Gmail scope. Until the OAuth consent screen is published and verified, the project stays in Testing: at most 100 test users, and every authorization (including the refresh token) expires 7 days after consent. Restricted scopes (gmail.readonly, gmail.modify, gmail.metadata, mail.google.com) also require a CASA security assessment by a Google-authorized lab, revalidated every 12 months. gmail.send alone is a sensitive scope: verification, but no CASA.

**Which Gmail scope should an AI-built app ask for?**

The narrowest one that does the job. gmail.send if you only send (sensitive, no CASA). gmail.readonly if you only read, gmail.modify only if you must label or archive (both restricted, CASA required). Never mail.google.com (full access, including permanent deletion) by default. AI coding tools often request full access because it makes every feature work; verification reviewers and users both penalize it.

**Where should Gmail refresh tokens be stored?**

Server-side, encrypted at rest with a key the application server does not own outright (a KMS or vault), bound to one user record, never in the browser, never in logs, never in the repo. Rotate the encryption key on a schedule and revoke the Google token (oauth2.revoke) when the user deletes their account.

**Why did my Gmail push notifications stop after a week?**

Gmail watch() subscriptions expire after 7 days with no error and no warning. Google recommends calling watch once per day. Production apps renew on a schedule and, after any gap, reconcile with history.list from the last stored historyId. AI-generated integrations usually create the watch once at setup and never renew it.

**What changed in Gmail API quotas in 2026?**

On May 1, 2026 Google introduced a tiering model for Gmail API usage. Cloud projects created on or after that date get 1,200,000 quota units per minute per project and 6,000 per minute per user, with messages.get costing 20 units, threads.get 40, and users.watch 100. Projects that used the API between November 2025 and April 2026 keep their previous quotas. A backfill that fetches every message on connect will hit the per-user limit.

**How much does it cost to make a Gmail-connected AI-built app production-ready?**

Verification and the CASA assessment are external costs and calendar time (Google says restricted-scope verification potentially takes several weeks). The engineering work, when the app already works, is typically a fixed-scope hardening pass of one to two weeks: SystemTrails prices that from $2,500, quoted after a free recorded teardown.



Free teardown: https://systemtrails.com/free-teardown/ | Contact: https://systemtrails.com/contact/ | Book a call: https://cal.com/dan-podina-snqasy/30min

