Microsoft 365
Ein Runbook für das Plugin m365. Der Agent bekommt einen eigenen
Microsoft-365-Benutzer und arbeitet darin wie ein Kollege: Er liest und
beantwortet seine Mail, führt seinen Kalender und findet, bearbeitet und legt
Dokumente in OneDrive und SharePoint ab. Alles läuft über die Microsoft Graph API
mit einer App-Registrierung in Entra ID.
Kurzfassung: ein lizenzierter Benutzer für den Agenten, eine App-Registrierung mit Anwendungsberechtigungen, ein Exchange-Scope, der die App in dieses eine Postfach einzäunt, das System in covey aktiviert, zwei Secrets, eine Zeile in ACCESS.md, drei Egress-Hosts. Abschnitt 2 geht jeden Klick durch.
Wie es sich von den Nachbarn unterscheidet:
m365 |
email |
sharepoint |
|
|---|---|---|---|
| Exchange Online über Graph | jeder IMAP/SMTP-Server, Passwort-Anmeldung | — | |
| Kalender | ja | — | — |
| Dateien | eigenes OneDrive + jede Site, die die App erreichen darf | — | eine Bibliothek hinter einem Freigabelink |
Exchange Online nimmt über IMAP keine Passwort-Anmeldung mehr an; für ein
Microsoft-365-Postfach ist deshalb m365 der Weg, nicht email.
1. Was der Agent kann
- Mail — einen Ordner auflisten (nur Ungelesene oder nach Suchwörtern), eine Nachricht als Text mit ihrer Anhangsliste lesen, einen Anhang in die Sandbox legen, antworten oder allen antworten (mit Dateien aus der Sandbox), eine neue Mail senden, einen Entwurf hinterlegen, den ein Mensch prüft und abschickt, eine Mail in einen Ordner verschieben, als gelesen markieren.
- Kalender — den Kalender zwischen zwei Zeitpunkten lesen (Serien aufgelöst), einen Termin mit Teilnehmenden oder als Teams-Besprechung anlegen, eine Einladung annehmen / ablehnen / mit Vorbehalt annehmen, einen eigenen Termin absagen, die Frei/Gebucht-Zeiten von Kolleginnen und Kollegen abfragen.
- Dateien — SharePoint-Sites finden, die Bibliotheken einer Site auflisten,
eine Bibliothek oder das eigene OneDrive (
drive_idme) auflisten und durchsuchen, eine Textdatei lesen, eine Datei in die Sandbox laden, eine aus ihr hochladen, eine Textdatei schreiben, Ordner anlegen. Eine Löschaktion gibt es absichtlich nicht. - Links —
open_linknimmt einen SharePoint-, OneDrive- oder Teams-Dateien- Link (einen Freigabelink oder die normale Adresse einer Datei oder eines Ordners) und antwortet mit Laufwerk und Pfad, mit denen die Dateiaktionen arbeiten. „Bitte das Protokoll hier ergänzen: “ ist ein vollständiger Auftrag. - Office-Dokumente — das Plugin zerlegt sie nicht. Der Agent lädt eine
.docx,.xlsxoder.pptxherunter, bearbeitet sie in der Sandbox mitpython3(docx,openpyxl,pptxliegen im Basis-Arbeitsplatz) und lädt sie auf denselben Pfad zurück.
Mail senden und Leute einladen erreicht echte Menschen. Die Guard-Rail-Subjekte
sind eines je Aktion (m365:send_mail, m365:create_event, …); eine
Organisation, die einen Menschen vorher draufschauen lassen will, setzt
require_approval genau auf diese und lässt das Lesen frei.
2. Einrichtung
Die Arbeit von zwei Rollen, in dieser Reihenfolge: zuerst ein Microsoft-365- Admin (Benutzer, App, Exchange-Scope, SharePoint), dann ein covey-Admin (aktivieren, Secrets, Egress, einstellen). Rechnet mit einer halben Stunde. Haltet eine Notiz offen für fünf Werte, die unterwegs anfallen:
| Wert | Aus | Gebraucht in |
|---|---|---|
| Adresse des Agenten | 2.1 | m365_url, Exchange-Scope |
| Verzeichnis-ID (Mandant) | 2.2 | m365_token |
| Anwendungs-ID (Client) | 2.2 | m365_token, Exchange, SharePoint |
| Wert des Clientgeheimnisses | 2.2 | m365_token |
| Objekt-ID der Unternehmensanwendung | 2.3 | New-ServicePrincipal |
2.1 Ein Benutzer für den Agenten (Microsoft 365 Admin Center)
- admin.microsoft.com → Benutzer → Aktive Benutzer → Benutzer hinzufügen.
- Nach seiner Aufgabe benennen (z. B. Office Agent), Benutzername z. B.
office@contoso.com. Eine Lizenz mit Exchange Online und OneDrive zuweisen (Microsoft 365 Business Basic genügt). - Das Passwort benutzt covey nie — ein langes zufälliges setzen und nicht weitergeben. Der Agent meldet sich als App an, nicht als dieser Benutzer.
- Einmal als dieser Benutzer bei outlook.office.com
anmelden (oder das Postfach als Admin öffnen) und die Ordner anlegen, die das
Playbook nennt, z. B.
Erledigt. Mailordner legt das Plugin nicht an.
Ein freigegebenes Postfach reicht für Mail und Kalender, hat aber kein OneDrive; soll der Agent eigene Dateien haben, einen lizenzierten Benutzer nehmen.
2.2 Die App-Registrierung (Entra ID)
entra.microsoft.com → Anwendungen → App-Registrierungen → Neue Registrierung. Name: z. B.
covey office agent. Unterstützte Kontotypen: nur Konten in diesem Organisationsverzeichnis. Umleitungs-URI: leer lassen. Registrieren.Auf der Übersichtsseite Anwendungs-ID (Client) und Verzeichnis-ID (Mandant) kopieren.
API-Berechtigungen → Berechtigung hinzufügen → Microsoft Graph → Anwendungsberechtigungen (nicht Delegierte). Hinzufügen:
Berechtigung Wofür Mail.ReadWrite,Mail.Senddas Postfach Calendars.ReadWriteder Kalender Files.ReadWrite.AllOneDrive und Dokumentbibliotheken Sites.ReadWrite.AlloderSites.SelectedSites finden — siehe 2.4 Dann Administratorzustimmung für
erteilen . Jede Zeile muss grün Gewährt zeigen; eine Berechtigung ohne Zustimmung bewirkt nichts.Zertifikate & Geheimnisse → Geheime Clientschlüssel → Neuer geheimer Clientschlüssel. Beschreibung
covey, Ablauf so lang wie eure Richtlinie erlaubt (höchstens 24 Monate). Die Spalte Wert sofort kopieren — sie wird nur einmal angezeigt. Die Geheimnis-ID daneben ist nicht das Geheimnis; mit ihr kommtinvalid_client(AADSTS7000215).Das Ablaufdatum in einen Kalender eintragen. Danach scheitert jede Aktion mit
invalid_client; auf derselben Seite erneuern undm365_tokenin covey ersetzen.
2.3 Die App in das Postfach des Agenten einzäunen (Exchange-Online-PowerShell)
Anwendungsberechtigungen gelten mandantenweit: Nach 2.2 könnte die App aus jedem Postfach der Organisation lesen und senden. RBAC for Applications in Exchange begrenzt Mail und Kalender auf den einen Benutzer. Diesen Schritt nicht auslassen.
Die Objekt-ID der Unternehmensanwendung holen: Entra ID → Anwendungen → Unternehmensanwendungen → nach dem Namen der App suchen → Objekt-ID. Das ist eine andere ID als die auf der Seite der App-Registrierung; mit der Objekt-ID der Registrierung scheitert
New-ServicePrincipaloder bindet das falsche Objekt.PowerShell (Windows PowerShell 5.1 oder PowerShell 7) als Exchange-Admin öffnen:
Install-Module ExchangeOnlineManagement -Scope CurrentUser # einmalig Connect-ExchangeOnline -UserPrincipalName admin@contoso.comScope anlegen, die App bei Exchange bekannt machen und ihr die drei Rollen innerhalb des Scopes geben:
New-ManagementScope -Name "covey-office" ` -RecipientRestrictionFilter "PrimarySmtpAddress -eq 'office@contoso.com'" New-ServicePrincipal -AppId <client-id> -ObjectId <objekt-id-der-unternehmensanwendung> ` -DisplayName "covey office agent" New-ManagementRoleAssignment -App <client-id> -Role "Application Mail.ReadWrite" ` -CustomResourceScope "covey-office" New-ManagementRoleAssignment -App <client-id> -Role "Application Mail.Send" ` -CustomResourceScope "covey-office" New-ManagementRoleAssignment -App <client-id> -Role "Application Calendars.ReadWrite" ` -CustomResourceScope "covey-office"Zurück in Entra ID → die App-Registrierung → API-Berechtigungen: dort
Mail.ReadWrite,Mail.SendundCalendars.ReadWriteentfernen. Rechte aus Entra ID und aus Exchange addieren sich — solange die mandantenweiten stehen, begrenzt der Scope nichts.Prüfen:
Test-ServicePrincipalAuthorization -Identity <client-id> -Resource office@contoso.com Test-ServicePrincipalAuthorization -Identity <client-id> -Resource jemand.anderes@contoso.comDas erste antwortet für die drei Rollen
InScope : True, das zweiteFalse. Bis Exchange die Änderung anwendet, können bis zu zwei Stunden vergehen; ein 403 direkt nach diesem Schritt ist meist diese Verzögerung.
Das Plugin selbst spricht nur das Postfach aus m365_url an. Das ist eine
Konvention des Codes, keine Grenze: Die Grenze ist dieser Schritt.
2.4 SharePoint: welche Sites der Agent erreicht
Zuerst entscheiden, wo der Agent arbeiten wird, und vor allem, wohin die Links
zeigen werden, die man ihm schickt. Der Agent öffnet einen Link als App, nicht als
sein Benutzer: Eine Datei mit office@contoso.com zu teilen, lässt die App nicht
hinein.
| Wahl | Wirkung |
|---|---|
Sites.ReadWrite.All |
jede Site und jeder Link im Mandanten öffnet sich. Am einfachsten; die App erreicht den ganzen SharePoint-Bestand |
Sites.Selected |
nur Sites, die der App einzeln freigegeben sind. Ein Link in eine andere Site endet mit einem 403, der das sagt |
Mit Sites.Selected jede Site freigeben. Beide Wege unten funktionieren; dafür
braucht es einen SharePoint-Admin.
PnP PowerShell (am kürzesten):
Install-Module PnP.PowerShell -Scope CurrentUser # einmalig
Connect-PnPOnline -Url https://contoso.sharepoint.com/sites/Team -Interactive -ClientId <eure PnP-Admin-App>
Grant-PnPAzureADAppSitePermission -AppId <client-id> -DisplayName "covey office agent" `
-Site https://contoso.sharepoint.com/sites/Team -Permissions Write
Graph Explorer (aka.ms/ge, angemeldet als Admin, der dort
Sites.FullControl.All zugestimmt hat):
Site-ID:
GET https://graph.microsoft.com/v1.0/sites/contoso.sharepoint.com:/sites/Team→idkopieren (drei Teile, durch Kommas getrennt).Freigeben:
POST https://graph.microsoft.com/v1.0/sites/{site-id}/permissions { "roles": ["write"], "grantedToIdentities": [{ "application": { "id": "<client-id>", "displayName": "covey office agent" } }] }
Je Site wiederholen. list_sites zeigt in covey dann genau diese Sites. Das eigene
OneDrive des Agenten braucht keine Freigabe — Files.ReadWrite.All deckt es ab.
2.5 In covey
Das System für die Organisation aktivieren: Zielsysteme → Microsoft 365 → Aktivieren. Ein einkompiliertes Plugin ist pro Organisation bis dahin aus, und die Zeile in der
ACCESS.mdeines Agenten schaltet es nicht ein.Die Secrets beim Agenten hinterlegen: Agent → Einstellungen → Secrets:
m365_url = office@contoso.com m365_token = <tenant-id>:<client-id>:<wert-des-clientgeheimnisses>Für nationale Clouds nimmt
m365_urldie Endpunkte hinter der Adresse:office@contoso.us graph=https://graph.microsoft.us login=https://login.microsoftonline.us.Zugriff — in der
ACCESS.mddes Agenten:- system: m365 scope: read,writeEgress — Egress → Templates: Microsoft 365 aus dem Katalog übernehmen und auf der Agenten-Seite im Reiter Egress ankreuzen. Oder die Hosts als eigene des Agenten eintragen:
Host Warum graph.microsoft.comdie API login.microsoftonline.comdas Token *.sharepoint.comDatei-Downloads: /contentleitet auf den SharePoint-Host des Mandanten weiter
2.6 Testen
- Verbindungstest (Zielsysteme → Microsoft 365 → Verbindung testen): Er liest
den Posteingang und antwortet
mailbox office@contoso.com reachable: 3 unread of 41 in the inbox. - Den Agenten einstellen und seiner Adresse aus dem Postfach eines Kollegen einen
kleinen Auftrag schicken. Innerhalb des Herzschlag-Intervalls startet ein Lauf;
seine Aufzeichnung zeigt
list_mail,get_mailund die Antwort, die er geschickt hat. - In einer zweiten Mail einen SharePoint-Link schicken („bitte in diesem Dokument
eine Zeile ergänzen: “), um
open_linkund die Site-Freigaben zu prüfen.
2.7 Wenn etwas scheitert
| Symptom | Ursache | Abhilfe |
|---|---|---|
entra id token: HTTP 401 … invalid_client / AADSTS7000215 |
falsches Geheimnis (die Geheimnis-ID kopiert) oder abgelaufen | neues Clientgeheimnis, dessen Wert kopieren, m365_token ersetzen (2.2) |
AADSTS700016 |
Client-ID gibt es in diesem Mandanten nicht | Reihenfolge und Werte in tenant-id:client-id prüfen |
HTTP 403 … ErrorAccessDenied bei Mail oder Kalender |
Rollenzuweisung fehlt, Scope deckt die Adresse nicht ab, oder die Änderung greift noch nicht | Test-ServicePrincipalAuthorization (2.3); nach einer Änderung bis zu zwei Stunden warten |
HTTP 403 bei jedem Postfach, auch dem des Agenten |
Administratorzustimmung fehlt, oder die Graph-Mailrechte wurden entfernt, bevor die Exchange-Rollen da waren | 2.2 Schritt 3, 2.3 Schritt 3 |
HTTP 403 von open_link oder list_drives |
Sites.Selected ohne Freigabe für diese Site |
Site freigeben (2.4) |
list_sites leer |
Sites.Selected, noch keine Site freigegeben |
mindestens eine Site freigeben (2.4) |
Auflisten geht, download_file endet mit Forbidden |
Egress sperrt den SharePoint-Download-Host | *.sharepoint.com (2.5 Schritt 4); das Egress-Protokoll zeigt den abgelehnten CONNECT |
m365 is not activated, oder im Prompt des Agenten stehen keine Microsoft-365-Aktionen |
System für die Organisation nicht aktiviert | 2.5 Schritt 1 |
no m365_token stored for this agent |
Secrets angelegt, aber nicht bei diesem Agenten | 2.5 Schritt 2 |
3. Eingang
Einen Webhook gibt es nicht: Graph-Änderungsbenachrichtigungen brauchen ein öffentlich validiertes Abonnement, das alle paar Tage erneuert werden muss. Der Eingang ist ein Herzschlag mit einer Vorprüfung, die einen Aufruf kostet:
- alle: 10m nur-wenn: m365 titel: Das Postfach betreuen
aufgabe: Lies die ungelesene Mail (list_mail unread:true) und bearbeite sie nach dem Playbook.
nur-wenn: m365 fragt nach der ungelesenen Mail im Posteingang
(nur-wenn: m365:<ordner> für einen anderen Ordner). Es meldet einen Eintrag je
Nachricht (mail:<id>@<zuletzt geändert>): Es feuert, wenn eine Mail ankommt oder
sich ändert, bleibt still, solange der Posteingang stillsteht, und ein
Ablauf mit only_if: m365 führt einen Vorgang je
Mail. Die eigenen mark_read, move_mail und reply_mail des Agenten sind als
signaturverändernd bekannt und wecken ihn nicht erneut.
Ids sind die unveränderlichen Ids von Graph: Eine Mail behält ihre Id, wenn sie verschoben wird; eine Notiz oder ein Vorgang, der sie nennt, bleibt richtig.
4. Grenzen
| Was | Grenze |
|---|---|
| Anhänge einer ausgehenden Mail | 3 MB zusammen (Graph lehnt eine Anfrage über 4 MB ab) — eine größere Datei geht mit upload_file ins OneDrive, und die Mail trägt ihren Link |
| Ein Anhang, der in die Sandbox geladen wird | COVEY_M365_ATTACHMENT_MAX_MB, Standard 25 |
| Ein Upload | COVEY_M365_UPLOAD_MAX_MB, Standard und Höchstwert 250 (einfacher Upload) |
read_file |
Text bis 1 MB; alles andere über download_file |
list_mail |
50 je Aufruf |