Étape 67 : adresse + bouton dans l'onglet « Messages » pour envoyer tout de suite un email de test, résultat réel affiché (envoyé, désactivé, connexion ou message refusé, réponse du serveur SMTP) — POST .../notifications/test. Étape 66 : prénom et nom facultatifs à l'ajout manuel d'un bénévole ; un bénévole sans nom s'affiche « Sans nom » / « ? » partout. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
84 lines
2.7 KiB
Python
84 lines
2.7 KiB
Python
"""Email de test depuis l'écran « Messages » (`POST .../notifications/test`) :
|
|
envoi synchrone, résultat réel du serveur SMTP renvoyé à la coordination."""
|
|
|
|
import smtplib
|
|
|
|
import pytest
|
|
|
|
from app.config import get_settings
|
|
from app.models import Role
|
|
|
|
|
|
def _url(edition):
|
|
return f"/editions/{edition.id}/notifications/test"
|
|
|
|
|
|
class _FakeSmtp:
|
|
def __init__(self, error=None):
|
|
self.sent = []
|
|
self.error = error
|
|
|
|
def __enter__(self):
|
|
return self
|
|
|
|
def __exit__(self, *exc):
|
|
return False
|
|
|
|
def send_message(self, message):
|
|
if self.error:
|
|
raise self.error
|
|
self.sent.append(message)
|
|
|
|
|
|
@pytest.fixture
|
|
def smtp_enabled(monkeypatch):
|
|
monkeypatch.setenv("EMAIL_ENABLED", "true")
|
|
get_settings.cache_clear()
|
|
|
|
|
|
def test_disabled_email_is_reported(client, edition):
|
|
resp = client.post(_url(edition), json={"email": "moi@exemple.fr"})
|
|
assert resp.status_code == 200
|
|
assert resp.json()["status"] == "disabled"
|
|
|
|
|
|
def test_sends_the_test_email(client, edition, smtp_enabled, monkeypatch):
|
|
fake = _FakeSmtp()
|
|
monkeypatch.setattr("app.email.sender.open_smtp", lambda settings: fake)
|
|
resp = client.post(_url(edition), json={"email": " moi@exemple.fr "})
|
|
assert resp.json()["status"] == "sent"
|
|
(message,) = fake.sent
|
|
assert message["To"] == "moi@exemple.fr"
|
|
|
|
|
|
def test_connection_failure_is_reported_with_the_server_message(
|
|
client, edition, smtp_enabled, monkeypatch
|
|
):
|
|
def refuse(settings):
|
|
raise smtplib.SMTPAuthenticationError(535, b"authentication failed")
|
|
|
|
monkeypatch.setattr("app.email.sender.open_smtp", refuse)
|
|
body = client.post(_url(edition), json={"email": "moi@exemple.fr"}).json()
|
|
assert body["status"] == "connection_failed"
|
|
assert "535" in body["detail"]
|
|
|
|
|
|
def test_rejected_message_never_echoes_the_address(client, edition, smtp_enabled, monkeypatch):
|
|
refused = smtplib.SMTPRecipientsRefused({"moi@exemple.fr": (550, b"no such user")})
|
|
monkeypatch.setattr("app.email.sender.open_smtp", lambda settings: _FakeSmtp(refused))
|
|
body = client.post(_url(edition), json={"email": "moi@exemple.fr"}).json()
|
|
assert body["status"] == "rejected"
|
|
assert "550" in body["detail"]
|
|
assert "moi@exemple.fr" not in body["detail"]
|
|
|
|
|
|
@pytest.mark.parametrize("email", ["", "pas-un-email", "@exemple.fr", "moi@", "a b@c.fr"])
|
|
def test_invalid_address_is_rejected(client, edition, email):
|
|
resp = client.post(_url(edition), json={"email": email})
|
|
assert resp.status_code == 422
|
|
|
|
|
|
def test_is_coordinator_only(edition, make_account, as_account):
|
|
lead = as_account(make_account(Role.LEAD))
|
|
assert lead.post(_url(edition), json={"email": "moi@exemple.fr"}).status_code == 403
|