Skip to main content
OxiMail is JMAP-first, but real deployments have Thunderbird, Apple Mail, eM Client, and phone clients that speak the classic protocols. The legacy feature provides them as translation layers over the same JMAP data model — an IMAP flag change and a JMAP keyword change are the same mutation, seen through two protocols. There is no second mail store to drift out of sync.

IMAP (RFC 9051)

The IMAP bridge implements IMAP4rev2 on port 993 (implicit TLS). Points that matter to an operator:
  • Same data, live. A message moved in the webmail appears moved to every IMAP session; sibling-connection changes are announced correctly — a shrinking mailbox is announced as EXPUNGE lines (old-view numbering, descending), never as a bare decreasing EXISTS, which RFC 9051 forbids and which multi-connection clients like eM Client punish with a full folder resync.
  • Incremental resync. CONDSTORE and QRESYNC are supported, including VANISHED responses, so a reconnecting client fetches deltas instead of re-listing the folder.
  • UIDs are durable. Per-mailbox UID uniqueness is enforced at the storage layer; UID EXPUNGE honors its uid-set.
  • Honest identification. The ID command reports the server name and its real version, and logs the client’s declared identity — when a specific client misbehaves, the logs can name it.
  • App passwords. Clients that cannot do the web login flow authenticate with per-client app passwords; failures feed fail2ban like every other listener.

CalDAV (RFC 4791) and CardDAV (RFC 6352)

Calendars, task lists, and address books are served over HTTPS on the main listener, under the configured path prefixes. The bridges translate to the same JMAP objects the webmail edits, and every mutation is change-logged, so JMAP /changes, RFC 6578 sync-collection, and push all see a DAV write immediately. Interop behaviours verified against real clients (Apple Calendar, Thunderbird, eM Client 10.4):
  • Bootstrap at the server root. Some clients take only the hostname from autodiscovery and probe OPTIONS / PROPFIND on /. The root advertises the combined DAV compliance classes and answers an authenticated PROPFIND with current-user-principal; each principal cross-advertises the other service’s home set, so one discovery pass finds calendars, task lists, and address books.
  • Strict-parser-safe XML. Text payloads that embed HTML or a bare & are CDATA-wrapped, so one decorated event description cannot make a whole multiget unparseable and kill a sync.
  • ETags are content hashes. A VEVENT’s ETag changes exactly when its representation changes — including when a recurrence override is added from another client — so a stale If-Match fails with 412 and the client resyncs instead of silently clobbering the change it never saw. Same for VTODO.
  • Server-side filtering is real. calendar-query evaluates time-range (recurrence-aware, overlap semantics), prop-filter, param-filter, and text-match; a filter shape the server does not model degrades to over-inclusive, never to a silently empty result. free-busy-query returns a proper VFREEBUSY.
  • Time zones round-trip. DTSTART;TZID= is emitted with the matching VTIMEZONE component (generated from the IANA database, 597 zones), Windows registry zone names from Outlook/Exchange are normalized to IANA on every ingest path, and Outlook-style parameterised properties (SUMMARY;LANGUAGE=fr-FR:…) parse correctly.
  • Client-created collections. MKCALENDAR at a client-chosen URL works (Apple Calendar and Thunderbird create collections at a UUID URL of their choosing).
  • Alarms are modelled. VEVENT and VTODO VALARM components import into the alert model and re-emit on GET, including absolute (VALUE=DATE-TIME) triggers. Public ICS feeds deliberately carry no VALARMs — a subscriber must not inherit the publisher’s reminders.

Autodiscovery endpoints

Four endpoint families configure clients automatically (backed by the DNS records from the email-auth page):
Behind a reverse proxy, proxy everything to OxiMail except the ACME challenge path — the wizard’s generated snippet does exactly that. A route allowlist or a proxy-level OPTIONS/CORS interception silently breaks discovery and DAV; see First boot.

What legacy mode does not change

The bridges are read/write access paths, not a parallel server: authentication, encryption at rest, tenant isolation, fail2ban, and rate limiting are the same machinery as JMAP. Disabling [legacy] removes the listeners and route prefixes; the data is untouched.