Logo in system mail; "don't ask for the 2FA code on this device"

System mail: the password-reset email (and the admin panel's test email) now
opens with the Ultimo logo, centered. It is a PNG rendered from
icons/ultimo-logo.svg and embedded in the message (multipart/related, cid:),
so it shows where remote images are blocked and in clients that do not
render SVG. The PNG is listed in package-data so the Docker image carries it.

Trusted devices: a 2FA sign-in offers "Don't ask for the code on this device
in future". Ticked with a correct code, the browser gets its own HttpOnly
trusted-device cookie (token in Redis, 90 days, renewed on use); later
sign-ins to the same account from that browser need only the password. Other
accounts and browsers are unaffected. The trust is revoked on a password
reset, when 2FA is turned off, and when an admin blocks or deletes the user;
signing out keeps it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-01 21:02:44 +02:00
co-authored by Claude Opus 5.5
parent d1f6d183e0
commit 165442d897
14 changed files with 334 additions and 12 deletions
@@ -307,3 +307,26 @@ async def test_admin_configures_system_mail_without_ever_seeing_the_password(
test = await c.post("/api/admin/mail/test", json={"to": "me@example.com"})
assert test.status_code == 200
assert ctx.sent.mails[-1][:2] == ("me@example.com", "Ultimo Email test message")
async def test_reset_mail_carries_the_logo_inline(monkeypatch: pytest.MonkeyPatch) -> None:
"""The logo is a PNG inside the message (cid:), not a remote image or SVG."""
import aiosmtplib
from app.identity import mailer
sent: list[object] = []
async def fake_send(msg: object, **kwargs: object) -> None:
sent.append(msg)
monkeypatch.setattr(aiosmtplib, "send", fake_send)
subject, text, html = mailer.reset_mail("https://mail.example.com/x", "a@test.local")
await mailer.send_mail(CFG, "to@example.com", subject, text, html)
msg = sent[0]
parts = {p.get_content_type(): p for p in msg.walk()} # type: ignore[attr-defined]
assert {"multipart/alternative", "text/plain", "multipart/related", "text/html"} <= set(parts)
logo = parts["image/png"]
assert logo["Content-ID"] == "<ultimo-logo@ultimo.email>"
assert logo.get_payload(decode=True).startswith(b"\x89PNG")
assert 'src="cid:ultimo-logo@ultimo.email"' in parts["text/html"].get_content()