fix(email): support a delegated-mailbox alias distinct from the delegated Workspace account

Real-world case found during setup: the sending address ([email protected]) is an
alias of an existing Workspace user, not its own paid seat (a deliberate cost-saving choice).
Domain-wide delegation authorizes a real Workspace ACCOUNT, not an arbitrary alias string, so
using the alias directly as the delegated 'sub' claim would have been wrong. Added
GOOGLE_DELEGATED_USER (the account that actually owns the alias and was granted delegation) as
an optional override, falling back to EMAIL_FROM_ADDRESS unchanged when the sending address is
itself a primary account. EMAIL_FROM_ADDRESS remains the visible From: header in both cases.
Documented in docs/RUNBOOK_GOOGLE_WORKSPACE_EMAIL.md with a concrete example.
This commit is contained in:
2026-08-25 17:38:59 -05:00
parent 777efd168d
commit 7baf7074e5
2 changed files with 40 additions and 10 deletions
+13 -3
View File
@@ -1,6 +1,16 @@
// Phase 5C §2 — the Google Workspace adapter. Sends via the Gmail API
// (users.messages.send), authenticated as a Google Cloud service account using Workspace
// domain-wide delegation to impersonate a dedicated sending mailbox (EMAIL_FROM_ADDRESS).
// domain-wide delegation to impersonate a Workspace user.
//
// GOOGLE_DELEGATED_USER vs. EMAIL_FROM_ADDRESS — two different things, deliberately kept
// separate: domain-wide delegation authorizes the service account to act as one real Workspace
// USER ACCOUNT (the "sub" claim below) — if the sending address is an ALIAS of a real account
// rather than its own paid seat (a deliberate cost-saving choice, not a mistake), the delegated
// user must be the ALIAS'S OWNER (the real account it belongs to), not the alias string itself.
// EMAIL_FROM_ADDRESS is only ever the visible From: header — Gmail lets any account send as its
// own verified aliases, so this can safely be the alias while GOOGLE_DELEGATED_USER is the real
// account underneath it. If the sending address IS a primary account already,
// GOOGLE_DELEGATED_USER can be left unset and this falls back to EMAIL_FROM_ADDRESS.
//
// WHY this mechanism, not SMTP or a human login: Google's own guidance for a backend
// application sending mail as a specific Workspace address is a service account + domain-wide
@@ -42,8 +52,8 @@ function loadServiceAccount() {
// implements.
async function getAccessToken() {
const sa = loadServiceAccount();
const impersonate = process.env.EMAIL_FROM_ADDRESS;
if (!impersonate) throw configError('EMAIL_FROM_ADDRESS is not set (required as the delegated-user "sub" claim)');
const impersonate = process.env.GOOGLE_DELEGATED_USER || process.env.EMAIL_FROM_ADDRESS;
if (!impersonate) throw configError('Set GOOGLE_DELEGATED_USER (or EMAIL_FROM_ADDRESS if the sending address is itself a primary account) — required as the delegated-user "sub" claim');
const now = Math.floor(Date.now() / 1000);
const header = Buffer.from(JSON.stringify({ alg: 'RS256', typ: 'JWT' })).toString('base64url');