RFC 9610 | JMAP Contacts | December 2024 |
Jenkins | Standards Track | [Page] |
This document specifies a data model for synchronising contact data with a server using the JSON Meta Application Protocol (JMAP).¶
This is an Internet Standards Track document.¶
This document is a product of the Internet Engineering Task Force (IETF). It represents the consensus of the IETF community. It has received public review and has been approved for publication by the Internet Engineering Steering Group (IESG). Further information on Internet Standards is available in Section 2 of RFC 7841.¶
Information about the current status of this document, any errata, and how to provide feedback on it may be obtained at https://www.rfc-editor.org/info/rfc9610.¶
Copyright (c) 2024 IETF Trust and the persons identified as the document authors. All rights reserved.¶
This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Revised BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Revised BSD License.¶
The JSON Meta Application Protocol (JMAP) [RFC8620] is a generic protocol for synchronising data, such as mail, calendars, or contacts, between a client and a server. It is optimised for mobile and web environments and aims to provide a consistent interface to different data types.¶
This specification defines a data model for synchronising contacts between a client and a server using JMAP.¶
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here.¶
Type signatures, examples, and property descriptions in this document follow the conventions established in Section 1.1 of [RFC8620]. The Id, UnsignedInt, and UTCDate data types defined in Sections 1.2, 1.3, and 1.4 of [RFC8620] are also used in this document.¶
The same terminology used in the core JMAP specification (see Section 1.6 of [RFC8620]) is also used in this document.¶
The terms AddressBook and ContactCard (with these specific capitalizations) are used to refer to the data types defined in this document and instances of those data types.¶
An Account (see Section 1.6.2 of [RFC8620]) with support for the contact data model contains zero or more AddressBook objects, which is a named collection of zero or more ContactCards. A ContactCard is a representation of a person, company, entity, or a group of such entities in JSContact Card format, as defined in Section 2 of [RFC9553]. Each ContactCard belongs to one or more AddressBooks.¶
In servers with support for JMAP Sharing [RFC9670], users may see and configure sharing of contact data with others. Sharing permissions are managed per AddressBook.¶
The capabilities object is returned as part of the JMAP Session object; see Section 2 of [RFC8620]. This document defines one additional capability URI.¶
This represents support for the AddressBook and ContactCard data types and associated API methods. The value of this property in the JMAP Session "capabilities" property is an empty object.¶
The value of this property in an account's "accountCapabilities" property is an object that MUST contain the following information on server capabilities and permissions for that account:¶
UnsignedInt|null
Boolean
An AddressBook is a named collection of ContactCards. All ContactCards are associated with one or more AddressBooks.¶
An AddressBook object has the following properties:¶
Id
(immutable; server-set)String
String|null
(default: null)UnsignedInt
(default: 0)Defines the sort order of AddressBooks when presented in the client's UI so it is consistent between devices. The number MUST be an integer in the range 0 <= sortOrder < 231.¶
An AddressBook with a lower order is to be displayed before a AddressBook with a higher order in any list of AddressBooks in the client's UI. AddressBooks with equal order should be sorted in alphabetical order by name. The sorting should take into account locale-specific character order convention.¶
Boolean
(server-set)Boolean
True if the user has indicated they wish to see this AddressBook in their client. This SHOULD default to false for AddressBooks in shared accounts that the user has access to and true for any new AddressBooks created by the user themself.¶
If false, the AddressBook and its contents SHOULD only be displayed when the user explicitly requests it. The UI may offer to the user the option of subscribing to it.¶
Id[AddressBookRights]|null
(default: null)urn:ietf:params:jmap:principals:owner
capability of the Account to which the AddressBook belongs.¶
AddressBookRights
(server-set)An AddressBookRights object has the following properties:¶
Boolean
Boolean
Boolean
Boolean
This is a standard "/get" method as described in Section 5.1 of [RFC8620]. The "ids" argument may be null to fetch all at once.¶
This is a standard "/changes" method as described in Section 5.2 of [RFC8620].¶
This is a standard "/set" method as described in Section 5.3 of [RFC8620], but with the following additional request arguments:¶
Boolean
(default: false)Id|null
If the id is not found or if the change is not permitted by the server for policy reasons, it MUST be ignored and the current default AddressBook (if any) will remain as such. No error is returned to the client in this case.¶
As per Section 5.3 of [RFC8620], if the default AddressBook is successfully changed, any changed objects MUST be reported in either the "created" or "updated" argument in the response as appropriate, with the server-set value included.¶
The "shareWith" property may only be set by users that have the "mayShare" right. When modifying the "shareWith" property, the user cannot give a right to a Principal if the Principal did not already have that right and the user making the change also does not have that right. Any attempt to do so MUST be rejected with a "forbidden" SetError.¶
Users can subscribe or unsubscribe to an AddressBook by setting the "isSubscribed" property. The server MAY forbid users from subscribing to certain AddressBooks even though they have permission to see them, rejecting the update with a "forbidden" SetError.¶
The following extra SetError type is defined for "destroy":¶
A ContactCard object contains information about a person, company, or other entity, or represents a group of such entities. It is a JSContact Card object as defined in Section 2 of [RFC9553] with the following additional properties:¶
Id
(immutable; server-set)Id[Boolean]
For any Media object in the card (see Section 2.6.4 of [RFC9553]), a new property is defined:¶
Id
When returning ContactCards, any Media with a URI that uses the "data:" URL scheme [RFC2397] SHOULD return a "blobId" property and omit the "uri" property, as this lets clients load the (potentially large) image file only when needed and avoids the overhead of Base64 encoding. The "mediaType" property MUST also be set. Similarly, when creating or updating a ContactCard, clients MAY send a "blobId" instead of the "uri" property for a Media object.¶
A contact card with a "kind" property equal to "group" represents a group of contacts. Clients often present these separately from other contact cards. The "members" property, as defined in Section 2.1.6 of [RFC9553], contains a set of uids (as defined in Section 2.1.9 of [RFC9553]) for other contacts that are the members of this group.
Clients should consider the group to contain any ContactCard with a matching uid from any account they have access to that has support for the urn:ietf:params:jmap:contacts
capability. Any uid that cannot be found SHOULD be ignored but preserved. For example, suppose a user adds contacts from a shared address book to their private group, then temporarily loses access to this address book. The uids cannot be resolved, so the contacts will disappear from the group. However, if they are given permission to access the data again, the uids will be found and the contacts will reappear.¶
This is a standard "/get" method as described in Section 5.1 of [RFC8620].¶
This is a standard "/changes" method as described in Section 5.2 of [RFC8620].¶
This is a standard "/query" method as described in Section 5.5 of [RFC8620].¶
A FilterCondition object has the following properties, any of which may be omitted:¶
Id
String
String
String
UTCDate
UTCDate
UTCDate
UTCDate
String
String
String
String
String
String
String
String
String
String
String
String
If zero properties are specified on the FilterCondition, the condition MUST always evaluate to true. If multiple properties are specified, ALL must apply for the condition to be true (it is equivalent to splitting the object into one-property conditions and making them all the child of an AND filter operator).¶
The exact semantics for matching String
fields is deliberately not defined to allow for flexibility in indexing implementation, subject to the following:¶
\"
, \'
, and \\
to match a literal "
, '
, and \
respectively in a phrase.¶
bus
would match "buses", but not "business").¶
The following values for the "property" field on the Comparator object MUST be supported for sorting:¶
The following values for the "property" field on the Comparator object SHOULD be supported for sorting:¶
This is a standard "/queryChanges" method as described in Section 5.6 of [RFC8620].¶
This is a standard "/set" method as described in Section 5.3 of [RFC8620].¶
To set a new photo, the file must first be uploaded using the upload mechanism as described in Section 6.1 of [RFC8620]. This will give the client a valid blobId, size, and type to use. The server MUST reject attempts to set a file that is not a recognised image type as the photo for a card.¶
This is a standard "/copy" method as described in Section 5.4 of [RFC8620].¶
For brevity, only the "methodCalls" property of the Request object and the "methodResponses" property of the Response object is shown in the following examples.¶
A user has authenticated and the client has fetched the JMAP Session object. It finds a single Account with the "urn:ietf:params:jmap:contacts" capability with id "a0x9" and wants to fetch all the address books and contacts. It might make the following request:¶
The server might respond with something like:¶
The client tries to change the default address book from "Personal" to "Autosaved" (and makes no other change):¶
The server allows the change, returning the following response:¶
Experience has shown that unrestricted use of Unicode can lead to problems such as inconsistent rendering, users reading text and interpreting it differently than intended, and unexpected results when copying text from one location to another. Servers MAY choose to mitigate this by restricting the set of characters allowed in otherwise unconstrained String
fields. The FreeformClass, as documented in Section 4.3 of [RFC8264], might be a good starting point for
this.¶
Attempts to set a value containing code points outside of the permissible set can be handled in a few ways by the server. The server could choose to strip the forbidden characters or replace them with U+FFFD (the Unicode replacement character) and store the resulting string. This is likely to be appropriate for non-printable characters -- such as the "Control Codes" defined in Section 23.1 of [UNICODE], excluding newline (U+000A), carriage return (U+000D), and tab (U+0009) -- that can end up in data accidentally due to copy-and-paste issues but are invisible to the end user. JMAP allows the server to transform data on create/update as long as any changed properties are returned to the client in the "/set" response so it knows what has changed, as per Section 5.3 of [RFC8620]. Alternatively, the server MAY just reject the create/update with an "invalidProperties" SetError.¶
All security considerations of JMAP [RFC8620] apply to this specification. Additional considerations specific to the data types and functionality introduced by this document are described in the following subsection.¶
Contacts consist almost entirely of private, personally identifiable information, and represent the social connections of users. Privacy leaks can have real world consequences, and contact servers and clients MUST be mindful of the need to keep all data secure.¶
Servers MUST enforce the Access Control Lists (ACLs) set on address books to ensure only authorised data is shared.¶
IANA has registered "contacts" in the "JMAP Capabilities" registry as follows:¶
IANA has registered "AddressBook" in the "JMAP Data Types" registry as follows:¶
IANA has registered "ContactCard" in the "JMAP Data Types" registry as follows:¶
The following subsection has registered a new error code in the "JMAP Error Codes" registry, as defined in Section 9 of [RFC8620].¶
IANA has registered the following additional properties in the "JSContact Properties" registry, as defined in Section 3 of [RFC9553].¶