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.
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)
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.
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"])
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.
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()
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.
Een bericht labelen en archiveren
- Maak een label aan met
users().labels().create(), of zoek een bestaand label-ID op metlabels().list(). - Verwerk inkomende berichten en bepaal welk label past.
- Roep
messages().modify()aan metaddLabelIdsenremoveLabelIds. - Verwijder
INBOXuit de labels om een bericht te archiveren.
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.
Push-notificaties instellen via Pub/Sub
- Maak een Pub/Sub-topic aan en geef het serviceaccount
gmail-api-push@system.gserviceaccount.compubliceerrechten op dat topic. - Roep
users().watch()aan met het topic en de labels die je wilt volgen. - Gmail publiceert bij elke wijziging een melding met een nieuwe
historyIdop het topic. - Je verwerker haalt de gewijzigde berichten op met
users().history().list()vanaf de laatst bekendehistoryId. - Vernieuw de
watchregelmatig (Google adviseert dagelijks), want hij verloopt na zeven dagen.
request = {
"labelIds": ["INBOX"],
"topicName": "projects/mijn-project/topics/gmail-meldingen",
}
service.users().watch(userId="me", body=request).execute()
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
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.