jan@dunkel.tech
dunkel.Tech
Odoo

E-Mails mit Odoo versenden

Warum eigene E-Mails in Odoo? Odoo ist eine mächtige Plattform, aber manchmal reicht die Standardfunktionalität nicht aus. Du möchtest vielleicht: Eine spezielle Benachrichtigung versenden, wenn ein bestimmtes Kriterium in deinem benutzerdefinierten Modul erfüllt ist. Eine E-Mail mit dynamischen Inhalten an einen externen Dienstleister schicken. Ein einzigartiges Design für Transaktions-E-Mails verwenden, das nicht zum Standard passt. Der einfachste und robusteste Weg in Odoo ist die Verwendung von E-Mail-Templates (XML) in Kombination mit Python-Code (API-Aufrufe). So trennst du das Design vom Code und profitierst von Odoos integrierter E-Mail-Infrastruktur.

E-Mails mit Odoo versenden

Das E-Mail-Template in XML erstellen

Zuerst definierst du das Aussehen und den Inhalt deiner E-Mail. Für dynamische und strukturierte Inhalte nutzen wir ein QWeb2 Template innerhalb des body_html-Feldes deines mail.template Datensatzes. Dieses Template speicherst du typischerweise in einer XML-Datei in deinem Modul, z.B. unter data/mail_template.xml

