Récapitulatif de planning : créneaux en tableau avec le référent
ci-cd / build-backend (push) Successful in 48s
ci-cd / deploy (push) Successful in 13s
ci-cd / build-frontend (push) Successful in 7s

{creneaux} devient un tableau par jour de festival (horaire, poste,
référent avec son téléphone), en HTML dans l'email et en lignes lisibles
dans la version texte — envoi réel et email de test.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
AdamThomas
2026-10-28 19:52:06 +01:00
co-authored by Claude Opus 5.5
parent 440466ccf9
commit 8d6781e6ce
6 changed files with 291 additions and 76 deletions
+21 -3
View File
@@ -8,7 +8,7 @@ Pour diagnostiquer : `python -m app.email.check <destinataire>`."""
import logging
import smtplib
import ssl
from collections.abc import Iterable, Sequence
from collections.abc import Iterable, Mapping, Sequence
from email.message import EmailMessage
from app.config import Settings, get_settings
@@ -44,8 +44,15 @@ def build_message(
*,
logo: tuple[bytes, str] | None = None,
attachments: Sequence[Attachment] = (),
html_body: str | None = None,
html_blocks: Mapping[str, str] | None = None,
) -> EmailMessage:
"""`logo` = (octets, content-type) (voir `app/email/branding.py:
"""`html_body` / `html_blocks` : corps de la version HTML quand il
diffère du texte — repères remplacés par des blocs HTML déjà construits
(ex. tableau des créneaux, `app/email/html.py:render_planning_table`) ;
le texte brut garde sa propre version lisible.
`logo` = (octets, content-type) (voir `app/email/branding.py:
edition_logo`) : ajoute une version HTML au thème de l'appli
(`app/email/html.py`) en alternative au texte brut — le texte reste la
version de référence, envoyée telle quelle si aucun client ne préfère le
@@ -61,7 +68,12 @@ def build_message(
message["Subject"] = subject
message.set_content(body)
message.add_alternative(
render_html(subject=subject, body=body, has_logo=logo is not None),
render_html(
subject=subject,
body=html_body if html_body is not None else body,
has_logo=logo is not None,
blocks=html_blocks,
),
subtype="html",
)
if logo is not None:
@@ -189,6 +201,12 @@ def send(
deliver_many([build_message(to, subject, body, logo=logo, attachments=attachments)])
def send_messages(messages: list[EmailMessage]) -> None:
"""Remet des messages déjà construits (`build_message`) — ex. le
récapitulatif de planning, dont la version HTML porte un tableau."""
deliver_many(messages)
def send_many(
items: Iterable[tuple[str, str, str]], *, logo: tuple[bytes, str] | None = None
) -> None: