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
EXPUNGElines (old-view numbering, descending), never as a bare decreasingEXISTS, which RFC 9051 forbids and which multi-connection clients like eM Client punish with a full folder resync. - Incremental resync.
CONDSTOREandQRESYNCare supported, includingVANISHEDresponses, 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 EXPUNGEhonors its uid-set. - Honest identification. The
IDcommand 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/PROPFINDon/. The root advertises the combined DAV compliance classes and answers an authenticatedPROPFINDwithcurrent-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-Matchfails with412and the client resyncs instead of silently clobbering the change it never saw. Same for VTODO. - Server-side filtering is real.
calendar-queryevaluatestime-range(recurrence-aware, overlap semantics),prop-filter,param-filter, andtext-match; a filter shape the server does not model degrades to over-inclusive, never to a silently empty result.free-busy-queryreturns a properVFREEBUSY. - Time zones round-trip.
DTSTART;TZID=is emitted with the matchingVTIMEZONEcomponent (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.
MKCALENDARat a client-chosen URL works (Apple Calendar and Thunderbird create collections at a UUID URL of their choosing). - Alarms are modelled. VEVENT and VTODO
VALARMcomponents 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.