- Created demo emails with various states (inbox, sent, drafts, trash, etc.) in `emails.ts`.
- Added demo file nodes representing directories and files in `files.ts`.
- Implemented demo Sieve capabilities and scripts in `filters.ts`.
- Defined demo identities for users in `identities.ts`.
- Established demo mailboxes with permissions and counts in `mailboxes.ts`.
- Created a demo vacation response in `vacation.ts`.
- Introduced a comprehensive JMAP client interface in `client-interface.ts` to standardize interactions with the JMAP API.
Add expandRecurrences: true to CalendarEvent/query when a date range
filter is provided, so the JMAP server returns individual occurrences
of recurring events instead of only the master event.
- Show address books in sidebar organized by personal directories and
shared accounts, replacing the flat shared accounts list
- Make contact list items draggable with multi-select support using
native HTML5 drag-and-drop (application/x-contact-ids MIME type)
- Add drop targets on sidebar address book items with visual feedback
- Add moveContactToAddressBook store method supporting same-account
updates and cross-account create+delete moves
- Add address book picker dropdown in contact create/edit form
- Update ContactCategory type from sharedAccountId to addressBookId
- Add address_books translations to all 8 locales
- Fix contact-list-item tests for new selectedContactIds prop
When authenticating with a local-part username (e.g. 'user' instead of
'user@domain.tld') on Stalwart 0.15.x, the default sender could resolve
to an alias identity instead of the canonical mailbox address.
- Add emailMatchesUsername() helper that matches local-part usernames
against full email addresses (e.g. 'user' matches 'user@domain.tld')
- Prefer canonical identities (mayDelete=false) over aliases as tiebreaker
- Add preferredPrimaryId to identity store (persisted to localStorage)
so users can explicitly set their default sender
- Add 'Set as Primary' star button in identity manager modal
- Fix sendEmail() fallback identity resolution for local-part usernames
- Add i18n strings for all 8 supported locales
Fixes#43
- Implemented Zustand store for S/MIME functionality, including state management for key records and public certificates.
- Added methods for importing PKCS#12 files and public certificates, binding identities to keys, and managing unlocked keys.
- Introduced session storage for remembering unlocked keys across sessions.
- Enhanced error handling and loading states during data operations.
- Implement JMAP FileNode client methods (get, query, list, create,
update, destroy, copy) with Stalwart-compatible flat name encoding
- Add FileNode/FileNodeFilter types to JMAP type definitions
- Create file-store with Zustand for file management state (navigate,
upload, delete, rename, move, cut/copy/paste, undo, favorites)
- Add folder tree sidebar component for sidebar navigation layout
- Add files settings dialog and settings page component with options
for view mode, sort, icons, thumbnails, hidden files, folder layout
- Update files page and file browser to support JMAP FileNode backend
alongside WebDAV, with folder layout switching and settings integration
- Add settings tab for files configuration in the settings page
- Add translation keys for file settings, calendar subscriptions,
identity deletion, contact deletion, email navigation, and
reconnection messages across all 8 locales
- Change WebDAV file storage to File storage in availability messages
- Enhance translations test to verify source-referenced keys exist in
the en locale
- Fix duplicate JSX attribute in folder-tree-sidebar
- Render HTML emails in sandboxed iframe (srcdoc) for true-to-life
display with complete CSS isolation from app styles
- Detect emails with native dark mode (prefers-color-scheme) and
let them handle their own theming
- Apply CSS filter inversion for dark mode on emails without native
support, with re-inversion for images/media to preserve appearance
- Add per-email light/dark toggle button (Sun/Moon icon) next to
email size, resets on email change (not persisted)
- Fix HTML reply/forward to include original email HTML content
- Send replies as multipart/alternative (text + HTML)
- Add drag-and-drop file attachments with overlay indicator
- Auto-resize composer textarea to avoid double scrolling
- Pin attachments section and bottom toolbar outside scroll area
- Collapsible attachment list (show 3, toggle for more)
Add a new Files section powered by WebDAV for browsing, uploading,
downloading, renaming, and deleting files and folders.
New features:
- WebDAV file browser with grid/list views and breadcrumb navigation
- File upload (drag-and-drop and button), folder creation, rename, delete
- File preview modals for images and other file types
- WebDAV proxy API route to handle authentication
- Navigation rail entry for Files (auto-hidden when WebDAV is unsupported)
Auth improvements:
- Fix premature redirects on calendar, contacts, and settings pages by
adding explicit auth check on mount before redirecting to login
- Persist active settings tab in localStorage
Other:
- Expose getAuthHeader() and getServerUrl() on JMAPClient
- Add WebDAV store with connection testing and capability detection
- Add i18n translations for file browser in all 8 locales (de, en, es,
fr, it, ja, nl, pt)
Inline CID images were replaced with raw JMAP download URLs that require authentication. When the browser loaded these as <img src>, the server responded with WWW-Authenticate: Basic, triggering a native login popup.
- Add fetchBlobAsObjectUrl() to JMAPClient that fetches blobs via authenticated request and returns blob: object URLs
- Update email-viewer and thread-conversation-view to fetch CID images asynchronously with auth, using blob: URLs instead of raw server URLs
- Add ALLOWED_URI_REGEXP to DOMPurify config so blob: URLs are not stripped during sanitization
- Add tests for fetchBlobAsObjectUrl and CID/blob URL sanitization
Add opt-in SSO authentication alongside Basic Auth. OAuth endpoints are
auto-discovered via .well-known, with support for external IdPs
(Keycloak, Authentik) via configurable OAUTH_ISSUER_URL. Sessions
persist through httpOnly refresh token cookies with automatic renewal.
- Emails now include the identity display name in the From field so recipients
see "Name <email>" instead of bare "<email>"
- Primary identity (matching login username) is pre-selected in composer dropdown
Distinguish CORS-blocked requests from genuine network failures using
a no-cors probe, so users deploying via Docker see a specific message
pointing to their JMAP server's CORS settings instead of a misleading
"unable to reach the server" error.
Full calendar support via JMAP Calendars (RFC 8984):
- Event create/edit/delete with recurrence rules and reminders
- Multi-day event spanning, column-based overlap layout
- Locale-aware date formatting, first day of week and time format settings
- Real-time updates via push notifications
- ARIA accessibility, input validation, color sanitization
- Keyboard shortcuts, mobile touch targets, focus trap
- ICU pluralization for all 8 supported languages
- Address book with JMAP sync and local fallback (contacts CRUD,
search/filter, composer autocomplete, i18n for 8 languages)
- Fix email layout: remove horizontal scroll, left-side clipping,
and empty spaces from blocked external images in newsletters
- Update all dependencies to latest compatible versions
- Expand i18n from 3 to 8 languages (added ES, IT, DE, NL, PT)
- Upgrade Next.js to 16.1.6 for security patches
This release significantly expands internationalization support and adds comprehensive identity management features.
Internationalization (i18n):
- Add 5 new languages: Spanish, Italian, German, Dutch, Portuguese
- Expand from 3 to 8 total supported languages
- Redesign language switcher for better scalability (dropdown UI)
- Complete translations for all features across all languages
Identity Management:
- Multiple sender identities with per-identity signatures
- Sub-addressing support (user+tag@domain.com)
- Context-aware tag suggestions for sub-addresses
- Identity badges in email viewer and list
- Full CRUD operations for managing identities
Newsletter Management:
- RFC 2369 List-Unsubscribe support (one-click unsubscribe)
- HTTP and mailto unsubscribe methods
- Security validation prevents XSS attacks
- Two-step confirmation with persistent dismissal
Security & Accessibility:
- Dark mode email readability (intelligent color transformation)
- WCAG 2.0 Level AA color contrast compliance
- Comprehensive XSS prevention with validation utilities
- Unit test coverage for security-critical code (57 validation tests)
Testing:
- Add unit tests for validation utilities
- Add unit tests for email sanitization
- Add unit tests for color transformation
- Full test coverage for XSS attack vectors
- Add pagination support to search (previously limited to 50 results)
- Search now scoped to current mailbox/folder
- Support shared mailbox folders in search
- Display total results count (e.g., "50 of 1400 conversations")
- Add clear (X) button to search input
- Re-run search when changing folders during active search
- Remove unused sidebar screenshot
A modern, privacy-focused webmail client built with Next.js and the JMAP protocol.
Designed for Stalwart Mail Server.
Features:
- Full email operations (compose, reply, forward, threading)
- Real-time push notifications
- Dark/light theme support
- Mobile responsive design
- Keyboard shortcuts
- Drag-and-drop organization
- i18n (English/French)
- Security-first (external content blocked, HTML sanitization)