mirror of
https://github.com/root-fr/jmap-webmail.git
synced 2026-09-28 00:01:19 +00:00
37 KiB
37 KiB
JMAP Webmail - TODO List
Mail Server: Using Stalw.art JMAP server
✅ Completed
Initial Setup
- Initialize Next.js 15.5 project with TypeScript
- Configure Tailwind CSS v4 with Oxide engine
- Set up git repository
- Install core dependencies (jmap-jam, zustand, lucide-react)
UI Components
- Create Button component with variants
- Create Input component
- Create EmailListItem component with unread/starred indicators
- Create EmailList component with avatars
- Create EmailViewer component with full HTML support
- Create EmailComposer modal component
- Create Sidebar with mailbox navigation
- Create Avatar component with color hashing
Layout & Styling
- Implement three-pane layout (sidebar, list, viewer)
- Add minimalist design system with gray palette
- Configure custom scrollbars
- Add responsive design considerations
- Fix Tailwind CSS v4 compatibility issues
State Management
- Set up Zustand store for email state
- Create mock data for development
- Implement email selection logic
- Implement mailbox selection
JMAP Integration (Partial)
- Create JMAP types (Email, Mailbox, Thread, etc.)
- Create JMAP client wrapper class
- Define core JMAP methods (getEmails, sendEmail, etc.)
📝 To Do
Authentication
- Create auth store with Zustand
- Create login page with JMAP server URL input
- Use environment variable for JMAP server URL configuration
- Simplify login UI with minimalistic design (no technical jargon)
- Redesign login page with modern minimalist UI
- Disable browser autocomplete for username field
- Implement custom username autocomplete with localStorage
- Add session management (note: no persistent sessions by design - password not stored)
- Implement logout functionality
- Add remember me functionality (username history only - no password storage for security)
- Handle authentication errors
- Add TOTP 2FA support (Stalwart-compatible password$totp concatenation, user-toggled field)
JMAP Server Connection
- Connect to real JMAP server
- Implement session establishment
- Handle connection errors and retries
- Fetch and display storage quota
- Add server capability detection
- Implement keep-alive mechanism
- Add shared folders support (multi-account access)
- Implement ID namespacing for shared mailboxes
- Fix unread counters for shared folders
- Auto-mark emails as read when opened in shared folders
Email Operations
- Wire up real email fetching from JMAP
- Implement email sending functionality
- Fetch full email content on selection
- Display actual dates instead of relative time
- Implement reply/reply-all/forward with proper quoting
- Add color tags/labels for emails (like Thunderbird)
- Implement mark as read/unread
- Implement star/unstar emails
- Implement delete email
- Implement archive email
- Implement full-text search
- Add draft auto-save
- Fix draft auto-save integration (properly use drafts when sending)
- Add draft discard confirmation with cleanup
- Add attachment download support
- Add attachment upload support
- Implement batch operations (mark read/unread, delete multiple)
- Implement functional quick reply form
- Add email threading support (Gmail-style inline expansion)
- Add List-Unsubscribe header support (RFC 2369) with one-click unsubscribe
Real-time Updates
- Set up EventSource for JMAP push notifications
- Implement state synchronization
- Handle email arrival notifications
- Update unread counts in real-time
- Handle mailbox changes
UI Enhancements
- Improve mailbox subfolder UI/UX with hierarchical display
- Improve email viewer UI with better sender display
- Add compact attachment display with file type icons
- Modernize email list with better visual hierarchy
- Widen email list panel for better readability
- Redesign email action buttons with modern look
- Improve email headers display with expandable details
- Add minimalist external content warning banner
- Simplify email notification banners (removed separators, cleaner spacing)
- Implement color tags with background tint display
- Create compact dynamic color picker (hover to reveal)
- Redesign Message Details with security & authentication indicators
- Add SPF/DKIM/DMARC status display with visual indicators
- Create organized sections for technical email details
- Parse and display email header information
- Add dark mode toggle with proper theme persistence
- Add i18n (internationalization) support with English, French, Japanese, Spanish, Italian, German, Dutch, and Portuguese
- Fix next-intl timezone configuration with auto-detection for global users
- Redesign sidebar footer with improved UI/UX for settings
- Fix theme switching and light mode application
- Fix language switcher functionality
- Add visual storage quota indicator with progress bar
- Add loading states and skeletons
- Add smooth email loading transitions with cross-fade effect
- Implement functional quick reply with auto-expand and direct send
- Implement error boundaries
- Create settings page
- Integrate mark-as-read delay setting in email viewer
- Integrate delete action setting (trash vs permanent)
- Integrate show preview toggle in email list
- Integrate external content policy with image loading
- Integrate debug mode with console logging
- Integrate animations toggle throughout components (uses CSS variable --transition-duration)
- Add keyboard shortcuts (j/k navigation, etc.)
- Implement drag-and-drop for emails (native HTML5 DnD API)
- Add context menus (right-click on emails with all actions)
- Create mobile-responsive design (hamburger menu, single/multi-pane adaptive layout)
- Implement pagination/infinite scroll for email list
- Fix dark mode email readability (transform inline color styles for unreadable emails)
- Fix email layout overflow (horizontal scroll, left-side clipping, blocked image empty spaces)
- Add ConfirmDialog component with promise-based useConfirmDialog hook (async await confirmation flow)
- Add WelcomeBanner onboarding component (one-time display, localStorage persistence, animated dismiss)
- Add NavigationRail component (vertical desktop icon rail, horizontal mobile bottom tab bar)
- Implement unified notification banner hierarchy in email viewer (external content, unsubscribe, calendar invitation)
- Add reusable focus trap hook (useFocusTrap: Tab cycling, Escape handling, focus restore)
- Add inline form validation with shake animation (email composer: required fields, contact form: email format on blur)
- Add login form UX polish (shake on error, TOTP slide animation, password visibility toggle, session expired banner)
- Add empty state patterns for contacts (distinct "no data" vs "no search results" with contextual actions)
- Add WCAG AA compliant reduced-motion media query (global animation/transition reset)
- Add safe area inset utilities for notched devices (env(safe-area-inset-*))
- Add sr-only live region for screen reader announcements
- Add toast notification system with undo action support (Zustand store, typed durations, stacking)
- Add dynamic page title updates (mailbox name, email subject, composer mode)
- Create UI/UX patterns documentation (docs/UI_UX_PATTERNS.md)
Identity Management & Sub-Addressing
- Add Identity/set methods to JMAP client (create, update, delete)
- Create identity store with Zustand (identities + sub-addressing state)
- Create sub-addressing utilities (parse, generate, suggest tags)
- Build Identity Manager Modal (list, create, edit, delete identities)
- Build Identity Form component (name, email, signatures)
- Create Identity Settings panel
- Add Identities tab to Settings page
- Add i18n keys for identity management (EN + FR + JA + ES + IT + DE + NL + PT)
- Build Sub-Address Helper component (tag input, suggestions, preview)
- Build Email Identity Badge component (viewer + list display)
- Integrate identity selector into email composer
- Add sub-addressing support to email composer
- Show identity badges in email viewer
- Show sub-address badges in email list
- Test identity CRUD operations (20 JMAP client tests)
- Test sub-addressing workflow (60 unit tests)
- Test error handling and edge cases (31 store tests)
Calendar Integration
- Add JMAP Calendar TypeScript types (Calendar, CalendarEvent, Participant, RecurrenceRule, Alert, Location)
- Add JMAP Calendar client methods (getCalendars, queryCalendarEvents, createCalendarEvent, updateCalendarEvent, deleteCalendarEvent)
- Add calendar capability detection (supportsCalendars via urn:ietf:params:jmap:calendars)
- Create calendar Zustand store with persist middleware (calendars, events, view mode, date range)
- Add calendar i18n translations (all 8 locales: EN/FR/JA/ES/IT/DE/NL/PT)
- Build calendar page with month/week/day/agenda views
- Build event modal (create/edit/delete with date/time, recurrence, reminders)
- Build mini-calendar sidebar and calendar list with color toggles
- Add calendar settings tab (default view, week start, time format)
- Integrate calendar into sidebar navigation (capability-gated)
- Integrate calendar into auth store (auto-fetch on login, clear on logout)
- Add calendar state to push notification handling
- Fix multi-day events rendering across all spanned days
- Fix overlapping timed events with column-based layout (Google Calendar style)
- Wire firstDayOfWeek and timeFormat settings to all calendar views
- Add locale-aware date formatting via next-intl useFormatter
- Add error handling with toast feedback on event CRUD failures
- Add capability check on calendar page (redirect if unsupported)
- Add ARIA roles/labels to calendar grids (role=grid, gridcell, aria-selected)
- Add ARIA labels to event cards (title, time, calendar context)
- Add timezone support on event creation (Intl.DateTimeFormat auto-detection)
- Add input length validation on event fields (title, description, location)
- Add color value sanitization for calendar/event colors in inline styles
- Add start/end time validation in event modal (auto-adjust end if before start)
- Add focus trap in event modal
- Add mobile touch targets (44px minimum) on event card chips
- Add P1W (week) duration parsing in event cards
- Fix current time indicator to update every minute (was static)
- Fix week view date label to use correct week start
- Fix calendar push notifications (Calendar/CalendarEvent state changes now refresh data)
- Fix error messages to use generic text (no server detail leakage)
- Fix debug logging (calendar store now uses lib/debug.ts)
- Fix ICU pluralization for alert time translations (all 8 locales)
- Fix sidebar panel heading semantic mismatch (now uses "My calendars")
- Add loading indicator during event fetching
- Add store error state display via toast
- Add agenda view keyboard shortcut (a)
Address Book & Contacts
- Create contact store with Zustand (dual mode: JMAP sync + local fallback)
- Implement contact CRUD operations (create, read, update, delete)
- Create contacts list view with search/filter
- Add contact details view/edit form
- Sync contacts with JMAP server (RFC 9553/9610 ContactCard/AddressBook)
- Implement email autocomplete from contacts
- Integrate contacts with email composer (To/Cc/Bcc autocomplete)
- Add i18n support for contacts (all 8 languages)
- Implement contact groups/lists management (JMAP members map, group CRUD, composer autocomplete expansion)
- Add vCard import/export support (custom RFC 6350 parser/generator, import with duplicate detection, export via Blob API)
- Add bulk contact operations (multi-select, bulk delete, bulk add to group, bulk export)
Advanced Features
- Implement email filters (JMAP Sieve Scripts RFC 9661 — visual rule builder + raw Sieve editor, capability-gated)
- Add calendar integration (JMAP Calendars - see Calendar Integration section)
- Create email templates (local storage, placeholder variables, composer integration, settings tab, 48 tests)
- Add calendar event drag-and-drop rescheduling (week/day time snap, month date move, visual indicators)
- Add participant scheduling with iTIP invitations (organizer/attendee UI, RSVP buttons, contact autocomplete, scheduling messages, DnD notification, 26 tests)
- Add free/busy queries (Principal/getAvailability)
- Add iCalendar import via CalendarEvent/parse (file upload, preview, bulk import, 5MB limit)
- Add inline calendar invitation banner in email viewer (auto-detect .ics attachments, parse event details, RSVP Accept/Maybe/Decline, import to calendar, cancellation display, 25 tests)
- Add calendar sharing UI (JMAP Sharing RFC 9670)
- Add calendar event notifications display (client-side alert evaluation, toast notifications, sound, global hook, settings toggles, 26 tests)
- Add signature management (implemented via Identity Management - per-identity signatures)
- Implement vacation responder settings (JMAP VacationResponse singleton, settings tab, sidebar indicator)
- Add email aliases support (implemented via Sub-Addressing - user+tag@domain.com)
- Create advanced search with filters (JMAP filter panel, search chips, debounced inputs, AbortController dedup)
- Add email encryption support (PGP/GPG)
Performance Optimizations
- Implement virtual scrolling for large email lists (@tanstack/react-virtual, dynamic measurement, keyboard scroll-to)
- Add email content caching
- Optimize bundle size
- Add service worker for offline support
- Implement lazy loading for attachments
- Add image optimization for email content
Testing
- Add unit tests for utilities (validation.test.ts: 57 tests, full coverage including XSS vectors)
- Add unit tests for contact store (contact-store.test.ts: 56 tests)
- Add unit tests for JMAP contact client (jmap-contact-client.test.ts: 41 tests)
- Add unit tests for vCard parser (vcard.test.ts: 18 tests)
- Add unit tests for thread utilities (thread-utils.test.ts: 20 tests)
- Add unit tests for email headers (email-headers.test.ts: 39 tests)
- Create component tests (contact-list, contact-detail, contact-form, contact-list-item, button, input, avatar: 41 tests)
- Test JMAP client methods (identity: 20 tests, contacts: 41 tests)
- Set up Playwright E2E framework (login, contacts, email test skeletons)
- Add E2E tests with real JMAP server
- Add accessibility testing
- Performance testing
Documentation
- Create user documentation
- Add API documentation for JMAP client
- Create deployment guide
- Add configuration documentation
- Create contributing guidelines
Deployment
- Create environment variable management (.env.local and .env.example)
- Add runtime configuration support (Docker-friendly, no rebuild required)
- Add health check endpoint
- Add Docker support (Dockerfile multi-stage build, docker-compose.yml, .dockerignore)
- Add Next.js standalone output for container deployments
- Add structured server-side logger (lib/logger.ts - text/JSON format, configurable level)
- Publish Docker image to GitHub Container Registry (ghcr.io/root-fr/jmap-webmail, multi-arch amd64/arm64)
- Add GitHub Actions CI/CD for automated image builds (path-filtered, version-tagged)
- Configure production build optimizations
- Set up monitoring and logging
Security
- Block external images/content by default (privacy protection)
- Add user control for loading external content
- Sanitize HTML email content with DOMPurify (comprehensive config with forbidden tags/attributes)
- Implement CSP headers (Content-Security-Policy-Report-Only via proxy.ts middleware with per-request nonce)
- Add security headers (X-Content-Type-Options, X-Frame-Options, Referrer-Policy, Permissions-Policy, X-XSS-Protection)
- Implement rate limiting
- Add CORS configuration
- Implement secure cookie handling (note: uses Basic Auth, no session tokens)
🐛 Known Issues
- Fix Next.js workspace root warning
- Handle port conflicts more gracefully (using port 3001)
- Improve error messages for failed JMAP operations (login errors now properly displayed)
- Fixed JamClient import issue from jmap-jam library
- Fixed multiple JMAP client files issue (cleaned up to single client.ts)
- Fixed session persistence on page refresh (using sessionStorage for credentials)
- Fixed mailbox ID mismatch (now using actual IDs from server)
- Fixed email not displaying (proper mailbox filtering)
- Fixed mailbox counters showing fake data (now showing real server data)
- Fixed color removal not working (keywords now set to false instead of deleted)
- Fixed color indicator showing previous color after removal
- Fixed HTML emails showing unwanted borders (selective CSS for data tables)
- Fixed email remaining open when switching mailboxes (now clears selection)
- Fixed attachment downloads returning 404 (proper URI template handling)
- Fixed plain text emails displaying on one line (smart HTML/text version selection)
- Fixed light mode not applying properly (replaced hardcoded colors with CSS variables)
- Fixed all hardcoded colors in email viewer for proper theme support
- Fixed sidebar footer menu extending page height when scrolling (overflow containment)
- Fixed dark mode folder selection not visible (improved accent color contrast)
- Fixed inbox not selected by default on login (auto-select primary account inbox)
- Fixed email store not cleared on logout (proper state reset)
- Fixed search results limited to 50 (added pagination support to searchEmails)
- Fixed email layout horizontal scroll and left-side text clipping (removed width: max-content CSS)
- Fixed blocked external images leaving large empty spaces in newsletter emails (container collapsing)
📊 Code Audit Summary (Last verified: 2026-02-17)
Settings Integration Status
All settings are now properly wired to their functionality:
| Setting | Store Location | UI Control | Actual Integration |
|---|---|---|---|
| deleteAction | settings-store.ts:26 | email-settings.tsx | ✅ Moves to trash or permanently deletes |
| showPreview | settings-store.ts:27 | email-settings.tsx | ✅ Conditionally renders preview in email list |
| externalContentPolicy | settings-store.ts:29 | email-settings.tsx | ✅ Controls external content blocking (ask/block/allow) |
| debugMode | settings-store.ts:40 | advanced-settings.tsx | ✅ Conditional logging via lib/debug.ts |
| animationsEnabled | settings-store.ts:17 | appearance-settings.tsx | ✅ Works via CSS variable |
| markAsReadDelay | settings-store.ts:25 | email-settings.tsx | ✅ Fully integrated |
New UI Features (2025-12-10)
- Drag-and-Drop: Native HTML5 DnD API - drag emails to mailbox folders in sidebar
- Files: contexts/drag-drop-context.tsx, hooks/use-email-drag.ts, hooks/use-mailbox-drop.ts
- Multi-select support, permission validation, visual feedback
- Context Menus: Right-click on email list items
- Files: components/ui/context-menu.tsx, components/email/email-context-menu.tsx, hooks/use-context-menu.ts
- Reply, Forward, Move to, Color tags, Delete - supports batch operations
- Mobile Responsive: Adaptive single/multi-pane layout
- Files: stores/ui-store.ts, hooks/use-media-query.ts, components/layout/mobile-header.tsx
- Hamburger menu navigation, view switching, safe area support
Keyboard Shortcuts (2025-12-10)
- Hook: hooks/use-keyboard-shortcuts.ts
- Modal: components/keyboard-shortcuts-modal.tsx
- Navigation: j/k or arrows (next/prev email), Enter/o (open), Esc (close)
- Actions: r (reply), R/a (reply all), f (forward), s (star), e (archive), #/Del (delete), u (unread)
- Global: c (compose), / (search), ? (help), Shift+G (refresh), Ctrl+A (select all)
- Threads: x (expand/collapse thread)
- Disabled when typing in inputs or when composer is open
Email Threading (2025-12-10)
- Style: Gmail-style inline expansion (desktop), full-screen conversation view (mobile)
- Files:
- lib/thread-utils.ts - Thread grouping utilities
- lib/jmap/types.ts - ThreadGroup interface
- lib/jmap/client.ts - getThread(), getThreadEmails() methods
- stores/email-store.ts - Thread expansion state (expandedThreadIds, threadEmailsCache)
- components/email/thread-list-item.tsx - Collapsed/expanded thread view (desktop), tap-to-open (mobile)
- components/email/thread-email-item.tsx - Compact email within thread
- components/email/thread-conversation-view.tsx - Full-screen mobile conversation view
- components/email/email-list.tsx - Groups emails by threadId
- Desktop Features:
- Threads grouped by threadId (client-side grouping)
- Collapsed view shows: participants, email count badge, latest subject/date
- Expanded view shows: all emails in thread with indentation
- Lazy loading: complete thread fetched via Thread/get on expansion
- State preserved per-mailbox, cleared on mailbox switch
- Keyboard: x to expand/collapse selected thread
- Mobile Features:
- Tap thread → full-screen conversation view (no inline expansion)
- Collapsible email cards, most recent auto-expanded
- Full HTML email content with DOMPurify sanitization
- External content blocking with user override
- Inline attachments with download support
- Reply/Reply All/Forward buttons on expanded cards
- Back navigation returns to email list
Dark Mode Email Readability (2026-01-08)
- Problem: HTML emails with inline color styles (e.g.,
color: #333333) became unreadable in dark mode - Solution: Intelligent color transformation during HTML sanitization
- Files:
- lib/color-transform.ts - Color parsing, luminance calculation, and transformation utilities
- lib/tests/color-transform.test.ts - Comprehensive test suite (40 tests)
- components/email/email-viewer.tsx - Extended DOMPurify hook to transform inline styles
- Features:
- Automatically detects and transforms dark text colors in dark mode
- Preserves light colors and original design intent
- Only affects dark mode (light mode unchanged)
- Supports multiple color formats (hex, rgb, rgba, hsl, named colors)
- Transforms
color,background-color,background, andborder-colorproperties - Uses WCAG 2.0 luminance calculation for accurate color detection
- Handles edge cases: transparency, inherit, currentColor, !important
- Technical Details:
- Luminance < 0.4 (very dark): Inverted and brightened
- Luminance 0.4-0.6 (medium): Lightened by 40-50%
- Luminance > 0.6 (light): Preserved as-is
- Falls back gracefully on parse errors
Identity Management & Sub-Addressing (2026-01-08)
- Identity Management: Full CRUD operations for multiple email identities
- Files: stores/identity-store.ts, lib/jmap/client.ts (Identity/get, Identity/set)
- Components: components/identity/identity-manager-modal.tsx, components/identity/identity-form.tsx
- UI Integration: components/settings/identity-settings.tsx
- Sub-Addressing: Generate tagged email addresses (user+tag@domain.com)
- Files: lib/sub-addressing.ts (parse, generate, suggest utilities)
- Component: components/identity/sub-address-helper.tsx
- Features: Tag suggestions based on mailbox/subject, email preview, validation
- Email Composer Integration:
- Identity selector dropdown with signatures
- Sub-address generation with real-time preview
- Automatic From field population
- Visual Indicators:
- components/email/email-identity-badge.tsx - Shows identity + sub-address tags
- Displayed in email viewer (recipient chips) and email list (compact badges)
- i18n Support: Full EN/FR/JA/ES/IT/DE/NL/PT translations in locales//common.json (identity., sub_address.*)
- Security: Input validation, XSS prevention in signatures (DOMPurify), sub-address format validation
Newsletter Unsubscribe (2026-01-08)
- RFC 2369 Compliance: Parses List-Unsubscribe headers from emails
- Files: lib/validation.ts (parseUnsubscribeUrls, isValidUnsubscribeUrl)
- Files: lib/email-headers.ts (extractListHeaders function)
- Component: components/email/unsubscribe-banner.tsx
- Integration: email-viewer.tsx detects and displays unsubscribe banner
- Security Features:
- URL validation blocks XSS vectors (javascript:, data:, file:, etc.)
- Only allows http://, https://, and mailto: protocols
- Email validation for mailto: URLs
- Comprehensive test coverage (57 tests including XSS attack vectors)
- User Experience:
- Two-step confirmation process (prevents accidental clicks)
- Dismissible with localStorage persistence (won't re-show for same email)
- Supports both HTTP (one-click) and mailto methods
- Auto-prefers HTTP over mailto when both available
- Integrated with external content banner (unified notification area)
- Success/error states with auto-dismiss
- Mobile-friendly with 44px touch targets
- i18n Support: Full EN/FR/JA/ES/IT/DE/NL/PT translations in email_viewer.unsubscribe_banner.*
Accessibility Improvements (2026-01-08)
- WCAG 2.0 Level AA Compliance: Comprehensive color contrast review and fixes
- Files: app/globals.css (blockquote/quoted text colors)
- Files: components/email/email-viewer.tsx (email preview colors)
- Documentation: CLAUDE.md (accessibility guidelines and standards)
- Critical Fixes:
- Replaced hardcoded hex colors (#666, #999) with CSS variables in email preview
- Strengthened blockquote text color from #6b7280 → #4b5563 (5.3:1 → 7.8:1 contrast)
- Strengthened quoted email text color to match blockquote improvement
- All fixes maintain dark mode compatibility
- Color Contrast Standards:
- Normal text: 4.5:1 minimum (AA), 7:1 target (AAA)
- Large text: 3:1 minimum
- Tested combinations documented in CLAUDE.md
- Guidelines Established:
- Never use hardcoded hex colors in components
- Always use CSS variables or Tailwind classes
- Minimum opacity 0.7 for text-muted-foreground in light mode
- Semantic color patterns for success/error/warning/info states
- Testing requirements for both light and dark modes
- Developer Resources:
- Color decision tree for choosing appropriate text colors
- Common mistakes to avoid documented
- Browser DevTools accessibility testing instructions
Email Layout & Blocked Content Fix (2026-02-16)
- Problem: Newsletter emails had horizontal scroll, left-side text clipping, and large empty spaces when images blocked
- Root Cause: CSS
width: max-contentanddisplay: inline-blockon email content wrappers forced content wider than container - Files:
- app/globals.css - Removed problematic width/display rules from
.email-content-wrapperand.email-content - lib/email-sanitization.ts - New
collapseBlockedImageContainers()utility - components/email/email-viewer.tsx - Post-processing to collapse empty containers after DOMPurify
- components/email/thread-conversation-view.tsx - Same fix for thread view
- app/globals.css - Removed problematic width/display rules from
- Fixes:
- Removed
display: inline-blockfrom wrapper,width: max-contentfrom content,min-width: max-contentfrom tables - Added
overflow-wrap: break-wordfor long text handling - Blocked images: walks up DOM from hidden
<img>to parent<td>/<th>/<div>, collapses if no visible text/links/media
- Removed
Dependency Updates (2026-02-16)
- All packages updated to latest compatible versions
- Major upgrades: @types/node 22→25, jsdom 27→28, lucide-react 0.562→0.564
- Notable: next 16.1.6, react 19.2.4, next-intl 4.8.3, zustand 5.0.11, vitest 4.0.18
- eslint 10 skipped (ecosystem plugins not yet compatible)
Calendar Integration (2026-02-16)
- JMAP Calendars: Full CalendarEvent CRUD with RFC 8984 types
- Files: lib/jmap/types.ts (Calendar, CalendarEvent, Participant, RecurrenceRule, Alert, Location types)
- Files: lib/jmap/client.ts (getCalendars, queryCalendarEvents, createCalendarEvent, updateCalendarEvent, deleteCalendarEvent)
- Capability detection:
urn:ietf:params:jmap:calendarsin auth-store.ts
- Store: stores/calendar-store.ts (Zustand with persist middleware)
- Calendars, events, view mode (month/week/day/agenda), date range, selected event
- Auto-fetch on login, clear on logout via auth-store integration
- Error logging via lib/debug.ts, generic user-facing error messages
- UI Components: components/calendar/ (9 components)
- month-view.tsx, week-view.tsx, day-view.tsx, agenda-view.tsx
- toolbar.tsx, event-modal.tsx, event-card.tsx
- mini-calendar.tsx, calendar-sidebar-panel.tsx
- Settings: components/settings/calendar-settings.tsx (default view, week start, time format)
- Page: app/[locale]/calendar/page.tsx
- Capability check (redirects if server doesn't support calendars)
- Error handling with toast feedback on CRUD failures
- Loading indicator during event fetching
- Settings forwarded to all view components (firstDayOfWeek, timeFormat)
- Integration: auth-store capability detection, sidebar nav link (capability-gated), settings tab, push notification state handling (Calendar + CalendarEvent)
- i18n: Full EN/FR/JA/ES/IT/DE/NL/PT translations (calendar.* namespace, ICU pluralization)
- Multi-day Events: Events spanning multiple days render on each day they cover
- Overlap Detection: Column-based layout for concurrent events (Google Calendar style)
- Locale-aware Dates: Month/day names via next-intl useFormatter (respects user locale)
- Accessibility: ARIA grid roles, event card labels, 44px mobile touch targets, focus trap in modal
- Security: Input length validation, color value sanitization, timezone auto-detection, error message sanitization
- Keyboard Shortcuts: m (month), w (week), d (day), a (agenda), t (today), n (new event), arrows (navigate)
- Drag-and-Drop Rescheduling: Drag events in week/day views to change time (15-min snap), month view to change date
- HTML5 DnD API with
application/x-calendar-eventpayload - Visual snap indicator with time label in week/day views, blue ring highlight in month view
- Optimistic update via updateEvent, error rollback with toast
aria-roledescription="draggable event"for accessibility
- HTML5 DnD API with
- iCalendar Import: Upload .ics files, parse via JMAP CalendarEvent/parse, bulk create
- Files: lib/jmap/client.ts (parseCalendarEvents), components/calendar/ical-import-modal.tsx
- Multi-step flow: file select → preview list → calendar selector → import
- File validation (5MB max, .ics/.ical extension), DOMPurify for descriptions
- Select/deselect individual events, progress indicator, success/error toasts
- Toolbar Import button with Upload icon
- i18n: calendar.import.* keys in all 8 locales (17 strings each)
Email Filters & Sieve Rules (2026-02-16)
- JMAP Sieve Scripts (RFC 9661): Full server-side email filtering with visual builder + raw editor
- Types: lib/jmap/sieve-types.ts (SieveScript, SieveCapabilities, FilterRule, FilterCondition, FilterAction)
- Client: lib/jmap/client.ts (12 Sieve methods: supportsSieve, getSieveCapabilities, getSieveScripts, getSieveScriptContent, createSieveScript, updateSieveScript, deleteSieveScript, activateSieveScript, deactivateSieveScript, validateSieveScript)
- Capability detection:
urn:ietf:params:jmap:sievein auth-store.ts
- Sieve Generator/Parser: lib/sieve/generator.ts, lib/sieve/parser.ts
- Rules stored as JSON metadata in
/* @metadata:begin ... @metadata:end */comment block - Dynamic
requireextension computation from enabled rules' actions - Round-trip fidelity: parse → edit → regenerate preserves all rule data
- Hand-edited scripts detected as "opaque" → raw editor only
- 64 tests (50 generator + 14 parser)
- Rules stored as JSON metadata in
- Store: stores/filter-store.ts (Zustand, no persist)
- Rules CRUD: addRule, updateRule, deleteRule, reorderRules, toggleRule
- fetchFilters, saveFilters, validateScript via JMAP client
- Opaque script detection for hand-edited Sieve scripts
- Auto-fetch on login via auth-store, clear on logout
- UI Components:
- components/settings/filter-settings.tsx — Settings tab: rule list with drag-and-drop reorder, toggle, edit, delete, raw editor toggle
- components/filters/filter-rule-modal.tsx — Modal: name, match type (all/any), condition rows, action rows, stop processing
- components/filters/sieve-editor-modal.tsx — Modal: monospace editor with line numbers, validate button, two-step save confirmation
- Conditions: From, To, Cc, Subject, Custom Header, Size, Body with comparators: contains, not contains, is, not is, starts with, ends with, matches, greater than, less than
- Actions: Move to folder, Copy to folder, Forward, Mark as read, Star, Add label, Discard, Reject, Keep, Stop processing
- Integration: Settings tab (capability-gated), push notification handling (SieveScript state changes), auth-store init/cleanup
- i18n: Full EN/FR/JA/ES/IT/DE/NL/PT translations (settings.filters.* namespace + sieve_editor sub-namespace)
- Accessibility: Focus trap in modals, ARIA labels, keyboard support (Esc to close, Ctrl+Enter to save), drag-and-drop reorder with grip handles
Email Templates (2026-02-17)
- Local Storage: Templates persisted in browser via Zustand persist middleware
- Files: lib/template-types.ts (EmailTemplate type), stores/template-store.ts (CRUD, categories, search)
- Categories: General, Business, Personal, Support, Follow-up, custom
- Placeholder Variables: Dynamic
{{variable}}syntax with auto-fill from composer context- Files: lib/template-utils.ts (extractPlaceholders, fillPlaceholders, variable suggestions)
- Built-in variables: recipientName, recipientEmail, senderName, senderEmail, date, time, subject
- Custom placeholders prompted via modal on template use
- Context-aware: auto-fills from To field, identity, current date/time
- UI Components: components/templates/ (4 components)
- template-manager-modal.tsx — Full CRUD: list, search, filter by category, edit, delete, duplicate
- template-form.tsx — Create/edit with name, category, subject, body, placeholder preview
- template-picker.tsx — Quick picker in composer toolbar with search and category filter
- placeholder-fill-modal.tsx — Prompt for custom placeholder values before inserting
- Composer Integration: Template picker button in email composer toolbar
- Populates subject and body fields, merges placeholders with context
- Keyboard shortcut: Ctrl+Shift+T to open template picker
- Settings: components/settings/template-settings.tsx — Settings tab for template management
- i18n: Full EN/FR/JA/ES/IT/DE/NL/PT translations (templates.* namespace)
- Testing: 48 tests (lib/tests/template-utils.test.ts)
Feature Completeness
- Authentication: ✅ Complete (secure design, no password storage)
- Email Operations: ✅ Complete (including threading, unsubscribe)
- Real-time Updates: ✅ Complete (EventSource push, toast notifications, status indicator)
- UI Enhancements: ✅ Settings fully integrated, drag-drop, context menus, mobile responsive, keyboard shortcuts, WCAG AA accessibility
- Identity Management: ✅ Complete (CRUD, sub-addressing, signatures, visual badges)
- Newsletter Management: ✅ RFC 2369 List-Unsubscribe support with security validation
- Contacts/Address Book: ✅ Phase 2 complete (groups, vCard import/export, bulk ops, composer group expansion)
- Advanced Search: ✅ Complete (JMAP filters, advanced panel, search chips, cross-mailbox)
- Vacation Responder: ✅ Complete (JMAP VacationResponse, settings tab, sidebar indicator, 8 locales)
- Virtual Scrolling: ✅ Complete (@tanstack/react-virtual, dynamic measurement, keyboard scroll-to)
- Security: ✅ CSP Report-Only + all P0 headers deployed (nonce-based scripts, proxy.ts middleware)
- Calendar: ✅ Phase 3 complete (inline invitation banner with RSVP/import, drag-and-drop rescheduling, iCalendar import, plus phase 1: views, event CRUD, multi-day, overlaps, locale dates, accessibility, security)
- Email Filters: ✅ Complete (JMAP Sieve RFC 9661, visual rule builder, raw Sieve editor, 64 tests, capability-gated, 8 locales)
- Calendar Notifications: ✅ Complete (client-side alert evaluation, toast display, notification sound, proactive event fetch, settings toggles, acknowledged persistence, 44 tests)
- Email Templates: ✅ Complete (local storage, placeholder variables with auto-fill, composer integration, settings management, 48 tests)
- Testing: ✅ 669 tests passing (identity, sub-addressing, contacts, vCard, validation, color, threads, headers, sieve generator, sieve parser, calendar alerts, calendar notification store, calendar invitation, template utils)