Zum Inhalt springen

Odoo Outlook E-Mail Versand über Microsoft Graph

Viele Odoo Installationen senden E-Mails über Microsoft 365. Mit vielen Benutzern wird die Standard-OAuth-Integration aber schnell unpraktisch, weil sich jeder User einzeln anmelden muss. Für einen Kunden mit rund 200 Benutzern habe ich deshalb eine Lösung implementiert, die die userbasierte Authentifizierung umgeht und E-Mails direkt über die Microsoft Graph API sendet.
23. Juni 2026 durch
Odoo Outlook E-Mail Versand über Microsoft Graph
Nathanael Lee
| Noch keine Kommentare

Eine E-Mail aus Odoo zu senden klingt zuerst nach einer sehr einfachen Aufgabe: Odoo erstellt eine Mail, hängt vielleicht noch ein PDF an, nimmt den richtigen Empfänger und schickt das Ganze über den ausgehenden Mailserver raus. Fertig.

In der Praxis ist es aber nicht ganz so einfach. Vor allem dann nicht, wenn Odoo mit Microsoft 365 verbunden ist und viele Benutzer mit unterschiedlichen Absenderadressen arbeiten.

Bei einem Kundenprojekt hatte ich genau diese Situation. Es ging um Odoo 18, Odoo.sh und Microsoft 365. Odoo sollte zuverlässig E-Mails über die Firmenmailboxen senden. Angebote, Bestellungen, Chatter-Nachrichten, Follower-Benachrichtigungen und normale Kundenkommunikation. Der Standardweg über OAuth funktioniert grundsätzlich. Aber in diesem Fall war er nicht ideal, da der Kunde rund 200 Benutzer hat. Für jeden Benutzer einzeln eine Authentifizierung in Odoo einzurichten und sauber zu betreiben, ist nicht schön und sehr aufwendig. 

Die Alternative wäre ein gemeinsames Outlook-Postfach (shared Mailbox). Das funktioniert technisch, erfordert aber mehr Admin-Aufwand in Exchange und passt nicht immer zum gewünschten Absenderverhalten.

Deshalb habe ich einen eigenen Mail Transport über Microsoft Graph gebaut.

Screenshot Ausgehender Mailserver

Warum Microsoft Graph?

Microsoft Graph ist die API-Schicht von Microsoft 365. Darüber kann man unter anderem E-Mails senden, Kalender auslesen, Kontakte verwalten und vieles mehr.

Für diesen Use-Case war vor allem ein Punkt interessant: Nicht jeder einzelne Odoo Benutzer muss sich mit Microsoft anmelden. Stattdessen gibt es eine App Registration in Microsoft Entra ID. Diese App bekommt die nötigen Rechte, zum Beispiel Mail.Send, und Odoo kann mit einem Client Secret ein Access Token holen.

Dadurch wird das Setup für viele Benutzer deutlich einfacher. Nicht perfekt, aber deutlich besser als 200 einzelne OAuth-Verbindungen.

Die Grundidee war also:

  • Odoo entscheidet weiterhin wie gewohnt, welcher ausgehende Mailserver verwendet wird.

  • Für bestimmte Absender oder Domains wird der Graph Mailserver gewählt.

  • Unser Modul ersetzt dann nur den eigentlichen Versand.

  • Alles andere soll möglichst nahe am Odoo Standard bleiben.

Das war wichtig. Ich wollte keine grosse neue Mail-Lösung bauen. Solche Lösungen werden schnell schwer wartbar. Gerade beim Mailversand ist Einfachheit und Zuverlässigkeit absolut wichtig, da bei Fehler direkt Kunden betroffen sind.

Der erste funktionierende Ansatz: Graph MIME Versand

Microsoft Graph kann Mails auf zwei Arten senden: JSON oder MIME.

Bei JSON baut man eine Nachricht über strukturierte Felder auf. Also zum Beispiel:

  • Subject

  • Body

  • To Recipients

  • Cc Recipients

  • Bcc Recipients

  • Attachments

Bei MIME sendet man die komplette E-Mail, so wie sie auch über SMTP gesendet würde. Inklusive Header, Body, Anhänge, Message-ID, Reply-To und allem, was dazugehört.

Mein erster Ansatz war MIME. Das passte sehr gut zu Odoo, weil Odoo intern schon eine fertige MIME-Mail vorbereitet. Odoo macht beim Mailversand nämlich deutlich mehr, als man auf den ersten Blick sieht.

