Skip to content

Commit

Permalink
Modification du contenu des emails de notifications (template HTML)
Browse files Browse the repository at this point in the history
- Ajoute un template HTML avec style unifié pour tous les emails de notifications
- Inclut les informations de l'expéditeur et le lien vers la fiche
- Styles CSS appliqués directement dans les balises HTML pour maximiser la compatibilité avec les différents clients email (cf. score Mailtrap)
- Dans les tests de notifications, renomme les variables pour éviter l'ambiguïté entre le contenu du message et l'objet Message lui-même :
    * 'message' en 'content' pour le contenu textuel
    * 'instance' en 'message_obj' pour l'objet Message
- Ajout de tests pour notification AC et compte rendu

Ticket Notion : https://www.notion.so/incubateur-masa/Mail-au-format-HTML-pour-respecter-les-maquettes-150de24614be80d0921bd8463ded61d8?pvs=4
PR : #551
  • Loading branch information
alanzirek committed Dec 20, 2024
1 parent db135c1 commit 462ca6a
Show file tree
Hide file tree
Showing 2 changed files with 159 additions and 79 deletions.
87 changes: 48 additions & 39 deletions core/notifications.py
Original file line number Diff line number Diff line change
@@ -1,56 +1,65 @@
from post_office.mail import send
from post_office.models import EmailTemplate

from core.constants import MUS_STRUCTURE
from core.models import Message, Contact
from django.conf import settings


