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:
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user