83 Commits
Author SHA1 Message Date
Matthieu MALVACHE fc7b22a74a chore: v1.7.3 - dependency maintenance
Next.js 16.3.5, DOMPurify 3.4.15, React 19.3, next-intl 4.14.5 and
tooling patch releases.
v1.7.3
2026-09-20 22:21:56 +02:00
Matthieu MALVACHE 773284e12e fix: restore lock file consistency for npm ci
The 1.7.2 version bump regenerated the lock and left a nested @emnapi
entry unresolved, which broke the Docker image build.
v1.7.2
2026-09-19 17:40:03 +02:00
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 d682f5fe23 fix: v1.7.1 - OIDC logout with Keycloak, favicon badge on Firefox, settings cleanup v1.7.1 2026-08-28 02:42:32 +02:00
Matthieu MALVACHE c4b1487328 docs: changelog entries for the pending fixes 2026-08-28 02:22:33 +02:00
Matthieu MALVACHE 147f1b36b5 fix: remove the dead-end sub-addressing Learn More control
The button in Settings > Identities opened the identity manager, which
says nothing about sub-addressing. The info row keeps the explanation;
acting on +tag mail (auto-filing into folders) is planned as part of
the filter rule builder. Refs #76
2026-08-28 02:21:27 +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 38234c2c68 test: cover the favicon badge href-mutation contract
Locks in the single-link behaviour Firefox depends on: badge by
mutating the existing icon link, restore the original href on zero
count and on unmount.
2026-08-28 02:07:12 +02:00
Matthieu MALVACHE e80088e111 Merge pull request #66 from nykk-io/fix/favicon-badge-firefox-compat
Favicon badge: mutate the existing icon link href so Firefox picks up
the badge; strokeRect fix for the Safari <=15 fallback. Resolved the
zero-unread repaint in favour of the href-restore approach.
2026-08-28 02:07:12 +02:00
Matthieu MALVACHE c3a79a8bc3 feat: v1.7.0 - unified inbox across accounts, cross-account search, send-as for shared accounts v1.7.0 2026-08-28 01:59:13 +02:00
Matthieu MALVACHE 6aa83258cd feat: v1.6.0 - global search, list pagination fix, server-side sort, Polish locale, menu accessibility v1.6.0 2026-07-05 14:25:39 +02:00
Matthieu MALVACHE 45f8417846 fix: regenerate lockfile with resolved optional platform packages v1.5.3 2026-07-05 05:08:01 +02:00
Matthieu MALVACHE 21a43d686d fix: restore optional platform deps in lockfile for the Docker image build 2026-07-05 05:01:36 +02:00
Matthieu MALVACHE e6a712f8b8 fix: v1.5.3 - stability and security fixes across send, filters, shared mailboxes and CSP 2026-07-05 04:53:54 +02:00
Matthieu M. b684314be8 Merge pull request #68 from travier/main-keep-stop-discard
sieve: Do not skip 'stop' when last action is 'discard'
2026-07-05 04:51:39 +02:00
Matthieu MALVACHE 3ea7441f93 fix: v1.5.2 - patch Next.js WebSocket SSRF (CVE-2026-44578)
Security: upgrade Next.js 16.2.4 -> 16.2.6 to patch CVE-2026-44578
(GHSA-c4j6-fc7j-m34r, CVSS 8.6, unauthenticated WebSocket-upgrade
SSRF on the built-in Node server) and eleven other May 2026
advisories bundled in the same release. next-intl patched for
GHSA-4c35-wcg5-mm9h prototype pollution in the experimental
precompile path. React/react-dom rolled forward to 19.2.6.

Fixes:
- bulk delete now honours the "delete to trash" setting instead of
  always hard-deleting
- favicon repaints the base icon on zero unread so the badge clears
2026-05-14 22:32:20 +02:00
Timothée Ravier 86166df79e sieve: Do not skip 'stop' when last action is 'discard'
See: https://thsmi.github.io/sieve-reference/en/action/core/discard.html
Fixes: https://github.com/root-fr/jmap-webmail/issues/67
2026-04-22 15:20:31 +02:00
Javier Infante 54a2f8569c fix: favicon badge — remove favicon.ico, fix Firefox compat
- Delete app/favicon.ico so Next.js renders a single <link rel="icon">
  for icon.svg. With two icon links in the DOM, browsers disagreed on
  which to use: Chrome and Firefox on Linux both picked the *first* one,
  making the dynamically-appended badge link invisible.
- Mutate href on the existing <link> instead of injecting a second one.
  Firefox only updates the tab icon when the href of the element it
  already tracks changes — adding new <link> nodes dynamically is ignored.
- Simplify image loading: replace fetch → blob → FileReader → Image
  chain with new Image() + crossOrigin="anonymous".
- Fix badge border in Safari 15 fallback: use strokeRect instead of
  stroke() after fillRect (fillRect does not add to the canvas path).
