Skip to content

feat: show domain favicons as sender avatar fallback - #260

Open
salmonumbrella wants to merge 1 commit into
maathimself:mainfrom
salmonumbrella:feat/sender-favicon-fallback
Open

feat: show domain favicons as sender avatar fallback#260
salmonumbrella wants to merge 1 commit into
maathimself:mainfrom
salmonumbrella:feat/sender-favicon-fallback

Conversation

@salmonumbrella

@salmonumbrella salmonumbrella commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds optional sender avatars → domain favicon → initial. The backend proxies favicons from Twenty's favicon service and caches them in Redis; the browser only talks to MailFlow.

Changes

  • Adds GET /api/sender-favicons/:domain — authenticated, rate-limited, preference-gated, no-store
  • Sends the provider only the normalized sender domain, never local parts or user identifiers
  • Accepts only square PNGs ≤64px and ≤64KB, over HTTPS with no redirects and a 5s timeout
  • Resolves subdomains recursively to the registrable domain (mail.notion.sonotion.so), with a public-suffix stoplist and a 10-label cap
  • Caches per domain in Redis: 7-day hits, 6-hour misses, 5-minute transient failures
  • Adds a default-on "Sender favicons" toggle in Settings → Appearance; it fails closed before hydration and the backend enforces it independently
  • Writes nothing to contacts or vCards; adds no dependencies or migrations

Testing

  • Backend: 442 tests (vitest); frontend: 1,143 tests (node --test); lint and build clean on both
  • Exercised against a live account: fallback ordering, disabled-state 404s, subdomain walk, and cache persistence verified in the running app

Contributor License Agreement

By submitting this pull request I confirm that:

  • I have read and agree to the Contributor License Agreement.
  • My contribution is my own original work (or I have identified any
    third-party material and confirmed it is compatible with the CLA).
  • I have the right to submit this contribution under the terms of the CLA.

Sender avatars fall back contact photo -> domain favicon -> initial.
Favicons are proxied from twenty-icons.com and cached in Redis; the
browser only makes same-origin requests, and only the normalized sender
domain (with recursive registrable-parent fallback) reaches the
provider. Governed by a default-on per-user preference that fails
closed before hydration and is enforced independently by the backend.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant