E-Mails senden mit Python

Sie senden E-Mails in Python mit email.message.EmailMessage und smtplib.SMTP_SSL aus der Standardbibliothek oder rufen für die Zustellung im Produktivbetrieb eine HTTP-E-Mail-API mit dem Paket messagebird-sdk auf.

Die Standardbibliothek von Python enthält smtplib für die SMTP-Verbindung und email.message.EmailMessage zum Erstellen der Nachricht, sodass ein einfacher SMTP-Versand keine Pakete von Drittanbietern benötigt. Für die Zustellung im Produktivbetrieb übernimmt eine HTTP-E-Mail-API das IP-Warmup, erneute Versuche und Bounce-Events, ohne dass Sie einen eigenen Mailserver betreiben müssen.

Wie senden Sie E-Mails mit der Standardbibliothek?

EmailMessage erstellt die Nachricht und setzt die Header für Sie. smtplib.SMTP_SSL öffnet eine verschlüsselte Verbindung auf Port 465:

import smtplib
from email.message import EmailMessage

msg = EmailMessage()
msg["From"] = "you@yourdomain.com"
msg["To"] = "recipient@example.org"
msg["Subject"] = "Your receipt"
msg.set_content("Thanks for your order. This is the plain-text version.")
msg.add_alternative("<p>Thanks for your order.</p>", subtype="html")

with smtplib.SMTP_SSL("smtp.example.com", 465) as server:
    server.login("smtp-user", "smtp-password")
    server.send_message(msg)

set_content schreibt den Klartext-Body und add_alternative hängt die HTML-Version an, sodass Clients rendern, was sie unterstützen. Beide Teile zu senden ist gute Praxis und hilft bei der Zustellbarkeit.

SSL oder STARTTLS?

Es gibt zwei Verschlüsselungswege, die unterschiedliche Ports nutzen. SMTP_SSL auf 465 handelt TLS ab dem ersten Byte aus. Die Alternative ist reines SMTP auf 587, gefolgt von starttls(), das eine Klartextverbindung hochstuft:

with smtplib.SMTP("smtp.example.com", 587) as server:
    server.starttls()
    server.login("smtp-user", "smtp-password")
    server.send_message(msg)

Wählen Sie den Weg, den Ihr Mailserver unterstützt. Senden Sie Zugangsdaten niemals über eine unverschlüsselte Verbindung. Speichern Sie Benutzername und Passwort in Umgebungsvariablen und lesen Sie sie mit os.environ aus, statt sie im Quellcode abzulegen.

Wie fügen Sie einen Anhang hinzu?

add_attachment nimmt die Bytes plus einen MIME-Typ entgegen. Lesen Sie die Datei im Binärmodus:

with open("invoice.pdf", "rb") as f:
    msg.add_attachment(
        f.read(),
        maintype="application",
        subtype="pdf",
        filename="invoice-1042.pdf",
    )

Warum im Produktivbetrieb weg von rohem SMTP?

Der Produktivbetrieb bringt Anforderungen mit sich, die die Standardbibliothek nicht abdeckt. Sie brauchen einen Mailserver mit sauberer IP-Reputation, SPF-, DKIM- und DMARC-Einträge, eine Logik für erneute Versuche bei vorübergehenden Fehlern und eine Möglichkeit, Bounces und Beschwerden zu verfolgen. Eine HTTP API übernimmt diese Schicht: Sie authentifizieren sich mit einem API-Schlüssel, senden JSON und lesen strukturierte Antworten, statt SMTP-Statuscodes zu parsen.

Senden mit Bird

Installieren Sie das Bird Python SDK (pip install messagebird-sdk), um über HTTPS zu senden, ohne eine SMTP-Verbindung verwalten zu müssen:

from bird import APIError, Bird

client = Bird()

try:
    message = client.email.send(
        from_="onboarding@messagebird.dev",
        to=["delivered@messagebird.dev"],
        subject="Hello from Python",
        text="It works.",
        html="<p>It works.</p>",
    )
    print(message.id, message.status)
except APIError as err:
    print("send failed:", err)

Bird() liest BIRD_API_KEY automatisch aus der Umgebung. Wenn Sie von onboarding@messagebird.dev an die delivered@messagebird.dev-Sandbox-Adresse senden, prüfen Sie Ihren Schlüssel und Ihre Payload, bevor Sie eine eigene Domain einrichten. Besteht die Anfrage die Validierung nicht, gibt APIError den HTTP-Statuscode und den Fehlercode aus.

Bauen Sie auf demselben Netzwerk auf.

Ein Test-API-Schlüssel steht Ihnen sofort zur Verfügung. Der Produktivbetrieb wird freigeschaltet, sobald Sie eine Zahlungsmethode hinzufügen und einen Absender verifizieren.

Ihre nächste Idee. Bereit zur Verbindung.