<odoo>
    <data noupdate="1">
        <record id="email_template_custom_notification" model="mail.template">
            <field name="name">Benutzerdefinierte Benachrichtigung (QWeb2)</field>
            <field name="model_id" ref="dein_modul.model_dein_modell"/>
            <field name="subject">Ihre Anfrage wurde erfolgreich bearbeitet! (#{{ object.name }})</field>
            <field name="email_to">{{ object.partner_id.email }}</field>
            <field name="body_html" type="html">
                <![CDATA[
                    <div style="font-family: 'Arial', sans-serif; font-size: 14px;">
                        <p>Sehr geehrte/r <t t-out="object.partner_id.name or 'Kunde'"/>,</p>
                        <p>
                            Vielen Dank für Ihre Bestellung/Anfrage <strong>#<t t-out="object.name"/></strong>.
                            Sie wurde erfolgreich verarbeitet und wird nun weiter bearbeitet.
                        </p>
                        <t t-if="object.details_available">
                            <h3>Details Ihrer Anfrage:</h3>
                            <ul>
                                <li>Referenz: <t t-out="object.reference_number"/></li>
                                <li>Betrag: <t t-out="object.amount" t-options='{"widget": "monetary", "display_currency": object.currency_id}'/></li>
                            </ul>
                        </t>
                        <p>
                            Bei Fragen kontaktieren Sie uns gerne.
                        </p>
                        <p>Mit freundlichen Grüßen,</p>
                        <p>Ihr Team</p>
                    </div>
                ]]>
            </field>
            <field name="auto_delete" eval="True"/>
        </record>
    </data>
</odoo>

Was ist QWeb2 und wie funktioniert es hier?

QWeb2 ist Odoos serverseitiges Templating-System, das HTML-Strukturen mit dynamischen Daten füllen kann. Innerhalb des <field name="body_html" type="html"> Blocks definieren wir den Inhalt.

  • <![CDATA[ ... ]]>: Dies ist wichtig, um sicherzustellen, dass dein HTML-Code und die QWeb2-Direktiven nicht vom XML-Parser als Tags interpretiert werden, sondern als reiner Textinhalt des Feldes.

  • <t t-out="expression"/>: Gibt den Wert einer Variablen aus (vergleichbar mit {{ variable }} in Jinja). Hier z.B. object.partner_id.name.

  • <t t-if="condition"> ... </t>: Ermöglicht bedingte Inhalte. Der Block wird nur gerendert, wenn die Bedingung wahr ist.

  • <t t-options='{"widget": "monetary", "display_currency": object.currency_id}'/>: Dies zeigt die Leistungsfähigkeit von QWeb2. Du kannst Odoo-Widgets direkt im Template verwenden, um Daten wie Währungen korrekt zu formatieren. Dafür musst du sicherstellen, dass dein object auch ein currency_id Feld besitzt.

  • Variablenzugriff: Wie zuvor wird der Record, für den die E-Mail gesendet wird, als object im Template verfügbar gemacht. Du kannst auf alle seine Felder und verknüpften Felder zugreifen.

Den Versand im Python-Code auslösen

Nun benötigst du den Python-Code, der den E-Mail-Versand basierend auf einem Ereignis in deinem Odoo-Modul auslöst. Dies geschieht in einer Methode deines Modells (z.B. bei einem Statuswechsel).

from odoo import api, fields, models

class DeinModell(models.Model):
    _name = 'dein_modul.dein_modell'
    _description = 'Ein benutzerdefiniertes Odoo-Modell'

    name = fields.Char(string="Referenz")
    partner_id = fields.Many2one('res.partner', string="Kunde")
    status = fields.Selection([('draft', 'Entwurf'), ('done', 'Erledigt')], default='draft')
    details_available = fields.Boolean(string="Details vorhanden", default=False)
    reference_number = fields.Char(string="Interne Referenz")
    amount = fields.Monetary(string="Betrag")
    currency_id = fields.Many2one('res.currency', string="Währung", default=lambda self: self.env.company.currency_id)


    def action_send_notification_mail(self):
        """Versendet die E-Mail, z.B. sobald der Status auf 'done' gesetzt wird."""
        # Hole die ID des E-Mail-Templates
        template = self.env.ref('dein_modul.email_template_custom_notification')

        # Die E-Mail pro Record in der Recordset (self) versenden
        for record in self:
            if record.status == 'done' and record.partner_id.email: # Sicherstellen, dass eine E-Mail-Adresse existiert
                try:
                    # Sende das Template. Der Record wird als Kontextobjekt übergeben (object)
                    template.send_mail(
                        record.id,
                        force_send=True, # E-Mail sofort versenden, nicht in der Queue lassen
                        raise_exception=True # Exception werfen, falls etwas schief geht
                    )
                except Exception as e:
                    record.message_post(body=f"Fehler beim Senden der E-Mail an {record.partner_id.email}: {e}")
                    self.env.cr.rollback() # Optional: Rollback bei Fehler

        return True

Erklärung der Schlüsselfunktion template.send_mail():

  • self.env.ref('dein_modul.email_template_custom_notification'): Dies holt das XML-Template anhand der externen ID (<record id="..." />).

  • record.id: Dies ist der entscheidende Parameter. Odoo weiß dadurch, dass der Record (record) des aktuellen Modells (dein_modul.dein_modell) als Kontext-Objekt (object) für das Template verwendet werden soll. Alle Platzhalter (<t t-out="object.name" />) werden von diesem Record gefüllt.

Fazit: Die volle Macht der Odoo E-Mail-Automatisierung

Die Kombination aus einem dedizierten QWeb2-Template in XML und dem Aufruf per Python-Code ist die Best Practice in Odoo, insbesondere wenn du:

  1. Komplexe Layouts oder dynamische Inhalte basierend auf Geschäftslogik benötigst.

  2. Odoo-Widgets zur korrekten Formatierung von Daten (z.B. Datumsangaben, Währungen) nutzen möchtest.

  3. Übersichtlichkeit im Code beibehalten und das E-Mail-Design von der Versandlogik trennen willst.

Mit QWeb2 hast du die volle Kontrolle über den E-Mail-Inhalt und kannst ansprechende, datengesteuerte Nachrichten direkt aus deinem Odoo-System versenden.

Mehr aus Odoo
Eigene Cronjobs in Odoo
25. October 2025

Eigene Cronjobs in Odoo

Was sind Cronjobs in Odoo? In Odoo sind Cronjobs (auch bekannt als Scheduled Actions oder Geplante Aktionen) das Herzstück der Automatisierung. Sie ermöglichen es dir, Python-Code zu bestimmten, wiederkehrenden Zeiten auszuführen, ohne dass ein Benutzer eingreifen muss. Typische Anwendungsfälle sind: Tägliches Abholen von Wechselkursen. Wöchentliches Versenden von Marketing-E-Mails. Automatische Lagerbereinigungen. In diesem Artikel zeigen wir, wie du einen benutzerdefinierten Cronjob erstellst, um Mitarbeiter automatisch an ihr jährliches Performance-Gespräch zu erinnern – einen Monat vor ihrem Jahrestag.

Mehr erfahren
Die eigene Odoo Extension
11. July 2025

Die eigene Odoo Extension

In diesem Beitrag zeige ich, wie man in Odoo eine bestehende App – in unserem Fall die HR-App (Human Resources) – technisch erweitert. Wir erstellen eine eigene Erweiterung, mit der sich die Standard-Ansicht der Mitarbeiterliste auf Listenansicht umstellen lässt. Zusätzlich erweitern wir das zugehörige Datenmodell um ein eigenes benutzerdefiniertes Feld, das sich direkt im Backend verwenden lässt. Der Artikel richtet sich an Entwickler:innen, die bestehende Odoo-Module gezielt anpassen und eigene Funktionen integrieren möchten – ohne die Kernlogik zu verändern.

Mehr erfahren