66 lines
2.4 KiB
Python
66 lines
2.4 KiB
Python
"""Magic-link delivery. SMTP when configured, dev log fallback otherwise."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import logging
|
|
import smtplib
|
|
from email.message import EmailMessage
|
|
|
|
from app.settings import settings
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
def magic_link(token: str) -> str:
|
|
return f"{settings.frontend_url.rstrip('/')}/login?token={token}"
|
|
|
|
|
|
def send_magic_link(to_email: str, link: str) -> bool:
|
|
"""Mail the login link. Returns False (logs instead) when SMTP is unset.
|
|
|
|
The plaintext link only ever appears here: service/api logging must
|
|
never include tokens or session ids (see test_auth no-leak test).
|
|
"""
|
|
if not settings.smtp_host:
|
|
logger.info("SMTP not configured; magic link for %s: %s", to_email, link)
|
|
return False
|
|
message = EmailMessage()
|
|
message["Subject"] = "Your kirche-einfach login link"
|
|
message["To"] = to_email
|
|
message["From"] = settings.mail_from or settings.contact_to or to_email
|
|
if settings.contact_to:
|
|
message["Reply-To"] = settings.contact_to
|
|
message.set_content(
|
|
f"Hello,\n\nUse this link to log in (valid 15 minutes, single use):\n{link}\n"
|
|
)
|
|
with smtplib.SMTP(settings.smtp_host, settings.smtp_port, timeout=10) as smtp:
|
|
smtp.starttls()
|
|
if settings.smtp_username:
|
|
smtp.login(settings.smtp_username, settings.smtp_password)
|
|
smtp.send_message(message)
|
|
logger.info("magic link mailed to %s", to_email)
|
|
return True
|
|
|
|
|
|
def send_access_notification(request_id: str, name: str, email: str) -> bool:
|
|
"""Notify CONTACT_TO about a new access request (best effort)."""
|
|
if not settings.smtp_host or not settings.contact_to:
|
|
logger.info("new access request %s from %s <%s>", request_id, name, email)
|
|
return False
|
|
message = EmailMessage()
|
|
message["Subject"] = f"New access request: {name}"
|
|
message["To"] = settings.contact_to
|
|
message["From"] = settings.mail_from or settings.contact_to
|
|
message.set_content(
|
|
f"Name: {name}\nEmail: {email}\nRequest: {request_id}\n"
|
|
)
|
|
try:
|
|
with smtplib.SMTP(settings.smtp_host, settings.smtp_port, timeout=10) as smtp:
|
|
smtp.starttls()
|
|
if settings.smtp_username:
|
|
smtp.login(settings.smtp_username, settings.smtp_password)
|
|
smtp.send_message(message)
|
|
except OSError:
|
|
logger.warning("access-request notification failed for %s", request_id)
|
|
return False
|
|
return True
|