Matthieu MALVACHE 0a084613d1 fix(print): inline the sandboxed iframe body before print
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.
2026-04-17 14:22:17 +02:00
2026-03-16 12:41:37 +01:00

JMAP Webmail

A modern, privacy-focused webmail client built with Next.js and the JMAP protocol.

Screenshots

Login

Login

Inbox

Inbox

Email Viewer

Email Viewer

Compose

Compose

Dark Mode

Dark Mode

Settings

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

S
Description
Modern JMAP webmail client built for Stalwart Mail Server. Privacy-focused, responsive, with real-time updates.
Readme MIT
6.9 MiB
Languages
TypeScript 99.1%
CSS 0.7%
JavaScript 0.1%