Emails : robustesse SMTP + diagnostic
- config.py : retrait des identifiants OVH réels remis en dur ; défauts neutres (email_enabled=false). Les vraies valeurs vont dans .env. - open_smtp : le port 465 force le SSL implicite (SMTPS) même si SMTP_SSL=false — c'était la cause des envois qui ne partaient pas (connexion en clair sur un port TLS -> timeout). - deliver_many : les erreurs de connexion / auth / rejet sont journalisées avec le message du serveur et ne remontent plus (l'appel HTTP n'échoue pas). - Lien magique : envoi en tâche de fond (BackgroundTasks) comme les notifications ; ne bloque plus la réponse. - app/email/check.py : `python -m app.email.check <destinataire>` — affiche la config effective et envoie un email de test, avec la cause exacte en cas d'échec. - Tests : fixture autouse forçant EMAIL_ENABLED=false (aucun test ne touche un vrai SMTP, quel que soit le .env local) ; test_full_flow lit l'email capturé au lieu des logs. 137 tests OK. - .env.example : notes port 465 / From = boîte authentifiée / commande check. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017uUsRg7XzopkCPWimwg9ZM
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
6b08dcc953
commit
b84f62dfab
@@ -0,0 +1,63 @@
|
||||
"""Diagnostic de la configuration SMTP.
|
||||
|
||||
docker compose run --rm backend \\
|
||||
uv run python -m app.email.check destinataire@exemple.fr
|
||||
|
||||
Affiche la configuration effective, ouvre une session SMTP et envoie un email
|
||||
de test. En cas d'échec, imprime la cause exacte renvoyée par le serveur.
|
||||
"""
|
||||
|
||||
import sys
|
||||
|
||||
from app.config import get_settings
|
||||
from app.email.sender import build_message, open_smtp
|
||||
|
||||
|
||||
def main() -> int:
|
||||
if len(sys.argv) != 2:
|
||||
print("Usage : python -m app.email.check <destinataire@exemple.fr>")
|
||||
return 2
|
||||
recipient = sys.argv[1]
|
||||
settings = get_settings()
|
||||
|
||||
print("Configuration SMTP effective :")
|
||||
print(f" EMAIL_ENABLED : {settings.email_enabled}")
|
||||
print(f" SMTP_HOST : {settings.smtp_host}:{settings.smtp_port}")
|
||||
print(f" SMTP_SSL : {settings.smtp_ssl}")
|
||||
print(f" SMTP_STARTTLS : {settings.smtp_starttls}")
|
||||
print(f" SMTP_USER : {settings.smtp_user or '(aucun)'}")
|
||||
print(f" SMTP_FROM : {settings.smtp_from}")
|
||||
print()
|
||||
|
||||
if not settings.email_enabled:
|
||||
print("EMAIL_ENABLED est false : aucun envoi réel. Passe-le à true.")
|
||||
return 1
|
||||
|
||||
try:
|
||||
smtp = open_smtp(settings)
|
||||
except Exception as exc:
|
||||
print(f"ÉCHEC connexion / authentification : {exc!r}")
|
||||
return 1
|
||||
|
||||
message = build_message(
|
||||
recipient,
|
||||
"Test SMTP — gestion des bénévoles",
|
||||
"Cet email confirme que la configuration SMTP fonctionne.",
|
||||
)
|
||||
try:
|
||||
with smtp:
|
||||
smtp.send_message(message)
|
||||
except Exception as exc:
|
||||
print(f"ÉCHEC envoi (le serveur a refusé) : {exc!r}")
|
||||
print(
|
||||
"Piste fréquente (OVH…) : SMTP_FROM doit être la boîte "
|
||||
"authentifiée (= SMTP_USER) ou un alias validé."
|
||||
)
|
||||
return 1
|
||||
|
||||
print(f"OK — email de test envoyé à {recipient}.")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
Reference in New Issue
Block a user