Enneo

Kontaktkanäle

Microsoft 365 per App-Registrierung

Postfächer über eine eigene App-Registrierung im Entra-ID-Mandanten anbinden

Tip

Statt sich für jedes Postfach einzeln bei Microsoft anzumelden, hinterlegen Sie einmal eine eigene App-Registrierung aus Ihrem Entra-ID-Mandanten. Enneo authentifiziert sich danach als Anwendung („App-only-Autorisierung", OAuth 2.0 Client Credentials) — ohne Anmeldung je Postfach und ohne zusätzliche Lizenz je Postfach. Die Verbindung wird in der Einstellungskategorie Einstellungen → E-Mail angelegt und anschließend am Postfach ausgewählt.

Der Weg lohnt sich vor allem für freigegebene Postfächer (service@, info@, rechnung@), für die es keinen persönlichen Anmelder gibt, und für Organisationen, in denen mehrere Postfächer angebunden werden sollen. Sie geben enneo dafür vier Angaben: Mandanten-ID, Anwendungs-(Client-)ID, geheimer Clientschlüssel und das Ablaufdatum dieses Schlüssels.

Planen Sie für die erste Einrichtung 60 bis 90 Minuten ein — der größere Teil davon entfällt auf die Einschränkung des Zugriffs in Exchange Online PowerShell. Jedes weitere Postfach ist danach eine Sache von Minuten.

Info

Die klassische Anmeldung pro Postfach über Konto verknüpfen bleibt unverändert verfügbar und ist weiterhin der schnellste Weg für ein einzelnes Postfach. Die App-Registrierung ist eine Alternative, kein Ersatz — siehe E-Mail.

Voraussetzungen

  • Ein Entra-ID-Administrator, der App-Registrierungen anlegen und die Administrator-Zustimmung erteilen darf (z. B. Rolle „Anwendungsadministrator" oder „Globaler Administrator") — siehe Anwendung registrieren.

  • Ein Exchange-Online-Administrator. Die Einschränkung des Zugriffs ist ausschließlich per PowerShell möglich, und zwar mit dem Modul ExchangeOnlineManagement — nicht mit dem allgemeinen Azure-PowerShell-Modul:

    Install-Module ExchangeOnlineManagement -Scope CurrentUser
    Connect-ExchangeOnline -UserPrincipalName admin@ihre-domain.de

    Siehe Verbindung mit Exchange Online PowerShell.

  • Die Liste der Postfachadressen, die enneo lesen und über die enneo senden soll — und für den Graph-Weg eine per E-Mail aktivierte Sicherheitsgruppe (mail-enabled security group), die genau diese Postfächer enthält. Eine gewöhnliche Verteilerliste genügt nicht: der Bereichsfilter in Schritt 3 wertet sie nicht aus.

Note

In der Azure Cloud Shell ist das Modul bereits vorhanden, dort ist aber die Anmeldung per Gerätecode nötig — und -UserPrincipalName lässt sich nicht mit -Device kombinieren. Verwenden Sie dort Connect-ExchangeOnline -Device ohne weitere Parameter.

Schritt 1 — Anwendung in Entra ID registrieren

App-Registrierung anlegen

Öffnen Sie im Microsoft Entra Admin Center Identität → Anwendungen → App-Registrierungen → Neue Registrierung. Ein Name genügt (z. B. enneo Mail); eine Umleitungs-URI wird für App-only-Autorisierung nicht benötigt.

Mandanten-ID und Anwendungs-ID notieren

Beide Werte stehen direkt auf der Seite Übersicht der neuen Registrierung: Verzeichnis-(Mandanten-)ID und Anwendungs-(Client-)ID.

Geheimen Clientschlüssel erstellen

Unter Zertifikate & Geheimnisse → Geheime Clientschlüssel → Neuer geheimer Clientschlüssel einen Schlüssel anlegen, eine Beschreibung und eine Gültigkeitsdauer wählen und den Wert sofort kopieren.

Note

Der Wert des Schlüssels wird nur unmittelbar nach dem Anlegen angezeigt — danach nicht mehr. Kopieren Sie die Spalte Wert, nicht die Spalte Geheimnis-ID: beide stehen nebeneinander und sehen ähnlich aus. Notieren Sie zusätzlich das Ablaufdatum, enneo fragt es ab.

Das Portal erlaubt eine Gültigkeitsdauer von höchstens 24 Monaten; Microsoft empfiehlt weniger als 12 Monate. Kürzer ist sicherer, bedeutet aber häufigeres Erneuern — planen Sie den Wechsel als wiederkehrende Aufgabe ein.

Schritt 2 — Berechtigungen erteilen und Administrator-Zustimmung geben

Die Berechtigungen werden unter API-Berechtigungen → Berechtigung hinzufügen vergeben — jeweils als Anwendungsberechtigungen, nicht als delegierte Berechtigungen.

TransportAPIBerechtigungen
Microsoft Graph (empfohlen)Microsoft GraphMail.ReadWrite und Mail.Send. Mail.Read genügt nur, wenn Nachrichten nach dem Import unverändert bleiben — siehe Hinweis unten
IMAP / SMTPOffice 365 Exchange OnlineIMAP.AccessAsApp und SMTP.SendAsApp

Note

Die IMAP- und SMTP-Berechtigungen liegen nicht unter Microsoft Graph. Sie finden sie im Dialog Berechtigung hinzufügen im Reiter APIs, die meine Organisation verwendet unter Office 365 Exchange Online. Wer sie unter Graph sucht, findet sie nicht — sie existieren dort nicht.

Note

Lesen genügt selten. Enneo markiert eine importierte Nachricht standardmäßig als gelesen, damit sie nicht wieder abgeholt wird — und das ist bereits ein Schreibzugriff, den Mail.Read nicht abdeckt. Ohne Schreibrecht kommt allein die Einstellung Nachricht nach dem Import: unverändert lassen am E-Mail-Konto aus; „als gelesen markieren", „in Ordner verschieben" und „löschen" benötigen Mail.ReadWrite.

Fehlt das Recht, entsteht ein Zustand, der leicht zu übersehen ist: das Ticket wird korrekt angelegt, nur das Markieren schlägt fehl. Die Nachricht bleibt ungelesen, wird im nächsten Durchlauf erneut abgeholt, als Duplikat erkannt — und erneut nicht markiert. Der Fehler wiederholt sich damit bei jedem Durchlauf.

Anschließend erteilt ein Administrator einmalig die Zustimmung: Schaltfläche Administratorzustimmung für <Ihre Organisation> erteilen. In der Spalte Status muss danach bei jeder Berechtigung „Gewährt für …" stehen.

Warning

Für Microsoft Graph in Kombination mit RBAC ist diese Zustimmung nur ein Durchgangszustand: sie muss nach der Rollenzuweisung wieder entfernt werden, weil sie Zugriff auf alle Postfächer erteilt und damit die Einschränkung aufhebt. Das ist keine Randbemerkung, sondern ein eigener Arbeitsschritt — Zum Schluss: die mandantenweite Zustimmung entfernen am Ende von Schritt 3.

Schritt 3 — Zugriff auf die gewünschten Postfächer einschränken

Warning

Dieser Schritt ist Pflicht, nicht optional. Eine Anwendungsberechtigung gilt ohne Einschränkung für jedes Postfach im Mandanten. Ohne Schritt 3 könnte enneo also technisch alle Postfächer Ihrer Organisation lesen — auch die persönlichen.

Welcher Mechanismus greift, hängt vom Transport ab. Beide beginnen mit demselben Befehl: den Dienstprinzipal der Anwendung in Exchange Online bekannt machen. Führen Sie ihn einmal aus, auch wenn Sie beide Transporte einrichten — ein zweiter Aufruf scheitert daran, dass das Objekt bereits existiert.

New-ServicePrincipal -AppId <Anwendungs-ID> `
  -ObjectId <Objekt-ID aus Unternehmensanwendungen> -DisplayName "enneo Mail"

# Die ObjectId, unter der Exchange den Prinzipal jetzt kennt - fuer den
# Pruefbefehl im Hinweis unten und fuer den Tab IMAP/SMTP
(Get-ServicePrincipal -Identity "enneo Mail").ObjectId

Warning

Das -ObjectId-Argument von New-ServicePrincipal erwartet die Objekt-ID aus Unternehmensanwendungen (Enterprise Applications), nicht die Objekt-ID aus App-Registrierungen. Beide heißen gleich und stehen an vergleichbarer Stelle im Portal. Microsoft dokumentiert ausdrücklich, dass die falsche der beiden zu einem Authentifizierungsfehler führt — und zwar zu einem, der nicht auf die Ursache hinweist.

Note

Was diesem Dienstprinzipal bereits zugewiesen ist, zeigt Get-ManagementRoleAssignment -RoleAssignee <ObjectId>. Das Argument -App besitzt nur New-ManagementRoleAssignment; bei Get-ManagementRoleAssignment führt es zu einer Meldung über einen unbekannten Parameter.

Für Graph verwenden Sie RBAC for Applications: eine Rolle, die nur auf einen definierten Bereich von Empfängern wirkt. Den Bereich beschreibt die Gruppe aus den Voraussetzungen — und deren Distinguished Name ist das einzige Argument dieser Anleitung, das sich nicht ablesen, sondern nur abfragen lässt:

# Gruppe pruefen - RecipientTypeDetails muss MailUniversalSecurityGroup sein
Get-Group "enneo Mailboxes" | Format-List Name,DisplayName,RecipientTypeDetails,DistinguishedName

$groupDN = (Get-Group "enneo Mailboxes").DistinguishedName

Warning

Der Name einer im Exchange Admin Center angelegten Gruppe ist nicht ihr Anzeigename: das EAC hängt an den Namen einen Zeitstempel an, aus dem Anzeigenamen enneo Mailboxes wird also ein Name wie enneo Mailboxes20260101120000. Der Distinguished Name enthält den Namen. Wer ihn „wie erwartet" aus dem Anzeigenamen zusammensetzt, verweist damit auf ein Objekt, das nicht existiert — und der Bereich trifft anschließend kein einziges Postfach, ohne jede Fehlermeldung. Fragen Sie den DN deshalb ab, statt ihn zu tippen.

Warning

Benennen Sie die Gruppe danach nicht um. Der Bereich speichert den Distinguished Name als Zeichenkette, und der DN enthält den Name der Gruppe. Eine Umbenennung schreibt den DN also neu — der gespeicherte Filter zeigt anschließend auf ein Objekt, das es nicht mehr gibt, und der Bereich umfasst kein Postfach mehr. Der Zugriff bricht dabei ohne Meldung weg, und zwar zu einem Zeitpunkt, der mit dieser Einrichtung nichts mehr zu tun hat.

Ist es passiert, setzen Sie den Filter auf den neuen DN:

$groupDN = (Get-Group "enneo Mailboxes").DistinguishedName
Set-ManagementScope -Identity "enneo Postfaecher" `
  -RecipientRestrictionFilter "MemberOfGroup -eq '$groupDN'"

Der Anzeigename ist davon nicht betroffen — er kommt im DN nicht vor und darf sich jederzeit ändern.

# 1. Bereich ueber die Gruppe definieren
New-ManagementScope -Name "enneo Postfaecher" `
  -RecipientRestrictionFilter "MemberOfGroup -eq '$groupDN'"

# 2. Rollen ausschliesslich auf diesen Bereich zuweisen - Empfang und Versand
New-ManagementRoleAssignment -Role "Application Mail.ReadWrite" `
  -App <Anwendungs-ID> -CustomResourceScope "enneo Postfaecher"
New-ManagementRoleAssignment -Role "Application Mail.Send" `
  -App <Anwendungs-ID> -CustomResourceScope "enneo Postfaecher"

# 3. Ergebnis pruefen - je ein Postfach innerhalb und ausserhalb des Bereichs
Test-ServicePrincipalAuthorization -Identity <Anwendungs-ID> -Resource service@ihre-domain.de

Zur Wahl der Empfangsrolle siehe den Hinweis in Schritt 2: Application Mail.Read reicht nur, wenn Nachrichten nach dem Import unverändert bleiben sollen.

Test-ServicePrincipalAuthorization ist die Abnahme der Rollenzuweisung: prüfen Sie damit ein Postfach, das enthalten sein soll, und eines, das es nicht sein soll. Erst wenn das zweite verneint wird, ist die Zuweisung richtig geschnitten — für die Wirksamkeit der Einschränkung fehlt dann noch der letzte Abschnitt dieses Schritts.

Note

Ohne Gruppe, für einen festen kleinen Bestand. Umfasst der Bereich genau ein Postfach und ändert sich das nicht, geht es auch ohne Gruppe:

New-ManagementScope -Name "enneo Postfaecher" `
  -RecipientRestrictionFilter "PrimarySmtpAddress -eq 'service@ihre-domain.de'"

Bei mehreren oder wachsenden Beständen ist die Gruppe die bessere Wahl, und zwar aus einem organisatorischen Grund: ein neues Postfach nimmt dann die Person auf, die die Gruppe ohnehin pflegt, ohne diese Anleitung zu kennen. Ein Bereich über Adressen müsste stattdessen jedes Mal von einem Exchange-Administrator geändert werden.

Note

Im Bereichsfilter zählt nur die direkte Mitgliedschaft in der Gruppe. Postfächer, die über eine verschachtelte Gruppe Mitglied sind, liegen außerhalb des Bereichs — und zwar ohne Fehlermeldung.

Zum Schluss: die mandantenweite Zustimmung entfernen (nur Graph)

Dieser Abschnitt widerspricht Schritt 2 bewusst, und er ist der Teil, der die Einschränkung überhaupt wirksam macht. Die Zustimmung war nötig, damit die Berechtigung existiert; sobald die Rollenzuweisung steht, ist sie schädlich, weil sie für alle Postfächer gilt und sich mit dem Bereich zur Summe addiert.

Öffnen Sie in der App-Registrierung API-Berechtigungen und entziehen Sie die Administrator-Zustimmung für die Graph-Berechtigungen aus Schritt 2 — Mail.ReadWrite und Mail.Send, dazu Mail.Read, falls es aus einer früheren Einrichtung noch steht. Die Berechtigung kommt danach aus der bereichsbezogenen Rollenzuweisung.

Die Reihenfolge ist dabei nicht beliebig: erst die Rollenzuweisung, dann die Zustimmung entziehen. Umgekehrt entsteht eine Zeitspanne, in der kein Zugriff möglich ist.

Für IMAP/SMTP gilt dieser Abschnitt nicht: IMAP.AccessAsApp hat kein RBAC-Gegenstück, die Zustimmung muss dort bestehen bleiben. Die Einschränkung leistet dort die Postfachberechtigung.

Warning

Test-ServicePrincipalAuthorization prüft nur den RBAC-Teil und kennt die Zustimmung nicht. Solange die mandantenweite Zustimmung steht, verneint der Befehl ein Postfach außerhalb des Bereichs also korrekt, während die Anwendung es tatsächlich erreicht. Der Abnahmetest aus dem Graph-Tab kann diesen Fehler folglich nicht finden.

Prüfen Sie den Endzustand deshalb an der Wirkung:

# Abgefragt statt eingefuegt - siehe Hinweis unter dem Block
$secret = Read-Host 'Geheimer Clientschluessel' -AsSecureString

$body = @{ client_id     = '<Anwendungs-ID>'
           client_secret = [Net.NetworkCredential]::new('', $secret).Password
           scope         = 'https://graph.microsoft.com/.default'
           grant_type    = 'client_credentials' }
$token = (Invoke-RestMethod -Method Post -Body $body `
  -Uri 'https://login.microsoftonline.com/<Mandanten-ID>/oauth2/v2.0/token').access_token

# 1. Schnellpruefung: der roles-Anspruch muss leer bleiben
$p = $token.Split('.')[1].Replace('-','+').Replace('_','/')
$p += '=' * ((4 - $p.Length % 4) % 4)
([Text.Encoding]::UTF8.GetString([Convert]::FromBase64String($p)) | ConvertFrom-Json).roles

# 2. Postfach im Bereich - erwartet wird eine Antwort mit id
Invoke-RestMethod -SkipHttpErrorCheck -Headers @{ Authorization = "Bearer $token" } `
  -Uri 'https://graph.microsoft.com/v1.0/users/service@ihre-domain.de/mailFolders/inbox'

# 3. Postfach ausserhalb - erwartet wird 403 ErrorAccessDenied
Invoke-RestMethod -SkipHttpErrorCheck -Headers @{ Authorization = "Bearer $token" } `
  -Uri 'https://graph.microsoft.com/v1.0/users/jemand.anderes@ihre-domain.de/mailFolders/inbox'

Gibt Befehl 1 nichts aus und antwortet 3 mit ErrorAccessDenied, ist die Einschränkung wirksam. Nennt Befehl 1 noch Mail.Read, Mail.ReadWrite oder Mail.Send, ist die Zustimmung nicht entzogen. Liefert 3 eine Antwort statt eines Fehlers, greift der Bereich nicht.

Der Schlüssel wird abgefragt und nicht in den Block geschrieben: eingetippte Befehlszeilen landen in der PowerShell-Historie, und in der Cloud Shell überlebt das Basisverzeichnis die Sitzung, sobald ein Speicherkonto verbunden ist. Ein eingefügter Schlüssel bliebe dort stehen.

-SkipHttpErrorCheck setzt PowerShell 7 voraus (in der Cloud Shell vorhanden); ohne diesen Schalter erscheint der 403 als abbrechender Fehler statt als lesbare Antwort.

Note

Prüfen Sie dabei nicht nur, ob ein Postfach lesbar bleibt. Die Rollenzuweisung trägt nach dem Entzug alles, was die Verbindung braucht: das Abholen, die Aktion nach dem Import — als gelesen markieren, verschieben, löschen — und den Versand.

Der Fehler, der an dieser Stelle übrig bleibt, sieht deshalb so aus: das Lesen gelingt, und erst das Markieren scheitert. Dann ist die zugewiesene Rolle Application Mail.Read statt Application Mail.ReadWrite. Die mandantenweite Zustimmung hatte den Unterschied bis hierher verdeckt, weil sie beides mitbrachte — sichtbar wird er erst beim ersten echten Abholen, nicht beim Verbindungstest und nicht beim Befehl oben.

Schritt 4 — Verbindung in enneo eintragen

Verbindung anlegen

Öffnen Sie Einstellungen → E-Mail und legen Sie eine neue Microsoft-365-Verbindung an. Ein sprechender Name hilft später bei der Zuordnung, wenn mehrere Mandanten oder Anwendungen im Spiel sind.

Die vier Angaben eintragen

Mandanten-ID, Anwendungs-(Client-)ID, geheimer Clientschlüssel und das Ablaufdatum des Schlüssels. Das Ablaufdatum wird nicht geprüft, sondern gespeichert — enneo zeigt es an, damit Sie den Wechsel rechtzeitig einplanen können.

Verbindung testen

Mit Verbindung testen holt enneo ein Token für Ihren Mandanten. Schlägt das fehl, liegt die Ursache in Schritt 1 oder 2 — siehe Fehlerbehebung. Gelingt es, ist damit noch nichts über den Zugriff auf ein einzelnes Postfach gesagt; das entscheidet Schritt 3.

Postfach auf die Verbindung umstellen

Im betreffenden E-Mail-Konto die Autorisierung auf die Anwendung der Organisation setzen, die eben angelegte Verbindung auswählen und den Transport (Microsoft Graph oder IMAP/SMTP) wählen. Danach mit dem Empfangstest des E-Mail-Kontos prüfen.

Graph oder IMAP/SMTP? Eine Empfehlung

Beide Transporte funktionieren mit App-only-Autorisierung. Wenn Ihr Mandant die Wahl lässt, empfehlen wir Microsoft Graph — aus zwei nachprüfbaren Gründen, nicht aus Geschmack:

  • Weniger Rechte beim Empfang. Graph lässt sich auf eine Gruppe von Postfächern beschränken und dabei auf die Rolle, die tatsächlich gebraucht wird — Application Mail.ReadWrite, bei unverändert bleibenden Nachrichten sogar Application Mail.Read. Für IMAP existiert in RBAC for Applications keine Rolle, daher bleibt nur Add-MailboxPermission … -AccessRights FullAccess — also Vollzugriff dort, wo Lesezugriff genügen würde. (Für den Versand gilt das nicht: SMTP lässt sich über Application SMTP.SendAsApp ebenfalls bereichsbezogen zuweisen.)
  • Weniger Aufwand pro Postfach. Mit Graph deckt ein Bereich die gesamte Gruppe ab; ein neues Postfach wird der Gruppe hinzugefügt, und das war es. Mit IMAP ist jedes hinzugefügte Postfach ein weiterer PowerShell-Befehl und jedes entfernte einer zum Zurücknehmen. Das ist die Antwort auf die Frage, welcher Weg bei mehreren Postfächern bequemer ist.

Dazu kommen zwei Fehlerquellen, die es bei Graph nicht gibt: die unterschiedlichen Scopes im nächsten Abschnitt und die Verwechslungsgefahr bei der Objekt-ID aus Schritt 3.

Info

Das ist eine Empfehlung, keine Voraussetzung. Erlaubt Ihr Mandant nur IMAP/SMTP, lässt sich diese Anleitung vollständig damit umsetzen. Microsoft stellt OAuth für IMAP und POP weiterhin bereit; abgekündigt ist die Basisauthentifizierung, nicht OAuth.

IMAP und POP — zwei unterschiedliche Scopes

Warning

Für IMAP und POP sind die Scopes für Autorisierung und Token nicht identisch. Wer denselben Wert für beides verwendet, erhält eine Konfiguration, die korrekt aussieht und trotzdem nicht funktioniert — ohne aussagekräftige Meldung. Dies ist die wahrscheinlichste Ursache für einen solchen Fall.

AnfrageProtokollScope
Administrator-Zustimmung / AutorisierungIMAP, POPhttps://ps.outlook.com/.default
TokenIMAP, POPhttps://outlook.office365.com/.default
Autorisierung und TokenSMTPhttps://outlook.office365.com/.default

Fehlerbehebung

Gut zu wissen

  • Keine wiederkehrende Zustimmung. Bei App-only-Autorisierung gibt es kein Refresh-Token und keine ablaufende Benutzer-Zustimmung. Die einzige wiederkehrende Aufgabe ist das Erneuern des geheimen Clientschlüssels vor dessen Ablauf. Enneo zeigt dazu das hinterlegte Ablaufdatum und den letzten Verbindungsfehler an.
  • Empfang über Graph setzt App-only-Autorisierung voraus. Die Zustimmung bei der Anmeldung pro Postfach erteilt in Microsofts Zustimmungsmodell nur das Recht zum Senden, nicht zum Lesen. Wer über Graph empfangen möchte, benötigt deshalb diesen Weg — das ist eine Eigenschaft des Microsoft-Modells, keine Einschränkung von enneo.
  • Eine Verbindung, viele Postfächer. Dieselbe Verbindung lässt sich an beliebig vielen E-Mail-Konten auswählen. Der Umfang wird nicht in enneo festgelegt, sondern durch die Einschränkung aus Schritt 3.
  • Ein Wechsel ist jederzeit möglich. Ein Postfach, das heute per Anmeldung verbunden ist, kann später auf die Verbindung umgestellt werden und umgekehrt — die bereits importierten Tickets bleiben davon unberührt.