Naar inhoud
lightbulb Welkom op de nieuwe kennisbank | We hebben de docs volledig vernieuwd met meer dan 160 features. Bekijk wat nieuw isarrow_forward

Gmail-regels beheren via de API

Gebruik de Gmail API om e-mailfilters programmatisch aan te maken, te lezen en te verwijderen, ideaal voor het beheren van filters voor grote teams via code.

Gmail-filters via de API

Gmail-filters zijn automatische regels die acties uitvoeren op inkomende e-mails. Via de Gmail API kun je filters programmatisch beheren. Dat is handig voor het uitrollen van standaardfilters naar meerdere gebruikers, het importeren van filters uit een configuratiesysteem of het automatisch aanpassen van filters op basis van bedrijfslogica.

info

Welke scope heb je nodig?

Alle bewerkingen op filters (lezen, aanmaken en verwijderen) gebruiken dezelfde scope: https://www.googleapis.com/auth/gmail.settings.basic. Voor het beheren van labels heb je daarnaast https://www.googleapis.com/auth/gmail.labels nodig. Beide scopes worden door Google als gevoelig (sensitive) geclassificeerd, dus voor een productie-app is een Google-verificatie van je OAuth-consent-scherm vereist.

Authenticatie

from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import InstalledAppFlow
from googleapiclient.discovery import build
import os

SCOPES = [
    'https://www.googleapis.com/auth/gmail.settings.basic',
    'https://www.googleapis.com/auth/gmail.labels',
]

def get_gmail_service():
    creds = None
    if os.path.exists('token.json'):
        creds = Credentials.from_authorized_user_file('token.json', SCOPES)

    if not creds or not creds.valid:
        flow = InstalledAppFlow.from_client_secrets_file('credentials.json', SCOPES)
        creds = flow.run_local_server(port=0)
        with open('token.json', 'w') as token:
            token.write(creds.to_json())

    return build('gmail', 'v1', credentials=creds)

Bestaande filters ophalen

def haal_filters_op(service):
    result = service.users().settings().filters().list(userId='me').execute()
    filters = result.get('filter', [])

    for f in filters:
        criteria = f.get('criteria', {})
        action = f.get('action', {})
        print(f'Filter ID: {f["id"]}')
        print(f'  Van: {criteria.get("from", "Niet ingesteld")}')
        print(f'  Onderwerp bevat: {criteria.get("subject", "Niet ingesteld")}')
        print(f'  Acties: {action}')
        print('---')

    return filters

Een filter aanmaken

Een filter bestaat uit twee delen: criteria (waar het filter op matcht) en action (wat er moet gebeuren). Acties verwijzen naar label-id's, niet naar labelnamen, dus zoek de id eerst op of maak het label aan.

def maak_filter_aan(service, van=None, onderwerp=None, label_naam=None,
                     archiveren=False, markeer_gelezen=False, verwijderen=False):
    criteria = {}
    if van:
        criteria['from'] = van
    if onderwerp:
        criteria['subject'] = onderwerp

    add_labels = []
    remove_labels = []

    if label_naam:
        label_id = haal_of_maak_label(service, label_naam)
        add_labels.append(label_id)

    if archiveren:
        remove_labels.append('INBOX')

    if markeer_gelezen:
        remove_labels.append('UNREAD')

    if verwijderen:
        add_labels.append('TRASH')

    filter_body = {
        'criteria': criteria,
        'action': {
            'addLabelIds': add_labels,
            'removeLabelIds': remove_labels
        }
    }

    result = service.users().settings().filters().create(
        userId='me',
        body=filter_body
    ).execute()

    print(f'Filter aangemaakt: {result["id"]}')
    return result['id']

def haal_of_maak_label(service, naam):
    labels = service.users().labels().list(userId='me').execute()
    for label in labels.get('labels', []):
        if label['name'] == naam:
            return label['id']

    nieuw_label = service.users().labels().create(
        userId='me',
        body={'name': naam, 'labelListVisibility': 'labelShow', 'messageListVisibility': 'show'}
    ).execute()

    return nieuw_label['id']

Filters in bulk aanmaken

