diff --git a/backend/app/mailer.py b/backend/app/mailer.py index 59104ec..e74b1e3 100644 --- a/backend/app/mailer.py +++ b/backend/app/mailer.py @@ -23,9 +23,13 @@ def send_html_email(settings: AppSettings, recipient: str, subject: str, body_ht message.add_alternative(body_html, subtype="html") context = ssl.create_default_context() - with smtplib.SMTP(settings.smtp_host, settings.smtp_port or 587, timeout=20) as server: + security = getattr(settings, "smtp_security", "") or ("starttls" if settings.smtp_use_tls else "none") + port = settings.smtp_port or (465 if security == "ssl" else 587) + smtp_client = smtplib.SMTP_SSL if security == "ssl" else smtplib.SMTP + connection = smtp_client(settings.smtp_host, port, timeout=20, context=context) if security == "ssl" else smtp_client(settings.smtp_host, port, timeout=20) + with connection as server: server.ehlo() - if settings.smtp_use_tls: + if security == "starttls": server.starttls(context=context) server.ehlo() if settings.smtp_username: diff --git a/backend/app/main.py b/backend/app/main.py index 36ebdab..f5fc051 100644 --- a/backend/app/main.py +++ b/backend/app/main.py @@ -88,6 +88,14 @@ Very small, pragmatic auto-migration (no alembic). - supports old schema (join_code/chip_code) and new schema (code/chip) """ + # --- app settings: explicit SMTP security mode (none/starttls/ssl) --- + if not _has_column(db, "app_settings", "smtp_security"): + try: + db.execute(text("ALTER TABLE app_settings ADD COLUMN smtp_security VARCHAR DEFAULT 'starttls'")) + db.commit() + except Exception: + db.rollback() + # --- users.display_name --- if not _has_column(db, "users", "display_name"): try: diff --git a/backend/app/models.py b/backend/app/models.py index 886ff52..4506be6 100644 --- a/backend/app/models.py +++ b/backend/app/models.py @@ -52,6 +52,7 @@ class AppSettings(Base): smtp_from_email: Mapped[str] = mapped_column(String, default="") smtp_from_name: Mapped[str] = mapped_column(String, default="Cluedo HP") smtp_use_tls: Mapped[bool] = mapped_column(Boolean, default=True) + smtp_security: Mapped[str] = mapped_column(String, default="starttls") app_base_url: Mapped[str] = mapped_column(String, default="http://localhost:8081") diff --git a/backend/app/routes/admin.py b/backend/app/routes/admin.py index a9da507..3a5c26a 100644 --- a/backend/app/routes/admin.py +++ b/backend/app/routes/admin.py @@ -163,6 +163,7 @@ def read_smtp_settings(req: Request, db: Session = Depends(get_db)): "smtp_password_configured": bool(settings.smtp_password), "smtp_from_email": settings.smtp_from_email, "smtp_from_name": settings.smtp_from_name, + "smtp_security": getattr(settings, "smtp_security", "starttls") or ("starttls" if settings.smtp_use_tls else "none"), "smtp_use_tls": settings.smtp_use_tls, "app_base_url": settings.app_base_url, } @@ -181,7 +182,11 @@ def update_smtp_settings(req: Request, data: dict, db: Session = Depends(get_db) settings.smtp_username = (data.get("smtp_username") or "").strip() settings.smtp_from_email = (data.get("smtp_from_email") or "").strip() settings.smtp_from_name = (data.get("smtp_from_name") or "Cluedo HP").strip() - settings.smtp_use_tls = bool(data.get("smtp_use_tls", True)) + security = data.get("smtp_security") or ("starttls" if data.get("smtp_use_tls", True) else "none") + if security not in ("none", "starttls", "ssl"): + raise HTTPException(400, "invalid SMTP security mode") + settings.smtp_security = security + settings.smtp_use_tls = security == "starttls" settings.app_base_url = (data.get("app_base_url") or "http://localhost:8081").strip().rstrip("/") if "smtp_password" in data and data.get("smtp_password"): settings.smtp_password = data["smtp_password"] diff --git a/frontend/src/components/AdminSettingsModal.jsx b/frontend/src/components/AdminSettingsModal.jsx index d9aeb00..4bfc841 100644 --- a/frontend/src/components/AdminSettingsModal.jsx +++ b/frontend/src/components/AdminSettingsModal.jsx @@ -7,7 +7,7 @@ import { useLanguage } from "../i18n"; const initial = { smtp_host: "", smtp_port: 587, smtp_username: "", smtp_password: "", - smtp_from_email: "", smtp_from_name: "Cluedo HP", smtp_use_tls: true, + smtp_from_email: "", smtp_from_name: "Cluedo HP", smtp_security: "starttls", app_base_url: window.location.origin, }; @@ -72,7 +72,11 @@ export default function AdminSettingsModal({ open, onClose }) { - +