fix: _eml_to_html retourne le payload QP brut (accents non cassés)

Problème : email.policy.default + get_content() décode déjà les accents
(=C3=A9 → é), puis picnic._decode_and_parse() les re-encode en ASCII
avec errors="replace" → les accents devenaient "?" → date introuvable.

Solution : utiliser l'ancienne API email.message_from_bytes() sans policy
et get_payload(decode=False) pour récupérer le corps brut encore QP-encodé,
exactement comme un fichier .html sauvegardé depuis le mail.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-25 18:27:58 +01:00
parent 8af474c928
commit 93333afffa

View File

@@ -114,24 +114,34 @@ def _parse(file_path: Path, source: str):
def _eml_to_html(file_path: Path) -> str:
"""Extrait la partie HTML d'un fichier .eml (email de confirmation Picnic).
Lit le .eml avec le module email stdlib, parcourt les parties MIME
et retourne le contenu de la première partie text/html trouvée.
Retourne le corps HTML brut, encore encodé en Quoted-Printable (QP),
exactement comme si on lisait un fichier .html sauvegardé depuis le mail.
Le parser Picnic (picnic._decode_and_parse) se charge lui-même du décodage QP.
Pourquoi ne pas utiliser policy.default / get_content() ?
Parce que cette API décode déjà les accents (=C3=A9 → é), ce qui empêche
picnic.py de les retrouver via sa propre pipeline QP → UTF-8.
Args:
file_path: Chemin vers le fichier .eml.
Returns:
Contenu HTML sous forme de chaîne.
Corps HTML brut (QP-encodé) sous forme de chaîne ASCII.
Raises:
ValueError: Si aucune partie HTML n'est trouvée dans le .eml.
"""
raw = file_path.read_bytes()
msg = email.message_from_bytes(raw, policy=policy.default)
# On utilise l'ancienne API (sans policy.default) pour garder le payload brut
msg = email.message_from_bytes(raw)
for part in msg.walk():
if part.get_content_type() == "text/html":
return part.get_content()
# decode=False → payload brut, encore QP-encodé, en str ASCII
payload = part.get_payload(decode=False)
if isinstance(payload, bytes):
return payload.decode("ascii", errors="replace")
return payload # déjà une str
raise ValueError(
f"Aucune partie HTML trouvée dans le fichier .eml : {file_path.name}"