← blog
Gmail API OAuth2 Netlify Functions Sicurezza

Gmail API + OAuth2: casella condivisa senza password reale

Come collegare una casella Gmail condivisa a un pannello interno — stessa esperienza di strumenti come Tidio, Front o Help Scout — senza che nessuno, nemmeno chi scrive il codice, veda mai la password reale della casella.

Due modi per collegarsi a Gmail, e quale scegliere

Google offre due strade per un'app che deve leggere/scrivere su Gmail per conto di qualcun altro:

Aspetto / AspectDomain-Wide DelegationOAuth2 app installata / installed app
Serve per
Impersonare più caselle di un intero dominio Workspace
Una singola casella specifica
Richiede
Service account + accesso admin a Workspace
Consenso una tantum di chi ha accesso reale alla casella
Svantaggio
Setup complesso, privilegi elevati
Va rifatto se il token viene revocato

Per una singola casella condivisa, OAuth2 app installata è quasi sempre la scelta giusta: nessun privilegio da amministratore di dominio, setup più semplice.

Setup su Google Cloud Console

  1. Abilita la Gmail API sul progetto Google Cloud
  2. Configura la schermata di consenso OAuth con gli scope gmail.readonly e gmail.send (minimi necessari — evita scope più ampi come gmail.modify se non servono)
  3. Aggiungi come "utente di test" l'indirizzo che darà il consenso — l'app resta in modalità Testing, niente pubblicazione o verifica Google necessaria per uso interno
  4. Crea un client OAuth di tipo "app desktop"
  5. Esegui il consenso una tantum: l'app riceve un refresh token, non una password

Regola ferrea: nessuna password reale deve mai passare per chat, ticket o codice. È proprio il senso di OAuth: nemmeno chi implementa l'integrazione ha bisogno di vedere la password vera della casella, in nessun momento del processo — solo il refresh token, salvato esclusivamente come variabile d'ambiente lato server.

Le tre Netlify Function tipiche

Un'integrazione completa si divide in tre funzioni server-side, mai nel bundle client:

  • list/read — poll periodico (es. ogni minuto) sulla casella per nuovi messaggi, con gmail.readonly
  • send — invio risposte con gmail.send, mai con la stessa function di lettura
  • attachments/inline images — risoluzione dei riferimenti cid: nelle immagini incorporate e download allegati su richiesta

Il 403 causato da un carattere in più

Un errore 403 con refresh token e client ID/secret apparentemente corretti è quasi sempre un problema di copia-incolla: uno spazio finale, un a-capo residuo, o un carattere invisibile nella variabile d'ambiente. Verifica sempre lunghezza e contenuto esatto della variabile su Netlify — non fidarti del campo di input, stampa la lunghezza della stringa in un log temporaneo se il dubbio persiste.

Limite della modalità Testing: un refresh token per un'app "installata" non ha scadenza fissa, ma può essere invalidato se l'utente cambia password, revoca manualmente l'accesso da Google, o se il client OAuth in modalità Testing supera 100 refresh token attivi. In quel caso basta ripetere il consenso una tantum per generarne uno nuovo.

Far sembrare un'email un'email, non una tabella del pannello

Il corpo HTML restituito da Gmail API va renderizzato con lo stile originale del messaggio, non riformattato con il CSS del pannello — altrimenti il risultato somiglia più a una riga di tabella che a una mail. Le immagini incorporate via cid: vanno risolte recuperando l'allegato corrispondente e sostituendo il riferimento con un URL o un data URI prima del render.

Checklist rapida

  • Scope minimi (gmail.readonly + gmail.send), niente gmail.modify se non serve
  • Refresh token solo come variabile d'ambiente server-side, mai nel repository né nel client
  • Funzioni di lettura e invio separate, per limitare il raggio d'azione di ciascuna chiave
  • Verifica byte-per-byte delle variabili d'ambiente se compare un 403 apparentemente ingiustificato
  • Consapevolezza del limite di 100 refresh token attivi in modalità Testing

Domande frequenti

Si può leggere e rispondere a una casella Gmail senza mai conoscere la password reale?

Sì, con OAuth2: chi ha accesso reale alla casella fa un consenso una tantum su Google, e l'app riceve un refresh token — non una password — che vive solo come variabile d'ambiente lato server.

Serve la Domain-Wide Delegation per collegare una sola casella Gmail?

No. Serve solo per impersonare più caselle di un intero dominio Workspace tramite service account, con accesso admin. Per una singola casella basta un OAuth2 "app installata" con consenso una tantum.

Un refresh token Gmail può scadere o smettere di funzionare?

Non ha scadenza fissa, ma può essere invalidato se l'utente cambia password, revoca l'accesso, o se il client OAuth in modalità Testing supera i 100 refresh token attivi. Basta ripetere il consenso per generarne uno nuovo.

Articolo correlato
Come ho ricostruito l'esperienza Tidio — con tutti i bug reali incontrati