- 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
63 lines
1.8 KiB
Python
63 lines
1.8 KiB
Python
from types import SimpleNamespace
|
|
|
|
from app.email import sender
|
|
|
|
|
|
def test_disabled_delivery_is_a_noop():
|
|
# email_enabled=False par défaut en test : aucune exception, pas de SMTP.
|
|
sender.send("a@b.fr", "Sujet", "Corps")
|
|
sender.send_many([("a@b.fr", "S", "B"), ("c@d.fr", "S", "B")])
|
|
|
|
|
|
def test_smtp_is_used_when_enabled(monkeypatch):
|
|
fake = SimpleNamespace(
|
|
email_enabled=True,
|
|
smtp_host="mail.test",
|
|
smtp_port=587,
|
|
smtp_user="u",
|
|
smtp_password="p",
|
|
smtp_starttls=True,
|
|
smtp_ssl=False,
|
|
smtp_from="Festival <no-reply@test>",
|
|
)
|
|
monkeypatch.setattr(sender, "get_settings", lambda: fake)
|
|
events: list = []
|
|
|
|
class FakeSMTP:
|
|
def __init__(self, host, port, timeout=None):
|
|
events.append(("connect", host, port))
|
|
|
|
def __enter__(self):
|
|
return self
|
|
|
|
def __exit__(self, *_a):
|
|
return False
|
|
|
|
def starttls(self, context=None):
|
|
events.append(("starttls",))
|
|
|
|
def login(self, user, _password):
|
|
events.append(("login", user))
|
|
|
|
def send_message(self, message):
|
|
events.append(("send", message["To"], message["Subject"]))
|
|
|
|
monkeypatch.setattr(sender.smtplib, "SMTP", FakeSMTP)
|
|
|
|
sender.send_many([("x@y.fr", "Sujet 1", "B"), ("z@y.fr", "Sujet 2", "B")])
|
|
|
|
assert ("connect", "mail.test", 587) in events
|
|
assert ("starttls",) in events
|
|
assert ("login", "u") in events
|
|
assert ("send", "x@y.fr", "Sujet 1") in events
|
|
assert ("send", "z@y.fr", "Sujet 2") in events
|
|
|
|
|
|
def test_render_magic_link_uses_translations():
|
|
from app.email import render_magic_link
|
|
|
|
subject, body = render_magic_link(link="https://x/connexion?token=abc", minutes=30)
|
|
assert subject
|
|
assert "https://x/connexion?token=abc" in body
|
|
assert "30" in body
|