La bibliothèque standard de Python inclut smtplib pour la connexion SMTP et email.message.EmailMessage pour construire le message, si bien qu'un envoi SMTP basique ne nécessite aucun paquet tiers. En production, une API e-mail HTTP gère la montée en charge progressive des IP, les nouvelles tentatives et les événements de rebond, sans que vous ayez à exploiter un serveur de messagerie.
Comment envoyer un e-mail avec la bibliothèque standard ?
EmailMessage construit le message et définit les en-têtes pour vous. smtplib.SMTP_SSL ouvre une connexion chiffrée sur le 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 écrit le corps en texte brut et add_alternative attache la version HTML, pour que les clients affichent ce qu'ils savent rendre. Envoyer les deux parties est une bonne pratique et aide à la délivrabilité.
SSL ou STARTTLS ?
Deux chemins de chiffrement existent et ils utilisent des ports différents. SMTP_SSL sur le port 465 négocie TLS dès le premier octet. L'alternative est SMTP en clair sur le port 587, suivi de starttls(), qui passe la connexion en mode chiffré :
with smtplib.SMTP("smtp.example.com", 587) as server:
server.starttls()
server.login("smtp-user", "smtp-password")
server.send_message(msg)
Choisissez en fonction de ce que votre serveur de messagerie prend en charge. N'envoyez pas d'identifiants sur une connexion non chiffrée. Conservez le nom d'utilisateur et le mot de passe dans des variables d'environnement, lues avec os.environ, plutôt que dans le code source.
Comment ajouter une pièce jointe ?
add_attachment prend les octets plus un type MIME. Lisez le fichier en mode binaire :
with open("invoice.pdf", "rb") as f:
msg.add_attachment(
f.read(),
maintype="application",
subtype="pdf",
filename="invoice-1042.pdf",
)
Pourquoi abandonner SMTP brut en production ?
L'envoi en production ajoute des exigences que la bibliothèque standard ne gère pas. Vous avez besoin d'un serveur de messagerie avec une bonne réputation IP, d'enregistrements SPF, DKIM et DMARC, d'une logique de nouvelle tentative pour les erreurs transitoires et d'un moyen de suivre les rebonds et les plaintes. Une HTTP API prend en charge cette couche : vous vous authentifiez avec une clé API, envoyez du JSON et lisez des réponses structurées au lieu d'analyser des codes de statut SMTP.
Envoyer avec Bird
Installez le SDK Python Bird (pip install messagebird-sdk) pour envoyer via HTTPS sans gérer de connexion SMTP :
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() lit automatiquement BIRD_API_KEY depuis l'environnement. Un envoi depuis onboarding@messagebird.dev vers l'adresse sandbox delivered@messagebird.dev vérifie votre clé et votre payload avant que vous configuriez un domaine personnalisé. Si la requête échoue à la validation, APIError renvoie le code de statut HTTP et le code d'erreur.