Skip to content

CalDAV - Working#343

Open
cjroth wants to merge 4 commits into
emersion:masterfrom
cjroth:master
Open

CalDAV - Working#343
cjroth wants to merge 4 commits into
emersion:masterfrom
cjroth:master

Conversation

@cjroth

@cjroth cjroth commented Jun 5, 2026

Copy link
Copy Markdown
  • Based on @zCri's PR - CalDAV support #282
  • This is fully working for me.
  • This is AI-generated code - I did a light review.
  • Creating events with attendees is working but adding them retroactively is not.

cjroth added 4 commits June 4, 2026 10:27
Squashes PR emersion#282 (zCri's CalDAV support) plus our fixes onto current
master, replacing the stale go-webdav v0.5.1 base. Ports the backend to
the go-webdav v0.7.0 caldav.Backend interface:
  - PutCalendarObject now returns (*caldav.CalendarObject, error)
  - implement CreateCalendar (MKCALENDAR) as 501 Not Implemented (Proton
    calendar provisioning is not supported yet; create via the web app)

Carries the three correctness fixes from the original port:
  1. event create detection via errors.As (wrapped APIError, code 2061)
  2. read-back of own events when Author is empty (fall back to user keyring)
  3. time-range calendar-query filtering via go-webdav's caldav.Match

Tests: protonmail/calendar_test.go (unit) + test/caldav_e2e.py
(full create/read/update/delete/query lifecycle, 12/12 against live API).
The CalDAV backend registered an events channel but never read it (empty
receiveEvents stub). events.Receiver dispatches each event to every
registered channel while holding its lock, over UNBUFFERED channels — so
the first real Proton event blocked the dispatcher forever with the lock
held. That in turn deadlocked the next events.Manager.Register call, i.e.
the first CardDAV request for the same account (manifesting as CardDAV
PROPFINDs hanging indefinitely once any calendar/mail event had fired).
Drain the channel so the shared receiver stays healthy.
Implements the PR's biggest deferred TODO. Outgoing: parse ATTENDEE props,
derive the Proton attendee token (SHA1(UID+normalized email)), build an
encrypted attendee card with the event's shared session key, populate the
Attendees clear list, and wrap the shared session key to each internal
Proton attendee's address key (AddedProtonAttendees) so they can decrypt
the event. Read-back: decode the AttendeesEvents card so clients see
invitees + RSVP status (and preserve multiple ATTENDEE props on merge).

Refactors makeUpdateData to generate the shared session key once up front
so the shared part and attendee card share it. Adds a unit test pinning the
token derivation.
hydroxide never signed attachments (two TODOs), so Proton rejected any
outgoing message with an attachment: [2011] One or more attachments are
missing a signature. Add Attachment.Sign (binary detached signature of the
plaintext, matching go-proton-api's GetBinary()) and upload it as the
Signature multipart field. smtp buffers the part, signs, then encrypts.
Unblocks sending attachments generally (and iMIP calendar invitations).
This was referenced Jun 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant