Commit Graph
197 Commits
Author SHA1 Message Date
Jabi Infante 393fd12e8f feat: custom favicon with unread badge, fix stale mailbox counts
Replace the default Next.js favicon.ico with an SVG mail icon from
Lucide and add useFaviconBadge, a canvas-based hook that draws a red
unread-count badge on the tab favicon. Shows "+" when count > 9. On
Safari 15 and below (no Canvas roundRect), falls back to fillRect.

Also fixes a real JMAP push bug in the email store: Mailbox state
changes on push weren't always paired with Email changes, so unread
counts in the sidebar could go stale when a new message arrived. Now
Email changes refresh mailbox counts too, and the Mailbox branch
de-dups when both fire in the same push.

Credits #63 (@jabiinfante).
2026-04-16 23:06:26 +02:00
Roy Petter Dyrdahl Torgersen 76cebb7905 fix(contacts): batch ContactCard/get to respect maxObjectsInGet
Contact loading silently returned empty when the address book held
more entries than the server's maxObjectsInGet (Stalwart defaults to
500). Replace the single back-reference get with a two-step flow:
query IDs first, then pack a batched get into one JMAP request. All
batches ride a single HTTP roundtrip via multiple method calls.
Address books at or under the server cap still get a single method
call, so no behavior change for small lists.

Adds getMaxObjectsInGet() capability helper that mirrors the existing
getMaxCallsInRequest() / getMaxSizeUpload() shape. 83 new test cases
cover single-batch, exact-boundary, over-cap, and direct-ids paths.

Closes #45. Credits #46 (@capitanroy).
2026-04-16 23:04:57 +02:00
Prastowo aGung Widodo 3c1a4496f9 fix(print): restrict print area to the email viewer
The print output was capturing the entire window, so portrait pages
only showed the sidebar and message list. Scope the print rendering
with a @media print block that hides everything, then re-reveals the
#email-viewer-container subtree and positions it full-page. Add
print:hidden to the More Actions dropdown and the Quick Reply section
so they don't appear in the printed output.

Credits #55 (@prastowoagungwidodo).
2026-04-16 23:03:25 +02:00
Prastowo aGung Widodo e12bf45e84 fix(contacts): stop action buttons from wrapping on empty state
Apply whitespace-nowrap + overflow-hidden + text-ellipsis to the "New
Contact" / "Import vCard" buttons on the empty state, and add flex-wrap
+ min-w-0 on the parent so longer future translations wrap to a new
row instead of clipping behind the ellipsis. Icons get shrink-0 so
they stay rendered.

Credits #56 (@prastowoagungwidodo).
2026-04-16 23:02:23 +02:00
Joel Purra 7272466ffa ci: publish major version container image tag
Adds a `{{major}}` tag so users can pin to `jmap-webmail:1` and receive
non-breaking minor/patch updates without manually bumping the tag each
release.

Closes #57. Thanks @joelpurra.
2026-04-16 23:00:53 +02:00
Matthieu MALVACHE 09f72d3d4f 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.
2026-04-16 22:55:48 +02:00
Matthieu MALVACHE d33309a8b6 fix(security): escape quotes in plain-text linkifier, bump vulnerable deps
Plain-text email bodies were escaped for <, >, & but not " or ', and the
URL linkifier regex captured every non-whitespace character up to the
next <. A URL containing a double or single quote broke out of the
href attribute in the rendered anchor, allowing arbitrary event handlers
to be injected into otherwise plain-text mail. Reported by @rathlinus.

Extract a shared plainTextToSafeHtml helper in lib/email-sanitization.ts
that escapes all five HTML-significant characters in the correct order
before linkification, and route both email-viewer and thread view
through it. Add tests that parse the output and assert no onmouseover
attribute lands on the anchor element.

Also bump dependencies flagged by npm audit: next 16.2.4 (DoS in Server
Components), next-intl 4.9.1 (open redirect), dompurify 3.4.0
(FORBID_TAGS bypass); picomatch/vite/brace-expansion resolve
transitively. npm audit is clean.

