Skip to main content

gmail-draft

Backs Save to my Gmail drafts on the email draft card in Ask SABLE. The browser calls POST /api/gmail-draft, which forwards the person's own session here.

{ "to": ["Paul Robinson <paul.robinson@globe.com>"], "cc": [], "subject": "Next steps", "body": "Hi Paul, ...", "draft_id": "uuid" }

It creates one draft in the signed-in person's own mailbox and returns { ok, gmail_draft_id, open_url, mailbox }. It never sends: the only Gmail call is drafts.create, and a test fails if any other Gmail endpoint appears in the code.

Checks, in order​

  1. A signed-in, active staff member (admin, lead or consultant). Portal users are refused.
  2. GMAIL_DRAFTS_ENABLED=true (an Edge secret). Otherwise 412, and the card suggests Copy.
  3. The mailbox is the person's own @indigotrigger.com address from SABLE. Nothing in the request can choose another mailbox. The web route also refuses while View as is set to someone else.
  4. A valid draft: every address is printable ASCII and parses, at least one To, at most 20 recipients, subject up to 250 characters, body up to 20,000 characters. Header values can't carry a line break, so nothing on the card can add a header such as Bcc.
  5. The GMAIL_COMPOSE_SA_JSON key is set (503 otherwise).
  6. At most 30 drafts per person per hour (429). A request first records an audit row (gmail_draft_created, status pending) and then counts, so requests sent at once cannot slip past the limit. The row is removed if the draft isn't made, and updated to created when it is. It holds the recipient count and subject, never the body.

One-time setup​

warning

Google has no draft-only permission. gmail.compose also allows sending mail as anyone in the domain. SABLE's code only creates drafts, but anyone holding the key below could send. That is why it uses a service account of its own, holding only this one permission, with its key in a single Edge secret. Never add gmail.compose to SABLE's shared Workspace service account: its key is also kept in other Edge secrets and a Vault row.

Google side (a Google Workspace super admin: Chris or Lindsey).

  1. Open console.cloud.google.com, choose the Indigo Trigger project that holds SABLE's existing service account, and go to IAM & Admin → Service Accounts → Create service account. Name it sable-gmail-drafts. It needs no project roles: skip that step and choose Done. The project must have the Gmail API enabled (APIs & Services → Library); it already is if SABLE's Gmail sync uses this project.
  2. Open the new account. On Details, copy the Unique ID (a long number): this is its client ID.
  3. On Keys, choose Add key → Create new key → JSON. A file downloads. Hand it to a SABLE admin through a password manager, never email or chat, then delete your copy. If key creation is blocked, the organisation policy iam.disableServiceAccountKeyCreation needs an exception for this project.
  4. Open admin.google.com and go to Security → Access and data control → API controls → Manage Domain Wide Delegation → Add new.
  5. Client ID: the Unique ID from step 2. OAuth scopes: https://www.googleapis.com/auth/gmail.compose and nothing else. Choose Authorize. This is a new entry: leave SABLE's existing entry (Drive, Calendar and Gmail read scopes: drive.readonly, calendar.readonly, calendar.events, gmail.readonly) exactly as it is.

SABLE side (a SABLE admin).

  1. In Supabase, Project settings → Edge Functions → Secrets, add GMAIL_COMPOSE_SA_JSON with the whole contents of the JSON key file, then delete the file.
  2. Add GMAIL_DRAFTS_ENABLED = true.
  3. Test: draft an email in Ask SABLE, choose Save to my Gmail drafts, and open the link. A new delegation can take from a few minutes up to 24 hours to apply; until then the button reports "SABLE isn't allowed to write Gmail drafts yet".

To turn it off: set GMAIL_DRAFTS_ENABLED to anything else. To remove the permission completely: delete the delegation entry from step 5 and the service account from step 1, and remove GMAIL_COMPOSE_SA_JSON.

Where the code lives​

  • supabase/functions/gmail-draft/index.ts (Google calls) and logic.js (checks and the message)
  • web/api/gmail-draft.js (forwarding route) and web/email-draft-card.js (the button)