Skip to content

Releases: maathimself/mailflow

v2.1.0

Choose a tag to compare

@maathimself maathimself released this 06 Jul 00:51

What's new in v2.1.0

Features

  • OIDC group claim → admin role mapping (#190) — SSO providers can now grant or revoke admin access automatically via a group claim in the JWT. Configure the claim name and expected value in Settings → SSO.
  • Custom CSS (#191) — Inject your own CSS from Settings → Appearance to personalise the interface beyond the built-in themes.
  • Mark-as-read behaviour (#195) — Choose when messages are marked as read: immediately on open, after a configurable delay (1–10 seconds), or never automatically. Configurable in Settings → Appearance → Layout.
  • Sender avatars (#197) — Contact photos from CardDAV-synced contacts now appear as avatars in the message list, falling back to the existing initials circle when no photo is available.

Fixes

  • Select button on desktop (#194) — The bulk-select button was missing from the message list header on desktop; it now appears alongside the other header controls.
  • Inbox refresh delays — Deleting a message now immediately broadcasts a folder update, eliminating the lag before the list refreshed. iOS warm-start stale state is also resolved via a visibility change listener.
  • AI private IP hint (#192) — A clearer hint is shown when the AI base URL points to a private IP that requires ALLOW_PRIVATE_HOSTS=true.

v2.0.2

Choose a tag to compare

@maathimself maathimself released this 04 Jul 16:38

Bug Fixes

  • Drafts: Clicking "Save Draft" now keeps the compose window open and shows a confirmation toast instead of closing. The window only closes when saving from the discard dialog.

  • Drafts: Sent and discarded drafts are now removed from the Drafts folder immediately. Previously the stale entry lingered until the next background sync (up to 10 minutes).

  • Drafts: Closing compose after a keep-open save no longer re-prompts to save. The dirty state now correctly resets after each save, including for CC/BCC fields, forwarded attachments, and uncommitted recipient input.

  • Message list: Preview snippets no longer show `[image: alt text]` placeholders for image-heavy emails. The plain-text alternative body is stripped of these placeholders, with fallback to the HTML body if the entire text part consists of image tags.

  • Unsubscribe: One-click unsubscribe state is now persisted to the database so the unsubscribe banner does not reappear after reloading. Failures are surfaced to the user rather than silently ignored. A "Move to trash" action is offered in the confirmation toast.

  • Mobile: Wide HTML emails no longer overflow the message pane on small screens.

  • Sync: Eliminated a spurious "Message sync phase 2 skipped" log warning caused by a stale sequence range when a move or delete arrived concurrently during an IDLE sync."

v2.0.1

Choose a tag to compare

@maathimself maathimself released this 03 Jul 14:29

What's new in v2.0.1

This is a patch release with mobile UI fixes.

Mobile fixes

  • Settings tab bar now shows a gradient overflow indicator when there are more tabs to the right, and hides it automatically when scrolled to the last tab (#185)
  • Sidebar bottom section (profile, settings, sign out) is now collapsible on mobile — tap your name to expand or collapse, keeping the sidebar compact by default (#186)

Security

  • window.open calls for mailto: links now consistently pass noopener,noreferrer to prevent the opened tab from holding a reference back to the app

Upgrading from v2.0.0: pull the new image and restart — no database migrations or configuration changes required.

Upgrading from v1.x: four additive database migrations run automatically on first startup (spam training log, password reset tokens, message categories, and list-unsubscribe columns). All are idempotent and non-breaking. See the v2.0.0 release notes for the full list of changes since v1.x.

v2.0.0

Choose a tag to compare

@maathimself maathimself released this 03 Jul 04:43

What's new in v2.0.0

Email categorization

  • New inbox tabs: Primary, Newsletters, Social, Notifications, and Other automatically sort incoming mail by type using header detection and sender heuristics
  • Unified inbox view shows all mail across tabs
  • AI-powered classify button reclassifies a message when the automatic detection gets it wrong
  • Unsubscribe button appears directly in the message pane for detected newsletters — one click sends the unsubscribe request or opens the unsubscribe URL

AI assistant

  • Integrated AI assistant powered by any OpenAI-compatible provider (configure your own endpoint and API key in admin settings)
  • Summarize long email threads, draft replies, and ask questions about a message
  • AI assist button added to the mobile compose toolbar
  • AI tab in admin settings is clearly marked Beta

Spam feedback (v0.1)

  • Mark any message as spam or not spam from the context menu, message pane toolbar, or bulk actions
  • Feedback is stored and will feed into automated filtering in a future release
  • Available in all 7 supported languages

Password recovery

  • Users can now recover their account via a recovery email address set in profile settings
  • Three-tier SMTP fallback ensures delivery even when the primary sending account is misconfigured (#176)

Compose improvements

  • Image resize handles in the rich-text editor (#182)
  • Pasting Excel tables now converts them to HTML tables (#182)

Todoist integration

  • Tasks created from emails now include a deep link back to the original message (#180)

Mark as unread

  • Mark messages as unread from the message pane toolbar and the mobile action menu (#183)

Security hardening

  • TOTP replay prevention: one-time codes can no longer be reused within their validity window
  • SSRF improvements: IMAP host validation now resolves DNS and blocks 6to4 and Teredo IPv6 tunnel addresses that embed private IPv4 ranges
  • CSS exfiltration prevention: external url() references in email <style> blocks are stripped at sanitization time
  • Password reset race condition: the token is now consumed atomically so two concurrent reset requests cannot both succeed
  • Signature sanitization: edited signatures are sanitized on send and draft save, not only at storage time
  • AI and subscription URL validation: custom AI base URLs and category subscription URLs are now validated through the same SSRF-safe host validator used for IMAP
  • Encryption key guard: the server now refuses to start and throws on encrypt rather than silently storing plaintext if ENCRYPTION_KEY is missing
  • Microsoft 365 id_token issuer validation: multi-tenant OAuth flows now verify the iss claim matches the tenant in the token
  • Trusted device cookie cleared on logout
  • Security headers: X-Frame-Options: DENY and Referrer-Policy: same-origin added to all responses
  • Double-send prevention: idempotency key support on the send endpoint prevents duplicate emails on network retry

Reliability improvements

  • Database migrations: all migrations are now idempotent (IF NOT EXISTS) and run without a statement timeout so large deployments don't fail mid-migration
  • IMAP connection leak fix: failed sync attempts now correctly close and remove the stale connection instead of leaving zombie TCP sockets
  • WebSocket broadcast isolation: a failing client socket no longer aborts delivery to other connected clients
  • Inbox rules N+1 fix: folder resolution for delete and archive rules is now cached across the message batch instead of re-queried per message
  • Shared Redis client: session store, TOTP replay prevention, and send idempotency now share a single Redis connection

Upgrade notes

  • No manual migration steps required. All schema changes apply automatically on first startup.
  • If you are running without ENCRYPTION_KEY set, the server will now refuse to start rather than silently degrading. Set ENCRYPTION_KEY to a 64-character hex string (openssl rand -hex 32) before upgrading.

v1.9.2

Choose a tag to compare

@maathimself maathimself released this 01 Jul 15:10

Bug fixes

  • Todoist: due date not saved — Dates selected in the date picker were silently ignored. The backend was not updated when the frontend switched from the free-text due_string field to due_date; the fix passes the ISO date through to the Todoist API correctly.
  • Todoist: "Open in Todoist" opened a blank tab — The Todoist REST API v1 does not include a task URL in its response. The URL is now constructed from the task ID (https://app.todoist.com/app/task/<id>) and returned alongside the task, so the notification link opens the correct task directly.

v1.9.1

Choose a tag to compare

@maathimself maathimself released this 01 Jul 14:00

Bug fixes

  • Todoist: crypto.randomUUID error on task creation — Fixed a JavaScript exception thrown after successfully creating a Todoist task when MailFlow is served over HTTP (non-secure context). The task was created successfully but the error was surfaced to the user. A safe fallback is now used in environments where crypto.randomUUID is unavailable.
  • Todoist: due date field replaced with date picker — The due date input was previously a free-form text field. It is now a native date picker, consistent with user expectations.
  • Todoist: integration icon updated — The toolbar and modal now display the recognisable Todoist logo instead of a generic checkmark icon, making the button immediately identifiable.

v1.9.0

Choose a tag to compare

@maathimself maathimself released this 01 Jul 13:09

New features

  • Two-factor authentication — TOTP (authenticator app), email OTP, and persistent device trust. Admins can set enforcement policy (off / required) and trust duration (7 days, 30 days, permanent, or never) in the admin panel.
  • Todoist integration — link a Todoist account from the admin Apps tab. Create tasks directly from emails via the message toolbar.
  • Composer font groups and email priority — choose font family groups in the composer and set message priority (low / normal / high / urgent).
  • Improved mobile compose UX — cleaner field layout and simplified toolbar for composing on mobile.

Fixes

  • Wide fixed-layout HTML emails no longer clip on mobile — content is scaled to fit the viewport.
  • Mark-as-read now fires immediately on tap rather than waiting for the synthesized click event, closing the window where a fast back-swipe could race against the state update.
  • Mark-as-read is retried once on network failure before reverting, reducing spurious "still unread" appearances on unreliable mobile connections.
  • Resolved ghost touches and scrambled gesture recognition in the mobile message list after rapid swiping.
  • Fixed an edge case where thread resolution could overwrite the optimistic mark-as-read update before the API call completed.
  • Back swipe no longer exits the PWA context on iOS standalone mode.
  • Todoist connection status now syncs correctly on app load.
  • Message toolbar cleaned up — icon-only buttons with tighter spacing.

Performance

  • Div-renderer utilities (PostCSS, CSS scoping) are now lazy-loaded and excluded from the main bundle when the div renderer is disabled.

Upgrade notes

  • Two database migrations run automatically on startup (0019_user_integrations, 0020_mfa_device_trust). No manual steps required.
  • 2FA is off by default. Existing users are not affected unless an admin enables enforcement under Settings → Security.
  • One new optional environment variable: VITE_EMAIL_DIV_RENDER (default false). The div-based renderer is experimental — do not enable in production.

v1.8.0

Choose a tag to compare

@maathimself maathimself released this 29 Jun 15:48

What's new in 1.8.0

Contacts

MailFlow now has a full contacts manager, accessible from the sidebar.

  • Create, edit, and delete contacts with name, email addresses, phone numbers, organization, and notes
  • Search across all contact fields including secondary emails and phone numbers
  • Contacts are automatically learned from people you send mail to and from inbound senders, and ranked by how frequently you correspond with them
  • Auto-learned contacts are promoted to full contacts when you edit them
  • Type labels (work, home, mobile, etc.) are localized in all supported languages

CardDAV sync

MailFlow now includes a CardDAV server compatible with Apple Contacts, Thunderbird, DAVx⁵, and other CardDAV clients.

  • Sync URL: https://your-instance/carddav/
  • Auto-discovery supported via /.well-known/carddav
  • Full vCard 3.0 support with ETag-based conflict detection

Settings

  • New search function in the settings panel to quickly find any setting
  • Settings sidebar reorganized into logical groups
  • Search labels are now fully translated

Other improvements

  • Bulk and newsletter senders are excluded from autocomplete so frequent senders stay at the top (#168)
  • Thread read state now syncs to the parent row in real time when individual messages within a thread are marked read (#162)
  • Selecting multiple messages and marking them read now works correctly (#174)
  • Manual reindex now runs refreshBulkFlags as a background job so it does not block the response (#168)

Bug fixes

  • Contact display names are no longer overwritten on every send for manually edited contacts
  • Contacts panel correctly closes when navigating to an account or folder
  • Stale error banners no longer appear when switching between contacts
  • Contacts page state is preserved when navigating away and back
  • CardDAV well-known redirect upgraded from 301 to 308 to preserve request methods

Upgrade notes

Managed PostgreSQL users: Migration 0018 enables the pg_trgm extension for faster contact search. If your database user does not have superuser privileges (e.g. RDS, Supabase, Neon), run CREATE EXTENSION IF NOT EXISTS pg_trgm; as a superuser before upgrading, or the migration will fail.

v1.7.3

Choose a tag to compare

@maathimself maathimself released this 28 Jun 03:56

New Features

  • Text highlight color — The compose toolbar now has a highlight color picker (distinct from text color) for marking up email content with background colors. Includes a "remove highlight" swatch to clear applied colors. (#172)
  • Sent replies in threads — Replies you send now appear inline in conversation threads and update live without a page refresh.
  • Smart contact autocomplete — Recipients you send mail to are automatically learned and ranked higher in autocomplete suggestions. (#168)

Bug Fixes

  • Mobile: Cc/Bcc toggle buttons — The Cc and Bcc toggle buttons were cramped inside the To field row on mobile; they now appear in their own dedicated row below it. (#171)
  • Mobile: message headers screen — The View Headers screen is now a full-screen overlay on mobile with headers broken out into individual labeled rows, making them readable on narrow displays. (#173)
  • Mobile toolbar — Print and View Headers are now tucked into the overflow menu on mobile to avoid crowding the toolbar. (#170)
  • Sidebar: INBOX subfolder nesting — Subfolders of INBOX now nest correctly in the sidebar when the INBOX row is not yet present. (#169)

v1.7.2

Choose a tag to compare

@maathimself maathimself released this 25 Jun 19:06

Bug Fixes

  • Email preview snippets: Fixed a regression where snippet text in the message list could show garbled content — raw HTML entities (&amp;, &hellip;, etc.) or Markdown link syntax ([label](url)) from ESPs like Klaviyo that generate text/plain by converting HTML anchors to Markdown. All snippet-building paths now share a single canonical function with consistent entity decoding and link stripping.
  • Message deletion: Fixed missing undo timer bar when deleting a message from the reading pane (the bar was only showing when deleting from the list).
  • IMAP sync: Fixed an unhandled error when the server rejects an invalid message-set during sync phases 1 and 2; these are now caught and logged via extractImapError rather than crashing the sync.

Documentation

  • Added ROADMAP.md and updated README navigation links
  • Updated Contributing and Roadmap links to point to mailflow.sh