be81fe52cf
Check Cross-Plugin Imports / check (push) Has been cancelled
serializers.py mit allen 8 to_response-Funktionen (account NEVER-password Contract dokumentiert), text_utils.py mit extract_email_addresses+_strip_html als pure functions. Re-Export via noqa F401 in services.py — alle Consumer unveraendert. services.py jetzt 2786 Z. (von 3087). Beweis: mail+sig_label_routes 51/51 passed nach ruff --fix; ruff clean.
36 lines
949 B
Python
36 lines
949 B
Python
"""Text utilities for the Mail plugin.
|
|
|
|
Extracted from services.py as part of the God-object split (BUG-018 pilot).
|
|
Re-exported by ``app.plugins.builtins.mail.services``.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import re
|
|
|
|
|
|
def extract_email_addresses(text: str) -> list[str]:
|
|
"""Extract email addresses from a text string."""
|
|
if not text:
|
|
return []
|
|
return re.findall(r"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}", text)
|
|
|
|
|
|
def _strip_html(html: str) -> str:
|
|
"""Simple HTML to text conversion for plain text fallback."""
|
|
if not html:
|
|
return ""
|
|
# Remove tags
|
|
text = re.sub(r"<[^>]+>", "", html)
|
|
# Replace HTML entities
|
|
text = (
|
|
text.replace(" ", " ")
|
|
.replace("&", "&")
|
|
.replace("<", "<")
|
|
.replace(">", ">")
|
|
.replace(""", '"')
|
|
.replace("'", "'")
|
|
)
|
|
# Collapse whitespace
|
|
return re.sub(r"\s+", " ", text).strip()
|