def _send_message(recipients: list[str], copy: list[str], subject, message, instance):
message += (
f"\n\n Pour voir la fiche concernée par cette notification, consultez SEVES : "
f'<a href="{settings.ROOT_URL}{instance.content_object.get_absolute_url()}" target="_blank">{settings.ROOT_URL}{instance.content_object.get_absolute_url()}</a>'
def _send_message(recipients: list[str], copy: list[str], subject: str, content: str, message_obj: Message):
template, _ = EmailTemplate.objects.update_or_create(
name="seves_email_template",
defaults={
"subject": f"Sèves - {message_obj.content_object.numero} - {message_obj.message_type} - {subject}",
"html_content": """
<!DOCTYPE html>
<html>
<div style="font-family: Arial, sans-serif;">
<p style="white-space: pre-wrap; line-height: 1.5;">{{ content }}</p>
<p style="font-weight: bold; margin-top: 20px; margin-bottom: 0px;">{{ message_obj.sender.agent.prenom }} {{ message_obj.sender.agent.nom }}</p>
<p style="margin-top: 0px;">{{ message_obj.sender.agent.structure }}</p>
<p style="margin-top: 20px;">Consulter la fiche dans Sèves : <a href="{{ fiche_url }}">{{ fiche_url }}</a></p>
</div>
</html>
""",
},
)
send(
recipients=recipients,
cc=copy,
sender="no-reply@beta.gouv.fr",
subject=f"SEVES - {subject}",
html_message=message,
template=template,
context={
"message_obj": message_obj,
"content": content,
"fiche_url": f"{settings.ROOT_URL}{message_obj.content_object.get_absolute_url()}",
},
)


def notify_message(instance: Message):
def notify_message(message_obj: Message):
recipients, copy = [], []
message, subject = None, None
if instance.message_type == Message.MESSAGE:
subject = instance.title
message = f"Bonjour,\n Vous avez reçu un message sur SEVES dont voici le contenu : \n {instance.content}"
recipients = [r.email for r in instance.recipients.all()]
copy = [r.email for r in instance.recipients_copy.all()]
elif instance.message_type == Message.COMPTE_RENDU:
subject = instance.title
message = f"Bonjour,\n Vous avez reçu un compte rendu sur demande d'intervention sur SEVES dont voici le contenu : \n {instance.content}"
recipients = [r.email for r in instance.recipients.all()]
elif instance.message_type == Message.DEMANDE_INTERVENTION:
subject = instance.title
message = "Bonjour,\n Vous avez reçu un message sur SEVES."
recipients = [r.email for r in instance.recipients.structures_only()]
copy = [r.email for r in instance.recipients_copy.structures_only()]
elif instance.message_type == Message.POINT_DE_SITUATION:
subject = instance.title
message = "Bonjour,\n Vous avez reçu un nouveau point de suivi sur SEVES."
recipients = [c.email for c in instance.content_object.contacts.agents_only()]
elif instance.message_type == Message.FIN_SUIVI:
subject = instance.title
message = "Bonjour,\n Vous avez reçu un nouveau point de suivi sur SEVES."
recipients = instance.content_object.contacts.agents_only().filter(agent__structure__niveau2=MUS_STRUCTURE)
recipients = [r.email for r in recipients]
elif instance.message_type == Message.NOTIFICATION_AC:
subject = instance.title
message = (
f"Bonjour,\n une personne a déclarée la fiche {instance.content_object.numero} à l'administration centrale."
)
recipients = [Contact.objects.get_mus().email, Contact.objects.get_bsv().email]
content = message_obj.content

if recipients and message:
_send_message(recipients, copy, subject=subject, message=message, instance=instance)
match message_obj.message_type:
case Message.MESSAGE:
recipients = [r.email for r in message_obj.recipients.all()]
copy = [r.email for r in message_obj.recipients_copy.all()]
case Message.COMPTE_RENDU:
recipients = [r.email for r in message_obj.recipients.all()]
case Message.DEMANDE_INTERVENTION:
recipients = [r.email for r in message_obj.recipients.structures_only()]
copy = [r.email for r in message_obj.recipients_copy.structures_only()]
case Message.POINT_DE_SITUATION:
recipients = [c.email for c in message_obj.content_object.contacts.agents_only()]
case Message.FIN_SUIVI:
recipients = message_obj.content_object.contacts.agents_only().filter(
agent__structure__niveau2=MUS_STRUCTURE
)
recipients = [r.email for r in recipients]
case Message.NOTIFICATION_AC:
content = f"Bonjour,\nLa fiche {message_obj.content_object.numero} vient d'être déclarée à l'administration centrale."
recipients = [Contact.objects.get_mus().email, Contact.objects.get_bsv().email]

if recipients and content:
_send_message(recipients, copy, subject=message_obj.title, content=content, message_obj=message_obj)
151 changes: 111 additions & 40 deletions sv/tests/test_notifications.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import pytest
from django.utils import html
from model_bakery import baker

from core.constants import AC_STRUCTURE, MUS_STRUCTURE, BSV_STRUCTURE
from core.models import Structure, Agent, Contact, Message
from core.notifications import notify_message

Expand Down Expand Up @@ -28,16 +30,16 @@ def test_notification_message(mailoutbox, fiche_detection):
notify_message(message)

assert len(mailoutbox) == 1
message = mailoutbox[0]
assert message.subject == "SEVES - TITLE"
assert (
message.body
== f"Bonjour,\n Vous avez reçu un message sur SEVES dont voici le contenu : \n My message \n Thanks\n\n Pour voir la fiche concernée par cette notification, consultez SEVES : "
f'<a href="http://testserver.com/sv/fiches-detection/{fiche_detection.pk}/" target="_blank">http://testserver.com/sv/fiches-detection/{fiche_detection.pk}/</a>'
)
assert message.from_email == "no-reply@beta.gouv.fr"
assert set(message.to) == {contact_1.email, contact_2.email}
assert set(message.cc) == {contact_3.email, contact_4.email}
mail = mailoutbox[0]
assert mail.subject == f"Sèves - {fiche_detection.numero} - {message.message_type} - {message.title}"
assert message.content in mail.body
assert message.sender.agent.prenom in mail.body
assert message.sender.agent.nom in mail.body
assert str(message.sender.agent.structure) in mail.body
assert fiche_detection.get_absolute_url() in mail.body
assert mail.from_email == "no-reply@beta.gouv.fr"
assert set(mail.to) == {contact_1.email, contact_2.email}
assert set(mail.cc) == {contact_3.email, contact_4.email}


@pytest.mark.django_db
Expand All @@ -63,16 +65,16 @@ def test_notification_demande_intervention(mailoutbox, fiche_detection):
notify_message(message)

assert len(mailoutbox) == 1
message = mailoutbox[0]
assert message.subject == "SEVES - TITLE"
assert (
message.body
== f"Bonjour,\n Vous avez reçu un message sur SEVES.\n\n Pour voir la fiche concernée par cette notification, consultez SEVES : "
f'<a href="http://testserver.com/sv/fiches-detection/{fiche_detection.pk}/" target="_blank">http://testserver.com/sv/fiches-detection/{fiche_detection.pk}/</a>'
)
assert message.from_email == "no-reply@beta.gouv.fr"
assert set(message.to) == {structure_1.email}
assert set(message.cc) == {structure_2.email}
mail = mailoutbox[0]
assert mail.subject == f"Sèves - {fiche_detection.numero} - {message.message_type} - {message.title}"
assert message.content in mail.body
assert message.sender.agent.prenom in mail.body
assert message.sender.agent.nom in mail.body
assert str(message.sender.agent.structure) in mail.body
assert fiche_detection.get_absolute_url() in mail.body
assert mail.from_email == "no-reply@beta.gouv.fr"
assert set(mail.to) == {structure_1.email}
assert set(mail.cc) == {structure_2.email}


@pytest.mark.django_db
Expand All @@ -95,22 +97,22 @@ def test_notification_point_de_situation(mailoutbox, fiche_detection):
notify_message(message)

assert len(mailoutbox) == 1
message = mailoutbox[0]
assert message.subject == "SEVES - TITLE"
assert (
message.body
== f"Bonjour,\n Vous avez reçu un nouveau point de suivi sur SEVES.\n\n Pour voir la fiche concernée par cette notification, consultez SEVES : "
f'<a href="http://testserver.com/sv/fiches-detection/{fiche_detection.pk}/" target="_blank">http://testserver.com/sv/fiches-detection/{fiche_detection.pk}/</a>'
)
assert message.from_email == "no-reply@beta.gouv.fr"
assert set(message.to) == {agent_1.email}
assert set(message.cc) == set()
mail = mailoutbox[0]
assert mail.subject == f"Sèves - {fiche_detection.numero} - {message.message_type} - {message.title}"
assert message.content in mail.body
assert message.sender.agent.prenom in mail.body
assert message.sender.agent.nom in mail.body
assert str(message.sender.agent.structure) in mail.body
assert fiche_detection.get_absolute_url() in mail.body
assert mail.from_email == "no-reply@beta.gouv.fr"
assert set(mail.to) == {agent_1.email}
assert set(mail.cc) == set()


@pytest.mark.django_db
def test_notification_fin_de_suivi(mailoutbox, fiche_detection):
sender = baker.make(Contact, agent=baker.make(Agent))
agent_1 = baker.make(Contact, agent=baker.make(Agent, structure__niveau2="MUS"))
agent_1 = baker.make(Contact, agent=baker.make(Agent, structure__niveau2=MUS_STRUCTURE))
agent_2 = baker.make(Contact, agent=baker.make(Agent, structure__niveau2="FOO"))
structure_1 = baker.make(Contact, structure=baker.make(Structure))

Expand All @@ -126,13 +128,82 @@ def test_notification_fin_de_suivi(mailoutbox, fiche_detection):
notify_message(message)

assert len(mailoutbox) == 1
message = mailoutbox[0]
assert message.subject == "SEVES - TITLE"
assert (
message.body
== f"Bonjour,\n Vous avez reçu un nouveau point de suivi sur SEVES.\n\n Pour voir la fiche concernée par cette notification, consultez SEVES : "
f'<a href="http://testserver.com/sv/fiches-detection/{fiche_detection.pk}/" target="_blank">http://testserver.com/sv/fiches-detection/{fiche_detection.pk}/</a>'
mail = mailoutbox[0]
assert mail.subject == f"Sèves - {fiche_detection.numero} - {message.message_type} - {message.title}"
assert message.content in mail.body
assert message.sender.agent.prenom in mail.body
assert message.sender.agent.nom in mail.body
assert str(message.sender.agent.structure) in mail.body
assert fiche_detection.get_absolute_url() in mail.body
assert mail.from_email == "no-reply@beta.gouv.fr"
assert set(mail.to) == {agent_1.email}
assert set(mail.cc) == set()


def test_notification_notification_ac(mailoutbox, fiche_detection):
sender = baker.make(Contact, agent=baker.make(Agent))
agent_1 = baker.make(Contact, agent=baker.make(Agent))
structure_1 = baker.make(Contact, structure=baker.make(Structure))
contact_mus = baker.make(Contact, structure=baker.make(Structure, niveau1=AC_STRUCTURE, niveau2=MUS_STRUCTURE))
contact_bsv = baker.make(Contact, structure=baker.make(Structure, niveau1=AC_STRUCTURE, niveau2=BSV_STRUCTURE))

message = Message.objects.create(
title="TITLE",
content="My message \n Thanks",
sender=sender,
message_type=Message.NOTIFICATION_AC,
content_object=fiche_detection,
)
message.recipients.set([agent_1, structure_1])

notify_message(message)

assert len(mailoutbox) == 1
mail = mailoutbox[0]

assert mail.subject == f"Sèves - {fiche_detection.numero} - {message.message_type} - {message.title}"

expected_content = f"Bonjour,\nLa fiche {fiche_detection.numero} vient d'être déclarée à l'administration centrale."
assert html.escape(expected_content) in mail.body
assert message.content not in mail.body

assert message.sender.agent.prenom in mail.body
assert message.sender.agent.nom in mail.body
assert str(message.sender.agent.structure) in mail.body
assert fiche_detection.get_absolute_url() in mail.body

assert mail.from_email == "no-reply@beta.gouv.fr"
assert set(mail.to) == {contact_mus.email, contact_bsv.email}
assert set(mail.cc) == set()


def test_notification_compte_rendu(mailoutbox, fiche_detection):
sender = baker.make(Contact, agent=baker.make(Agent))
contact_mus = baker.make(Contact, structure=baker.make(Structure, niveau1=AC_STRUCTURE, niveau2=MUS_STRUCTURE))
contact_bsv = baker.make(Contact, structure=baker.make(Structure, niveau1=AC_STRUCTURE, niveau2=BSV_STRUCTURE))

message = Message.objects.create(
title="TITLE",
content="My message \n Thanks",
sender=sender,
message_type=Message.COMPTE_RENDU,
content_object=fiche_detection,
)
assert message.from_email == "no-reply@beta.gouv.fr"
assert set(message.to) == {agent_1.email}
assert set(message.cc) == set()
message.recipients.set([contact_mus, contact_bsv])

notify_message(message)

assert len(mailoutbox) == 1
mail = mailoutbox[0]

assert mail.subject == f"Sèves - {fiche_detection.numero} - {message.message_type} - {message.title}"

assert message.content in mail.body
assert message.sender.agent.prenom in mail.body
assert message.sender.agent.nom in mail.body
assert str(message.sender.agent.structure) in mail.body
assert fiche_detection.get_absolute_url() in mail.body

assert mail.from_email == "no-reply@beta.gouv.fr"
assert set(mail.to) == {contact_mus.email, contact_bsv.email}
assert set(mail.cc) == set()

0 comments on commit 462ca6a

Please sign in to comment.