Bump version to 1.4.1.
2026-04-16 22:47:15 +02:00
Matthieu MALVACHE e0bdf99d0d chore: exclude superpowers dirs from public release, reinforce no-AI-reference policy 2026-04-16 22:46:55 +02:00
Prastowo Agung Widodo b8df1f3051 Fix: missing email_viewer.send translation 2026-03-23 22:58:06 +01:00
Matthieu MALVACHE c78b766f2a fix: add type text/plain to textBody for RFC 8621 compliance (#48)
Apache JAMES requires the type field on textBody parts per strict
RFC 8621, while Stalwart is lenient. This fixes compose failures
on non-Stalwart JMAP backends.
2026-03-23 22:57:39 +01:00
Matthieu MALVACHE 4bdf98525c chore: remove AI reference from spam header comment 2026-03-23 15:26:12 +01:00
Matthieu MALVACHE 3cd3e26825 chore: bump version to 1.4.0
New features: folder management (#44), mail multi-selection (#43).
Bug fixes: health endpoint (#41), identity deletion (#42), inline CID
images, email list flicker, dependency updates.

Thanks to @wrenix, @ClemaX, @freddij, @dlecourtaltimafr, and @capitanroy
for reporting issues and contributing to this release.
2026-03-23 15:21:20 +01:00
Matthieu MALVACHE 301386c709 chore: fix stale tests, rename spam label, update deps and fix flatted CVE
- Fix oauth-discovery tests expecting removed console.error
- Rename "AI Analysis" to "Spam Analysis" in email viewer
- Update next 16.2.1, tailwind 4.2.2, zustand 5.0.12, eslint 9.39.4,
  typescript-eslint 8.57.1, tanstack/react-virtual 3.13.23
- Fix flatted prototype pollution (GHSA-rf6f-7fwh-wjgh)
2026-03-23 15:20:53 +01:00
Matthieu MALVACHE d3ef46f760 fix: add copy-to-clipboard feedback and neutralize dark mode background tint
Copy source button now shows a checkmark and "Copied" text for 2s
after clicking. Dark mode email background blend target changed to
perfectly neutral gray (R=G=B) to eliminate perceived color cast on
certain displays.
2026-03-23 15:14:14 +01:00
Matthieu MALVACHE 3ba5cf16c3 fix(sidebar): fix context menu viewport clipping and delete dialog overflow (#44)
Render context menu and delete confirmation dialog via portal to escape
sidebar overflow-hidden. Clamp context menu position to viewport bounds.
2026-03-23 14:39:20 +01:00
Matthieu MALVACHE be6907f863 feat(sidebar): add folder drag-and-drop reparenting (#44) 2026-03-23 14:29:16 +01:00
Matthieu MALVACHE 01cb0f173f feat(sidebar): add folder management UI with context menu, inline editing, and move-to (#44) 2026-03-23 14:26:22 +01:00
Matthieu MALVACHE adbf46770d feat(drag-drop): handle mailbox reparenting on drop (#44) 2026-03-23 14:20:20 +01:00
Matthieu MALVACHE d14b8f6567 feat(i18n): add folder management translation keys for all 8 locales (#44) 2026-03-23 14:18:51 +01:00
Matthieu MALVACHE d9d6b02987 feat(drag-drop): extend context with dragType for mailbox drag support (#44) 2026-03-23 14:17:20 +01:00
Matthieu MALVACHE 0b952dcce4 feat(store): add mailbox CRUD methods with optimistic UI (#44) 2026-03-23 14:15:17 +01:00
Matthieu MALVACHE a030707cd6 feat(jmap): add Mailbox/set methods for create, update, destroy (#44) 2026-03-23 14:13:01 +01:00
Matthieu MALVACHE cb862994e3 fix: render inline CID images in email body instead of showing as attachments
Emails with embedded images (cid: references) displayed them as
downloadable attachments because the browser cannot resolve cid: URLs
and the attachments were not filtered. Added fetchBlobAsObjectUrl to
the JMAP client, pre-fetch inline images as object URLs, replace cid:
references in sanitized HTML, and filter CID attachments from the
download list in both the email viewer and thread conversation view.
2026-03-23 14:11:25 +01:00
Matthieu MALVACHE 146921d5f0 fix: eliminate email list flicker during loading and after-action refreshes
Shared isLoading flag caused the list to dim on unrelated operations
(send, batch actions, mailbox refresh). After-action fetches also
triggered a full loading overlay unnecessarily. Now operations that
don't fetch emails no longer set isLoading, after-action refreshes
use silent refreshCurrentMailbox, and the loading overlay only appears
after a 300ms delay to skip fast fetches.
2026-03-23 14:11:09 +01:00
Matthieu MALVACHE c80a5a4d51 docs: add folder management implementation plan (#44)
8-task plan covering JMAP client methods, store layer, DragDropContext
extension, i18n, sidebar UI with inline editing and drag-and-drop.
2026-03-23 14:09:28 +01:00
Matthieu MALVACHE 7bed7ff7c7 docs: add folder management design spec (#44)
Spec for IMAP folder CRUD operations: create, rename, move, and delete
mailboxes via the sidebar context menu and drag-and-drop.
2026-03-23 13:59:28 +01:00
Matthieu MALVACHE f646badc55 fix: remove production console statements and explain eslint-disable comments
Remove ~60 console.error/log/warn calls from application code that were
leaking implementation details to browser devtools. Errors are already
surfaced to users via toast notifications or state updates.

Add missing rationale to all 9 bare eslint-disable comments so future
readers understand why deps are intentionally excluded.
2026-03-23 13:25:50 +01:00
Matthieu MALVACHE 4c97d2d41d fix(i18n): add missing delete_confirm_title and delete_confirm_message keys (#43) 2026-03-23 13:21:51 +01:00
Matthieu MALVACHE b685e37c4e fix: resolve lint errors in email store and move-to-popover (#43) 2026-03-23 13:07:24 +01:00
Matthieu MALVACHE ae92bd2cbc feat: complete multi-selection store methods, toolbar integration, and shift-click support (#43) 2026-03-23 13:02:58 +01:00
Matthieu MALVACHE 6fc7217185 feat(i18n): add translation keys for multi-selection batch actions (#43) 2026-03-23 12:56:00 +01:00
Matthieu MALVACHE 837ef722b6 feat: add MoveToPopover component with search and keyboard navigation (#43) 2026-03-23 12:55:43 +01:00
Matthieu MALVACHE 3835efb3fa feat(store): add range selection, filter selection, and lastSelectedIndex tracking (#43) 2026-03-23 12:54:23 +01:00
Matthieu MALVACHE 84c43f8b0e fix: add urn:ietf:params:jmap:submission to Identity and EmailSubmission ops (#42)
Per RFC 8621, Identity/get, Identity/set, and EmailSubmission/set require
the submission capability. Missing it caused Stalwart to reject identity
deletion (and potentially other identity operations).
2026-03-23 12:18:42 +01:00
Matthieu MALVACHE 0948108792 fix: use v8 heap_size_limit for health check instead of heapTotal (#41)
heapTotal is V8's current allocation, not the max. A 35MB process with
37MB allocated reads as 95% when the real limit is ~2GB, causing
container restarts. Also fix stale calendar-participants test expectations.
2026-03-23 12:18:27 +01:00
Matthieu MALVACHE df53c31708 chore: update Next.js 16.1.6 -> 16.2.0 (5 security fixes)
Fixes: CSRF bypass on Server Actions, HTTP request smuggling in
rewrites, unbounded image disk cache, postponed resume DoS, dev
HMR websocket CSRF bypass.
2026-03-20 16:52:32 +01:00
Rens Reinders 0153f66340 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:52 +01:00
Rens Reinders 167014871d 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:52 +01:00
WrenIX e9baac022c fix: hide vertical nav rail on tablet to avoid duplicate navigation (#40) 2026-03-18 11:09:35 +01:00
Rens Reinders 53ecfe5f69 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-18 11:09:35 +01:00
Rens Reinders ae0412d3db feat: add week numbers column to month view grid (#38) 2026-03-18 11:09:35 +01:00
Rens Reinders f6492bbeda 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-18 11:09:35 +01:00
Rens Reinders 3c0f3400b4 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-18 11:09:35 +01:00
Matthieu MALVACHE da158613ea chore: bump version to 1.3.2 2026-03-17 13:40:28 +01:00
Matthieu MALVACHE 961b3edc3a fix: consistent tablet navigation across all pages and nav bar polish
Show bottom nav on tablet breakpoint (768-1023px) for calendar and
contacts pages, matching the mail page. Add z-index to prevent content
bleeding through. Remove redundant active indicator bar since color
already signals active state.
2026-03-16 22:18:59 +01:00
Matthieu MALVACHE 52ae100c97 fix: show bottom navigation on tablet breakpoint for calendar and contacts pages
Consistent with the mail page fix - all three sections now show the
horizontal navigation bar on tablet/landscape viewports (768-1023px).
2026-03-16 21:20:10 +01:00
Matthieu MALVACHE ccd146f3da chore: bump version to 1.3.1 2026-03-16 17:14:54 +01:00
Matthieu MALVACHE 65d7f9c922 fix: show bottom navigation bar on tablet/landscape breakpoint (768-1023px)
Neither desktop vertical nav nor mobile bottom nav rendered in the
tablet range, leaving users with no way to switch sections.

Closes #30
2026-03-16 17:14:20 +01:00
Matthieu MALVACHE 05cdb6311a chore: bump version to 1.3.0 2026-03-16 16:30:46 +01:00
Matthieu MALVACHE 3bc2bc0ad8 docs: update ARCHITECTURE.md with v1.2.0 features 2026-03-16 16:24:48 +01:00