Setup
Diese Anleitung führt durch alles, was nötig ist, um ein Microsoft-365-Postfach aus
OctoMesh abzufragen — zuerst im Azure Portal, dann die entsprechenden Azure-CLI-(az)-
Befehle und schließlich die OctoMesh-Seite (Anmeldedaten, Pipeline, Deployment, Test).
Anders als der Teams-Bot verwendet diese Integration einen App-only- (Client-Credentials-)Flow: Es gibt keine Azure-Bot-Ressource und keine Benutzeranmeldung. Die App- Registrierung authentifiziert sich als sie selbst und liest/verschiebt E-Mails über die Application- Berechtigungen von Microsoft Graph.
Voraussetzungen
- Ein Azure-Abonnement und die Berechtigung, eine App-Registrierung in Microsoft Entra ID zu erstellen.
- Ein Global Administrator (oder Privileged Role Administrator), um die Admin-Einwilligung (admin consent) für die Graph-Application-Berechtigung zu erteilen.
- Ein Microsoft-365-Postfach, das abgefragt werden soll, und die Ordnerstruktur, die Sie als
Arbeitswarteschlange verwenden möchten (z. B. ein
ToDo- und einDone-Ordner). - Ein laufender OctoMesh-Mesh Adapter für den Ziel-Tenant.
Die Beispiele verwenden den App-Namen octo-mail-import, das Postfach
accounting@company.com, den Quellordner Archive/Invoices/ToDo und den Erfolgsordner
Archive/Invoices/Done. Ersetzen Sie sie durch Ihre eigenen Werte.
Schritt 1 — App-Registrierung + Client-Secret
Die App-Registrierung ist die Identität, als die sich der Adapter authentifiziert. Ihre Client-
ID/-Secret und Tenant-ID gehen in die OctoMesh-MicrosoftGraphConfiguration.
Portal
- Microsoft Entra ID → App registrations → + New registration.
- Name:
octo-mail-import. - Supported account types: Accounts in this organizational directory only (Single tenant).
- Register, dann Application (client) ID und Directory (tenant) ID notieren.
- Certificates & secrets → + New client secret → eine Ablaufzeit festlegen → Add → den Value sofort kopieren (er wird nur einmal angezeigt).
Azure CLI
# create a single-tenant app registration
az ad app create --display-name "octo-mail-import" --sign-in-audience AzureADMyOrg
# -> note the "appId" from the output
# add a client secret (prints the secret once)
az ad app credential reset --id <APP_ID> --append --display-name mail-import --years 1 \
--query password -o tsv
# your tenant id
az account show --query tenantId -o tsv
Bewahren Sie drei Werte für später auf: App (client) ID, Client-Secret, Tenant-ID.
Schritt 2 — Graph-Application-Berechtigung Mail.ReadWrite
Der Trigger liest Nachrichten und verschiebt sie zwischen Ordnern, daher benötigt er die
Application-Berechtigung Mail.ReadWrite (nicht die delegierte), gefolgt von einer Admin-
Einwilligung.
Portal
- In der App-Registrierung: API permissions → + Add a permission → Microsoft Graph → Application permissions.
- Nach
Mail.ReadWritesuchen, ankreuzen, Add permissions. - Auf Grant admin consent for <tenant> klicken und bestätigen — die Spalte Status muss ein grünes Granted-Häkchen anzeigen.
Azure CLI
GRAPH=00000003-0000-0000-c000-000000000000 # Microsoft Graph resource appId
MAIL_RW=e2a3a72e-5f79-4c64-b1b1-878b674786c9 # Mail.ReadWrite (application) role id
# add the application permission
az ad app permission add --id <APP_ID> \
--api $GRAPH --api-permissions ${MAIL_RW}=Role
# grant admin consent (requires an admin)
az ad app permission admin-consent --id <APP_ID>
# verify the grant
az ad app permission list-grants --id <APP_ID> -o table
Die Application-Berechtigung Mail.ReadWrite gewährt der App Zugriff auf jedes Postfach im
Tenant, nicht nur auf das, das Sie konfigurieren. Bevor Sie dies in der Produktion verwenden, schränken Sie sie
auf die konkrete(n) Mailbox(en) mit einer Application Access Policy in Exchange Online ein
(erstellen Sie eine mail-fähige Sicherheitsgruppe, die nur die freizugebende(n) Mailbox(en) enthält, dann):
# Exchange Online PowerShell
New-ApplicationAccessPolicy -AppId <APP_ID> `
-PolicyScopeGroupId mail-import-scope@company.com `
-AccessRight RestrictAccess `
-Description "Restrict octo-mail-import to the accounting mailbox"
# confirm the app can access the target mailbox but not others
Test-ApplicationAccessPolicy -AppId <APP_ID> -Identity accounting@company.com
Schritt 3 — Die Postfachordner vorbereiten
Der Trigger behandelt einen Ordner als Arbeitswarteschlange. Erstellen Sie den Quell- und (optional) den Erfolgs- ordner im Postfach, zum Beispiel:
Archive
└── Invoices
├── ToDo ← trigger polls this (folderPath)
└── Done ← messages moved here on success (moveToFolderPathOnSuccess)
folderPath-Segmente müssen den Graph-Anzeigenamen entsprechen, die nicht
lokalisiert sind. Verwenden Sie Archive, nicht den lokalisierten Outlook-Namen (z. B. Archivieren).
Wohlbekannte Ordner (inbox, archive, …) werden auch über ihren wohlbekannten Namen aufgelöst.
Das Blatt (leaf) des Erfolgsordners wird automatisch erstellt, falls es fehlt, aber sein übergeordneter Pfad muss
bereits existieren.
Leiten Sie eingehende Rechnungen nach Belieben in den ToDo-Ordner (eine Outlook-Regel, ein
Workflow für gemeinsame Postfächer oder manuelle Ablage).
Schritt 4 — OctoMesh konfigurieren
1. Anmeldedaten (MicrosoftGraphConfiguration)
Geben Sie die Tenant-ID / Client-ID / das Secret als
System.Communication/MicrosoftGraphConfiguration-Entität an. Speichern Sie das Secret außerhalb
der Versionsverwaltung (eine lokale Secrets-Datei, ein Key Vault, …). Dies ist der gleiche
Konfigurationstyp, den die Teams-Trigger verwenden.
- rtId: <config-rtId>
ckTypeId: System.Communication/MicrosoftGraphConfiguration
rtWellKnownName: MicrosoftGraphDocuments
attributes:
- id: System.Communication/AzureTenantId
value: "<tenant id>"
- id: System.Communication/ClientId
value: "<app (client) id>"
- id: System.Communication/ClientSecret
value: "<client secret>"
2. Pipeline mit FromMicrosoftGraphEmail@1
Die Pipeline muss eine System.Communication/Uses-Assoziation zur
MicrosoftGraphConfiguration tragen (die GlobalConfiguration wird nur aus Uses-
Assoziationen aufgebaut — der Name allein wird nicht aufgelöst).
# on the Pipeline entity
associations:
- roleId: System.Communication/Uses
targetRtId: <config-rtId>
targetCkTypeId: System.Communication/MicrosoftGraphConfiguration
Eine minimale Pipeline-Definition, die jeden PDF-Anhang staged (der Trigger liefert eine
Nachricht pro Lauf, daher iteriert das äußere ForEach@1 über ein einzelnes Element):
triggers:
- type: FromMicrosoftGraphEmail@1
serverConfiguration: MicrosoftGraphDocuments
mailbox: accounting@company.com
folderPath: Archive/Invoices/ToDo
moveToFolderPathOnSuccess: Archive/Invoices/Done
pollingIntervalSeconds: 120
transformations:
- type: ForEach@1
iterationPath: $.Emails
targetPath: $.emailResults
targetValueKind: Simple
targetValueWriteMode: Overwrite
transformations:
- type: ForEach@1
iterationPath: $.key.Attachments
targetPath: $.attachmentResults
targetValueKind: Simple
targetValueWriteMode: Overwrite
transformations:
- type: If@1
path: $.key.ContentType
operator: Equals
value: "application/pdf"
valueType: String
transformations:
# ... store $.key.Data, run OCR / AI, create entities ...
Die Nachrichten-Metadaten ($.key.Subject, $.key.FromAddress, $.key.Date,
$.key.Body) sowie FileName / ContentType / Length / Data jedes Anhangs
sind unter dem Element-Key des ForEach@1 verfügbar — siehe die
vereinheitlichte Nachrichtenstruktur.
3. Deployment
Importieren Sie die Konfiguration und die Pipeline und stellen Sie den Datenfluss mit dem octo-cli bereit
(ImportRt, DeployDataFlow). Nach dem Deployment beginnt der Adapter, im
konfigurierten Intervall abzufragen.
Schritt 5 — Test
- Legen Sie eine Testnachricht mit einem PDF-Anhang in den Ordner
Archive/Invoices/ToDo. - Innerhalb eines Abfrageintervalls (Standard 120 s) läuft die Pipeline für diese Nachricht.
- Bei Erfolg verschwindet die Nachricht aus
ToDound erscheint inDone; bei einem Fehler bleibt sie inToDound wird bis zumaxAttemptsPerMessageMal erneut versucht.
Beobachten Sie das Adapter-Log, um den Umlauf zu bestätigen — ein Token-Fehler, ein Berechtigungsfehler oder ein fehlender Ordner tauchen alle dort auf (siehe Fehlerbehebung).
Node-Referenz
FromMicrosoftGraphEmail@1 (Trigger)
| Property | Default | Beschreibung |
|---|---|---|
serverConfiguration | — | WellKnownName der MicrosoftGraphConfiguration (Tenant-ID + Client-ID/-Secret). |
mailbox | — | Abzufragender Postfach-UPN (z. B. accounting@company.com). |
folderPath | — | /-getrennter Ordnerpfad, aufgelöst vom Postfach-Root. |
moveToFolderPathOnSuccess | (none) | Ordner, in den die Nachricht nach einem erfolgreichen Lauf verschoben wird (Blatt automatisch erstellt). Weggelassen → Nachricht bleibt am Platz. |
pollingIntervalSeconds | 120 | Sekunden zwischen den Abfragezyklen. |
maxMessagesPerPoll | 25 | Maximale Anzahl pro Zyklus abgerufener Nachrichten (älteste zuerst). |
senderFilter | (none) | Nur Nachrichten verarbeiten, deren Absenderadresse diese Zeichenkette enthält. |
maxAttemptsPerMessage | 3 | Wiederholungen für eine fehlschlagende Nachricht, bevor sie bis zum Neustart des Adapters übersprungen wird. |
Ausgabe: $.Emails[] (ein Element pro Lauf) — siehe den
Überblick. Siehe auch die kompakte
FromMicrosoftGraphEmail@1-Node-Referenz.
Sicherheit
- App-only-Zugriff. Der Adapter authentifiziert sich als App-Registrierung über Client-Credentials; es gibt keinen Benutzerkontext. Behandeln Sie das Client-Secret wie ein Passwort — speichern Sie es außerhalb der Versionsverwaltung und rotieren Sie es vor Ablauf.
- Minimale Rechte. Die Application-Berechtigung
Mail.ReadWriteerstreckt sich über den gesamten Tenant. Schränken Sie sie mit einer Application Access Policy auf die Ziel-Mailbox(en) ein (siehe die Admonition in Schritt 2). Ohne sie legt ein geleaktes Secret jedes Postfach offen. - Lese-/Schreib-Fußabdruck. Der Trigger liest Nachrichten, lädt Anhänge herunter und verschiebt Nachrichten zwischen Ordnern. Er löscht oder sendet keine E-Mails.
Fehlerbehebung
| Symptom | Ursache / Behebung |
|---|---|
invalid_client / AADSTS7000215 beim Abrufen des Tokens | Falsches oder abgelaufenes Client-Secret oder falsche AzureTenantId. Setzen Sie das Secret zurück (Schritt 1) und prüfen Sie die Tenant-ID erneut. |
ErrorAccessDenied / 403 von Graph | Die Application-Berechtigung Mail.ReadWrite fehlt oder die Admin-Einwilligung wurde nicht erteilt (Schritt 2), oder eine Application Access Policy blockiert dieses Postfach. Prüfen Sie mit az ad app permission list-grants und Test-ApplicationAccessPolicy. |
ErrorItemNotFound / Ordner nicht gefunden | folderPath verwendet einen lokalisierten Namen (z. B. Archivieren) oder einen nicht existierenden Pfad. Verwenden Sie die (nicht lokalisierten) Graph-Anzeigenamen; der übergeordnete Ordner des Erfolgsordners muss existieren. |
| Nichts wird abgefragt, obwohl E-Mail im Ordner liegt | mailbox-UPN falsch, folderPath zeigt auf den falschen Ordner, oder senderFilter schließt die Nachrichten aus. Bestätigen Sie, dass der Ordner die Nachrichten tatsächlich enthält, und prüfen Sie das Adapter-Log. |
| Eine Nachricht wird wiederholt verarbeitet | Der Pipeline-Lauf schlägt immer wieder fehl, sodass die Nachricht nie aus dem Quellordner verschoben wird. Beheben Sie den Pipeline-Fehler; nach maxAttemptsPerMessage Fehlschlägen wird die Nachricht bis zum Neustart des Adapters übersprungen. |
| Anhänge sind leer | Nur die Inhalte von fileAttachment werden heruntergeladen — Inline-/Item-/Reference-Anhänge werden übersprungen. Prüfen Sie ContentType/Length an $.Emails[0].Attachments[]. |
| Überhaupt keine Abfrageaktivität im Log | Der Datenfluss ist nicht bereitgestellt, oder der Adapter-Build ist älter als der Node — stellen Sie erneut bereit und starten Sie den Adapter neu. |