Zum Beispiel:

  • Odoo wählt den passenden ausgehenden Mailserver anhand der Absenderadresse.

  • Odoo schreibt den sichtbaren From-Header um, wenn nötig.

  • Odoo unterscheidet zwischen sichtbarem Absender und Envelope Sender.

  • Odoo entfernt Bcc aus den sichtbaren Headern, sendet aber trotzdem an die Bcc-Empfänger.

  • Odoo setzt Reply-To, Message-ID und weitere Header, damit Antworten wieder sauber im Chatter ankommen.

Genau diese Logik wollte ich nicht nachbauen. Deshalb hat das Modul zuerst eine kleine Fake-SMTP-Session gebaut. Odoo glaubt also, es sendet ganz normal über SMTP. Intern nimmt unser Modul aber die vorbereitete MIME-Mail und schickt sie über Microsoft Graph.

Das war sehr schlank und hat für normale E-Mails gut funktioniert.

Fake SMTP Session Code Screenshot

Odoo.sh Mailserver-Splitting

Ein weiterer wichtiger Punkt war das Routing der ausgehenden Mailserver.

In Odoo wird der ausgehende Mailserver gewählt, bevor unser Graph-Code überhaupt läuft. Das ist gut, weil wir Odoos Standardlogik weiterverwenden können.

Für den Kunden habe ich die Mailserver so getrennt:

  • kundendomain.net läuft über den Microsoft Graph Mailserver.

  • kundendomain.odoo.com läuft über einen separaten internen Odoo / CLI Mailserver.

  • Falls nötig, können einzelne Adressen wie notifications@... über exakte From Filter separat gesteuert werden.

Das ist sehr wichtig. Man sollte nicht einfach "alle Mails" durch einen Custom Transport schicken, wenn unterschiedliche Domains und Odoo.sh Systemmails beteiligt sind.

Der erste Edge-Case: Probleme bei langen Kundennamen

Fast alle normalen Mails funktionierten.

Dann kam eine Mail an einen Kontakt mit einem sehr langen Anzeigenamen. Der Kontakt hatte ungefähr diese Struktur (die gesamte Adresse wurde in den Namen geschrieben):

"Demo Analytics Pvt. Ltd. Alex Example, Demo House House no.42, Sample Road, Example City P.O. BOX 1234"

Also ein Anzeigename mit Punkten, Kommas und Adressbestandteilen. Klar ist es nicht korrekt, und die Adresse muss korrekt gepflegt werden. Dennoch darf das keinen Fehler auslösen beim Mailversand.

Odoo wusste intern genau, an welche E-Mail-Adresse gesendet werden sollte. Der echte Empfänger war korrekt. Aber Graph hat die MIME-Mail anders interpretiert und versucht, einen Teil vom Anzeigenamen als Empfänger aufzulösen.

Die Fehlermeldung war sinngemäss:

ErrorInvalidRecipients - Recipient 'Demo Analytics Pvt.Ltd.Alex Example' is not resolved.

Das war spannend, weil Odoo aus seiner Sicht nichts "falsch" gemacht hatte. Über normales SMTP hätte die Mail sehr wahrscheinlich funktioniert, weil SMTP einen separaten Envelope-Empfänger hat. Der sichtbare To-Header ist dort nicht allein entscheidend.

Bei Graph MIME ist das heikler. Graph bekommt die MIME-Mail und muss die Header selber interpretieren.

Das war der Moment, wo ich dachte: Vielleicht sollte ich auf Graph JSON wechseln.

Der JSON-Versuch

Graph JSON wirkt auf den ersten Blick sehr sauber.

Statt eine ganze MIME-Mail einzureichen, sendet man die Empfänger explizit:

  • toRecipients

  • ccRecipients

  • bccRecipients

Damit war der konkrete Empfängerfehler gelöst. Der lange Anzeigename war egal, weil Graph direkt die echte E-Mail-Adresse bekam.

Auch Cc und Bcc konnten wir sauber testen. Bcc war dabei besonders interessant, weil Odoo im normalen SMTP-Fluss den sichtbaren Bcc-Header entfernt und den echten Empfänger separat übergibt. Genau deshalb muss man bei JSON den Bcc-Wert vor der Odoo-Nachbereitung sichern.

Für normale Testmails sah das gut aus.

Aber dann kam das nächste Problem:

Warum JSON für Odoo nicht einfach besser ist

JSON hat den Empfängerfehler gelöst, aber dabei ein anderes Problem geöffnet.

Antworten auf Mails wurden nicht mehr sauber nach Odoo geroutet.

Zuerst sah es aus wie ein Reply-To Problem, welches durch falsche Alias-Konfiguration oder fehlende Weiterleitung ausgelöst wird. Aber es war tiefer. Selbst wenn man Reply-To manuell auf die Catchall-Adresse gesetzt hat, kam die Antwort nicht sauber im richtigen Chatter an.

