From 9521034207f6a6093301e7261c10f1e75c889a85 Mon Sep 17 00:00:00 2001 From: AdamThomas Date: Thu, 10 Sep 2026 19:42:34 +0200 Subject: [PATCH] Emails / logs : trace de remise + logging racine fiable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - deliver_many : log INFO « Emails remis : N/M — sujet=… » sur chaque lot (sans destinataire ni corps). Avant, un envoi réussi ne journalisait rien. - configure_logging : basicConfig(force=True) pour que les logs app.* sortent dans la sortie du conteneur même quand uvicorn configure le logging avant l'import de app.main. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_017uUsRg7XzopkCPWimwg9ZM --- backend/app/email/sender.py | 9 +++++++++ backend/app/logging_config.py | 4 ++++ 2 files changed, 13 insertions(+) diff --git a/backend/app/email/sender.py b/backend/app/email/sender.py index 9329ea1..b7c7358 100644 --- a/backend/app/email/sender.py +++ b/backend/app/email/sender.py @@ -73,10 +73,12 @@ def deliver_many(messages: list[EmailMessage]) -> None: ) return + sent = 0 with smtp: for message in messages: try: smtp.send_message(message) + sent += 1 except smtplib.SMTPException as exc: # Ex. « 550 sender not authorized », « 535 auth failed ». logger.error( @@ -84,6 +86,13 @@ def deliver_many(messages: list[EmailMessage]) -> None: message["From"], exc, ) + # RGPD : ni destinataire ni corps, seulement le compte et le sujet. + logger.info( + "Emails remis : %d/%d — sujet=%r", + sent, + len(messages), + messages[0]["Subject"], + ) def send(to: str, subject: str, body: str) -> None: diff --git a/backend/app/logging_config.py b/backend/app/logging_config.py index fbb05ad..4d35cc9 100644 --- a/backend/app/logging_config.py +++ b/backend/app/logging_config.py @@ -9,7 +9,11 @@ from app.config import get_settings def configure_logging() -> None: + # `force=True` : on réinstalle le handler racine même si l'import de + # `app.main` se fait après la configuration de logging d'uvicorn/gunicorn, + # sinon les logs `app.*` n'apparaissent pas dans la sortie du conteneur. logging.basicConfig( level=get_settings().log_level, format="%(asctime)s %(levelname)s %(name)s %(message)s", + force=True, )