Bump version to 1.2.3 across package.json, VERSION, README badge, and login page. Add changelog entry for features and fixes since v1.1.2.
264 lines
8.0 KiB
Markdown
264 lines
8.0 KiB
Markdown
<div align="center">
|
|
|
|
<picture>
|
|
<source media="(prefers-color-scheme: dark)" srcset="public/branding/Bulwark%20Logo%20with%20Lettering%20White%20and%20Color.svg" />
|
|
<source media="(prefers-color-scheme: light)" srcset="public/branding/Bulwark%20Logo%20with%20Lettering%20Dark%20Color.svg" />
|
|
<img src="public/branding/Bulwark%20Logo%20with%20Lettering%20Dark%20Color.svg" alt="Bulwark Webmail" width="280" />
|
|
</picture>
|
|
|
|
# Bulwark Webmail
|
|
|
|
A modern, self-hosted webmail client for [Stalwart Mail Server](https://stalw.art/).<br/>
|
|
Built with Next.js and the JMAP protocol.
|
|
|
|
[](LICENSE)
|
|
[](CHANGELOG.md)
|
|
[](https://ghcr.io/bulwarkmail/webmail)
|
|
|
|
</div>
|
|
|
|
---
|
|
|
|
## Screenshots
|
|
|
|
<table>
|
|
<tr>
|
|
<td width="50%">
|
|
|
|
<img src="screenshots/02-inbox.png" width="100%" alt="Inbox — three-pane layout with sidebar, email list, and viewer">
|
|
|
|
</td>
|
|
<td width="50%">
|
|
|
|
<img src="screenshots/05-dark-mode.png" width="100%" alt="Dark mode">
|
|
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td width="50%">
|
|
|
|
<img src="screenshots/04-compose.png" width="100%" alt="Compose with templates and autocomplete">
|
|
|
|
</td>
|
|
<td width="50%">
|
|
|
|
<img src="screenshots/06-settings.png" width="100%" alt="Settings">
|
|
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
|
|
<details>
|
|
<summary>More screenshots</summary>
|
|
<table>
|
|
<tr>
|
|
<td width="50%">
|
|
|
|
<img src="screenshots/01-login.png" width="100%" alt="Login page">
|
|
|
|
</td>
|
|
<td width="50%">
|
|
|
|
<img src="screenshots/03-email-viewer.png" width="100%" alt="Email viewer with thread expansion">
|
|
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</details>
|
|
|
|
## Features
|
|
|
|
### Mail
|
|
|
|
- **Read, compose, reply, reply-all, forward** with rich HTML rendering
|
|
- **Threading** — Gmail-style inline expansion with thread navigation
|
|
- **Draft auto-save** with discard confirmation
|
|
- **Attachments** — upload, download, and inline preview
|
|
- **Search** — full-text with JMAP filter panel, search chips, and cross-mailbox queries
|
|
- **Batch operations** — multi-select, archive, delete, move, tag
|
|
- **Color tags/labels** and star/unstar
|
|
- **Virtual scrolling** for large mailboxes
|
|
- **Quick reply** from the viewer
|
|
|
|
### Calendar
|
|
|
|
- **Month, week, day, and agenda views** with mini-calendar sidebar
|
|
- **Drag-and-drop rescheduling**, click-drag creation, edge-resize (15-min snap)
|
|
- **Recurring events** with edit/delete scope (this / this and following / all)
|
|
- **Participant scheduling** — iTIP invitations, organizer/attendee UI, RSVP
|
|
- **Inline calendar invitations** in email viewer — auto-detect `.ics`, RSVP, import
|
|
- **iCalendar import** with preview and bulk create
|
|
- **Notifications** with configurable sound and alert persistence
|
|
- **Real-time sync** via JMAP push
|
|
|
|
### Contacts
|
|
|
|
- **Contact management** with JMAP sync (RFC 9553/9610) and local fallback
|
|
- **Contact groups** with group expansion and member management
|
|
- **vCard import/export** (RFC 6350) with duplicate detection
|
|
- **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…)
|
|
- **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.)
|
|
|
|
### Security & Privacy
|
|
|
|
- **External content blocked** by default — trusted senders list for auto-load
|
|
- **HTML sanitization** via DOMPurify with XSS prevention
|
|
- **SPF/DKIM/DMARC** status indicators
|
|
- **OAuth2/OIDC with PKCE** for SSO (Keycloak, Authentik, or built-in)
|
|
- **TOTP two-factor authentication**
|
|
- **"Remember me"** — AES-256-GCM encrypted httpOnly cookie (opt-in)
|
|
- **Security headers** — CSP with per-request nonce, X-Frame-Options, Referrer-Policy
|
|
- **Newsletter unsubscribe** (RFC 2369)
|
|
|
|
### Interface
|
|
|
|
- **Three-pane layout** — sidebar, email list, viewer
|
|
- **Dark and light themes** with intelligent email color transformation
|
|
- **Responsive** — desktop sidebar + mobile bottom tab bar
|
|
- **Keyboard shortcuts** — full navigation without a mouse
|
|
- **Drag-and-drop** email organization between mailboxes
|
|
- **Right-click context menus**, toast notifications with undo, form validation with shake feedback
|
|
- **Accessibility** — WCAG AA contrast, reduced-motion support, focus trap, screen reader live regions
|
|
|
|
### Internationalization
|
|
|
|
8 languages: English · Français · 日本語 · Español · Italiano · Deutsch · Nederlands · Português
|
|
|
|
Automatic browser detection with persistent preference.
|
|
|
|
### Identity Management
|
|
|
|
- **Multiple sender identities** with per-identity signatures
|
|
- **Sub-addressing** — `user+tag@domain.com` with contextual tag suggestions
|
|
- **Identity badges** in viewer and email list
|
|
|
|
---
|
|
|
|
## Quick Start
|
|
|
|
### Docker (recommended)
|
|
|
|
```bash
|
|
docker run -d -p 3000:3000 \
|
|
-e JMAP_SERVER_URL=https://mail.example.com \
|
|
ghcr.io/bulwarkmail/webmail:latest
|
|
```
|
|
|
|
Or with Docker Compose:
|
|
|
|
```bash
|
|
cp .env.example .env.local
|
|
# Edit .env.local — set JMAP_SERVER_URL
|
|
docker compose up -d
|
|
```
|
|
|
|
### From Source
|
|
|
|
```bash
|
|
git clone https://github.com/bulwarkmail/webmail.git
|
|
cd webmail
|
|
npm install
|
|
cp .env.example .env.local
|
|
# Edit .env.local — set JMAP_SERVER_URL
|
|
npm run build && npm start
|
|
```
|
|
|
|
### Development
|
|
|
|
```bash
|
|
npm run dev # Start dev server (mock JMAP server included)
|
|
npm run typecheck # Type checking
|
|
npm run lint # Linting
|
|
```
|
|
|
|
## Configuration
|
|
|
|
Edit `.env.local`:
|
|
|
|
```env
|
|
# Required
|
|
JMAP_SERVER_URL=https://mail.example.com
|
|
|
|
# Optional
|
|
APP_NAME=My Webmail
|
|
```
|
|
|
|
All variables are **runtime** — Docker deployments can be configured without rebuilding.
|
|
|
|
<details>
|
|
<summary>OAuth2/OIDC (SSO)</summary>
|
|
|
|
```env
|
|
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`.
|
|
|
|
</details>
|
|
|
|
<details>
|
|
<summary>Remember Me</summary>
|
|
|
|
```env
|
|
SESSION_SECRET=your-secret-key # Generate with: openssl rand -base64 32
|
|
```
|
|
|
|
Credentials encrypted with AES-256-GCM, stored in an httpOnly cookie (30-day expiry).
|
|
|
|
</details>
|
|
|
|
## Keyboard Shortcuts
|
|
|
|
| Key | Action |
|
|
| ------------- | ----------------------- |
|
|
| `j` / `k` | Navigate between emails |
|
|
| `Enter` / `o` | Open email |
|
|
| `Esc` | Close / deselect |
|
|
| `c` | Compose |
|
|
| `r` / `R` | Reply / Reply all |
|
|
| `f` | Forward |
|
|
| `s` | Star |
|
|
| `e` | Archive |
|
|
| `#` | Delete |
|
|
| `/` | Search |
|
|
| `?` | Show all shortcuts |
|
|
|
|
## Tech Stack
|
|
|
|
| | |
|
|
| ------------- | ------------------------------------------------- |
|
|
| **Framework** | [Next.js 16](https://nextjs.org/) with App Router |
|
|
| **Language** | TypeScript |
|
|
| **Styling** | [Tailwind CSS v4](https://tailwindcss.com/) |
|
|
| **State** | [Zustand](https://zustand-demo.pmnd.rs/) |
|
|
| **Protocol** | Custom JMAP client (RFC 8620) |
|
|
| **i18n** | [next-intl](https://next-intl-docs.vercel.app/) |
|
|
| **Icons** | [Lucide React](https://lucide.dev/) |
|
|
|
|
## 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.
|
|
|
|
## Contributing
|
|
|
|
See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
|
|
|
|
## Roadmap
|
|
|
|
See [ROADMAP.md](ROADMAP.md) for planned features and current status.
|
|
|
|
## License
|
|
|
|
[MIT](LICENSE)
|