Der Grund ist wahrscheinlich folgender: Mit JSON haben wir nicht mehr die komplette von Odoo vorbereitete E-Mail gesendet. Wir haben aus der MIME-Mail wieder eine vereinfachte Graph-Nachricht gebaut.

Dabei gehen wichtige Mail-Metadaten verloren oder werden von Microsoft neu erzeugt:

  • Message-ID

  • References

  • In-Reply-To

  • bestimmte Odoo Header

  • die genaue MIME-Struktur

Für eine normale E-Mail sieht das vielleicht egal aus. Für Odoo ist es aber nicht egal.

Odoo nutzt diese Informationen, damit Antworten wieder beim richtigen Datensatz landen. Zum Beispiel beim Verkaufsauftrag, beim Helpdesk-Ticket oder im Chatter eines Dokuments.

Die Catchall-Adresse alleine reicht nicht. Sie ist nicht einfach ein magischer Eingang, der jede Antwort automatisch richtig zuordnet. Die Mail muss auch zur ursprünglichen Odoo-Nachricht passen.

Aus diesem Grund war JSON wieder raus. Vielleicht hätte ich es irgendwie lösen können, aber die Mail-Metadaten müssen absolut passen und sicher-sein, deshalb habe ich die JSON-Methode wieder verworfen.

Was ist jetzt die richtige Lösung?

Für Outlook E-Mail über die Graph API würde ich heute sagen:

MIME sollte der Hauptweg bleiben.

Warum?

  • Odoo baut bereits eine vollständige MIME-Mail.

  • Odoo setzt wichtige Header für Antworten und Chatter-Routing.

  • Odoo verarbeitet Bcc und technische Absenderlogik sauber.

  • Attachments, Inline-Bilder und Reply-Metadaten bleiben näher am Standard.

JSON kann trotzdem nützlich sein. Aber eher als spezieller Fallback für einfache One-Way-Mails oder sehr kontrollierte Sonderfälle.

Für normale Odoo-Kommunikation, bei der Antworten wieder in Odoo landen müssen, ist MIME die sicherere Basis.

Der bessere finale Ansatz ist deshalb nicht: "Alles auf JSON umbauen".

Der bessere Ansatz ist:

  • Odoo bereitet die MIME-Mail wie gewohnt vor.

  • Das Modul sendet diese MIME-Mail über Microsoft Graph.

  • Die Absenderlogik bleibt nahe am Odoo Standard.

  • Für den speziellen Empfängerfehler muss man gezielt die problematischen To/Cc/Bcc Header entschärfen, ohne die restliche Mailstruktur zu zerstören.

Das ist weniger elegant als JSON. Aber es ist robuster für Odoo.

Was das Modul aktuell macht

Das Modul ist bewusst schlank gehalten.

Die wichtigsten Punkte:

  • Pro ausgehendem Mailserver können Graph Tenant ID, Client ID und Client Secret hinterlegt werden.

  • Wenn der Mailserver aktiviert ist, wird statt SMTP Microsoft Graph verwendet.

  • Das Modul holt ein Access Token über Client Credentials.

  • Tokens werden gecacht, damit nicht für jede Mail ein neues Token geholt wird.

  • Bei temporären Fehlern gibt es Retry und Backoff.

  • Bei 401 wird das Token einmal erneuert.

  • Optional können gesendete Odoo Mail Records behalten werden.

Das Ziel war nicht, Microsoft 365 komplett nachzubauen. Das Ziel war ein kleiner, zuverlässiger Mail Transport für Odoo.

Was ich aus dem Projekt gelernt habe

Dieses Projekt war ein gutes Beispiel dafür, warum E-Mail-Integration oft schwieriger ist, als sie aussieht.

Eine Mail über eine API zu senden ist einfach.

Eine Odoo-Mail so zu senden, dass:

  • der richtige Mailserver gewählt wird,

  • der sichtbare Absender stimmt,

  • der technische Bounce-Absender nicht alles kaputt macht,

  • Bcc funktioniert,

  • Antworten wieder im Chatter landen,

  • Follower-Benachrichtigungen korrekt weitergeleitet werden,

  • Anhänge und Inline-Bilder erhalten bleiben,

  • und Microsoft Graph nichts falsch interpretiert,

ist deutlich anspruchsvoller.

Vor allem sollte man Odoos bestehende Mail-Logik nicht unterschätzen. Vieles davon sieht man im UI gar nicht. Aber es ist wichtig.

Wenn du Fragen zu Odoo, Microsoft 365 oder komplexeren Mailserver-Setups hast, kontaktiere mich gerne.


Nate

Danke für die Registrierung!



Anmelden , um einen Kommentar zu hinterlassen