v0.2.30
RustBox CI / rustbox (push) Waiting to run

This commit is contained in:
Mateusz Gruszczyński committed 2026-11-08 07:32:12 +01:00
1 parent 1b12899ff6
commit a3ac2a68fe
33 files changed
+5422 -28

No files matched your search

+147
View File
@@ -0,0 +1,147 @@
# CalDAV / CardDAV server
RustBox can serve each account's calendar and contacts over CalDAV (RFC 4791) and
CardDAV (RFC 6352). The DAV view and the webmail use the same tables, so an event
created on a phone appears in the webmail calendar and a contact edited in the
webmail appears on the phone after its next sync.
The server is **off by default**.
## Enabling
```toml
[dav]
enabled = true
auth_cache_secs = 300 # remember a successful login for 5 minutes (0 = always ask IMAP)
max_resource_size = 8388608 # largest accepted event / vCard in bytes
calendar_name = "Calendar"
addressbook_name = "Contacts"
```
Environment overrides use the usual form: `DAV__ENABLED=true`, `DAV__AUTH_CACHE_SECS=60`.
Run RustBox behind HTTPS when DAV is enabled: clients send the mail password with
every request (HTTP Basic).
## URLs
Below `<base_path>/dav` (with the default base path: `https://mail.example.com/dav/`):
| Resource | Path |
| :--- | :--- |
| Service root (for discovery) | `/dav/` |
| Principal | `/dav/principals/<login>/` |
| Calendar home | `/dav/calendars/<login>/` |
| Calendar | `/dav/calendars/<login>/default/` |
| Address book home | `/dav/addressbooks/<login>/` |
| Address book | `/dav/addressbooks/<login>/default/` |
`/.well-known/caldav` and `/.well-known/carddav` redirect to `<base_path>/dav/`
(RFC 6764). They are registered at the host root even when RustBox runs under a
base path; a reverse proxy that only forwards the base path must forward these two
paths as well.
`<login>` is the IMAP login the client authenticates with (normally the e-mail
address). A client may only open its own collections; other logins get `403`.
## Authentication
HTTP Basic with the IMAP login and password. RustBox checks them against the
configured `imap_host` exactly like the webmail login and protects the endpoint
with the same brute-force guard (`[login_rate_limit]`). A successful login is cached
in memory for `auth_cache_secs`, keyed by a hash of login and password, so changing
the mail password takes effect for DAV within that time. The tenant database is
created on the first DAV login, so DAV works for accounts that never opened the
webmail.
## Supported protocol
- `OPTIONS` (no authentication), `PROPFIND` (Depth 0/1), `PROPPATCH` (answered with
`403` per property: collection properties are fixed), `GET`/`HEAD`, `PUT`, `DELETE`.
- `REPORT`: `calendar-query` (VEVENT with optional `time-range`),
`calendar-multiget`, `addressbook-query` (prop-filter / text-match, `anyof`/`allof`,
`limit`), `addressbook-multiget`. Other reports (for example `sync-collection`)
return `403 DAV:supported-report`; `sync-token` is not advertised, so clients fall
back to CTag polling.
- Strong ETags (hash of the served object) with `If-Match` / `If-None-Match`,
and a collection CTag (`CS:getctag`) that changes on every change, including
webmail edits and deletions.
- One calendar (VEVENT only; `supported-calendar-component-set` lists VEVENT) and
one address book (vCard 3.0 and 4.0) per account. `MKCALENDAR` / `MKCOL` return
`403`. Tasks (VTODO) are not supported.
- RFC 4791 UID uniqueness: a second resource with an existing UID is refused with
`CALDAV:no-uid-conflict` — except that an event created in the webmail (for
example from an e-mail invitation) is adopted, so accepting an invitation on a
phone does not duplicate it.
## How data is mapped
Objects uploaded by a client are stored verbatim (`dav_data`) under the client's
resource name (`dav_name`) and decoded into the webmail columns:
| iCalendar | Webmail field |
| :--- | :--- |
| `SUMMARY`, `DESCRIPTION`, `LOCATION` | title, description, location |
| `DTSTART` / `DTEND` / `DURATION` | start / end (times with `TZID` are converted to UTC; dates make an all-day event) |
| `RRULE` | recurrence rule |
| `ATTENDEE`, `ORGANIZER` | attendees, organizer |
| `STATUS`, `URL`, `COLOR` | status, meeting link, colour |
| first two `VALARM` triggers before the start | reminders |
Only the master component is decoded; recurrence overrides (`RECURRENCE-ID`),
`EXDATE`, `VTIMEZONE` and unknown properties stay in the stored object and are
served back unchanged.
| vCard | Webmail field |
| :--- | :--- |
| `FN` (or `N`) | name |
| `EMAIL` (preferred first) | e-mail and further addresses |
| `TEL`, `ADR` | phone numbers, postal addresses |
| `ORG`, `TITLE`, `NOTE`, `URL`, `BDAY` | company, job title, notes, website, birthday |
| embedded `PHOTO` (JPEG/PNG/GIF/WebP up to 3 MB) | contact photo |
Cards without an e-mail address are accepted. Since migration V055 several
contacts may share an e-mail address.
When an event or contact that came from a DAV client is edited in the webmail,
only the properties whose value actually changed are rewritten in the stored
object (plus `DTSTAMP`/`LAST-MODIFIED`/`SEQUENCE` or `REV`); time zones, exceptions,
alarms the webmail does not model and vendor properties are kept. Events and
contacts created in the webmail are served as `<id>.ics` / `<id>.vcf` with a
generated object (iCalendar 2.0 / vCard 3.0).
## Clients
- **ActivePush** (Exchange ActiveSync gateway): no code changes are needed, only
the backend URLs. Its default paths already match RustBox:
```toml
[caldav]
enabled = true
base_url = "https://mail.example.com"
path = "/dav/calendars/%u/"
[carddav]
enabled = true
base_url = "https://mail.example.com"
path = "/dav/addressbooks/%u/"
```
With a RustBox `base_path` (for example `/mail`) prefix the paths:
`/mail/dav/calendars/%u/`. ActivePush authenticates with the same login and
password the phone uses, which must be the IMAP login RustBox accepts. Tasks stay
disabled because the calendar advertises VEVENT only; creating extra calendar or
contact folders from the phone is refused.
- **DAVx⁵, Thunderbird, Apple Calendar/Contacts, Evolution**: use the server URL
`https://mail.example.com/` (discovery through `.well-known`) or
`https://mail.example.com/dav/`, and the mail login and password.
## Limits
- Recurring events are not expanded server side: a `time-range` query returns a
recurring event whenever its first occurrence starts before the end of the range.
- ETags and the CTag are computed from the objects on each request; this is cheap
for personal calendars and address books (thousands of entries) but means a CTag
poll reads the whole collection.
- Contact groups are not exported as group vCards.
- Contacts photos added in the webmail are not included in generated vCards.
+1
View File
@@ -86,6 +86,7 @@ RustBox manages server-side filters over ManageSieve, the standard used by Dovec
- Events with all-day mode, location, attendees, status, colour and a meeting link.
- Two reminders per event (for example 15 minutes and one day before), with default reminders for new events. Reminders for all-day events fire at the start of the working day.
- ICS import and export, including importing an invitation attachment.
- Optional CalDAV/CardDAV server (`[dav]`): the same calendar and contacts sync with phones, Thunderbird, DAVx⁵, Apple Calendar/Contacts or an ActiveSync gateway such as ActivePush. See [CALDAV_CARDDAV.md](CALDAV_CARDDAV.md).
![Calendar](screenshots/calendar.png)
+8 -2
View File
@@ -1,7 +1,13 @@
# RustBox 0.2.29 - implementation status
# RustBox 0.2.30 - implementation status
- Draft saves are realtime-silent: Drafts folder/list updates continue, but saving a draft does not surface as a new-mail notification.
This file tracks the `0.2.29` source snapshot. Storage/search scope and outstanding acceptance work are tracked in `TODO.md`. A feature is only listed as implemented when working code exists in this source tree; partial items are called out explicitly.
This file tracks the `0.2.30` source snapshot. Storage/search scope and outstanding acceptance work are tracked in `TODO.md`. A feature is only listed as implemented when working code exists in this source tree; partial items are called out explicitly.
## 0.2.30 CalDAV / CardDAV server
- Optional (`[dav] enabled = true`): one calendar (VEVENT) and one address book per account under `<base_path>/dav/`, RFC 6764 `.well-known` redirects, HTTP Basic auth against IMAP with a login cache and the login brute-force guard.
- PROPFIND, REPORT (calendar-query with time-range, calendar-multiget, addressbook-query, addressbook-multiget), GET/HEAD, PUT, DELETE, strong ETags with If-Match/If-None-Match, CTag. Not implemented: sync-collection, VTODO, MKCALENDAR/MKCOL, server-side recurrence expansion.
- Uploaded objects are stored verbatim (`dav_data`, migration V055) and webmail edits are patched into them per property. Details: `docs/CALDAV_CARDDAV.md`.
## 0.2.29 realtime open-thread refresh