2mail — relais SMTP depuis une infrastructure belge

SMTP pour Python — le courrier de votre script ou app Django qui arrive

Python intègre SMTP : avec smtplib, vous envoyez un message en quelques lignes, et Django regroupe cela dans sa propre couche mail avec des réglages EMAIL. Ce qu'aucun des deux ne fournit, c'est la délivrabilité — elle dépend du serveur par lequel vous envoyez.

Que vous ayez un script isolé, une app Flask ou un projet Django : les réglages sont les mêmes cinq données. Vous les pointez vers votre relais et le code qui construit les messages demeure inchangé.

Pourquoi cela coince sans relais

Le courrier Python vient souvent de l'arrière-plan : un rapport nocturne, une tâche cron qui envoie des factures, un script qui alerte quand une mesure sort de la marge. Personne ne le surveille — et donc personne ne remarque que le serveur destinataire les refuse en silence. Avec Django s'ajoute la surprise classique de la mise en production : en développement, tout va vers la console, en production vers de vrais fournisseurs qui contrôlent bel et bien la réputation.

Configurer le SMTP dans Python

1

Récupérer les données

Connectez-vous à votre compte 2mail et récupérez-y votre serveur SMTP, votre nom d'utilisateur et votre mot de passe.

2

Compléter dans Python

Dans un projet Django, vous définissez les réglages EMAIL dans les settings : le backend SMTP comme backend e-mail, l'hôte du relais, le port 587, l'option STARTTLS activée, le nom d'utilisateur et le mot de passe, et une adresse d'expéditeur par défaut sur votre propre domaine. Si vous travaillez directement avec smtplib, vous vous connectez à l'hôte sur le port 587, vous appelez starttls, vous vous identifiez avec le nom d'utilisateur et le mot de passe, puis vous envoyez le message. Dans les deux cas, lisez les données depuis des variables d'environnement, pas depuis le code.

3

Authentifier le domaine

Veillez à ce que SPF, DKIM et DMARC soient correctement configurés pour votre domaine, afin que les destinataires puissent vérifier que le courrier vient bien de vous.

4

Tester

Depuis votre plateforme, envoyez un message de test vers une adresse chez un grand fournisseur et vérifiez qu'il arrive dans la boîte de réception et non dans les indésirables.

Les champs que Python demande

Chaque plateforme les nomme un peu différemment, mais il s'agit toujours des mêmes cinq champs. Les valeurs concrètes sont liées à votre compte et se trouvent dans votre compte 2mail — relevez-les à cet endroit, afin d'être certain d'utiliser les bonnes.

Champ Ce que vous indiquez
Serveur SMTP (host)Le nom de serveur figurant dans votre compte 2mail.
PortLe port correspondant au chiffrement que vous avez choisi ; votre compte indique lequel.
ChiffrementTLS. N'envoyez jamais sans chiffrement — vos identifiants circuleraient sinon en clair sur le réseau.
Nom d'utilisateurL'identifiant SMTP de votre compte 2mail.
Mot de passeLe mot de passe correspondant. N'utilisez jamais le mot de passe de la boîte aux lettres d'un collaborateur.

Configuration SMTP pour Python dans le code

Des exemples fonctionnels pour le port 587 avec STARTTLS, prêts à être repris. Remplacez l'adresse d'expéditeur par une adresse de votre propre domaine et vérifiez le nom du serveur et l'identifiant dans votre compte 2mail. Le mot de passe a sa place dans une variable d'environnement — jamais dans le code et jamais dans le gestionnaire de versions.

smtplib : se connecter sur le port 587 avec starttls()

La bibliothèque standard suffit. L'ordre compte : d'abord starttls(), et seulement ensuite login() — sinon votre mot de passe circule en clair sur le réseau, ou le relais refuse l'identification. Utilisez smtplib.SMTP et non SMTP_SSL : ce dernier va de pair avec le port 465. L'identifiant et le mot de passe proviennent de variables d'environnement.

import os
import smtplib
import ssl
from email.message import EmailMessage

