Skip to main content
Beyond mail, OxiMail serves calendars, contacts, tasks, files, and chat over JMAP, with CalDAV/CardDAV bridges for classic clients (legacy protocols). This page covers the behaviours an operator needs to understand and the knobs and repair tools that go with them.

Calendar scheduling (iTIP)

When users invite each other, the server exchanges the scheduling messages (REQUEST / REPLY / CANCEL) by email, per RFC 5546. Two rules keep this from misfiring:
  • Organizer-side only. OxiMail sends scheduling mail only for events whose ORGANIZER resolves to a local account (RFC 5546 §3.2: only the organizer’s server sends invitations). An event that arrived as an inbound invitation never re-emits a REQUEST when the attendee’s client writes it back, and deleting a received copy never broadcasts an unauthorized CANCEL — on both the JMAP and CalDAV paths, fail-closed.
  • Emitted after the commit. iTIP messages and calendar events are emitted only once the transaction that changed the event has actually committed. A concurrent-edit conflict (stateMismatch) or any commit failure emits nothing — invitations can no longer escape for a change that was rolled back, and an update REQUEST always carries the post-change content with the bumped SEQUENCE.
Inbound invitations (text/calendar parts) are processed on ingestion, including Outlook’s parameterised property style, and update the recipient’s calendar.

Free-busy and availability

Three read surfaces answer “when is this person free”, all through one occurrence-enumeration authority (a recurring event expands identically everywhere, DST included):
  • Principal/getAvailability (JMAP) composes availability from subscribed calendars whose includeInAvailability is all or attending; a privacy: "secret" event hides its busy time entirely; event details are only populated for callers who hold real read access — free-busy access never implies detail access. A caller with free-busy rights on none of the subject’s calendars gets an explicit forbidden, not a misleading empty answer.
  • CalDAV free-busy-query returns a VFREEBUSY of merged busy periods (tentative counts as busy; free/transparent, trashed, and cancelled events are excluded).
  • The scheduling UI in a client builds on the same data.

Time zones

Floating events (no explicit zone) resolve through a fallback chain: event zone → user zone → organization default → UTC. The wizard captures the organization default at install (first boot); change it later with:
Windows registry zone names (from Outlook, Exchange, eM Client) are normalized to IANA on every ingest path, and exported VEVENTs embed the matching VTIMEZONE so strict clients compute correct local times.

Notifications

Calendar changes produce CalendarEventNotification objects for the people concerned: a grantee’s write on a shared calendar notifies the owner, and an inbound scheduling message notifies the affected user (REQUEST/CANCEL → the recipient, REPLY → the organizer; self-authored changes are suppressed). Notifications are change-logged and pushed, so clients see them without polling. Alerts (reminders) support both offset and absolute triggers and fire once per occurrence through a deduplication table.

Tasks

Task lists mirror calendars: JMAP methods, CalDAV VTODO bridge, shared lists. Each account has exactly one default task list, enforced by a database invariant — a Task/set create without taskListIds goes there. Alerts on tasks support absolute triggers without requiring a due date.

Contacts

Contacts are JMAP ContactCards (RFC 9610) with a CardDAV bridge. The server owns the uid (a client-supplied one on create is rejected), and a CardDAV PUT that would create a cross-source duplicate of an existing UID is refused rather than silently forked. Name and address components round-trip completely between vCard and the JMAP form.

Sharing

Calendars, task lists, address books, and drive folders share one grant model (shareWith maps keyed by principal, RFC 9670 shapes). Two operator-relevant guarantees:
  • Per-viewer state stays per-viewer. A grantee hiding a shared calendar (isVisible) or starring a shared file affects their own view only, never the owner’s object.
  • Grantees must be human-backed. A grant to a non-loginnable technical identity is rejected at write time on every domain — a grant that could never be exercised is a lie in the ACL. Shared accounts’ drive custody has its own surface: oximail account custodian (see multi-tenancy).

Repair one-shots

Migration-era artifacts have dedicated, dry-run-by-default repair commands: Both record JMAP changes so clients resync cleanly. See the CLI reference.