from __future__ import annotations import logging import re from email.header import decode_header, make_header from typing import Optional LOGGER_NAME = "email_assistant" def setup_logging(level: str) -> None: """ Global logging setup. FastAPI/Uvicorn will inherit this config. """ logging.basicConfig( level=getattr(logging, level.upper(), logging.INFO), format="%(asctime)s %(levelname)s %(name)s - %(message)s", ) def get_logger(name: str = LOGGER_NAME) -> logging.Logger: return logging.getLogger(name) _TAG_RE = re.compile(r"<[^>]+>") def strip_html(html: str) -> str: """ Small HTML -> text helper (keeps dependencies minimal). If you expect complex HTML emails, replace with BeautifulSoup. """ text = _TAG_RE.sub("", html) text = re.sub(r"\r\n|\r", "\n", text) text = re.sub(r"[ \t]+\n", "\n", text) text = re.sub(r"\n{3,}", "\n\n", text) return text.strip() def decode_mime_words(value: Optional[str]) -> str: if not value: return "" try: return str(make_header(decode_header(value))) except Exception: return value def normalize_subject(subject: str) -> str: """ Normalize for threading: remove repeated 'Re:'/'Fwd:' prefixes and trim. """ s = (subject or "").strip() while True: lowered = s.lower() if lowered.startswith("re:"): s = s[3:].strip() continue if lowered.startswith("fwd:"): s = s[4:].strip() continue if lowered.startswith("fw:"): s = s[3:].strip() continue break return s