fix: remove jmap-jam reference, clean up README language
This commit is contained in:
@@ -1,177 +1,166 @@
|
|||||||
# JMAP Webmail
|
# JMAP Webmail
|
||||||
|
|
||||||
A modern, privacy-focused webmail client built with Next.js and the JMAP protocol.
|
A webmail client for [Stalwart Mail Server](https://stalw.art/), built with Next.js and the JMAP protocol.
|
||||||
|
|
||||||
## Built for Stalwart
|
## Why Stalwart?
|
||||||
|
|
||||||
This webmail client is designed to work seamlessly with [**Stalwart Mail Server**](https://stalw.art/) - a modern, secure, and blazingly fast mail server written in Rust.
|
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.
|
||||||
|
|
||||||
**Why Stalwart?**
|
[Stalwart on GitHub](https://github.com/stalwartlabs/mail-server) | [Documentation](https://stalw.art/docs/)
|
||||||
- **Modern Architecture**: Built from the ground up with Rust for performance and safety
|
|
||||||
- **JMAP-Native**: First-class support for the JMAP protocol (not just IMAP/SMTP bolted on)
|
|
||||||
- **Privacy-Focused**: Self-hosted, no third-party dependencies, full control over your data
|
|
||||||
- **Feature-Rich**: Supports JMAP, IMAP, SMTP, ManageSieve, and more
|
|
||||||
|
|
||||||
[Stalwart GitHub](https://github.com/stalwartlabs/mail-server) | [Documentation](https://stalw.art/docs/)
|
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
### Core Email Operations
|
### Email
|
||||||
- Read, compose, reply, reply-all, and forward emails
|
|
||||||
- Full HTML email rendering with security sanitization
|
- Read, compose, reply, reply-all, and forward
|
||||||
|
- HTML rendering with DOMPurify sanitization
|
||||||
- Attachment upload and download
|
- Attachment upload and download
|
||||||
- Draft auto-save with discard confirmation
|
- Draft auto-save with discard confirmation
|
||||||
- Email threading with Gmail-style inline expansion
|
- Threading with inline expansion
|
||||||
- Mark as read/unread, star/unstar
|
- Mark as read/unread, star/unstar
|
||||||
- Archive and delete with configurable behavior
|
- Archive and delete with configurable behavior
|
||||||
- Color tags/labels for email organization
|
- Color tags/labels
|
||||||
- Advanced search with JMAP filter panel, search chips, and cross-mailbox queries
|
- Search with JMAP filter panel, search chips, cross-mailbox queries
|
||||||
- Virtual scrolling for large email lists
|
- Virtual scrolling for large lists
|
||||||
|
|
||||||
### User Interface
|
### Interface
|
||||||
- Clean, minimalist three-pane layout
|
|
||||||
- Dark and light theme support
|
- Three-pane layout with dark and light themes
|
||||||
- Responsive design for mobile and desktop
|
- Responsive (desktop sidebar + mobile bottom tab bar)
|
||||||
- Navigation rail (desktop icon sidebar + mobile bottom tab bar)
|
- Keyboard shortcuts
|
||||||
- Keyboard shortcuts for power users
|
|
||||||
- Drag-and-drop email organization
|
- Drag-and-drop email organization
|
||||||
- Right-click context menus
|
- Right-click context menus
|
||||||
- Smooth animations and transitions (respects prefers-reduced-motion)
|
- Animations that respect `prefers-reduced-motion`
|
||||||
- Infinite scroll pagination
|
- Infinite scroll pagination
|
||||||
- Welcome banner for first-time users
|
- Toast notifications with undo support
|
||||||
- Confirmation dialogs with promise-based async flow
|
- Form validation with shake feedback
|
||||||
- Toast notifications with undo action support
|
- Safe area insets for notched devices
|
||||||
- Inline form validation with shake animation feedback
|
- Screen reader live regions
|
||||||
- Empty state patterns with contextual actions
|
|
||||||
- Login UX polish (error shake, discreet 2FA toggle, password visibility toggle, session expired banner)
|
### Real-time
|
||||||
- Safe area inset support for notched devices
|
|
||||||
- Screen reader live region announcements
|
|
||||||
|
|
||||||
### Real-time Updates
|
|
||||||
- Push notifications via JMAP EventSource
|
- Push notifications via JMAP EventSource
|
||||||
- Real-time unread counts
|
- Live unread counts
|
||||||
- Live email arrival notifications
|
- Email arrival notifications
|
||||||
- Connection status indicator
|
- Connection status indicator
|
||||||
|
|
||||||
### Identity Management
|
### Identity management
|
||||||
|
|
||||||
- Multiple sender identities with per-identity signatures
|
- Multiple sender identities with per-identity signatures
|
||||||
- Sub-addressing support (user+tag@domain.com) with tag suggestions
|
- Sub-addressing (user+tag@domain.com) with tag suggestions
|
||||||
- Identity badges in email viewer and list
|
- Identity badges in viewer and list
|
||||||
|
|
||||||
|
### Address book
|
||||||
|
|
||||||
### Address Book
|
|
||||||
- Contact management with search and filtering
|
- Contact management with search and filtering
|
||||||
- JMAP server sync (RFC 9553/9610) with local fallback
|
- JMAP server sync (RFC 9553/9610) with local fallback
|
||||||
- Email autocomplete from contacts in composer
|
- Email autocomplete in composer
|
||||||
- Contact groups/lists with group expansion in composer
|
- Contact groups with group expansion
|
||||||
- vCard import/export (RFC 6350) with duplicate detection
|
- vCard import/export (RFC 6350) with duplicate detection
|
||||||
- Bulk operations (multi-select, delete, group add, export)
|
- Bulk operations (multi-select, delete, group add, export)
|
||||||
|
|
||||||
### Calendar
|
### Calendar
|
||||||
- JMAP Calendar integration (RFC 8984) with capability detection
|
|
||||||
|
- JMAP Calendar (RFC 8984) with capability detection
|
||||||
- Month, week, day, and agenda views
|
- Month, week, day, and agenda views
|
||||||
- Event create, edit, and delete with recurrence rules and reminders
|
- Event create, edit, delete with recurrence and reminders
|
||||||
- Participant scheduling with iTIP invitations (organizer/attendee roles, RSVP)
|
- Participant scheduling with iTIP invitations and RSVP
|
||||||
- Inline calendar invitation banner in email viewer (auto-detect .ics attachments, RSVP, import)
|
- Inline calendar invitation banner in email viewer (.ics detection, RSVP, import)
|
||||||
- Multi-day events spanning across days, column-based overlap layout
|
- Multi-day events, column-based overlap layout
|
||||||
- Mini-calendar sidebar with calendar visibility toggles
|
- Mini-calendar sidebar with calendar visibility toggles
|
||||||
- Locale-aware date formatting (respects user's language)
|
- Locale-aware date formatting
|
||||||
- Settings for first day of week, time format (12h/24h), and default view
|
- Settings for first day of week, time format (12h/24h), default view
|
||||||
- Drag-and-drop rescheduling (week/day time snap, month date move)
|
- Drag-and-drop rescheduling with time snap
|
||||||
- Click-drag on empty time slots to create events with pre-filled time range
|
- Click-drag on empty slots to create events
|
||||||
- Resize events by dragging bottom edge (15-minute snap)
|
- Resize events by dragging (15-minute snap)
|
||||||
- Double-click quick create with inline title input
|
- Double-click quick create
|
||||||
- Event duplication (+1 day offset)
|
- Event duplication (+1 day offset)
|
||||||
- Recurring event edit/delete scope (this event, this and following, all events)
|
- Recurring event edit/delete scope (this, this and following, all)
|
||||||
- iCalendar (.ics) file import with event preview and bulk create
|
- iCalendar (.ics) file import with preview
|
||||||
- Real-time updates via JMAP push notifications
|
- Real-time updates via JMAP push
|
||||||
- Event notifications with client-side alert evaluation and toast display
|
- Event notifications with configurable sound
|
||||||
- Configurable notification sound and enable/disable toggles
|
|
||||||
- Keyboard shortcuts: m/w/d/a (views), t (today), n (new event), arrows (navigate)
|
|
||||||
|
|
||||||
### Email Templates
|
### Email templates
|
||||||
- Reusable email templates with category organization (General, Business, Personal, Support, Follow-up)
|
|
||||||
- Dynamic placeholder variables (`{{recipientName}}`, `{{date}}`, etc.) with auto-fill from composer context
|
|
||||||
- Template picker in compose toolbar with search and category filter
|
|
||||||
- Custom placeholder prompt when inserting templates
|
|
||||||
- Template manager for creating, editing, duplicating, and deleting templates
|
|
||||||
- Settings tab for template management
|
|
||||||
|
|
||||||
### Email Filters
|
- Reusable templates organized by category
|
||||||
- Server-side email filtering with JMAP Sieve Scripts (RFC 9661)
|
- Placeholder variables (`{{recipientName}}`, `{{date}}`, etc.) with auto-fill
|
||||||
- Visual rule builder with conditions (From, To, Subject, Size, Body, etc.) and actions (Move, Forward, Mark read, Star, Discard, Reject, etc.)
|
- Template picker in compose toolbar with search and filter
|
||||||
- Raw Sieve script editor for advanced users with syntax validation
|
- Template manager in settings
|
||||||
- Auto-save on rule changes with rollback on failure
|
|
||||||
|
### 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
|
- Drag-and-drop rule reordering
|
||||||
- Reset opaque scripts back to visual builder
|
- Only shown when the server supports Sieve
|
||||||
- Capability-gated (only shown when server supports Sieve)
|
|
||||||
|
|
||||||
### Vacation Responder
|
### Vacation responder
|
||||||
- JMAP VacationResponse management with date range scheduling
|
|
||||||
- Dedicated settings tab with message configuration
|
- JMAP VacationResponse with date range scheduling
|
||||||
- Sidebar indicator when vacation auto-reply is active
|
- Settings tab for message configuration
|
||||||
|
- Sidebar indicator when active
|
||||||
|
|
||||||
|
### Security and privacy
|
||||||
|
|
||||||
### Security & Privacy
|
|
||||||
- External content blocked by default
|
- External content blocked by default
|
||||||
- Trusted senders list for automatic image loading
|
- Trusted senders list for automatic image loading
|
||||||
- HTML sanitization with DOMPurify
|
- HTML sanitization (DOMPurify)
|
||||||
- SPF/DKIM/DMARC status indicators
|
- SPF/DKIM/DMARC status indicators
|
||||||
- No password storage by default (session-based auth)
|
- Session-based auth, no password storage by default
|
||||||
- TOTP two-factor authentication support
|
- TOTP two-factor authentication
|
||||||
- "Remember me" session persistence (AES-256-GCM encrypted httpOnly cookie, opt-in)
|
- "Remember me" with AES-256-GCM encrypted httpOnly cookie (opt-in)
|
||||||
- OAuth2/OIDC with PKCE for SSO login (opt-in, RP-initiated logout, Basic Auth remains default)
|
- OAuth2/OIDC with PKCE for SSO (opt-in, RP-initiated logout)
|
||||||
- External IdP support (Keycloak, Authentik) via configurable issuer URL
|
- External IdP support (Keycloak, Authentik) via configurable issuer URL
|
||||||
- Session persistence via httpOnly cookies (refresh tokens for OAuth, encrypted credentials for Basic Auth)
|
- CORS misconfiguration detection with detailed error messages
|
||||||
- CORS misconfiguration detection with actionable error messages
|
- Shared folder support
|
||||||
- Shared folder support with proper permissions
|
- Newsletter unsubscribe (RFC 2369)
|
||||||
- Newsletter unsubscribe support (RFC 2369)
|
- CSP, X-Content-Type-Options, X-Frame-Options, Referrer-Policy headers
|
||||||
- CSP headers and security headers (X-Content-Type-Options, X-Frame-Options, Referrer-Policy)
|
|
||||||
|
|
||||||
### Internationalization
|
### Internationalization
|
||||||
- 8 language support: English, French, Japanese, Spanish, Italian, German, Dutch, Portuguese
|
|
||||||
|
- 8 languages: English, French, Japanese, Spanish, Italian, German, Dutch, Portuguese
|
||||||
- Automatic browser language detection
|
- Automatic browser language detection
|
||||||
- Persistent language preference
|
- Persistent language preference
|
||||||
|
|
||||||
### Deployment
|
### Deployment
|
||||||
- Pre-built Docker image on [Docker Hub](https://hub.docker.com/r/rootfr/jmap-webmail) and [GHCR](https://ghcr.io/root-fr/jmap-webmail) (amd64/arm64)
|
|
||||||
- Docker support with multi-stage build and standalone output
|
|
||||||
- Runtime environment variables (no rebuild needed for config changes)
|
|
||||||
- Health check endpoint for container orchestration
|
|
||||||
- Structured server-side logging (text/JSON format)
|
|
||||||
|
|
||||||
## Tech Stack
|
- Pre-built Docker images on [Docker Hub](https://hub.docker.com/r/rootfr/jmap-webmail) and [GHCR](https://ghcr.io/root-fr/jmap-webmail) (amd64/arm64)
|
||||||
|
- Multi-stage build with standalone output
|
||||||
|
- Runtime environment variables (no rebuild needed)
|
||||||
|
- Health check endpoint
|
||||||
|
- Structured logging (text/JSON)
|
||||||
|
|
||||||
- **Framework**: [Next.js 16](https://nextjs.org/) with App Router
|
## Tech stack
|
||||||
- **Language**: TypeScript
|
|
||||||
- **Styling**: [Tailwind CSS v4](https://tailwindcss.com/)
|
|
||||||
- **State Management**: [Zustand](https://zustand-demo.pmnd.rs/)
|
|
||||||
- **JMAP Client**: [jmap-jam](https://www.npmjs.com/package/jmap-jam)
|
|
||||||
- **i18n**: [next-intl](https://next-intl-docs.vercel.app/)
|
|
||||||
- **Icons**: [Lucide React](https://lucide.dev/)
|
|
||||||
|
|
||||||
## Getting Started
|
- [Next.js 16](https://nextjs.org/) with App Router
|
||||||
|
- TypeScript
|
||||||
|
- [Tailwind CSS v4](https://tailwindcss.com/)
|
||||||
|
- [Zustand](https://zustand-demo.pmnd.rs/) for state management
|
||||||
|
- Custom JMAP client (RFC 8620)
|
||||||
|
- [next-intl](https://next-intl-docs.vercel.app/) for i18n
|
||||||
|
- [Lucide React](https://lucide.dev/) icons
|
||||||
|
|
||||||
|
## Getting started
|
||||||
|
|
||||||
### Prerequisites
|
### Prerequisites
|
||||||
|
|
||||||
- Node.js 18+
|
- Node.js 18+
|
||||||
- A JMAP-compatible mail server (we recommend [Stalwart](https://stalw.art/))
|
- A JMAP-compatible mail server ([Stalwart](https://stalw.art/) recommended)
|
||||||
|
|
||||||
### Installation
|
### Installation
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Clone the repository
|
|
||||||
git clone https://github.com/root-fr/jmap-webmail.git
|
git clone https://github.com/root-fr/jmap-webmail.git
|
||||||
cd jmap-webmail
|
cd jmap-webmail
|
||||||
|
|
||||||
# Install dependencies
|
|
||||||
npm install
|
npm install
|
||||||
|
|
||||||
# Copy environment configuration
|
|
||||||
cp .env.example .env.local
|
cp .env.example .env.local
|
||||||
```
|
```
|
||||||
|
|
||||||
### Configuration
|
### Configuration
|
||||||
|
|
||||||
Edit `.env.local` with your settings:
|
Edit `.env.local`:
|
||||||
|
|
||||||
```env
|
```env
|
||||||
# App name displayed in the UI
|
# App name displayed in the UI
|
||||||
@@ -181,7 +170,7 @@ APP_NAME=My Webmail
|
|||||||
JMAP_SERVER_URL=https://mail.example.com
|
JMAP_SERVER_URL=https://mail.example.com
|
||||||
```
|
```
|
||||||
|
|
||||||
**Note:** These are runtime environment variables, read at request time. This enables Docker deployments to be configured without rebuilding the image. Legacy `NEXT_PUBLIC_*` variables are still supported as fallbacks.
|
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)
|
#### OAuth2/OIDC (optional)
|
||||||
|
|
||||||
@@ -194,9 +183,9 @@ OAUTH_CLIENT_SECRET= # optional, for confidential clients
|
|||||||
OAUTH_ISSUER_URL= # optional, for external IdPs (Keycloak, Authentik)
|
OAUTH_ISSUER_URL= # optional, for external IdPs (Keycloak, Authentik)
|
||||||
```
|
```
|
||||||
|
|
||||||
OAuth 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`).
|
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)
|
#### Remember me (optional)
|
||||||
|
|
||||||
To enable "Remember me" for Basic Auth login:
|
To enable "Remember me" for Basic Auth login:
|
||||||
|
|
||||||
@@ -209,46 +198,38 @@ When set, a "Remember me" checkbox appears on the login form. Credentials are en
|
|||||||
### Development
|
### Development
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Start development server
|
npm run dev # Start dev server
|
||||||
npm run dev
|
npm run typecheck # Type checking
|
||||||
|
npm run lint # Linting
|
||||||
# Type checking
|
|
||||||
npm run typecheck
|
|
||||||
|
|
||||||
# Linting
|
|
||||||
npm run lint
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Production Build
|
### Production
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Build for production
|
|
||||||
npm run build
|
npm run build
|
||||||
|
|
||||||
# Start production server
|
|
||||||
npm start
|
npm start
|
||||||
```
|
```
|
||||||
|
|
||||||
### Docker
|
### Docker
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Using the pre-built image (recommended)
|
# Pre-built image
|
||||||
docker run -p 3000:3000 -e JMAP_SERVER_URL=https://mail.example.com rootfr/jmap-webmail:latest
|
docker run -p 3000:3000 -e JMAP_SERVER_URL=https://mail.example.com rootfr/jmap-webmail:latest
|
||||||
|
|
||||||
# Or from GHCR
|
# From GHCR
|
||||||
docker run -p 3000:3000 -e JMAP_SERVER_URL=https://mail.example.com ghcr.io/root-fr/jmap-webmail:latest
|
docker run -p 3000:3000 -e JMAP_SERVER_URL=https://mail.example.com ghcr.io/root-fr/jmap-webmail:latest
|
||||||
|
|
||||||
# Or with docker compose
|
# With docker compose
|
||||||
cp .env.example .env.local
|
cp .env.example .env.local
|
||||||
# Edit .env.local with your JMAP_SERVER_URL
|
# Edit .env.local with your JMAP_SERVER_URL
|
||||||
docker compose up -d
|
docker compose up -d
|
||||||
|
|
||||||
# Or build from source
|
# Build from source
|
||||||
docker build -t jmap-webmail .
|
docker build -t jmap-webmail .
|
||||||
docker run -p 3000:3000 -e JMAP_SERVER_URL=https://mail.example.com jmap-webmail
|
docker run -p 3000:3000 -e JMAP_SERVER_URL=https://mail.example.com jmap-webmail
|
||||||
```
|
```
|
||||||
|
|
||||||
## Keyboard Shortcuts
|
## Keyboard shortcuts
|
||||||
|
|
||||||
| Key | Action |
|
| Key | Action |
|
||||||
|-----|--------|
|
|-----|--------|
|
||||||
@@ -317,18 +298,17 @@ docker run -p 3000:3000 -e JMAP_SERVER_URL=https://mail.example.com jmap-webmail
|
|||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
We welcome contributions! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
|
See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
|
||||||
|
|
||||||
## Roadmap
|
## Roadmap
|
||||||
|
|
||||||
See [ROADMAP.md](ROADMAP.md) for planned features and development status.
|
See [ROADMAP.md](ROADMAP.md) for planned features.
|
||||||
|
|
||||||
## Acknowledgments
|
## Acknowledgments
|
||||||
|
|
||||||
- [Stalwart Labs](https://stalw.art/) for creating an excellent JMAP mail server
|
- [Stalwart Labs](https://stalw.art/) for the mail server
|
||||||
- The [JMAP](https://jmap.io/) working group for the protocol specification
|
- The [JMAP](https://jmap.io/) working group for the protocol spec
|
||||||
- All contributors and users of this project
|
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
MIT. See [LICENSE](LICENSE).
|
||||||
|
|||||||
+1
-1
@@ -8,7 +8,7 @@ This document tracks the development status and planned features for JMAP Webmai
|
|||||||
- [x] Next.js 16 with TypeScript and App Router
|
- [x] Next.js 16 with TypeScript and App Router
|
||||||
- [x] Tailwind CSS v4 with Oxide engine
|
- [x] Tailwind CSS v4 with Oxide engine
|
||||||
- [x] Zustand state management
|
- [x] Zustand state management
|
||||||
- [x] JMAP client implementation (jmap-jam)
|
- [x] Custom JMAP client implementation (RFC 8620)
|
||||||
|
|
||||||
### Authentication
|
### Authentication
|
||||||
- [x] Login with JMAP server authentication
|
- [x] Login with JMAP server authentication
|
||||||
|
|||||||
Reference in New Issue
Block a user