chore: update version to 1.5.0
@@ -0,0 +1,124 @@
|
|||||||
|
# Features
|
||||||
|
|
||||||
|
## Mail
|
||||||
|
|
||||||
|
- Read, compose, reply, reply-all, and forward with a Tiptap rich text editor (inline images, drag-and-drop embedding)
|
||||||
|
- Gmail-style threading with inline expansion and an optional conversation toggle
|
||||||
|
- Unified mailbox view across all connected accounts
|
||||||
|
- Draft auto-save with identity preservation
|
||||||
|
- Attachment upload, download, and inline preview; forgotten-attachment warning
|
||||||
|
- Full-text search with JMAP filter panel, search chips, wildcards, OR conditions, and cross-mailbox queries
|
||||||
|
- Batch operations — multi-select, archive, delete, move, tag
|
||||||
|
- Archive modes — direct, by year, or by month
|
||||||
|
- Multi-tag support with color labels, reordering, and drag-and-drop assignment
|
||||||
|
- Star/unstar with configurable mark-as-read delay
|
||||||
|
- Virtual scrolling for large mailboxes
|
||||||
|
- Quick reply, hover actions, sender avatars (favicon-based), and recipient popovers
|
||||||
|
- Plain-text composer mode and Reply-To support
|
||||||
|
- TNEF (`winmail.dat`) extraction and `message/rfc822` unwrapping
|
||||||
|
- Folder management with icon picker, subfolders, and sidebar counts
|
||||||
|
- Print directly from the viewer
|
||||||
|
- Browser history sync for back/forward navigation
|
||||||
|
|
||||||
|
## Calendar
|
||||||
|
|
||||||
|
- Month, week, day, and agenda views with a mini-calendar sidebar and task list
|
||||||
|
- Drag-to-reschedule, click-drag creation, and edge-resize with 15-minute snap
|
||||||
|
- Recurring events with scoped edit/delete (this / this and following / all)
|
||||||
|
- iMIP invitations on create and update (RFC 5545 / 6047), organizer/attendee UI, and RSVP with trust assessment
|
||||||
|
- Inline calendar invitations in the email viewer — auto-detect `.ics`, RSVP, import
|
||||||
|
- iCalendar import with preview, bulk create, and UID deduplication
|
||||||
|
- iCal / webcal subscriptions with editing and batch import
|
||||||
|
- Auto-generated birthday calendar from contacts
|
||||||
|
- Virtual locations (video conference URLs) as first-class event fields
|
||||||
|
- Task management with due dates, priority, and completion status
|
||||||
|
- Shared calendars with CalDAV discovery and multi-account home resolution
|
||||||
|
- Week numbers, event hover preview, notifications with sound picker
|
||||||
|
- Real-time sync via JMAP push
|
||||||
|
|
||||||
|
## Contacts
|
||||||
|
|
||||||
|
- JMAP sync (RFC 9553 / 9610) with local fallback
|
||||||
|
- Multiple address books with drag-and-drop between books
|
||||||
|
- Contact groups with member management
|
||||||
|
- vCard import/export (RFC 6350) with duplicate detection
|
||||||
|
- Trusted senders stored in a dedicated JMAP address book
|
||||||
|
- Autocomplete in the composer (To / Cc / Bcc)
|
||||||
|
|
||||||
|
## Filters & Templates
|
||||||
|
|
||||||
|
- Server-side filters via JMAP Sieve Scripts (RFC 9661)
|
||||||
|
- Visual rule builder with expanded view; conditions (From, To, Subject, Size, Body…) and actions (Move, Forward, Star, Discard…)
|
||||||
|
- Preserves rules authored in other clients
|
||||||
|
- Raw Sieve editor with syntax validation
|
||||||
|
- Vacation responder with date range scheduling
|
||||||
|
- Reusable email templates with placeholder auto-fill (`{{recipientName}}`, `{{date}}`, …)
|
||||||
|
|
||||||
|
## Files
|
||||||
|
|
||||||
|
- JMAP FileNode browser (Stalwart native cloud storage)
|
||||||
|
- Streamed WebDAV PUT upload and folder upload with progress tracking
|
||||||
|
- Dynamic upload limits based on server configuration
|
||||||
|
- Grid and list views with sorting by name, size, or date
|
||||||
|
- Previews for images, text, audio, and video
|
||||||
|
- Clipboard operations (cut, copy, paste, duplicate), favorites, and recent files
|
||||||
|
|
||||||
|
## Security & Privacy
|
||||||
|
|
||||||
|
- External content blocked by default, with a trusted senders list
|
||||||
|
- HTML sanitization via DOMPurify
|
||||||
|
- S/MIME — manage certificates, sign, encrypt, decrypt, and verify; legacy 3DES / PBE support; per-account key isolation
|
||||||
|
- SPF / DKIM / DMARC status indicators
|
||||||
|
- OAuth2 / OIDC with PKCE (Keycloak, Authentik, or built-in), OAuth-only mode, OAuth app passwords, and non-interactive SSO for embedded deployments
|
||||||
|
- TOTP two-factor authentication
|
||||||
|
- Account security panel for password and 2FA management via the Stalwart admin API
|
||||||
|
- Optional "Remember me" via AES-256-GCM encrypted httpOnly cookie
|
||||||
|
- Enforced CSP with per-request nonce, SSRF redirect validation, PDF iframe sandbox, and IP spoofing prevention
|
||||||
|
- Plugin hardening with dangerous-pattern detection and admin approval
|
||||||
|
- Newsletter unsubscribe (RFC 2369)
|
||||||
|
|
||||||
|
## Interface
|
||||||
|
|
||||||
|
- Three-pane layout with resizable columns
|
||||||
|
- Dark and light themes with intelligent email color transformation
|
||||||
|
- Responsive desktop, tablet, and mobile layouts
|
||||||
|
- Full keyboard navigation
|
||||||
|
- Drag-and-drop email organization and tag assignment
|
||||||
|
- Interactive guided tour for new users
|
||||||
|
- Right-click context menus, toast notifications with undo
|
||||||
|
- Customizable toolbar position, favicon, and login branding
|
||||||
|
- Pinnable sidebar apps with drag-and-drop reordering
|
||||||
|
- Encrypted settings sync across devices
|
||||||
|
- Storage quota display
|
||||||
|
- WCAG AA contrast, reduced-motion support, focus trap, and screen reader live regions
|
||||||
|
|
||||||
|
## Internationalization
|
||||||
|
|
||||||
|
14 languages: English · Français · 日本語 · Español · Italiano · Deutsch · Nederlands · Português · Русский · 한국어 · Polski · Latviešu · 简体中文 · Українська
|
||||||
|
|
||||||
|
Automatic browser detection with persistent preference. Configurable locale URL prefix via `NEXT_PUBLIC_LOCALE_PREFIX`.
|
||||||
|
|
||||||
|
## Identity & Multi-Account
|
||||||
|
|
||||||
|
- Up to 5 simultaneous accounts with instant switching and per-account session persistence
|
||||||
|
- Account switcher with connection status and default account selection
|
||||||
|
- Multiple sender identities with per-identity signatures, automatic sync, and badges in viewer/list
|
||||||
|
- Sub-addressing (`user+tag@domain.com`) with contextual tag suggestions
|
||||||
|
- Shared folders across accounts
|
||||||
|
- Optional custom JMAP endpoints on the login form (`ALLOW_CUSTOM_JMAP_ENDPOINT`)
|
||||||
|
|
||||||
|
## Admin & Extensibility
|
||||||
|
|
||||||
|
- Stalwart admin dashboard with dedicated policy sections
|
||||||
|
- Plugin system — schema-driven config UI, render and intercept hooks, `onAvatarResolve` and i18n APIs, calendar event slots, and managed policy enforcement
|
||||||
|
- Themes — upload, enforce, and manage admin-controlled themes as ZIP bundles
|
||||||
|
- Extension marketplace — browse and install plugins and themes from a configurable directory (`EXTENSION_DIRECTORY_URL`)
|
||||||
|
- Bundled plugins including Jitsi Meet calendar integration
|
||||||
|
|
||||||
|
## Operations
|
||||||
|
|
||||||
|
- Progressive Web App with service worker, install prompt, and dynamic manifest
|
||||||
|
- Automatic update check with server-side logging of new releases
|
||||||
|
- Structured logging (`text` or `json`) with category-based levels
|
||||||
|
- Release (`main`) and development (`dev`) Docker images on GHCR
|
||||||
|
- Demo mode with fixture data — no mail server required
|
||||||
@@ -8,8 +8,7 @@
|
|||||||
|
|
||||||
# Bulwark Webmail
|
# Bulwark Webmail
|
||||||
|
|
||||||
A modern, self-hosted webmail client for [Stalwart Mail Server](https://stalw.art/).<br/>
|
A modern, self-hosted webmail client for [Stalwart Mail Server](https://stalw.art/), built with Next.js and the JMAP protocol.
|
||||||
Built with Next.js and the JMAP protocol.
|
|
||||||
|
|
||||||
[](LICENSE)
|
[](LICENSE)
|
||||||
[](https://discord.gg/tYCujymGrT)
|
[](https://discord.gg/tYCujymGrT)
|
||||||
@@ -22,228 +21,56 @@ Built with Next.js and the JMAP protocol.
|
|||||||
|
|
||||||
## Screenshots
|
## Screenshots
|
||||||
|
|
||||||
|
<picture>
|
||||||
|
<source media="(prefers-color-scheme: dark)" srcset="screenshots/mail-dark.png" />
|
||||||
|
<img src="screenshots/mail-white.png" alt="Mail view" width="100%" />
|
||||||
|
</picture>
|
||||||
|
|
||||||
<table>
|
<table>
|
||||||
<tr>
|
<tr>
|
||||||
<td width="50%">
|
<td width="50%"><img src="screenshots/calendar.png" alt="Calendar" /></td>
|
||||||
|
<td width="50%"><img src="screenshots/contacts.png" alt="Contacts" /></td>
|
||||||
<img src="screenshots/inbox.png" width="100%" alt="Inbox - three-pane layout with sidebar, email list, and viewer (dark mode)">
|
|
||||||
|
|
||||||
**Mail** - Three-pane layout with sidebar, email list, and viewer
|
|
||||||
|
|
||||||
</td>
|
|
||||||
<td width="50%">
|
|
||||||
|
|
||||||
<img src="screenshots/calendar.png" width="100%" alt="Calendar">
|
|
||||||
|
|
||||||
**Calendar** - Month, week, day, and agenda views with event management
|
|
||||||
|
|
||||||
</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td width="50%">
|
<td><sub><b>Calendar</b> — month, week, day, and agenda views with drag-to-reschedule, iMIP invitations, and CalDAV subscriptions.</sub></td>
|
||||||
|
<td><sub><b>Contacts</b> — multiple address books, groups, vCard import/export, and autocomplete in the composer.</sub></td>
|
||||||
<img src="screenshots/contacts.png" width="100%" alt="Contacts">
|
</tr>
|
||||||
|
<tr>
|
||||||
**Contacts** - Contact management with groups and vCard support
|
<td><img src="screenshots/theme.png" alt="Themes" /></td>
|
||||||
|
<td><img src="screenshots/plugins.png" alt="Plugins" /></td>
|
||||||
</td>
|
</tr>
|
||||||
<td width="50%">
|
<tr>
|
||||||
|
<td><sub><b>Themes</b> — bundled color themes or upload your own as ZIP bundles; admins can enforce presets.</sub></td>
|
||||||
<img src="screenshots/files.png" width="100%" alt="File browser">
|
<td><sub><b>Plugins</b> — extend the client with bundled or third-party plugins installed from a .zip file.</sub></td>
|
||||||
|
</tr>
|
||||||
**Files** - Cloud file browser with upload, preview, and folder navigation
|
<tr>
|
||||||
|
<td><img src="screenshots/mail-white.png" alt="Light mode" /></td>
|
||||||
</td>
|
<td><img src="screenshots/settings.png" alt="Settings" /></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><sub><b>Light mode</b> — full theme support with intelligent color transformation for HTML emails.</sub></td>
|
||||||
|
<td><sub><b>Settings</b> — appearance, identities, filters, templates, security, and more.</sub></td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<details>
|
## Overview
|
||||||
<summary>More screenshots</summary>
|
|
||||||
<table>
|
|
||||||
<tr>
|
|
||||||
<td width="50%">
|
|
||||||
|
|
||||||
<img src="screenshots/inbox%20whitemode.png" width="100%" alt="Inbox - light mode">
|
Bulwark is a full webmail suite — not just an inbox. It bundles the four apps most self-hosters end up wanting on the same login:
|
||||||
|
|
||||||
**Light mode** - Full theme support with intelligent color transformation
|
- **Mail** — threading, unified inbox, full-text search, Sieve filters, S/MIME, templates
|
||||||
|
- **Calendar** — month/week/day/agenda, recurring events, iMIP invitations, CalDAV subscriptions
|
||||||
|
- **Contacts** — multiple address books, groups, vCard import/export
|
||||||
|
- **Files** — Stalwart's JMAP FileNode storage with previews and folder upload
|
||||||
|
|
||||||
</td>
|
Plus the infrastructure around them: OAuth2 / OIDC SSO, TOTP 2FA, multi-account (up to 5 at once), 14 languages, PWA install, dark/light themes, a plugin system with an extension marketplace, and a Stalwart admin dashboard.
|
||||||
<td width="50%">
|
|
||||||
|
|
||||||
<img src="screenshots/settings.png" width="100%" alt="Settings">
|
Full feature list: **[FEATURES.md](FEATURES.md)**.
|
||||||
|
|
||||||
**Settings** - Appearance, identities, filters, templates, and more
|
|
||||||
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td width="50%">
|
|
||||||
|
|
||||||
<img src="screenshots/login.png" width="100%" alt="Login page">
|
|
||||||
|
|
||||||
**Login** - Configurable branding with OAuth2/OIDC and 2FA support
|
|
||||||
|
|
||||||
</td>
|
|
||||||
<td width="50%">
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</details>
|
|
||||||
|
|
||||||
## Features
|
|
||||||
|
|
||||||
### Mail
|
|
||||||
|
|
||||||
- **Read, compose, reply, reply-all, forward** with rich HTML rendering and a Tiptap-based rich text editor (inline image upload, drag-and-drop embedding)
|
|
||||||
- **Threading** - Gmail-style inline expansion with thread navigation; optional conversation threading toggle
|
|
||||||
- **Unified mailbox** - view emails across all accounts in a single list
|
|
||||||
- **Draft auto-save** with discard confirmation; full draft editing with identity preservation
|
|
||||||
- **Attachments** - upload, download, and inline preview; attachment-keyword warning if a file is forgotten
|
|
||||||
- **Search** - full-text with JMAP filter panel, search chips, cross-mailbox queries, wildcard support, and OR conditions
|
|
||||||
- **Batch operations** - multi-select with checkboxes, archive, delete, move, tag
|
|
||||||
- **Archive modes** - archive directly or organize archived mail by year or month
|
|
||||||
- **Print** emails directly from the viewer
|
|
||||||
- **Answered/forwarded status icons** in email list and thread views
|
|
||||||
- **Multi-tag per email** with color labels, reorderable tags, and drag-and-drop tag assignment
|
|
||||||
- **Star/unstar** with configurable mark-as-read delay
|
|
||||||
- **Virtual scrolling** for large mailboxes
|
|
||||||
- **Quick reply** from the viewer
|
|
||||||
- **Hover actions** - configurable quick-action buttons on email rows with customizable placement
|
|
||||||
- **Sender avatars** - favicon-based with negative caching for performance
|
|
||||||
- **Recipient popover** for quick contact interaction
|
|
||||||
- **Plain text composer mode** and auto-select reply identity
|
|
||||||
- **Reply-to addresses** support in the composer
|
|
||||||
- **TNEF support** - extract Outlook `winmail.dat` message bodies and attachments automatically
|
|
||||||
- **message/rfc822 unwrapping** for embedded messages
|
|
||||||
- **Folder management** - create, rename, delete folders with icon picker and subfolder support
|
|
||||||
- **Tag counts** - unread and total counts displayed in sidebar
|
|
||||||
- **Browser history sync** - back/forward navigation mirrors mail view state
|
|
||||||
|
|
||||||
### Calendar
|
|
||||||
|
|
||||||
- **Month, week, day, and agenda views** with mini-calendar sidebar and a dedicated task list view
|
|
||||||
- **Event hover preview** popover with configurable details
|
|
||||||
- **Drag-and-drop rescheduling**, click-drag or double-click creation, edge-resize (15-min snap)
|
|
||||||
- **Recurring events** with edit/delete scope (this / this and following / all) and client-side recurrence expansion
|
|
||||||
- **Participant scheduling** - iMIP invitations sent on create and update (RFC 5545/6047 compliant), organizer/attendee UI, RSVP with trust assessment
|
|
||||||
- **Inline calendar invitations** in email viewer - auto-detect `.ics`, RSVP, import
|
|
||||||
- **iCalendar import** with preview, bulk create, and UID deduplication
|
|
||||||
- **iCal / webcal subscriptions** with editing and batch import
|
|
||||||
- **Birthday calendar** - auto-generated from contacts
|
|
||||||
- **Virtual locations** - video conference URLs as first-class event fields
|
|
||||||
- **Task management** - create, edit, and track tasks with due dates, priority, and completion status; external CalDAV client detection (Thunderbird)
|
|
||||||
- **Shared calendars** with visual grouping in the sidebar
|
|
||||||
- **CalDAV discovery** with automatic calendar home resolution for multi-account setups
|
|
||||||
- **Week numbers** in mini-calendar sidebar
|
|
||||||
- **Notifications** with configurable sound, alert persistence, and sound picker with preview playback
|
|
||||||
- **Real-time sync** via JMAP push
|
|
||||||
|
|
||||||
### Contacts
|
|
||||||
|
|
||||||
- **Contact management** with JMAP sync (RFC 9553/9610) and local fallback
|
|
||||||
- **Multiple address books** - create, rename, drag-and-drop between books, with editor picker in contact form
|
|
||||||
- **Collapsible sidebar** with address book grouping and bulk operations
|
|
||||||
- **Contact groups** with group expansion and member management
|
|
||||||
- **vCard import/export** (RFC 6350) with duplicate detection
|
|
||||||
- **Trusted senders** stored in a dedicated JMAP address book
|
|
||||||
- **Autocomplete** in composer (To/Cc/Bcc)
|
|
||||||
- **Bulk operations** - multi-select, delete, group add, export
|
|
||||||
|
|
||||||
### Filters & Automation
|
|
||||||
|
|
||||||
- **Server-side email filters** via JMAP Sieve Scripts (RFC 9661)
|
|
||||||
- **Visual rule builder** - conditions (From, To, Subject, Size, Body…) and actions (Move, Forward, Star, Discard…) with an expanded visual view
|
|
||||||
- **External rule preservation** - rules authored in other clients are displayed and preserved
|
|
||||||
- **Raw Sieve editor** with syntax validation
|
|
||||||
- **Vacation responder** with date range scheduling and sidebar indicator
|
|
||||||
- **Email templates** - reusable, categorized, with placeholder auto-fill (`{{recipientName}}`, `{{date}}`, etc.)
|
|
||||||
|
|
||||||
### Files
|
|
||||||
|
|
||||||
- **File browser** with JMAP FileNode cloud storage (Stalwart native)
|
|
||||||
- **Upload and download** files with progress tracking, folder upload, and streamed WebDAV PUT (no in-memory buffering)
|
|
||||||
- **Dynamic upload limits** - respects the server-configured maximum upload size
|
|
||||||
- **Folder navigation** with breadcrumb path and tree sidebar
|
|
||||||
- **Grid and list views** with sorting by name, size, or date
|
|
||||||
- **Clipboard operations** - cut, copy, paste, duplicate files
|
|
||||||
- **File preview** for images, text, audio, video, and more
|
|
||||||
- **Favorites and recent files** for quick access
|
|
||||||
- **Bulk operations** - multi-select, delete, move, download
|
|
||||||
|
|
||||||
### Security & Privacy
|
|
||||||
|
|
||||||
- **External content blocked** by default - trusted senders list for auto-load
|
|
||||||
- **HTML sanitization** via DOMPurify with XSS prevention
|
|
||||||
- **S/MIME** - manage certificates, sign outgoing mail, encrypt to recipients, decrypt messages, and verify signatures; self-signed certificate detection; legacy 3DES / PBE support; per-account key isolation
|
|
||||||
- **SPF/DKIM/DMARC** status indicators
|
|
||||||
- **OAuth2/OIDC with PKCE** for SSO (Keycloak, Authentik, or built-in), with OAuth-only mode, OAuth app passwords, configurable scopes, and non-interactive SSO for embedded/iframe deployments
|
|
||||||
- **TOTP two-factor authentication**
|
|
||||||
- **Account security panel** - manage passwords and 2FA via Stalwart admin API
|
|
||||||
- **"Remember me"** - AES-256-GCM encrypted httpOnly cookie (opt-in)
|
|
||||||
- **Security headers** - enforced CSP with per-request nonce, X-Frame-Options, Referrer-Policy; SSRF redirect validation; PDF iframe sandbox; IP spoofing prevention
|
|
||||||
- **Plugin hardening** - dangerous-pattern detection, admin approval required, secure HTTP proxy API (no auth-header exposure)
|
|
||||||
- **Newsletter unsubscribe** (RFC 2369)
|
|
||||||
|
|
||||||
### Interface
|
|
||||||
|
|
||||||
- **Three-pane layout** - sidebar, email list, viewer with resizable columns
|
|
||||||
- **Dark and light themes** with intelligent email color transformation
|
|
||||||
- **Always-light email rendering** option for problematic HTML messages in dark theme
|
|
||||||
- **Responsive** - desktop sidebar + mobile bottom tab bar with tablet support
|
|
||||||
- **Keyboard shortcuts** - full navigation without a mouse
|
|
||||||
- **Drag-and-drop** email organization between mailboxes and tag assignment
|
|
||||||
- **Interactive guided tour** - onboarding walkthrough for new users
|
|
||||||
- **Right-click context menus**, toast notifications with undo, form validation with shake feedback
|
|
||||||
- **Customizable toolbar** position, custom favicon, sidebar/login logos, and login page branding
|
|
||||||
- **Sidebar apps** - pin custom tools to the navigation rail with drag-and-drop reordering, mobile visibility toggles, and inline or new-tab launch modes
|
|
||||||
- **Settings sync** - preferences synchronized with the server (encrypted)
|
|
||||||
- **Storage quota** display
|
|
||||||
- **Version badge** in settings
|
|
||||||
- **Focused mode** with proper viewport bounds
|
|
||||||
- **Accessibility** - WCAG AA contrast, reduced-motion support, focus trap, screen reader live regions
|
|
||||||
|
|
||||||
### Internationalization
|
|
||||||
|
|
||||||
14 languages: English · Français · 日本語 · Español · Italiano · Deutsch · Nederlands · Português · Русский · 한국어 · Polski · Latviešu · 简体中文 · Українська
|
|
||||||
|
|
||||||
Automatic browser detection with persistent preference. Configurable locale URL prefix via `NEXT_PUBLIC_LOCALE_PREFIX`.
|
|
||||||
|
|
||||||
### Identity Management
|
|
||||||
|
|
||||||
- **Multiple sender identities** with per-identity signatures
|
|
||||||
- **Automatic identity synchronization** and refresh to keep the identity manager aligned with server-side changes
|
|
||||||
- **Sub-addressing** - `user+tag@domain.com` with contextual tag suggestions
|
|
||||||
- **Identity badges** in viewer and email list
|
|
||||||
|
|
||||||
### Multi-Account
|
|
||||||
|
|
||||||
- **Up to 5 simultaneous accounts** with instant switching and per-account session persistence
|
|
||||||
- **Account switcher** with connection status, default account selection, and per-account logout
|
|
||||||
- **Per-account settings** - encrypted settings storage with server-side sync
|
|
||||||
- **Shared folders** across accounts
|
|
||||||
- **Custom JMAP server endpoints** - optionally let users connect to any JMAP server from the login form (`ALLOW_CUSTOM_JMAP_ENDPOINT`)
|
|
||||||
|
|
||||||
### Admin & Extensibility
|
|
||||||
|
|
||||||
- **Stalwart admin dashboard** - sidebar access with reorganized dashboard and dedicated policy sections
|
|
||||||
- **Plugin system** - schema-driven admin config UI, render and intercept hooks, `onAvatarResolve` and i18n APIs, calendar event action slots, forced enable/disable and managed policy enforcement
|
|
||||||
- **Themes** - upload, enforce, and manage admin-controlled themes with ZIP bundles
|
|
||||||
- **Extension marketplace** - browse and install plugins/themes from a configurable directory (`EXTENSION_DIRECTORY_URL`)
|
|
||||||
- **Bundled plugins** - Jitsi Meet calendar integration
|
|
||||||
|
|
||||||
### Operations
|
|
||||||
|
|
||||||
- **Progressive Web App (PWA)** - installable with service worker, install prompt, and dynamic manifest (app name, description, icons, theme and background colors)
|
|
||||||
- **Automatic update check** - server logs when a newer release is available
|
|
||||||
- **Logging categories** with `text` or `json` formats for log aggregation
|
|
||||||
- **Docker images** - release (`main`) and development (`dev`) channels on GHCR
|
|
||||||
- **Demo mode** - try the webmail with fixture data for emails, calendars, contacts, files, filters, identities, and mailboxes - no mail server required
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Quick Start
|
## Quick Start
|
||||||
|
|
||||||
### Docker (recommended)
|
### Docker
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker run -d -p 3000:3000 \
|
docker run -d -p 3000:3000 \
|
||||||
@@ -255,7 +82,7 @@ Or with Docker Compose:
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
cp .env.example .env.local
|
cp .env.example .env.local
|
||||||
# Edit .env.local - set JMAP_SERVER_URL
|
# Edit .env.local — set JMAP_SERVER_URL
|
||||||
docker compose up -d
|
docker compose up -d
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -266,21 +93,21 @@ git clone https://github.com/bulwarkmail/webmail.git
|
|||||||
cd webmail
|
cd webmail
|
||||||
npm install
|
npm install
|
||||||
cp .env.example .env.local
|
cp .env.example .env.local
|
||||||
# Edit .env.local - set JMAP_SERVER_URL
|
# Edit .env.local — set JMAP_SERVER_URL
|
||||||
npm run build && npm start
|
npm run build && npm start
|
||||||
```
|
```
|
||||||
|
|
||||||
### Development
|
### Development
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npm run dev # Start dev server (mock JMAP server included)
|
npm run dev # Dev server with a mock JMAP server
|
||||||
npm run typecheck # Type checking
|
npm run typecheck
|
||||||
npm run lint # Linting
|
npm run lint
|
||||||
```
|
```
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
Edit `.env.local`:
|
All variables are evaluated at runtime, so Docker deployments can be reconfigured without rebuilding. Edit `.env.local`:
|
||||||
|
|
||||||
```env
|
```env
|
||||||
# Required
|
# Required
|
||||||
@@ -290,27 +117,25 @@ JMAP_SERVER_URL=https://mail.example.com
|
|||||||
APP_NAME=My Webmail
|
APP_NAME=My Webmail
|
||||||
```
|
```
|
||||||
|
|
||||||
All variables are **runtime** - Docker deployments can be configured without rebuilding.
|
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary>Server Listen Address</summary>
|
<summary>Server listen address</summary>
|
||||||
|
|
||||||
```env
|
```env
|
||||||
HOSTNAME=0.0.0.0 # Default; use "::" for IPv6
|
HOSTNAME=0.0.0.0 # Default; use "::" for IPv6
|
||||||
PORT=3000 # Default listen port
|
PORT=3000
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary>OAuth2/OIDC (SSO)</summary>
|
<summary>OAuth2 / OIDC</summary>
|
||||||
|
|
||||||
```env
|
```env
|
||||||
OAUTH_ENABLED=true
|
OAUTH_ENABLED=true
|
||||||
OAUTH_CLIENT_ID=webmail
|
OAUTH_CLIENT_ID=webmail
|
||||||
OAUTH_CLIENT_SECRET= # optional, for confidential clients
|
OAUTH_CLIENT_SECRET= # optional, for confidential clients
|
||||||
OAUTH_CLIENT_SECRET_FILE= # Path to a file containing the client secret
|
OAUTH_CLIENT_SECRET_FILE= # path to a file containing the secret
|
||||||
OAUTH_ISSUER_URL= # optional, for external IdPs (Keycloak, Authentik)
|
OAUTH_ISSUER_URL= # optional, for external IdPs
|
||||||
```
|
```
|
||||||
|
|
||||||
Endpoints are auto-discovered via `.well-known/oauth-authorization-server` or `.well-known/openid-configuration`.
|
Endpoints are auto-discovered via `.well-known/oauth-authorization-server` or `.well-known/openid-configuration`.
|
||||||
@@ -318,29 +143,28 @@ Endpoints are auto-discovered via `.well-known/oauth-authorization-server` or `.
|
|||||||
</details>
|
</details>
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary>Remember Me & Settings Sync</summary>
|
<summary>Session & settings sync</summary>
|
||||||
|
|
||||||
```env
|
```env
|
||||||
SESSION_SECRET=your-secret-key # Generate with: openssl rand -base64 32
|
SESSION_SECRET= # openssl rand -base64 32
|
||||||
SESSION_SECRET_FILE=/session-secret # Path to a file containing the session secret
|
SESSION_SECRET_FILE=/session-secret # path to a file containing the secret
|
||||||
|
|
||||||
SETTINGS_SYNC_ENABLED=true # Persist encrypted user settings on the server
|
SETTINGS_SYNC_ENABLED=true
|
||||||
SETTINGS_DATA_DIR=./data/settings # Storage location (mount a volume in Docker)
|
SETTINGS_DATA_DIR=./data/settings # mount as a volume in Docker
|
||||||
```
|
```
|
||||||
|
|
||||||
Credentials encrypted with AES-256-GCM, stored in an httpOnly cookie (30-day expiry).
|
Credentials are encrypted with AES-256-GCM and stored in an httpOnly cookie (30-day expiry). Settings sync stores per-account preferences encrypted at rest and requires `SESSION_SECRET`.
|
||||||
Settings sync stores per-account preferences encrypted at rest and requires `SESSION_SECRET`.
|
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary>Custom JMAP Endpoint</summary>
|
<summary>Custom JMAP endpoint</summary>
|
||||||
|
|
||||||
```env
|
```env
|
||||||
ALLOW_CUSTOM_JMAP_ENDPOINT=true # Shows a "JMAP Server" field on login
|
ALLOW_CUSTOM_JMAP_ENDPOINT=true
|
||||||
```
|
```
|
||||||
|
|
||||||
Lets users connect to any JMAP-compatible server. External servers must CORS-allow the webmail origin.
|
Shows a "JMAP Server" field on the login form. External servers must CORS-allow the webmail origin.
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
@@ -349,13 +173,13 @@ Lets users connect to any JMAP-compatible server. External servers must CORS-all
|
|||||||
|
|
||||||
```env
|
```env
|
||||||
APP_NAME=My Webmail
|
APP_NAME=My Webmail
|
||||||
APP_SHORT_NAME=Webmail # Home-screen label on mobile
|
APP_SHORT_NAME=Webmail
|
||||||
APP_DESCRIPTION=Your personal mail # Shown during PWA install
|
APP_DESCRIPTION=Your personal mail
|
||||||
|
|
||||||
FAVICON_URL=/branding/favicon.svg
|
FAVICON_URL=/branding/favicon.svg
|
||||||
PWA_ICON_URL=/branding/icon.svg # Falls back to FAVICON_URL
|
PWA_ICON_URL=/branding/icon.svg # falls back to FAVICON_URL
|
||||||
PWA_THEME_COLOR=#3b82f6 # Browser chrome color
|
PWA_THEME_COLOR=#3b82f6
|
||||||
PWA_BACKGROUND_COLOR=#ffffff # PWA splash background
|
PWA_BACKGROUND_COLOR=#ffffff
|
||||||
|
|
||||||
APP_LOGO_LIGHT_URL=/branding/logo-light.svg
|
APP_LOGO_LIGHT_URL=/branding/logo-light.svg
|
||||||
APP_LOGO_DARK_URL=/branding/logo-dark.svg
|
APP_LOGO_DARK_URL=/branding/logo-dark.svg
|
||||||
@@ -371,7 +195,7 @@ LOGIN_PRIVACY_POLICY_URL=https://example.com/privacy
|
|||||||
</details>
|
</details>
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary>Extension Directory</summary>
|
<summary>Extension directory</summary>
|
||||||
|
|
||||||
```env
|
```env
|
||||||
EXTENSION_DIRECTORY_URL=https://extensions.bulwarkmail.org
|
EXTENSION_DIRECTORY_URL=https://extensions.bulwarkmail.org
|
||||||
@@ -382,13 +206,13 @@ Enables the admin marketplace for browsing and installing plugins and themes.
|
|||||||
</details>
|
</details>
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary>Stalwart Integration & Logging</summary>
|
<summary>Stalwart integration & logging</summary>
|
||||||
|
|
||||||
```env
|
```env
|
||||||
STALWART_FEATURES=true # Password change, sieve filters, etc.
|
STALWART_FEATURES=true # password change, Sieve filters, etc.
|
||||||
|
|
||||||
LOG_FORMAT=text # "text" or "json"
|
LOG_FORMAT=text # "text" or "json"
|
||||||
LOG_LEVEL=info # "error", "warn", "info", "debug"
|
LOG_LEVEL=info # error | warn | info | debug
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
@@ -423,19 +247,16 @@ LOG_LEVEL=info # "error", "warn", "info", "debug"
|
|||||||
|
|
||||||
## Why Stalwart?
|
## Why Stalwart?
|
||||||
|
|
||||||
[Stalwart](https://github.com/stalwartlabs/mail-server) is a mail server written in Rust with **native JMAP support** - not IMAP/SMTP with JMAP bolted on. It handles JMAP, IMAP, SMTP, and ManageSieve in a single binary. Self-hosted, no third-party dependencies.
|
[Stalwart](https://github.com/stalwartlabs/mail-server) is a Rust mail server with native JMAP support — not IMAP/SMTP with JMAP bolted on. It handles JMAP, IMAP, SMTP, and ManageSieve in a single self-hosted binary with no third-party dependencies.
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
|
See [CONTRIBUTING.md](CONTRIBUTING.md).
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
[GNU AGPL v3](LICENSE)
|
[GNU AGPL v3](LICENSE). This repository preserves the original MIT attribution for the fork lineage in [NOTICE](NOTICE).
|
||||||
|
|
||||||
This repository also preserves the original MIT attribution notice for the
|
|
||||||
fork lineage in [NOTICE](NOTICE).
|
|
||||||
|
|
||||||
## Acknowledgments
|
## Acknowledgments
|
||||||
|
|
||||||
Thanks to [root-fr/jmap-webmail](https://github.com/root-fr/jmap-webmail/) and [@ma2t](https://github.com/ma2t) for doing most of the groundwork that this project builds upon.
|
Thanks to [root-fr/jmap-webmail](https://github.com/root-fr/jmap-webmail/) and [@ma2t](https://github.com/ma2t) for the groundwork this project builds upon.
|
||||||
|
|||||||
@@ -112,10 +112,9 @@ const emails: MockEmail[] = [
|
|||||||
preview: 'Hallo! This is a sample email to help you get started with the Bulwark Webmail development environment.',
|
preview: 'Hallo! This is a sample email to help you get started with the Bulwark Webmail development environment.',
|
||||||
hasAttachment: false,
|
hasAttachment: false,
|
||||||
textBody: [{ partId: 'p1', blobId: 'blob-001', size: 280, type: 'text/plain' }],
|
textBody: [{ partId: 'p1', blobId: 'blob-001', size: 280, type: 'text/plain' }],
|
||||||
htmlBody: [{ partId: 'p2', blobId: 'blob-002', size: 420, type: 'text/html' }],
|
htmlBody: [],
|
||||||
bodyValues: {
|
bodyValues: {
|
||||||
p1: { value: 'Hallo!\n\nThis is a sample email to help you get started with the Bulwark Webmail development environment.\n\nFeel free to explore the UI - all data here is mock data.\n\nBeste Grüße,\nSophie' },
|
p1: { value: 'Hallo!\n\nThis is a sample email to help you get started with the Bulwark Webmail development environment.\n\nFeel free to explore the UI - all data here is mock data.\n\nBeste Grüße,\nSophie' },
|
||||||
p2: { value: '<p>Hallo!</p><p>This is a sample email to help you get started with the <strong>Bulwark Webmail</strong> development environment.</p><p>Feel free to explore the UI - all data here is mock data.</p><p>Beste Grüße,<br>Sophie</p>' },
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 276 KiB After Width: | Height: | Size: 243 KiB |
|
Before Width: | Height: | Size: 230 KiB After Width: | Height: | Size: 210 KiB |
|
Before Width: | Height: | Size: 125 KiB |
|
Before Width: | Height: | Size: 356 KiB |
|
Before Width: | Height: | Size: 328 KiB |
|
Before Width: | Height: | Size: 182 KiB |
|
After Width: | Height: | Size: 258 KiB |
|
After Width: | Height: | Size: 263 KiB |
|
After Width: | Height: | Size: 183 KiB |
|
Before Width: | Height: | Size: 202 KiB After Width: | Height: | Size: 180 KiB |
|
After Width: | Height: | Size: 192 KiB |