Plus
/etc/oximail/ — config, DKIM keys, and the key material without which the two data stores are ciphertext. The three data locations plus /etc/oximail are the complete backup surface (operations).
How mail is laid out
A message is stored once, in two forms (ADR-009): the raw RFC 5322 bytes as a blob, and the parsed metadata (headers, structure,hasAttachment, preview, thread) as rows. Nothing re-parses on read. Blobs are addressed by the SHA-256 of their cleartext, so an attachment sent to ten colleagues is stored once per organization — deduplication happens below the mailbox level, and two copies of an email in two mailboxes are always two metadata rows pointing at one blob (never deduplicated at the message level; that class of bug is designed out).
The blob directory is namespaced per organization and per account ({tenant}/{account}/…, with a reserved _tenant/ area for organization-wide content), which is what makes per-account crypto-erasure and per-organization isolation physical rather than logical.
Folders
Folders are JMAP Mailboxes with RFC 8621 roles (inbox, sent, drafts, trash, junk, archive), provisioned per account in the account’s language. Hierarchy, per-folder counts, and sharing (shareWith) are all data. The IMAP bridge shows the same tree. Duplicate folders left over from old imports are repaired with oximail account dedupe-folders (migration).
Trash, undelete, and retention
Destruction is two-stage with a visible trash (ADR-035): a destroyed object lands indeleted_items and can be restored — this backs the trash surfaces in every client and the recovery of destroyed DAV resources. Independent of user-facing trash, two retention windows matter operationally:
change_log: 90 days. The delta-sync history (/changes,sync-collection) is pruned past 90 days; a client absent longer than that does a full resync instead of an incremental one. This is by design — the change log is a sync mechanism, not an audit trail.audit_log: years. The administrative audit trail has its own long horizon with an enforcing retention worker (compliance).
Quotas
- Per account:
oximail account quota --account <email> --mb <n>(0 = no per-account limit). Exposed to clients viaQuota/get. - Per collection: volume caps (ADR-072) bound what any single collection can grow to.
- Chat capacity caps are separate (multi-tenancy).
The search index is disposable
The Tantivy index carries no primary data. If it is lost, corrupted, or you change its storage, rebuild it:Database maintenance
None scheduled — this is deliberate. WAL checkpointing is automatic (bounded at ~64 MiB, checkpointed at shutdown), query-planner statistics are refreshed after migrations, and the connection pool needs no tuning below a few hundred concurrent users ([storage] pool_size, default 32, raise on read-heavy machines). The operational database story is: keep disk space, keep backups, and let the server run.
oximail sql exists as a guarded escape hatch for support scenarios; day-to-day inspection goes through the CLI verbs (oximail mailbox, oximail email) and the admin API’s per-account data views.