Skip to content

root-fr/jmap-webmail

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

42 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

JMAP Webmail

A webmail client for Stalwart Mail Server, built with Next.js and the JMAP protocol.

Why Stalwart?

Stalwart is a mail server written in Rust with native JMAP support, not IMAP/SMTP with JMAP added as an afterthought. It handles JMAP, IMAP, SMTP, and ManageSieve. Self-hosted, no third-party dependencies.

Stalwart on GitHub | Documentation

Features

Email

  • Read, compose, reply, reply-all, and forward
  • HTML rendering with DOMPurify sanitization
  • Attachment upload and download
  • Draft auto-save with discard confirmation
  • Threading with inline expansion
  • Mark as read/unread, star/unstar
  • Archive and delete with configurable behavior
  • Color tags/labels
  • Search with JMAP filter panel, search chips, cross-mailbox queries
  • Virtual scrolling for large lists

Interface

  • Three-pane layout with dark and light themes
  • Responsive (desktop sidebar + mobile bottom tab bar)
  • Keyboard shortcuts
  • Drag-and-drop email organization
  • Right-click context menus
  • Animations that respect prefers-reduced-motion
  • Infinite scroll pagination
  • Toast notifications with undo support
  • Form validation with shake feedback
  • Safe area insets for notched devices
  • Screen reader live regions

Real-time

  • Push notifications via JMAP EventSource
  • Live unread counts
  • Email arrival notifications
  • Connection status indicator

Identity management

  • Multiple sender identities with per-identity signatures
  • Sub-addressing (user+tag@domain.com) with tag suggestions
  • Identity badges in viewer and list

Address book

  • Contact management with search and filtering
  • JMAP server sync (RFC 9553/9610) with local fallback
  • Email autocomplete in composer
  • Contact groups with group expansion
  • vCard import/export (RFC 6350) with duplicate detection
  • Bulk operations (multi-select, delete, group add, export)

Calendar

  • JMAP Calendar (RFC 8984) with capability detection
  • Month, week, day, and agenda views
  • Event create, edit, delete with recurrence and reminders
  • Participant scheduling with iTIP invitations and RSVP
  • Inline calendar invitation banner in email viewer (.ics detection, RSVP, import)
  • Multi-day events, column-based overlap layout
  • Mini-calendar sidebar with calendar visibility toggles
  • Locale-aware date formatting
  • Settings for first day of week, time format (12h/24h), default view
  • Drag-and-drop rescheduling with time snap
  • Click-drag on empty slots to create events
  • Resize events by dragging (15-minute snap)
  • Double-click quick create
  • Event duplication (+1 day offset)
  • Recurring event edit/delete scope (this, this and following, all)
  • iCalendar (.ics) file import with preview
  • Real-time updates via JMAP push
  • Event notifications with configurable sound

Email templates

  • Reusable templates organized by category
  • Placeholder variables ({{recipientName}}, {{date}}, etc.) with auto-fill
  • Template picker in compose toolbar with search and filter
  • Template manager in settings

Email filters

  • Server-side filtering with JMAP Sieve Scripts (RFC 9661)
  • Visual rule builder: conditions (From, To, Subject, Size, Body...) and actions (Move, Forward, Mark read, Star, Discard, Reject...)
  • Raw Sieve editor with syntax validation
  • Auto-save with rollback on failure
  • Drag-and-drop rule reordering
  • Only shown when the server supports Sieve

Vacation responder

  • JMAP VacationResponse with date range scheduling
  • Settings tab for message configuration
  • Sidebar indicator when active

Security and privacy

  • External content blocked by default
  • Trusted senders list for automatic image loading
  • HTML sanitization (DOMPurify)
  • SPF/DKIM/DMARC status indicators
  • Session-based auth, no password storage by default
  • TOTP two-factor authentication
  • "Remember me" with AES-256-GCM encrypted httpOnly cookie (opt-in)
  • OAuth2/OIDC with PKCE for SSO (opt-in, RP-initiated logout)
  • External IdP support (Keycloak, Authentik) via configurable issuer URL
  • CORS misconfiguration detection with detailed error messages
  • Shared folder support
  • Newsletter unsubscribe (RFC 2369)
  • CSP, X-Content-Type-Options, X-Frame-Options, Referrer-Policy headers

Internationalization

  • 8 languages: English, French, Japanese, Spanish, Italian, German, Dutch, Portuguese
  • Automatic browser language detection
  • Persistent language preference

Deployment

  • Pre-built Docker images on Docker Hub and GHCR (amd64/arm64)
  • Multi-stage build with standalone output
  • Runtime environment variables (no rebuild needed)
  • Health check endpoint
  • Structured logging (text/JSON)
  • Update check on startup (server logs only, no client exposure)

Tech stack

Getting started

Prerequisites

  • Node.js 18+
  • A JMAP-compatible mail server (Stalwart recommended)

Installation

git clone https://github.com/root-fr/jmap-webmail.git
cd jmap-webmail
npm install
cp .env.example .env.local

Configuration

Edit .env.local:

# App name displayed in the UI
APP_NAME=My Webmail

# Your JMAP server URL (required)
JMAP_SERVER_URL=https://mail.example.com

These are runtime environment variables, read at request time. Docker deployments can be configured without rebuilding. Legacy NEXT_PUBLIC_* variables still work as fallbacks.

OAuth2/OIDC (optional)

To enable SSO login alongside Basic Auth:

OAUTH_ENABLED=true
OAUTH_CLIENT_ID=webmail
OAUTH_CLIENT_SECRET=              # optional, for confidential clients
OAUTH_ISSUER_URL=                 # optional, for external IdPs (Keycloak, Authentik)

Endpoints are auto-discovered via .well-known/oauth-authorization-server or .well-known/openid-configuration. If your JMAP server delegates auth to an external IdP, set OAUTH_ISSUER_URL to the IdP's base URL (e.g., https://keycloak.example.com/realms/mail).

Remember me (optional)

To enable "Remember me" for Basic Auth login:

SESSION_SECRET=your-secret-key    # Generate with: openssl rand -base64 32

When set, a "Remember me" checkbox appears on the login form. Credentials are encrypted with AES-256-GCM and stored in an httpOnly cookie (30-day expiry).

Development

npm run dev        # Start dev server
npm run typecheck  # Type checking
npm run lint       # Linting

Production

npm run build
npm start

Docker

# Pre-built image
docker run -p 3000:3000 -e JMAP_SERVER_URL=https://mail.example.com rootfr/jmap-webmail:latest

# From GHCR
docker run -p 3000:3000 -e JMAP_SERVER_URL=https://mail.example.com ghcr.io/root-fr/jmap-webmail:latest

# With docker compose
cp .env.example .env.local
# Edit .env.local with your JMAP_SERVER_URL
docker compose up -d

# Build from source
docker build -t jmap-webmail .
docker run -p 3000:3000 -e JMAP_SERVER_URL=https://mail.example.com jmap-webmail

Keyboard shortcuts

Key Action
j / k Navigate between emails
Enter / o Open selected email
Esc Close viewer / deselect
c Compose new email
r Reply
R / a Reply all
f Forward
s Toggle star
e Archive
# / Delete Delete
u Mark as unread
/ Focus search
x Expand/collapse thread
Ctrl+Shift+T Insert template
? Show shortcuts help

Screenshots

Login Login

Inbox Inbox

Email Viewer Email Viewer

Compose Compose

Dark Mode Dark Mode

Settings Settings

Contributing

See CONTRIBUTING.md for guidelines.

Roadmap

See ROADMAP.md for planned features.

Acknowledgments

License

MIT. See LICENSE.

About

Modern JMAP webmail client built for Stalwart Mail Server. Privacy-focused, responsive, with real-time updates.

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Packages

 
 
 

Languages