""" Email notifier — sends report emails via the SMTP account configured by the operator's organisation in Settings. Falls back to "not configured" so the frontend can mailto: as last resort. """ import logging import smtplib from email.message import EmailMessage from email.utils import formataddr from services import settings_store log = logging.getLogger(__name__) def smtp_configured() -> bool: s = settings_store.SETTINGS return bool(s.get("smtp_host") and s.get("smtp_from")) def send_email(to_addr: str, subject: str, body: str) -> tuple[bool, str]: """Send a plain-text email through the configured SMTP account. Returns (ok, detail). On failure detail carries the error message.""" s = settings_store.SETTINGS if not smtp_configured(): return False, "SMTP not configured" msg = EmailMessage() msg["From"] = formataddr((s.get("smtp_from_name") or "AidsMonitoring", s["smtp_from"])) msg["To"] = to_addr msg["Subject"] = subject msg.set_content(body) try: host = s["smtp_host"] port = int(s.get("smtp_port") or 587) if s.get("smtp_use_tls"): with smtplib.SMTP(host, port, timeout=15) as srv: srv.starttls() if s.get("smtp_user") and s.get("smtp_password"): srv.login(s["smtp_user"], s["smtp_password"]) srv.send_message(msg) else: with smtplib.SMTP_SSL(host, port, timeout=15) as srv: if s.get("smtp_user") and s.get("smtp_password"): srv.login(s["smtp_user"], s["smtp_password"]) srv.send_message(msg) return True, "sent" except Exception as e: log.warning("SMTP send failed to %s: %s", to_addr, e) return False, str(e)