Ξ

JMAP for Calendars is awesome

Published on 2023-10-29 code

The old thing: CalDAV

The predominant protocol used for syncing calendars is CalDAV (RFC 4791). CalDAV is a weird protocol. It sends events in the iCalendar format (RFC 5545) over WebDAV (RFC 4918), which in turn is based on XML and a modified version of HTTP. This is one example from the spec:

>> Request <<

REPORT /bernard/work/ HTTP/1.1
Host: cal.example.com
Depth: 1
Content-Type: application/xml; charset="utf-8"
Content-Length: xxxx

<?xml version="1.0" encoding="utf-8" ?>
<C:calendar-query xmlns:D="DAV:" xmlns:C="urn:ietf:params:xml:ns:caldav">
  <D:prop>
    <C:calendar-data>
      <C:limit-freebusy-set start="20060102T000000Z" end="20060103T000000Z"/>
    </C:calendar-data>
  </D:prop>
  <C:filter>
    <C:comp-filter name="VCALENDAR">
      <C:comp-filter name="VFREEBUSY">
        <C:time-range start="20060102T000000Z" end="20060103T000000Z"/>
      </C:comp-filter>
    </C:comp-filter>
  </C:filter>
</C:calendar-query>

>> Response <<

HTTP/1.1 207 Multi-Status
Date: Sat, 11 Nov 2006 09:32:12 GMT
Content-Type: application/xml; charset="utf-8"
Content-Length: xxxx

<?xml version="1.0" encoding="utf-8" ?>
<D:multistatus xmlns:D="DAV:" xmlns:C="urn:ietf:params:xml:ns:caldav">
  <D:response>
    <D:href>http://cal.example.com/bernard/work/abcd8.ics</D:href>
    <D:propstat>
      <D:prop>
        <D:getetag>"fffff-abcd8"</D:getetag>
        <C:calendar-data>BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//Example Corp.//CalDAV Client//EN
BEGIN:VFREEBUSY
ORGANIZER;CN="Bernard Desruisseaux":mailto:bernard@example.com
UID:76ef34-54a3d2@example.com
DTSTAMP:20050530T123421Z
DTSTART:20060101T100000Z
DTEND:20060108T100000Z
FREEBUSY;FBTYPE=BUSY-TENTATIVE:20060102T100000Z/20060102T120000Z
END:VFREEBUSY
END:VCALENDAR
</C:calendar-data>
      </D:prop>
      <D:status>HTTP/1.1 200 OK</D:status>
    </D:propstat>
  </D:response>
</D:multistatus>

Note how this uses the REPORT method, which is not part of stock HTTP. Also, note how iCalendar is embedded in XML. It is certainly not impossible to parse this, but it is far more complicated than it should be.

The biggest issue with CalDAV is that it is not universally supported. For example, FullCalendar, the go-to JavaScript calendar, does not support CalDAV on its own. Since version 5.5 it does at least allow to subscribe to read-only iCalendar feeds over HTTP though. Microsoft products do the same. If you want to get proper read-write support to your Microsoft calendars, you have to use their proprietary Exchange ActiveSync protocol.

I have recently worked with CalDAV and encountered two other issues:

Frustrated with all those issues, I started thinking about a new protocol that could replace CalDAV. After a bit of research, I found that someone had already done that work.

The new thing: JMAP Calendars

JMAP Calendars is a draft spec to send events in JSCalendar format (RFC 8984) over JMAP (RFC 8620), which in turn is an RPC protocol based on HTTP and JSON. Here is an example request from the spec:

[
  ["CalendarEvent/set", {
    "accountId": "a0x9",
    "create": {
      "k559": {
        "uid": "5d5776f6-ff8e-4bfd-ab3e-fe2fe5d4fa91",
        "calendarIds": {
          "3ddf2ad7-0e0c-4fb5-852d-f0ff56f3c662": true
        },
        "title": "Party at Pete’s",
        "start": "2023-02-03T19:00:00",
        "duration": "PT3H0M0S",
        "timeZone": "Australia/Melbourne",
        "showWithoutTime": false,
        "participants": {
          "1": {
            "@type": "Participant",
            "name": "Jane Doe"
            "scheduleId": "mailto:jane@example.com",
            "sendTo": {
              "imip": "mailto:jane@example.com",
              "other": "https://example.com/uri/for/internal/scheduling"
            }
            "kind": "individual",
            "roles": {
              "attendee": true,
              "owner": true
            },
            "participationStatus": "accepted",
            "expectReply": false
          },
          "2": {
            "@type": "Participant",
            "name": "Joe Bloggs",
            "sendTo": {
              "imip": "mailto:joe@example.com"
            },
            "kind": "individual",
            "roles": {
              "attendee": true
            },
            "participationStatus": "needs-action",
            "expectReply": true
          }
        },
        "mayInviteSelf": false,
        "mayInviteOthers": false,
        "useDefaultAlerts": false,
        "alerts": null
      }
    },
    "sendSchedulingMessages": true
  }, "0"]
]

This solves most of CalDAV problems:

Of course, support for JMAP Calendars is currently even worse than it is for CalDAV. To my knowledge, JMAP Calendars is not supported anywhere yet, and JMAP in general hasn't seen much adoption either.

On the other hand, HTTP and JSON are the de-facto standard for building APIs on the web. With this clean protocol based on popular technologies, there is hope that developers will add support once the spec stabilizes. I at least hope to see a switch from iCalendar-over-HTTP to JSCalendar-over-HTTP.

There are some other protocols (e.g. LDAP) that I would like to see replaced by something based on HTTP and JSON. There are certainly many pros and cons to this idea, not least of which is the difficulty for new protocols to gain traction. Maybe JMAP Calendars can serve as a test to see if this is worth the effort.