msg = EmailMessage()
msg["From"] = "Example <noreply@example.com>"
msg["To"] = "you@example.org"
msg["Subject"] = "SMTP test"
msg.set_content("Sent through the 2mail SMTP relay.")

context = ssl.create_default_context()

with smtplib.SMTP("relay.2mail.eu", 587, timeout=10) as server:
    server.starttls(context=context)  # upgrade to TLS first, log in afterwards
    server.login(os.environ["SMTP_USERNAME"], os.environ["SMTP_PASSWORD"])
    server.send_message(msg)          # call again for the next message, same connection

Django : les settings EMAIL_*

Django n'a besoin d'aucun paquet supplémentaire. Définissez explicitement le backend SMTP : en développement, il est souvent réglé sur le backend console, et la production n'envoie alors rien alors que tout semble fonctionner. sendtestemail est une commande de gestion intégrée qui vous permet de contrôler les réglages sans devoir appeler une vue ou une tâche.

# settings.py
import os

EMAIL_BACKEND = "django.core.mail.backends.smtp.EmailBackend"
EMAIL_HOST = "relay.2mail.eu"
EMAIL_PORT = 587
EMAIL_USE_TLS = True   # STARTTLS - never together with EMAIL_USE_SSL
EMAIL_HOST_USER = os.environ["SMTP_USERNAME"]
EMAIL_HOST_PASSWORD = os.environ["SMTP_PASSWORD"]
EMAIL_TIMEOUT = 10
DEFAULT_FROM_EMAIL = "Example <noreply@example.com>"
SERVER_EMAIL = "noreply@example.com"   # sender of error reports to ADMINS

# Test from the shell:
#   python manage.py sendtestemail you@example.org

Flask-Mail : les mêmes cinq données

Si vous travaillez avec Flask, Flask-Mail demande les mêmes données sous d'autres noms. La même règle s'applique : MAIL_USE_TLS pour le port 587, et MAIL_USE_SSL reste désactivé.

import os
from flask import Flask
from flask_mail import Mail

app = Flask(__name__)
app.config.update(
    MAIL_SERVER="relay.2mail.eu",
    MAIL_PORT=587,
    MAIL_USE_TLS=True,    # STARTTLS
    MAIL_USE_SSL=False,
    MAIL_USERNAME=os.environ["SMTP_USERNAME"],
    MAIL_PASSWORD=os.environ["SMTP_PASSWORD"],
    MAIL_DEFAULT_SENDER="noreply@example.com",
)
mail = Mail(app)

Les e-mails que Python envoie

Dès que le relais est configuré, tous ces messages passent par 2mail — vous ne devez pas les configurer un par un.

Réinitialisation de mot de passe et vérification d'adresse depuis Django
Rapports planifiés et exports issus de tâches cron
Alertes de scripts de monitoring et de traitement de données
Factures et confirmations issues d'une application web
Rapports d'erreur vers les administrateurs

Pièges avec Python

Option TLS et port doivent correspondre

Django connaît deux réglages TLS distincts : un pour STARTTLS et un pour TLS dès le début. N'activez que celui pour STARTTLS, qui correspond au port 587. Les deux à la fois provoquent une erreur de configuration ; aucun des deux envoie votre identifiant en clair, ce qu'un relais refuse à juste titre.

Une connexion par série, pas par message

Un script qui ouvre une nouvelle connexion SMTP pour chacun de mille messages se comporte comme un attaquant. Ouvrez une connexion, envoyez la série, fermez. Django dispose pour cela d'une fonction qui envoie plusieurs messages sur une seule connexion.

Erreurs silencieuses dans les tâches de fond

Une exception dans une tâche cron disparaît dans un fichier journal que personne ne lit. Interceptez les erreurs d'envoi et signalez-les là où elles se voient — et connectez les webhooks de 2mail pour la livraison et les bounces, afin de voir aussi ce qui échoue après la remise.

Messages d'erreur fréquents avec Python

