Digest polish: honest on-site wording, one-tap opt-in after sign-in, List-Unsubscribe

* On-site end-cap now says "You're caught up for now." — honest, since Highlights
  refreshes through the day (the email keeps the daily "see you tomorrow").
* Anonymous "Get tomorrow's brief by email" now honors the one-tap promise:
  sets a pending flag, opens sign-in, and auto-enables once auth resolves.
* Email compliance (RFC 2369/8058): send_email takes optional headers; the digest
  sets List-Unsubscribe + List-Unsubscribe-Post=One-Click, and a POST
  /api/digest/unsubscribe handles native one-click (GET still serves the page).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
jay
2026-06-09 16:35:05 -04:00
parent cf5cbb33c0
commit 1956d7fd23
6 changed files with 42 additions and 12 deletions
+4
View File
@@ -230,4 +230,8 @@ def test_digest_toggle_and_unsubscribe(tmp_path, monkeypatch):
assert "invalid" in TestClient(app).get(f"/api/digest/unsubscribe?u={uid}&t=nope").text.lower()
assert "unsubscribed" in TestClient(app).get(f"/api/digest/unsubscribe?u={uid}&t={tok}").text.lower()
assert tc.get("/api/auth/me").json()["digest_enabled"] is False
# RFC 8058 one-click POST also disables
tc.post("/api/account/digest", json={"enabled": True})
assert TestClient(app).post(f"/api/digest/unsubscribe?u={uid}&t={tok}").json() == {"ok": True}
assert tc.get("/api/auth/me").json()["digest_enabled"] is False
assert TestClient(app).post("/api/account/digest", json={"enabled": True}).status_code == 401 # gated
+5 -2
View File
@@ -28,13 +28,16 @@ def test_build_digest_is_calm_and_dated():
def test_send_due_digests_sends_dedupes_and_skips(monkeypatch, tmp_path):
sent = []
monkeypatch.setattr(email_send, "send_email", lambda to, subj, text, html=None: sent.append(to))
monkeypatch.setattr(email_send, "send_email",
lambda to, subj, text, html=None, headers=None, **k: sent.append((to, headers)))
c = connect(str(tmp_path / "d.db")); init_db(c)
date = _seed(c, n=5)
monkeypatch.setattr(digest, "local_today", lambda: date)
# force=True bypasses the morning window
assert digest.send_due_digests(c, force=True) == 1
assert sent == ["reader@x.com"]
assert sent[0][0] == "reader@x.com"
hdrs = sent[0][1] # RFC 8058 one-click unsubscribe headers present
assert "List-Unsubscribe" in hdrs and hdrs["List-Unsubscribe-Post"] == "List-Unsubscribe=One-Click"
assert c.execute("SELECT item_count FROM digest_sends WHERE user_id=1").fetchone()[0] == 5
# dedupe: a second run sends nothing
assert digest.send_due_digests(c, force=True) == 0