# Gmail API gebruiken in Python voor e-mailautomatisering [[TOC]] E-mail is nog altijd het kloppende hart van zakelijke communicatie, en veel ervan kun je automatiseren. Met de Gmail API in Python lees je berichten uit, stuur je geautomatiseerde mails, sorteer je met labels en reageer je realtime op nieuwe berichten. Of je nu een ticketsysteem voedt of nieuwsbrieven verwerkt, de API geeft je volledige controle. In dit artikel bouw je de kernfuncties stap voor stap op: lezen, sturen, labelen en realtime verwerken. ## Voorbereiding en authenticatie Installeer eerst de officiele Google-clientbibliotheken en stel je `service`-object samen. Gebruik altijd de smalste scope die je nodig hebt. ```python from google.oauth2.credentials import Credentials from googleapiclient.discovery import build SCOPES = [ "https://www.googleapis.com/auth/gmail.readonly", "https://www.googleapis.com/auth/gmail.send", ] creds = Credentials.from_authorized_user_file("token.json", SCOPES) service = build("gmail", "v1", credentials=creds) ``` :::tip title="Verklein je risico met scopes" Vraag nooit `gmail.modify` of `mail.google.com` aan als je alleen wilt lezen of sturen. Een te brede scope vergroot de impact als een token lekt en zorgt voor strengere verificatie door Google. Wijzig je de scopes? Verwijder dan `token.json`, anders blijf je de oude rechten gebruiken. ::: ## Berichten lezen Je haalt eerst een lijst van bericht-ID's op en vervolgens per ID de inhoud. De query gebruikt dezelfde syntax als de Gmail-zoekbalk. ```python resultaat = service.users().messages().list( userId="me", q="is:unread from:klant@voorbeeld.nl" ).execute() for ref in resultaat.get("messages", []): bericht = service.users().messages().get( userId="me", id=ref["id"] ).execute() print(bericht["snippet"]) ``` :::info title="Wat betekent userId='me'?" De waarde `me` als `userId` verwijst naar de geauthenticeerde gebruiker. Bij een service account met domain-wide delegation bepaalt het `subject` namens wie je handelt, dus je hoeft het e-mailadres niet apart mee te geven. ::: ## Een e-mail sturen De Gmail API verwacht een volledig MIME-bericht, base64url-gecodeerd. De `email`-module uit de standaardbibliotheek helpt hierbij. ```python import base64 from email.message import EmailMessage bericht = EmailMessage() bericht["To"] = "ontvanger@voorbeeld.nl" bericht["Subject"] = "Automatische bevestiging" bericht.set_content("Bedankt voor je aanvraag.") raw = base64.urlsafe_b64encode(bericht.as_bytes()).decode() service.users().messages().send( userId="me", body={"raw": raw} ).execute() ``` :::tip title="Laat de bibliotheek het MIME-werk doen" Gebruik de `email`-module om correcte headers en encoding te garanderen. Handmatig MIME opbouwen leidt snel tot fouten met speciale tekens of bijlagen. Bijlagen voeg je toe met `bericht.add_attachment(...)` voordat je het bericht codeert. ::: ## Labels en organisatie Labels zijn het sorteersysteem van Gmail. Je maakt ze aan en koppelt ze aan berichten met `modify`. Let op: hiervoor heb je de scope `gmail.modify` nodig. :::howto title="Een bericht labelen en archiveren" 1. Maak een label aan met `users().labels().create()`, of zoek een bestaand label-ID op met `labels().list()`. 2. Verwerk inkomende berichten en bepaal welk label past. 3. Roep `messages().modify()` aan met `addLabelIds` en `removeLabelIds`. 4. Verwijder `INBOX` uit de labels om een bericht te archiveren. ::: ```python service.users().messages().modify( userId="me", id=ref["id"], body={"addLabelIds": ["Label_123"], "removeLabelIds": ["INBOX"]}, ).execute() ``` ## Realtime met push-notificaties In plaats van steeds te pollen, laat je Gmail je een seintje geven via Cloud Pub/Sub zodra er iets verandert in de mailbox. :::howto title="Push-notificaties instellen via Pub/Sub" 1. Maak een Pub/Sub-topic aan en geef het serviceaccount `gmail-api-push@system.gserviceaccount.com` publiceerrechten op dat topic. 2. Roep `users().watch()` aan met het topic en de labels die je wilt volgen. 3. Gmail publiceert bij elke wijziging een melding met een nieuwe `historyId` op het topic. 4. Je verwerker haalt de gewijzigde berichten op met `users().history().list()` vanaf de laatst bekende `historyId`. 5. Vernieuw de `watch` regelmatig (Google adviseert dagelijks), want hij verloopt na zeven dagen. ::: ```python request = { "labelIds": ["INBOX"], "topicName": "projects/mijn-project/topics/gmail-meldingen", } service.users().watch(userId="me", body=request).execute() ``` :::warn title="Vergeet de watch niet te vernieuwen" Een `watch` verloopt na zeven dagen. Plan een geautomatiseerde vernieuwing in (bijvoorbeeld dagelijks), anders mis je stilletjes alle nieuwe meldingen. Bewaak ook of je `historyId` nog geldig is: bij grote gaten geeft de API een 404 terug en moet je een volledige hersynchronisatie doen. ::: ## Veelgestelde vragen :::faq ### Welke scope heb ik nodig om alleen te lezen? Gebruik `gmail.readonly`. Voor versturen gebruik je `gmail.send`, en voor labels beheren `gmail.modify`. Vraag altijd de smalste scope aan die past bij wat je code echt doet. ### Hoe verstuur ik bijlagen? Voeg ze toe aan het `EmailMessage`-object met `add_attachment` voordat je het bericht codeert. De Gmail API verwerkt de MIME-structuur dan automatisch, je hoeft de boundaries niet zelf te schrijven. ### Kan ik concepten maken in plaats van direct te sturen? Ja. Gebruik `users().drafts().create()` met dezelfde `raw`-body. Zo maak je een concept aan dat een gebruiker nog kan nakijken en later versturen via `drafts().send()`. ### Wat is het verschil tussen de formaten van messages.get? Met het `format`-veld kies je `full`, `metadata`, `minimal` of `raw`. Vraag `minimal` of `metadata` aan als je niet de volledige body nodig hebt, dat scheelt overgedragen data en quotaverbruik. ### Hoe ga ik om met de quota van de Gmail API? De API werkt met quota-eenheden per gebruiker per seconde. Lees-acties zoals `messages.get` zijn goedkoop, terwijl `messages.send` zwaarder telt. Bundel waar mogelijk met batch-requests en bouw exponential backoff in op `429`- en `403`-foutmeldingen. ### Werkt dit ook met een service account? Ja, maar alleen via domain-wide delegation in Google Workspace. Stel het `subject` in op de gebruiker namens wie je handelt. Voor gewone (niet-Workspace) Gmail-accounts gebruik je OAuth met gebruikerstoestemming. ::: Met de Gmail API in Python automatiseer je e-mailprocessen betrouwbaar, van eenvoudige bevestigingen tot realtime verwerking op schaal. Begin klein met lezen en sturen, en bouw de labelflow en push-notificaties uit zodra je proces stabiel draait.