Les messages qui s'affichent lorsque l'hôte, le port, le chiffrement ou l'identifiant sont incorrects — cités tels quels, pour que vous les reconnaissiez dans votre journal, avec la cause et la solution en regard.

Message Cause Solution
smtplib.SMTPAuthenticationError: (535, b'5.7.8 Error: authentication failed: …') Le relais refuse l'identifiant : un nom d'utilisateur ou un mot de passe erroné, ou une variable d'environnement qui a, dans le contexte cron ou service, une autre valeur que dans votre shell. Affichez ce que le processus lit réellement (le nom d'utilisateur, jamais le mot de passe) et utilisez l'identifiant SMTP de votre compte 2mail — pas le mot de passe d'une boîte aux lettres.
smtplib.SMTPNotSupportedError: SMTP AUTH extension not supported by server. login() est appelé avant starttls(). Un relais ne propose l'authentification qu'une fois la connexion chiffrée ; sur la connexion encore en clair, AUTH n'existe tout simplement pas. Appelez d'abord server.starttls(context=context) et seulement ensuite server.login(…). Dans Django : indiquez EMAIL_USE_TLS = True.
ssl.SSLError: [SSL: WRONG_VERSION_NUMBER] wrong version number (_ssl.c:…) Le code utilise smtplib.SMTP_SSL (ou, dans Django, EMAIL_USE_SSL) sur le port 587. Python entame alors d'emblée une négociation TLS, alors que le relais attend d'abord du SMTP en clair sur ce port et ne bascule qu'après STARTTLS. La confusion classique entre 465 et 587. Utilisez smtplib.SMTP(…, 587) suivi de starttls(), ou dans Django EMAIL_USE_TLS = True avec le port 587.
smtplib.SMTPServerDisconnected: Connection unexpectedly closed La connexion est tombée avant ou pendant l'échange. Le plus souvent, un script garde une connexion ouverte et la réutilise après une longue pause, alors que le serveur l'a entre-temps fermée pour inactivité — ou il s'agit d'une connexion SMTP en clair vers un port qui attend du TLS dès le premier octet. Ouvrez une connexion par série de messages et fermez-la ensuite ; interceptez l'exception et reconnectez-vous. Vérifiez que vous utilisez bien le port 587 avec starttls().
ValueError: EMAIL_USE_TLS/EMAIL_USE_SSL are mutually exclusive, so only set one of those settings to True. Les deux options TLS sont activées dans les settings Django — souvent parce que l'une provient d'un fichier de base partagé et l'autre des settings de production. Ne conservez que EMAIL_USE_TLS = True et indiquez EMAIL_USE_SSL = False.
SPF, DKIM & DMARC expliqués À propos de la délivrabilité

Une autre plateforme ?

SMTP est un protocole standard : tout système qui parle SMTP — un CRM, un ERP, une application maison ou un serveur — peut envoyer via 2mail avec les mêmes cinq champs.

Questions fréquentes sur le SMTP pour Python

smtplib et Django envoient, mais ne fournissent pas la délivrabilité : celle-ci dépend du serveur par lequel vous envoyez. Une fonction mail locale ou un serveur neuf n'a ni authentification ni réputation. Un relais SMTP avec des enregistrements SPF, DKIM et DMARC corrects règle le problème.
Le backend SMTP comme backend e-mail, l'hôte du relais, le port 587, l'option STARTTLS activée, votre nom d'utilisateur et votre mot de passe, et une adresse d'expéditeur par défaut sur votre propre domaine. Conservez l'identifiant dans des variables d'environnement, pas dans les settings eux-mêmes.
Connectez-vous à l'hôte sur le port 587, appelez starttls, identifiez-vous avec le nom d'utilisateur et le mot de passe, puis envoyez le message. Pour plusieurs messages, utilisez la même connexion au lieu d'en ouvrir une nouvelle par message.
Dans votre compte 2mail, par application. Ils sont liés au compte, nous ne les publions donc pas sur le site web. Créez de préférence un identifiant propre par script ou application, afin de pouvoir le révoquer séparément et suivre ce trafic à part.
Appelez-nous
Envoyer un e-mail