mirror of
https://github.com/root-fr/jmap-webmail.git
synced 2026-10-08 16:00:50 +00:00
0a084613d1dc0dee713923db8fa11c5b632c4745
HTML emails that go through SandboxedEmailFrame render inside an <iframe srcDoc=...>. cloneNode creates a fresh browsing context that reloads srcDoc asynchronously — after beforeprint has already fired and the browser has taken its DOM snapshot for printing — so the printed page saw an empty iframe. Plain-text mail was fine because it renders inline with dangerouslySetInnerHTML (which clones cleanly). When building the print overlay, walk each iframe's live contentDocument.body and move its already-rendered children into a plain div on the clone, copying over the computed font so it looks the same as on screen. No innerHTML on the overlay — nodes are cloned directly, preserving the upstream DOMPurify sanitisation. fix(avatar): skip domain favicons for freemail providers Showing Google's G for every gmail.com sender or Yahoo's logo for every yahoo.com sender misrepresents the individual: the domain belongs to the provider, not to the person. Maintain a small freemail denylist (gmail, outlook, icloud, protonmail, proton.me, yahoo, gmx, web.de, orange.fr, free.fr, etc.) that falls back to the initials avatar regardless of whether the favicon service has an icon for the domain.
JMAP Webmail
A modern, privacy-focused webmail client built with Next.js and the JMAP protocol.
Screenshots
Login
Inbox
Email Viewer
Compose
Dark Mode
Settings
Features
Core Email
- Modern UI - Clean, minimalist three-pane layout
- Email Threading - Gmail-style conversation view with inline expansion
- Real-time Updates - Push notifications for new emails via EventSource
- Attachments - Upload and download file attachments
- Search - Full-text email search with pagination
- Draft Auto-save - Never lose your work while composing
Identity & Privacy
- Identity Management - Multiple email identities with custom signatures
- Sub-Addressing - Generate tagged email addresses (user+tag@domain.com) for better organization
- Newsletter Management - RFC 2369 one-click unsubscribe with security validation
- Spam Reporting - Mark emails as spam with bidirectional handling and batch operations
- External Content Blocking - Privacy protection with user-controlled image loading
- Shared Folders - Multi-account access with proper ID namespacing
User Experience
- Keyboard Shortcuts - Navigate efficiently with vim-style hotkeys (j/k, r, f, etc.)
- Context Menus - Right-click for quick actions on emails
- Drag & Drop - Move emails between folders with native HTML5 DnD
- Color Tags - Organize emails with color labels
- Dark Mode - Full dark theme with intelligent email color transformation for readability
- i18n - English, French, Japanese, Spanish, Italian, German, Dutch, and Portuguese language support with auto-detection
- Mobile Responsive - Adaptive single/multi-pane layout for all screen sizes
Tech Stack
- Framework: Next.js 16 with Turbopack
- Styling: Tailwind CSS v4
- State: Zustand
- Protocol: JMAP (RFC 8620)
- i18n: next-intl
Getting Started
# Install dependencies
npm install
# Run development server
npm run dev
Open http://localhost:3000 and connect to your JMAP server.
Configuration
Create a .env.local file:
APP_NAME=Your Webmail
JMAP_SERVER_URL=https://your-jmap-server.com
Runtime vs Build-time Configuration
| Variable | Type | Description |
|---|---|---|
APP_NAME |
Runtime | App name displayed in the UI |
JMAP_SERVER_URL |
Runtime | JMAP server URL (required) |
NEXT_PUBLIC_APP_NAME |
Build-time | Legacy fallback for app name |
NEXT_PUBLIC_JMAP_SERVER_URL |
Build-time | Legacy fallback for server URL |
Runtime variables are read at request time, enabling post-build configuration (ideal for Docker).
Build-time variables are baked into the bundle and require a rebuild to change.
License
MIT
Languages
TypeScript
99.1%
CSS
0.7%
JavaScript
0.1%





