Kansho/backend/mailer.py
Lars 89d149684e
Some checks failed
Deploy Development / deploy (push) Successful in 58s
Test Suite / pytest-backend (push) Failing after 3m11s
Test Suite / smoke-dev (push) Successful in 0s
Test Suite / frontend-build (push) Successful in 16s
Add username login and expiring reset links so accounts stay recoverable.
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-12 20:00:17 +02:00

65 lines
2.1 KiB
Python

"""Operational mail for account links. No dialogue content, no model egress."""
from __future__ import annotations
import logging
import os
import smtplib
from email.message import EmailMessage
from env_loader import env_flag, runtime_env
log = logging.getLogger("kansho.mail")
OUTBOX: list[dict] = []
class MailNotConfigured(RuntimeError):
"""SMTP is required and neither configured nor in the development log path."""
def clear_outbox() -> None:
OUTBOX.clear()
def smtp_configured() -> bool:
return bool((os.environ.get("SMTP_HOST") or "").strip() and (os.environ.get("SMTP_FROM") or "").strip())
def send_mail(recipients: list[str], subject: str, body: str) -> None:
cleaned: list[str] = []
for item in recipients:
address = (item or "").strip().lower()
if address and address not in cleaned:
cleaned.append(address)
if not cleaned:
raise MailNotConfigured("Mailversand ist nicht konfiguriert")
if env_flag("KANSHO_FAKE_MAIL"):
OUTBOX.append({"to": cleaned, "subject": subject, "body": body})
return
host = (os.environ.get("SMTP_HOST") or "").strip()
sender = (os.environ.get("SMTP_FROM") or "").strip()
if not host or not sender:
if runtime_env() == "development":
log.warning("Kansho mail (development, SMTP fehlt): %s", body)
return
raise MailNotConfigured("Mailversand ist nicht konfiguriert")
port = int((os.environ.get("SMTP_PORT") or "587").strip() or "587")
user = (os.environ.get("SMTP_USER") or "").strip()
password = os.environ.get("SMTP_PASSWORD") or ""
message = EmailMessage()
message["Subject"] = subject
message["From"] = sender
message["To"] = ", ".join(cleaned)
message.set_content(body)
if port == 465:
with smtplib.SMTP_SSL(host, port, timeout=20) as smtp:
if user:
smtp.login(user, password)
smtp.send_message(message)
return
with smtplib.SMTP(host, port, timeout=20) as smtp:
smtp.starttls()
if user:
smtp.login(user, password)
smtp.send_message(message)