mailrs-dav
Server-side CalDAV (RFC 4791) and CardDAV (RFC 6352) handlers for Rust mail / calendar / contacts servers — framework-agnostic, BYO data layer via the CalendarStore and AddressBookStore traits.
Extracted from mailrs so any project that wants to expose CalDAV / CardDAV can do so without re-implementing the multistatus / propstat builder, multiget UID extraction, iCalendar / vCard field scrapers, or the per-resource precondition handling (If-Match, If-None-Match: *).
This is, at the time of writing, the only standalone server-side CalDAV / CardDAV library on crates.io.
Highlights
- Methods covered —
PROPFIND (principal / calendar home / calendar / addressbook home / addressbook) ·
REPORT (
calendar-multiget,calendar-query,addressbook-multiget,addressbook-query) · GET / PUT / DELETE on events + contacts · OPTIONS /Depthheader handling. - Preconditions —
If-Match(etag must equal current) andIf-None-Match: *(resource must not exist) honored on PUT. - Framework-free — no axum / actix / tower / hyper. Each handler returns a
DavResponse { status, headers, body }your server-side adapter translates into your framework's response type. - Store-free — implement
CalendarStore(8 async methods) and / orAddressBookStore(8 async methods); every handler works. - Pure helpers exposed —
xml_escape,multistatus,etag_of,options_response,extract_ical_field,extract_ical_datetime,extract_vcard_field,extract_multiget_uids,parse_depth. Use the handlers or grab the pieces. - Standard error envelope —
DavErrorenum with.to_dav_response()for a 4xx/5xx fallback your server can emit unchanged.
Quick start
use async_trait;
use ;
;
# async
How it slots into axum
use Arc;
use ;
use ;
async : ,
State: ,
headers: HeaderMap,
body: String,
)
# use IntoResponse;
The store impl is yours; mailrs itself wraps its sqlx::PgPool in a thin DavAdapter that bridges the schema's row types into mailrs_dav::types.
What's intentionally not in this crate
- HTTP auth. Basic / Bearer / OAuth is the wrapper's job — this crate takes a resolved
userstring. - Routing / URL parsing. Handlers take pre-resolved
calendar_id/book_id; the URL → ID lookup is your wrapper's call (and trivial, because the store trait gives youget_calendar/get_address_book). - Calendar-query time-range filters (RFC 4791 §9.7). Most clients work fine with "return all events"; if you need filtering, layer it on top of
list_events. - Free/busy reports (RFC 4791 §7.10) and scheduling extensions (RFC 6638) — different specs.
- ACL (RFC 3744). The handlers emit a fixed
<D:all/>privilege set for the authenticated owner. - MKCALENDAR / MKCOL. Calendar creation is a higher-level admin concern in most mail servers.
Versioning
1.0.0 and onward follows semver. The CalendarStore / AddressBookStore trait surfaces and the handler signatures are the public API; the exact XML shape inside multistatus may evolve within a minor version as long as it stays compliant with the matching RFC.
License
Licensed under either Apache License, Version 2.0 or MIT license at your option.