2026-04-19 21:21:18 +02:00
Matthieu MALVACHE f3e84a9549 fix: v1.5.1 - Gmail-origin attachments render, email-to-self delivered
- Attachments from providers that stamp a Content-ID on every part
  (e.g. Gmail) now show in the attachment panel; previously they were
  silently filtered out as "inline" even when the HTML body never
  cited their cid. The viewer now parses the body for actual cid:
  references and treats only those attachments as inline (#58).
- Email-to-self no longer gets discarded as a duplicate by the
  sender's own MTA. The send flow keeps the outgoing message in
  Drafts during submission and uses EmailSubmission.onSuccessUpdate\
Email to move it to Sent only after SMTP has accepted it, so the
  inbound delivery for self-send doesn't match a pre-existing
  Message-ID in the account (#60).

Thanks @melges-morgen and @tamisoft for the reports.
v1.5.1
2026-04-17 14:58:11 +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)
v1.5.0
2026-04-17 14:39:50 +02:00
Matthieu MALVACHE 01a7690b28 fix(security): escape linkClassName in plainTextToSafeHtml
Defense-in-depth. All current callers pass hardcoded tailwind class
strings, so this is not exploitable today, but a future caller that
forwarded a user-controlled value would get HTML injection through the
class attribute. Run the value through escapeHtml() and add a test
covering the attribute-escape case.
v1.4.1
2026-04-16 22:57:10 +02:00
Matthieu MALVACHE cc01b84f46 fix(security): XSS in plain-text linkifier, bump vulnerable dependencies
The plain-text email renderer escaped <, >, and & before building anchor
tags for linkified URLs, but did not escape " or '. A crafted URL
containing a quote broke out of the href attribute and could inject
event handlers into the rendered HTML. Affects both the single-email
viewer and the threaded conversation view.

Fix by extracting a shared plainTextToSafeHtml helper that escapes all
five HTML-significant characters in the correct order before
linkification. Both views route through it. Regression tests parse the
output and assert no event handler lands on the anchor element.

Reported privately by Linus Rath. Thank you for the responsible
disclosure.

Also bumps dependencies flagged by npm audit:
- Next.js 16.1.5 -> 16.2.4 (DoS in Server Components)
- next-intl 4.5.8 -> 4.9.1 (open redirect)
- DOMPurify 3.3.1 -> 3.4.0 (FORBID_TAGS bypass)
- picomatch, vite, brace-expansion resolve transitively

Also carries the Apache JAMES compose fix from the 1.4.0 cycle (explicit
text/plain type on textBody per RFC 8621 section 4.1.4) and the missing
email_viewer.send translation.

Release 1.4.1.
2026-04-16 22:51:58 +02:00
Matthieu M. 909c0efebe Merge pull request #47 from prastowoagungwidodo/fix-email_viewer-translation
Fix: missing email_viewer.send translation
2026-03-23 22:56:04 +01:00
Prastowo Agung Widodo 5890c3e3c2 Fix: missing email_viewer.send translation 2026-03-23 21:43:39 +07: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).
v1.4.0
2026-03-23 15:24:46 +01:00
Matthieu MALVACHE f6e188560f chore: release v1.3.3 - security patches, community contributions
Next.js 16.2.0 security update, plus merged PRs #33-#40 from
rensreinders and wrenix (calendar improvements, contacts UX, navigation)
v1.3.3
2026-03-20 16:54:09 +01:00
Rens Reinders 6758fae3ef fix: participant/invitation handling for Stalwart JMAP and deduplicate self-attendees (#36)
* fix: align calendar event payload with stalwart scheduling

* fix: dedupe calendar participants by normalized address

* chore: document calendar uid generation

* chore: clarify organizer participant guard
2026-03-18 21:13:36 +01:00
Rens Reinders 339c4e8640 feat: double-click to create event from month view with smart time suggestion (#37)
* feat: open event modal on month day cell click

* feat: suggest first available hour when creating from month view

* chore: document month view slot suggestion helpers

* fix(calendar): use double-click to create event in month view

* fix(calendar): use 9am fallback for non-today month slots
2026-03-18 21:13:33 +01:00
WrenIX b668373aa2 fix: hide vertical nav rail on tablet to avoid duplicate navigation (#40) 2026-03-18 11:07:28 +01:00
Rens Reinders 11a242ba40 fix: replace inline calendar delete confirms with centered modal dialog (#34)
* fix: more margin on the avatar to align with subject

* fix: fixed multi day events multiple items gap spacing

* fix: align sticky week headers with calendar grid

* fix: nice confirm modal

* fix: added locales

* fix: polish confirm dialog behavior and participant delete messaging

* fix: apply themed destructive colors without button shadow

* fix: restore destructive button theme styling
2026-03-17 23:46:34 +01:00
Rens Reinders ca6691fabb feat: simplify contact bulk selection actions menu (#39)
* feat(contacts): simplify bulk selection actions menu

* refactor(contacts): reuse shared context menu for bulk actions
2026-03-17 23:46:31 +01:00
Rens Reinders 9c75425503 feat: add week numbers column to month view grid (#38) 2026-03-17 23:46:28 +01:00
Matthieu MALVACHE c302a1a249 fix: consistent tablet navigation and nav bar polish (v1.3.2) v1.3.2 2026-03-17 13:42:12 +01:00
Matthieu MALVACHE f51c1feeab fix: consistent bottom navigation on tablet breakpoint for all pages
Bottom nav now renders on tablet/landscape viewports (768-1023px) across
Mail, Calendar, and Contacts. Added z-index for proper layering and
removed redundant active tab indicator bar.
v1.3.1
2026-03-16 22:20:29 +01:00
Matthieu MALVACHE d3f53a4ebd fix: show bottom navigation on tablet/landscape breakpoint (#30) 2026-03-16 17:17:18 +01:00
Rens Reinders 8c5f11f5fa fix: align sticky week headers with calendar grid and fix scroll offset (#33)
* fix: more margin on the avatar to align with subject

* fix: fixed multi day events multiple items gap spacing

* fix: align sticky week headers with calendar grid

* fix: account for sticky header in week view initial scroll
2026-03-16 16:51:15 +01:00
Matthieu MALVACHE 9b09f12e3a chore: bump version to 1.3.0 v1.3.0 2026-03-16 16:31:46 +01:00
Matthieu MALVACHE ede603563e feat: v1.2.0 — sandboxed email rendering, mobile UX, sidebar polish, API retry
New features:
- Sandboxed iframe rendering for rich HTML emails (CSS isolation)
- Mobile bottom action bar (Reply, Archive, Delete, More)
- Long-press context menu with haptic feedback on touch devices
- Tag counts sidebar section with batch JMAP queries
- Empty folder for Junk/Trash with batch delete progress
- Extra-compact density option (28px desktop, 44px touch)
- SPF/DKIM/DMARC security tooltips with plain-language explanations
- Resizable sidebars with drag, touch, and keyboard support
- Expandable sender info panel in email viewer
- API retry with exponential backoff for transient JMAP failures
- OAuth-only mode (OAUTH_ONLY env var)

Improvements:
- CSS-first responsive layout (no blink on orientation change)
- Touch-friendly context menu submenus (tap-to-expand)
- Click-to-toggle more-actions dropdown (was hover-only)
- Wide HTML emails horizontally scrollable in iframe
- All 8 locales updated with new translation keys
2026-03-16 16:29:47 +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.
v1.2.0
2026-03-16 13:08:40 +01:00
Matthieu MALVACHE 97546dbd58 fix: mobile navigation visibility and folder hierarchy in move dialog
- Bottom nav bar always visible on mobile, even when viewing an email (#30)
- Move-to-folder submenu shows hierarchical folder structure (#29)
v1.1.4
2026-03-16 12:58:50 +01:00
Matthieu MALVACHE 5880120431 fix: calendar crash on missing duration, sieve filter activation, security patches
- Guard parseDuration() against undefined event.duration (#31)
- Use onSuccessActivateScript per RFC 9661 for sieve filter activation (#21)
- Update dompurify, undici, flatted for security fixes
v1.1.3
2026-03-16 12:43:37 +01:00
Matthieu MALVACHE 58b9b70871 fix: resolve context menu submenu and move-to-folder issues (#19) v1.1.2 2026-03-02 09:10:03 +01:00
Matthieu MALVACHE 92620fb790 fix: details toggle UX, Edge Runtime warnings, minimatch CVE
- Keep show/hide details button in place when expanded (#18)
- Use i18n translations for details toggle text
- Split instrumentation for Edge Runtime compatibility
- Patch minimatch ReDoS (CVE-2026-27903)
v1.1.1
2026-02-28 21:03:02 +01:00
Matthieu MALVACHE a3fe9deaa6 feat: add server-side version update check
Logs current version on startup and checks GitHub for newer releases.
Only runs in production, output stays in server logs (no client exposure).
v1.1.0
2026-02-28 14:59:11 +01:00
Matthieu MALVACHE c65a6454c5 fix: remove jmap-jam reference, clean up README language 2026-02-26 13:50:39 +01:00
Matthieu MALVACHE a7908692ef fix(docker): resolve 4 CVEs in production image
Remove npm/npx from runner stage and upgrade Alpine packages to
patch minimatch, tar, busybox, and zlib vulnerabilities.
v1.0.2
2026-02-26 13:39:57 +01:00
Matthieu MALVACHE c59bf63603 chore: disable Next.js telemetry in Docker image v1.0.1 2026-02-26 01:16:24 +01:00
Matthieu MALVACHE 29f186b6f2 feat(ci): publish Docker image to Docker Hub and GHCR
Add dual-registry publishing to both Docker Hub (rootfr/jmap-webmail)
and GitHub Container Registry. Multi-arch support for amd64/arm64.
v1.0.0
2026-02-26 01:13:29 +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