merge: friendlier onboarding emails + deliverability headers

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

View file

@ -8,6 +8,7 @@ import logging
import smtplib
import ssl
from email.message import EmailMessage
from email.utils import formatdate
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)
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]
if not recipients:
return False
@ -29,6 +34,11 @@ def _send(to: list[str], subject: str, body: str) -> bool:
msg["Subject"] = subject
msg["From"] = settings.smtp_from or settings.smtp_user
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)
try:
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:
return _send(
[email],
"Your Subfeed access is approved",
"Good news — your access to Subfeed has been approved.\n\n"
"Sign in with this Google account to start browsing your subscriptions.\n",
admin = _admin_contact()
body = (
"Hi,\n\n"
"Your request to use Subfeed has been approved — welcome aboard.\n\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:
return _send(
admins,
"Subfeed: new access request",
f"{requester} has requested access to Subfeed.\n\n"
"Approve or deny it in Settings → Admin.\n",
body = (
f"{requester} just requested access to Subfeed.\n\n"
"Open Subfeed → Settings → Account → Access requests to approve or deny it.\n\n"
"(Reply to this email to reach the requester directly.)\n"
)
return _send(admins, f"Subfeed access request from {requester}", body, reply_to=requester)