Add HTML email templates for magic link sign-in
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 49s

Extract inline email body into separate Jinja2 templates
(_email/magic_link.html and .txt) with a styled sign-in
button and fallback plain-text link.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
giles
2026-02-18 15:09:49 +00:00
parent 23b1e35eac
commit dd7fbc89ce
3 changed files with 49 additions and 11 deletions

View File

@@ -5,7 +5,7 @@ import secrets
from datetime import datetime, timedelta, timezone
from typing import Optional, Tuple
from quart import current_app, request, g
from quart import current_app, render_template, request, g
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.orm import selectinload
@@ -45,16 +45,12 @@ async def send_magic_email(to_email: str, link_url: str) -> None:
password = os.getenv("SMTP_PASS")
mail_from = os.getenv("MAIL_FROM") or "no-reply@example.com"
subject = "Your sign-in link"
body = f"""Hello,
site_name = config().get("title", "Rose Ash")
subject = f"Your sign-in link — {site_name}"
Click this link to sign in:
{link_url}
This link will expire in 15 minutes.
If you did not request this, you can ignore this email.
"""
tpl_vars = dict(site_name=site_name, link_url=link_url)
text_body = await render_template("_email/magic_link.txt", **tpl_vars)
html_body = await render_template("_email/magic_link.html", **tpl_vars)
if not host or not username or not password:
# Fallback: log to console
@@ -74,7 +70,8 @@ If you did not request this, you can ignore this email.
msg["From"] = mail_from
msg["To"] = to_email
msg["Subject"] = subject
msg.set_content(body)
msg.set_content(text_body)
msg.add_alternative(html_body, subtype="html")
is_secure = port == 465 # implicit TLS if true
if is_secure: