Skip to Content
Coverage

Coverage

JMAP is a family of specifications: a server advertises capability URIs, and each brings its own types and methods. These are the ones IANA lists , and where jmapc stands on each.

CapabilitySpecificationSupported
urn:ietf:params:jmap:coreRFC 8620 
urn:ietf:params:jmap:mailRFC 8621 
urn:ietf:params:jmap:submissionRFC 8621 
urn:ietf:params:jmap:vacationresponseRFC 8621 
urn:ietf:params:jmap:contactsRFC 9610 
urn:ietf:params:jmap:calendarsdraft-ietf-jmap-calendars 
urn:ietf:params:jmap:principals:availabilitydraft-ietf-jmap-calendars 
urn:ietf:params:jmap:principalsRFC 9670 
urn:ietf:params:jmap:principals:ownerRFC 9670 
urn:ietf:params:jmap:smimeverifyRFC 9219 
urn:ietf:params:jmap:blobRFC 9404 
urn:ietf:params:jmap:quotaRFC 9425 
urn:ietf:params:jmap:sieveRFC 9661 
urn:ietf:params:jmap:mdnRFC 9007 
urn:ietf:params:jmap:webpush-vapidRFC 9749 

Two of these store objects from specifications of their own: a contact card is a JSContact  Card, and a calendar event is a JSCalendar  JSEvent. Both name types that JMAP also names, and each other’s too — there are three different Link types between them. So those carry a prefix: ContactEmailAddress is an address on a card, EmailAddress is one in a header field, and EventLink is a resource attached to a meeting. Each type’s documentation gives the name its specification uses.

JSCalendar also brings time types JMAP does not have. An event’s start is a LocalDateTime with no zone, and its duration is an ISO 8601 Duration, because “P1D” across a daylight saving change is not always 24 hours. Both are checked in a request, so a start written with a Z on the end, or a duration written as 90m, fails to build.

Not every capability brings types of its own. S/MIME verification adds four properties to Email and nothing else, so a request needs it without any method name saying so. jmapc works out which capabilities the properties a request touches belong to, and declares them: ask for smimeStatus and urn:ietf:params:jmap:smimeverify appears in using on its own.

Some define neither types nor methods, only a value for the client. VAPID is one, and that value is a key. Those are read from the session, and Session.Capability reads any of them, including one jmapc does not know.

vapid, err := session.WebPushVAPID() // vapid.ApplicationServerKey goes to the push service when subscribing there. var limits struct{ MaxSizeScript int `json:"maxSizeScript"` } err = session.Accounts[accountID].Capability(jmapc.CapabilitySieve, &limits)

A capability that is not built in can still be used: describe its types in a schema file and requests against them are checked like any other. That is the same mechanism a vendor extension uses, and the work is declarative — no Go to write.

Methods

81 methods, all of them checked and generated the same way.

TypeMethods
Mailboxget changes set request queryChanges
Threadget changes
Emailget changes set copy request queryChanges import parse
SearchSnippetget
Identityget changes set
EmailSubmissionget changes set request queryChanges
VacationResponseget set
AddressBookget changes set
ContactCardget changes set copy request queryChanges
Calendarget changes set
CalendarEventget changes set copy request queryChanges parse
CalendarEventNotificationget changes set request queryChanges
ParticipantIdentityget changes set
Principalget changes set request queryChanges getAvailability
ShareNotificationget changes set request queryChanges
Quotaget changes request queryChanges
SieveScriptget set request validate
MDNsend parse
Blobcopy upload get lookup
PushSubscriptionget set
Coreecho

What is not checked

One thing, and it is on purpose.

Open sets are not checked, deliberately. Where a specification fixes the values a property takes, jmapc checks them. Where it leaves the set open — a mailbox role, an email keyword, a Content-Disposition — it does not, because rejecting a value the server would have accepted is worse than letting a typo through.

Generation

internal/spec is a plain Go declaration of the data model, and the runtime types in types_gen.go are generated from the same catalogue the requests are checked against, so the two cannot drift apart.

Last updated on