11 Commits
Author SHA1 Message Date
Matthieu MALVACHE 70c5d1a839 fix: v1.7.2 - SSO sessions survive reloads with external identity providers
Request offline_access so the IdP issues a refresh token, and add an
OAUTH_SCOPES override for providers that reject or extend the default
list. Closes #104
2026-09-19 17:35:23 +02:00
Matthieu MALVACHE 20487d56f5 fix: send id_token_hint and client_id on the OIDC end-session redirect
Keycloak rejects an end-session request that carries
post_logout_redirect_uri without id_token_hint or client_id. Store the
id_token from the token exchange in an httpOnly cookie, pass it as
id_token_hint together with client_id on logout, and clear it with the
refresh token.

Fixes #102
2026-08-28 02:21:16 +02:00
Matthieu MALVACHE 41cc48203c feat: v1.5.0 - print, archive-thread, favicon badge + avatars, ru/uk locales
Community PRs and targeted feature work. Highlights:

Features
- Archive now operates on the whole conversation, matching Gmail (#49)
- Russian and Ukrainian locales, full translation sets (#59 @VsevolodSauta)
- Custom favicon with unread badge painted over the base mail icon;
  also fixes stale sidebar counters on JMAP push (#63 @jabiinfante)
- Optional domain-favicon avatars with a privacy-preserving proxy and
  a freemail denylist so the same provider logo isn't shown for every
  sender on a shared host (#22)

Fixes
- Print (Ctrl+P, button, menu) produces a clean single-column page for
  plain text and HTML emails alike, with actions/reply panels hidden,
  dark-mode overridden, and wide newsletters shrunk to fit A4
- Contacts now load past 500 entries by batching ContactCard/get to
  the server's maxObjectsInGet (#45 @capitanroy, #46)
- Sieve filter destinations use the full Parent/Child folder path so
  Stalwart can resolve them (#62 @travier)
- OIDC over plain HTTP shows a clear HTTPS-required banner instead of
  throwing crypto.subtle is undefined (#23 @jothoma1)
- Missing contacts delete-confirm translation keys added to every
  locale (only Dutch had them before)
- Favicon badge hook stopped tearing out Next.js's managed icon link,
  fixing a parentNode-is-null crash on route changes
- Contact empty-state action buttons fit their container (#56)
- Print layout excludes sidebar/list (#55 @prastowoagungwidodo)

Docs
- README example for OAUTH_ONLY=true to disable Basic Auth (#61
  @travier)

Infrastructure
- Container images also published under jmap-webmail:1 for major-tag
  pinning (#57 @joelpurra, closes #54)
2026-04-17 14:39:50 +02:00
Matthieu MALVACHE 384b757815 feat: v1.4.0 - folder management, mail multi-selection, bug fixes
New features:
- Folder management with context menu, inline editing, drag-and-drop (#44)
- Mail multi-selection with batch move/delete and shift-click (#43)

Bug fixes:
- Health endpoint false-positive restarts (#41, thanks @wrenix and @ClemaX)
- Identity deletion failing (#42, thanks @freddij)
- Inline CID images, email list flicker, dark mode clipboard tint

Feature requests from @dlecourtaltimafr (#43, #44).
Contact pagination fix contributed by @capitanroy (#46).

Dependencies: Next.js 16.2.1, Tailwind 4.2.2, Zustand 5.0.12,
flatted CVE fix (GHSA-rf6f-7fwh-wjgh).
2026-03-23 15:24:46 +01:00
Matthieu MALVACHE d56e05c146 feat: OAuth-only mode to enforce SSO-only login
New OAUTH_ONLY env var hides username/password form, showing only the
SSO button. Includes retry on discovery failure and accessibility fixes.
2026-03-16 13:08:40 +01:00
Matthieu MALVACHE 1b0e3e41c6 feat: add "Remember me" session persistence and simplify 2FA UX 2026-02-26 00:47:53 +01:00
Matthieu MALVACHE 7b6b8fc132 feat(auth): add RP-initiated logout and OAuth unit tests
OAuth logout now terminates the IdP session via end_session_endpoint
with HTTPS-only URL validation. Adds 14 unit tests for PKCE and
OAuth discovery.
2026-02-26 00:08:57 +01:00
Matthieu MALVACHE ec06b0c494 feat: add OAuth2/OIDC with PKCE for SSO login
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.
2026-02-25 23:41:37 +01:00
Matthieu MALVACHE fb414bf2c9 feat: add contacts phase 2, advanced search, vacation responder, Docker & TOTP 2FA
- Contact groups/lists, vCard import/export (RFC 6350), bulk operations
- Advanced search with JMAP filter panel, search chips, cross-mailbox queries
- Vacation responder with JMAP VacationResponse, settings tab, sidebar indicator
- TOTP two-factor authentication support
- Docker multi-stage build with standalone output and docker-compose
- CSP Report-Only headers and security headers via proxy middleware
- Virtual scrolling for large email lists
- Structured server-side logger (text/JSON, configurable level)
- 450+ tests (contacts, vCard, threads, headers, identity, components)
- Playwright E2E framework setup
- Updated README and ROADMAP with all new features
2026-02-16 18:51:30 +01:00
Matthieu MALVACHE 0d68851b63 feat(i18n): Complete internationalization with timezone fixes and language switching
Completes full internationalization coverage for the webmail application with enhanced language support:

- Replace all remaining hardcoded English strings with translation keys
- Add timezone auto-detection to prevent hydration mismatches
- Enable instant client-side language switching without page reload
- Add 60+ new translation keys in English and French locales
- Improve language switcher component with proper state management
- Add health check endpoint for container orchestration

All user-facing text now supports English and French with no hardcoded fallbacks, providing a fully localized experience.
2026-01-08 04:29:19 +01:00
Matthieu MALVACHE 58cfe09dc6 feat: Add runtime config, trusted senders, JMAP identities, and UI improvements
- Runtime environment variables for Docker-friendly configuration
- Trusted senders list for automatic image loading
- JMAP identities for proper sender address
- Improved email composer readability
- Horizontal scroll for wide HTML emails
2026-01-08 02:08:18 +01:00