Voor het uitrollen van een vaste set filters is het handig om de configuratie los van de code te houden, bijvoorbeeld in een JSON- of YAML-bestand. Zo kunnen niet-ontwikkelaars de filters aanpassen zonder de code te raken.

def importeer_filters_vanuit_config(service, filter_configuraties):
    resultaten = []

    for config in filter_configuraties:
        filter_id = maak_filter_aan(
            service,
            van=config.get('van'),
            onderwerp=config.get('onderwerp'),
            label_naam=config.get('label'),
            archiveren=config.get('archiveren', False),
            markeer_gelezen=config.get('markeer_gelezen', False)
        )
        resultaten.append({'config': config, 'filter_id': filter_id})

    return resultaten

filter_configuraties = [
    {
        'van': '@klantdomeinnaam.nl',
        'label': 'Klant A',
        'markeer_gelezen': False
    },
    {
        'onderwerp': '[SPAM]',
        'archiveren': True,
        'markeer_gelezen': True
    },
    {
        'van': 'noreply@github.com',
        'label': 'GitHub',
        'archiveren': True
    }
]

service = get_gmail_service()
resultaten = importeer_filters_vanuit_config(service, filter_configuraties)

Filter verwijderen

def verwijder_filter(service, filter_id):
    service.users().settings().filters().delete(
        userId='me',
        id=filter_id
    ).execute()
    print(f'Filter verwijderd: {filter_id}')

def verwijder_alle_filters(service):
    filters = haal_filters_op(service)
    for f in filters:
        verwijder_filter(service, f['id'])
    print(f'{len(filters)} filters verwijderd.')
warning

Maak altijd eerst een back-up

Verwijder nooit alle filters zonder een back-up. Exporteer de bestaande filters eerst met haal_filters_op() en sla de output op als JSON. Zo kun je bij een fout de oorspronkelijke situatie herstellen.

Uitrollen naar een heel team

Wil je filters niet voor je eigen account maar voor alle gebruikers in je Google Workspace-organisatie beheren, dan werk je met een serviceaccount en Domain-Wide Delegation. Het serviceaccount handelt dan namens elke gebruiker (impersonatie), zonder dat die gebruiker zelf hoeft in te loggen.

lightbulb

Zo verloopt de uitrol veilig

Test je filterset eerst op een testaccount, draai daarna een dry-run die alleen logt wat er aangemaakt zou worden, en rol pas daarna uit naar de hele organisatie. Houd er rekening mee dat het maximum 1.000 filters per account is.

Veelgestelde vragen

Kan ik filters beheren voor alle gebruikers in de organisatie?

Ja. Via een serviceaccount met Domain-Wide Delegation kun je namens elke gebruiker filters beheren. Dit vereist beheerdersrechten en wordt geactiveerd in de Admin Console onder Beveiliging en API-besturingselementen.

Ondersteunt de API ook AND/OR-logica?

De Gmail API ondersteunt meerdere criteria per filter, die altijd als AND worden behandeld. OR-logica is niet mogelijk binnen één filter. Maak meerdere filters aan als je OR-gedrag wilt nabootsen.

Kan ik filters importeren of exporteren als XML?

Gmail heeft een eigen XML-export via Instellingen, dan Filters en geblokkeerde adressen, en dan Exporteren. Rechtstreeks XML importeren via de API kan niet. Je moet het XML-bestand eerst vertalen naar API-aanroepen.

Welke scope heb ik nodig om filters te beheren?

Lezen, aanmaken en verwijderen van filters gebruiken allemaal de scope gmail.settings.basic. Voor het aanmaken van labels heb je daarnaast gmail.labels nodig.

Hoeveel filters kan ik maximaal aanmaken?

Gmail ondersteunt maximaal 1.000 filters per account. Houd hier rekening mee bij bulk-uitrol, want bij overschrijding geeft de API een foutmelding.

Worden filters direct toegepast op bestaande e-mails?

Nee. Een filter dat je via de API aanmaakt geldt alleen voor nieuw inkomende berichten. Om bestaande berichten te verwerken moet je apart een zoekopdracht draaien en de gewenste acties op die berichten uitvoeren.