Commit Graph
3 Commits
Author SHA1 Message Date
AdamThomasandClaude Sonnet 5 9521034207 Emails / logs : trace de remise + logging racine fiable
- 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 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017uUsRg7XzopkCPWimwg9ZM
2026-09-10 19:42:34 +02:00
AdamThomasandClaude Sonnet 5 b84f62dfab 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
2026-09-10 19:31:02 +02:00
AdamThomasandClaude Sonnet 5 b268e308ab Étape 10 : envoi d'emails par SMTP
- app/email/ : sender (smtplib, STARTTLS ou SSL, connexion réutilisée pour un
  lot) + templates (rendu, textes dans locales/fr.json). EMAIL_ENABLED=false
  (défaut) ⇒ journalisé seulement, sans destinataire ni corps (RGPD).
- Lien magique : POST .../auth/magic-link envoie désormais l'email
  (PUBLIC_BASE_URL + magic_link_path + ?token=). Helper app/auth/magic_link.py
  partagé. Sans SMTP, le jeton non nominatif reste journalisé pour le dev.
- Récapitulatif de planning : POST /editions/{id}/notifications/planning
  (COORDINATION). subject/body sont des modèles ({prenom}, {nom}, {nb_creneaux},
  {nb_heures}, {creneaux}, {lien_connexion} → lien magique personnel émis).
  Cible tous les bénévoles avec email ou une liste. Envoi en BackgroundTasks.
- Config : PUBLIC_BASE_URL, EMAIL_ENABLED, SMTP_* ; .env.example,
  docker-compose (dev + prod), deploy/README.
- 9 tests (sender activé/désactivé, rendu, notifications : contenu, gabarit par
  défaut, lien magique embarqué, sous-ensemble, réservé COORDINATION).
  137 tests au total ; ruff + alembic check verts.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017uUsRg7XzopkCPWimwg9ZM
2026-09-10 08:08:55 +02:00