merge: friendlier onboarding emails + deliverability headers

This commit is contained in:
npeter83 2026-06-12 02:05:18 +02:00
commit 0bba654ec5

View file

@ -8,6 +8,7 @@ import logging
import smtplib import smtplib
import ssl import ssl
from email.message import EmailMessage from email.message import EmailMessage
from email.utils import formatdate
from app.config import settings from app.config import settings
@ -18,7 +19,11 @@ def email_enabled() -> bool:
return bool(settings.smtp_host and settings.smtp_user and settings.smtp_password) return bool(settings.smtp_host and settings.smtp_user and settings.smtp_password)
def _send(to: list[str], subject: str, body: str) -> bool: def _admin_contact() -> str | None:
return next(iter(sorted(settings.admin_email_set)), None)
def _send(to: list[str], subject: str, body: str, reply_to: str | None = None) -> bool:
recipients = [e for e in to if e] recipients = [e for e in to if e]
if not recipients: if not recipients:
return False return False
@ -29,6 +34,11 @@ def _send(to: list[str], subject: str, body: str) -> bool:
msg["Subject"] = subject msg["Subject"] = subject
msg["From"] = settings.smtp_from or settings.smtp_user msg["From"] = settings.smtp_from or settings.smtp_user
msg["To"] = ", ".join(recipients) msg["To"] = ", ".join(recipients)
# A real Date and a Reply-To (so it's a conversation, not a no-reply blast) both
# nudge spam filters the right way; reputation still does most of the work.
msg["Date"] = formatdate(localtime=True)
if reply_to:
msg["Reply-To"] = reply_to
msg.set_content(body) msg.set_content(body)
try: try:
with smtplib.SMTP(settings.smtp_host, settings.smtp_port, timeout=20) as s: with smtplib.SMTP(settings.smtp_host, settings.smtp_port, timeout=20) as s:
@ -43,18 +53,23 @@ def _send(to: list[str], subject: str, body: str) -> bool:
def send_access_approved(email: str) -> bool: def send_access_approved(email: str) -> bool:
return _send( admin = _admin_contact()
[email], body = (
"Your Subfeed access is approved", "Hi,\n\n"
"Good news — your access to Subfeed has been approved.\n\n" "Your request to use Subfeed has been approved — welcome aboard.\n\n"
"Sign in with this Google account to start browsing your subscriptions.\n", "Just open Subfeed and sign in with this Google account, and your YouTube\n"
"subscriptions feed will be ready.\n\n"
"If you weren't expecting this, you can ignore the message.\n\n"
"— Subfeed"
+ (f"\n\nQuestions? Just reply to this email ({admin})." if admin else "")
) )
return _send([email], "You're in — your Subfeed access is approved", body, reply_to=admin)
def send_admin_new_request(admins: list[str], requester: str) -> bool: def send_admin_new_request(admins: list[str], requester: str) -> bool:
return _send( body = (
admins, f"{requester} just requested access to Subfeed.\n\n"
"Subfeed: new access request", "Open Subfeed → Settings → Account → Access requests to approve or deny it.\n\n"
f"{requester} has requested access to Subfeed.\n\n" "(Reply to this email to reach the requester directly.)\n"
"Approve or deny it in Settings → Admin.\n",
) )
return _send(admins, f"Subfeed access request from {requester}", body, reply_to=requester)