summaryrefslogtreecommitdiff
path: root/doc/rfc/rfc8620.txt
diff options
context:
space:
mode:
Diffstat (limited to 'doc/rfc/rfc8620.txt')
-rw-r--r--doc/rfc/rfc8620.txt5043
1 files changed, 5043 insertions, 0 deletions
diff --git a/doc/rfc/rfc8620.txt b/doc/rfc/rfc8620.txt
new file mode 100644
index 0000000..935ba47
--- /dev/null
+++ b/doc/rfc/rfc8620.txt
@@ -0,0 +1,5043 @@
+
+
+
+
+
+
+Internet Engineering Task Force (IETF) N. Jenkins
+Request for Comments: 8620 Fastmail
+Category: Standards Track C. Newman
+ISSN: 2070-1721 Oracle
+ July 2019
+
+
+ The JSON Meta Application Protocol (JMAP)
+
+Abstract
+
+ This document specifies a protocol for clients to efficiently query,
+ fetch, and modify JSON-based data objects, with support for push
+ notification of changes and fast resynchronisation and for out-of-
+ band binary data upload/download.
+
+Status of This Memo
+
+ 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/rfc8620.
+
+Copyright Notice
+
+ Copyright (c) 2019 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 Simplified BSD License text as described in Section 4.e of
+ the Trust Legal Provisions and are provided without warranty as
+ described in the Simplified BSD License.
+
+
+
+
+
+
+
+Jenkins & Newman Standards Track [Page 1]
+
+RFC 8620 JMAP July 2019
+
+
+Table of Contents
+
+ 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 4
+ 1.1. Notational Conventions . . . . . . . . . . . . . . . . . 4
+ 1.2. The Id Data Type . . . . . . . . . . . . . . . . . . . . 6
+ 1.3. The Int and UnsignedInt Data Types . . . . . . . . . . . 6
+ 1.4. The Date and UTCDate Data Types . . . . . . . . . . . . . 7
+ 1.5. JSON as the Data Encoding Format . . . . . . . . . . . . 7
+ 1.6. Terminology . . . . . . . . . . . . . . . . . . . . . . . 7
+ 1.6.1. User . . . . . . . . . . . . . . . . . . . . . . . . 7
+ 1.6.2. Accounts . . . . . . . . . . . . . . . . . . . . . . 7
+ 1.6.3. Data Types and Records . . . . . . . . . . . . . . . 8
+ 1.7. The JMAP API Model . . . . . . . . . . . . . . . . . . . 8
+ 1.8. Vendor-Specific Extensions . . . . . . . . . . . . . . . 9
+ 2. The JMAP Session Resource . . . . . . . . . . . . . . . . . . 9
+ 2.1. Example . . . . . . . . . . . . . . . . . . . . . . . . . 14
+ 2.2. Service Autodiscovery . . . . . . . . . . . . . . . . . . 15
+ 3. Structured Data Exchange . . . . . . . . . . . . . . . . . . 16
+ 3.1. Making an API Request . . . . . . . . . . . . . . . . . . 16
+ 3.2. The Invocation Data Type . . . . . . . . . . . . . . . . 16
+ 3.3. The Request Object . . . . . . . . . . . . . . . . . . . 16
+ 3.3.1. Example Request . . . . . . . . . . . . . . . . . . . 18
+ 3.4. The Response Object . . . . . . . . . . . . . . . . . . . 18
+ 3.4.1. Example Response . . . . . . . . . . . . . . . . . . 19
+ 3.5. Omitting Arguments . . . . . . . . . . . . . . . . . . . 19
+ 3.6. Errors . . . . . . . . . . . . . . . . . . . . . . . . . 19
+ 3.6.1. Request-Level Errors . . . . . . . . . . . . . . . . 20
+ 3.6.2. Method-Level Errors . . . . . . . . . . . . . . . . . 21
+ 3.7. References to Previous Method Results . . . . . . . . . . 22
+ 3.8. Localisation of User-Visible Strings . . . . . . . . . . 27
+ 3.9. Security . . . . . . . . . . . . . . . . . . . . . . . . 28
+ 3.10. Concurrency . . . . . . . . . . . . . . . . . . . . . . . 28
+ 4. The Core/echo Method . . . . . . . . . . . . . . . . . . . . 28
+ 4.1. Example . . . . . . . . . . . . . . . . . . . . . . . . . 28
+ 5. Standard Methods and Naming Convention . . . . . . . . . . . 29
+ 5.1. /get . . . . . . . . . . . . . . . . . . . . . . . . . . 29
+ 5.2. /changes . . . . . . . . . . . . . . . . . . . . . . . . 30
+ 5.3. /set . . . . . . . . . . . . . . . . . . . . . . . . . . 34
+ 5.4. /copy . . . . . . . . . . . . . . . . . . . . . . . . . . 40
+ 5.5. /query . . . . . . . . . . . . . . . . . . . . . . . . . 42
+ 5.6. /queryChanges . . . . . . . . . . . . . . . . . . . . . . 48
+ 5.7. Examples . . . . . . . . . . . . . . . . . . . . . . . . 51
+ 5.8. Proxy Considerations . . . . . . . . . . . . . . . . . . 58
+ 6. Binary Data . . . . . . . . . . . . . . . . . . . . . . . . . 58
+ 6.1. Uploading Binary Data . . . . . . . . . . . . . . . . . . 59
+ 6.2. Downloading Binary Data . . . . . . . . . . . . . . . . . 60
+ 6.3. Blob/copy . . . . . . . . . . . . . . . . . . . . . . . . 61
+
+
+
+
+Jenkins & Newman Standards Track [Page 2]
+
+RFC 8620 JMAP July 2019
+
+
+ 7. Push . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
+ 7.1. The StateChange Object . . . . . . . . . . . . . . . . . 63
+ 7.1.1. Example . . . . . . . . . . . . . . . . . . . . . . . 64
+ 7.2. PushSubscription . . . . . . . . . . . . . . . . . . . . 64
+ 7.2.1. PushSubscription/get . . . . . . . . . . . . . . . . 67
+ 7.2.2. PushSubscription/set . . . . . . . . . . . . . . . . 68
+ 7.2.3. Example . . . . . . . . . . . . . . . . . . . . . . . 69
+ 7.3. Event Source . . . . . . . . . . . . . . . . . . . . . . 71
+ 8. Security Considerations . . . . . . . . . . . . . . . . . . . 73
+ 8.1. Transport Confidentiality . . . . . . . . . . . . . . . . 73
+ 8.2. Authentication Scheme . . . . . . . . . . . . . . . . . . 73
+ 8.3. Service Autodiscovery . . . . . . . . . . . . . . . . . . 73
+ 8.4. JSON Parsing . . . . . . . . . . . . . . . . . . . . . . 74
+ 8.5. Denial of Service . . . . . . . . . . . . . . . . . . . . 74
+ 8.6. Connection to Unknown Push Server . . . . . . . . . . . . 74
+ 8.7. Push Encryption . . . . . . . . . . . . . . . . . . . . . 75
+ 8.8. Traffic Analysis . . . . . . . . . . . . . . . . . . . . 76
+ 9. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 76
+ 9.1. Assignment of jmap Service Name . . . . . . . . . . . . . 76
+ 9.2. Registration of Well-Known URI Suffix for JMAP . . . . . 76
+ 9.3. Registration of the jmap URN Sub-namespace . . . . . . . 77
+ 9.4. Creation of "JMAP Capabilities" Registry . . . . . . . . 77
+ 9.4.1. Preliminary Community Review . . . . . . . . . . . . 77
+ 9.4.2. Submit Request to IANA . . . . . . . . . . . . . . . 78
+ 9.4.3. Designated Expert Review . . . . . . . . . . . . . . 78
+ 9.4.4. Change Procedures . . . . . . . . . . . . . . . . . . 78
+ 9.4.5. JMAP Capabilities Registry Template . . . . . . . . . 79
+ 9.4.6. Initial Registration for JMAP Core . . . . . . . . . 79
+ 9.4.7. Registration for JMAP Error Placeholder in JMAP
+ Capabilities Registry . . . . . . . . . . . . . . . . 80
+ 9.5. Creation of "JMAP Error Codes" Registry . . . . . . . . . 80
+ 9.5.1. Expert Review . . . . . . . . . . . . . . . . . . . . 80
+ 9.5.2. JMAP Error Codes Registry Template . . . . . . . . . 81
+ 9.5.3. Initial Contents for the JMAP Error Codes Registry . 81
+ 10. References . . . . . . . . . . . . . . . . . . . . . . . . . 86
+ 10.1. Normative References . . . . . . . . . . . . . . . . . . 86
+ 10.2. Informative References . . . . . . . . . . . . . . . . . 89
+ Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . 90
+
+
+
+
+
+
+
+
+
+
+
+
+
+Jenkins & Newman Standards Track [Page 3]
+
+RFC 8620 JMAP July 2019
+
+
+1. Introduction
+
+ The JSON Meta Application Protocol (JMAP) is used 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 is for the generic mechanism of data
+ synchronisation. Further specifications define the data models for
+ different data types that may be synchronised via JMAP.
+
+ JMAP is designed to make efficient use of limited network resources.
+ Multiple API calls may be batched in a single request to the server,
+ reducing round trips and improving battery life on mobile devices.
+ Push connections remove the need for polling, and an efficient delta
+ update mechanism ensures a minimum amount of data is transferred.
+
+ JMAP is designed to be horizontally scalable to a very large number
+ of users. This is facilitated by separate endpoints for users after
+ login, the separation of binary and structured data, and a data model
+ for sharing that does not allow data dependencies between accounts.
+
+1.1. Notational Conventions
+
+ 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.
+
+ The underlying format used for this specification is JSON.
+ Consequently, the terms "object" and "array" as well as the four
+ primitive types (strings, numbers, booleans, and null) are to be
+ interpreted as described in Section 1 of [RFC8259]. Unless otherwise
+ noted, all the property names and values are case sensitive.
+
+ Some examples in this document contain "partial" JSON documents used
+ for illustrative purposes. In these examples, three periods "..."
+ are used to indicate a portion of the document that has been removed
+ for compactness.
+
+ For compatibility with publishing requirements, line breaks have been
+ inserted inside long JSON strings, with the following continuation
+ lines indented. To form the valid JSON example, any line breaks
+ inside a string must be replaced with a space and any other white
+ space after the line break removed.
+
+
+
+
+
+Jenkins & Newman Standards Track [Page 4]
+
+RFC 8620 JMAP July 2019
+
+
+ Unless otherwise specified, examples of API exchanges only show the
+ methodCalls array of the Request object or the methodResponses array
+ of the Response object. For compactness, the rest of the Request/
+ Response object is omitted.
+
+ Type signatures are given for all JSON values in this document. The
+ following conventions are used:
+
+ o "*" - The type is undefined (the value could be any type, although
+ permitted values may be constrained by the context of this value).
+
+ o "String" - The JSON string type.
+
+ o "Number" - The JSON number type.
+
+ o "Boolean" - The JSON boolean type.
+
+ o "A[B]" - A JSON object where the keys are all of type "A", and the
+ values are all of type "B".
+
+ o "A[]" - An array of values of type "A".
+
+ o "A|B" - The value is either of type "A" or of type "B".
+
+ Other types may also be given, with their representation defined
+ elsewhere in this document.
+
+ Object properties may also have a set of attributes defined along
+ with the type signature. These have the following meanings:
+
+ o "server-set" -- Only the server can set the value for this
+ property. The client MUST NOT send this property when creating a
+ new object of this type.
+
+ o "immutable" -- The value MUST NOT change after the object is
+ created.
+
+ o "default" -- (This is followed by a JSON value). The value that
+ will be used for this property if it is omitted in an argument or
+ when creating a new object of this type.
+
+
+
+
+
+
+
+
+
+
+
+Jenkins & Newman Standards Track [Page 5]
+
+RFC 8620 JMAP July 2019
+
+
+1.2. The Id Data Type
+
+ All record ids are assigned by the server and are immutable.
+
+ Where "Id" is given as a data type, it means a "String" of at least 1
+ and a maximum of 255 octets in size, and it MUST only contain
+ characters from the "URL and Filename Safe" base64 alphabet, as
+ defined in Section 5 of [RFC4648], excluding the pad character ("=").
+ This means the allowed characters are the ASCII alphanumeric
+ characters ("A-Za-z0-9"), hyphen ("-"), and underscore ("_").
+
+ These characters are safe to use in almost any context (e.g.,
+ filesystems, URIs, and IMAP atoms). For maximum safety, servers
+ SHOULD also follow defensive allocation strategies to avoid creating
+ risks where glob completion or data type detection may be present
+ (e.g., on filesystems or in spreadsheets). In particular, it is wise
+ to avoid:
+
+ o Ids starting with a dash
+
+ o Ids starting with digits
+
+ o Ids that contain only digits
+
+ o Ids that differ only by ASCII case (for example, A vs. a)
+
+ o the specific sequence of three characters "NIL" (because this
+ sequence can be confused with the IMAP protocol expression of the
+ null value)
+
+ A good solution to these issues is to prefix every id with a single
+ alphabetical character.
+
+1.3. The Int and UnsignedInt Data Types
+
+ Where "Int" is given as a data type, it means an integer in the range
+ -2^53+1 <= value <= 2^53-1, the safe range for integers stored in a
+ floating-point double, represented as a JSON "Number".
+
+ Where "UnsignedInt" is given as a data type, it means an "Int" where
+ the value MUST be in the range 0 <= value <= 2^53-1.
+
+
+
+
+
+
+
+
+
+
+Jenkins & Newman Standards Track [Page 6]
+
+RFC 8620 JMAP July 2019
+
+
+1.4. The Date and UTCDate Data Types
+
+ Where "Date" is given as a type, it means a string in "date-time"
+ format [RFC3339]. To ensure a normalised form, the "time-secfrac"
+ MUST always be omitted if zero, and any letters in the string (e.g.,
+ "T" and "Z") MUST be uppercase. For example,
+ "2014-10-30T14:12:00+08:00".
+
+ Where "UTCDate" is given as a type, it means a "Date" where the
+ "time-offset" component MUST be "Z" (i.e., it must be in UTC time).
+ For example, "2014-10-30T06:12:00Z".
+
+1.5. JSON as the Data Encoding Format
+
+ JSON is a text-based data interchange format as specified in
+ [RFC8259]. The Internet JSON (I-JSON) format defined in [RFC7493] is
+ a strict subset of this, adding restrictions to avoid potentially
+ confusing scenarios (for example, it mandates that an object MUST NOT
+ have two members with the same name).
+
+ All data sent from the client to the server or from the server to the
+ client (except binary file upload/download) MUST be valid I-JSON
+ according to the RFC and is therefore case sensitive and encoded in
+ UTF-8 [RFC3629].
+
+1.6. Terminology
+
+1.6.1. User
+
+ A user is a person accessing data via JMAP. A user has a set of
+ permissions determining the data that they can see.
+
+1.6.2. Accounts
+
+ An account is a collection of data. A single account may contain an
+ arbitrary set of data types, for example, a collection of mail,
+ contacts, and calendars. Most JMAP methods take a mandatory
+ "accountId" argument that specifies on which account the operations
+ are to take place.
+
+ An account is not the same as a user, although it is common for a
+ primary account to directly belong to the user. For example, you may
+ have an account that contains data for a group or business, to which
+ multiple users have access.
+
+
+
+
+
+
+
+Jenkins & Newman Standards Track [Page 7]
+
+RFC 8620 JMAP July 2019
+
+
+ A single set of credentials may provide access to multiple accounts,
+ for example, if another user is sharing their work calendar with the
+ authenticated user or if there is a group mailbox for a support-desk
+ inbox.
+
+ In the event of a severe internal error, a server may have to
+ reallocate ids or do something else that violates standard JMAP data
+ constraints for an account. In this situation, the data on the
+ server is no longer compatible with cached data the client may have
+ from before. The server MUST treat this as though the account has
+ been deleted and then recreated with a new account id. Clients will
+ then be forced to throw away any data with the old account id and
+ refetch all data from scratch.
+
+1.6.3. Data Types and Records
+
+ JMAP provides a uniform interface for creating, retrieving, updating,
+ and deleting various types of objects. A "data type" is a collection
+ of named, typed properties, just like the schema for a database
+ table. Each instance of a data type is called a "record".
+
+ The id of a record is immutable and assigned by the server. The id
+ MUST be unique among all records of the *same type* within the *same
+ account*. Ids may clash across accounts or for two records of
+ different types within the same account.
+
+1.7. The JMAP API Model
+
+ JMAP uses HTTP [RFC7230] to expose API, push, upload, and download
+ resources. All HTTP requests MUST use the "https://" scheme (HTTP
+ over TLS [RFC2818]). All HTTP requests MUST be authenticated.
+
+ An authenticated client can fetch the user's Session object with
+ details about the data and capabilities the server can provide as
+ shown in Section 2. The client may then exchange data with the
+ server in the following ways:
+
+ 1. The client may make an API request to the server to get or set
+ structured data. This request consists of an ordered series of
+ method calls. These are processed by the server, which then
+ returns an ordered series of responses. This is described in
+ Sections 3, 4, and 5.
+
+ 2. The client may download or upload binary files from/to the
+ server. This is detailed in Section 6.
+
+ 3. The client may connect to a push channel on the server, to be
+ notified when data has changed. This is explained in Section 7.
+
+
+
+Jenkins & Newman Standards Track [Page 8]
+
+RFC 8620 JMAP July 2019
+
+
+1.8. Vendor-Specific Extensions
+
+ Individual services will have custom features they wish to expose
+ over JMAP. This may take the form of extra data types and/or methods
+ not in the spec, extra arguments to JMAP methods, or extra properties
+ on existing data types (which may also appear in arguments to methods
+ that take property names).
+
+ The server can advertise custom extensions it supports by including
+ the identifiers in the capabilities object. Identifiers for vendor
+ extensions MUST be a URL belonging to a domain owned by the vendor,
+ to avoid conflict. The URL SHOULD resolve to documentation for the
+ changes the extension makes.
+
+ The client MUST opt in to use an extension by passing the appropriate
+ capability identifier in the "using" array of the Request object, as
+ described in Section 3.3. The server MUST only follow the
+ specifications that are opted into and behave as though it does not
+ implement anything else when processing a request. This is to ensure
+ compatibility with clients that don't know about a specific custom
+ extension and for compatibility with future versions of JMAP.
+
+2. The JMAP Session Resource
+
+ You need two things to connect to a JMAP server:
+
+ 1. The URL for the JMAP Session resource. This may be requested
+ directly from the user or discovered automatically based on a
+ username domain (see Section 2.2 below).
+
+ 2. Credentials to authenticate with. How to obtain credentials is
+ out of scope for this document.
+
+ A successful authenticated GET request to the JMAP Session resource
+ MUST return a JSON-encoded *Session* object, giving details about the
+ data and capabilities the server can provide to the client given
+ those credentials. It has the following properties:
+
+ o capabilities: "String[Object]"
+
+ An object specifying the capabilities of this server. Each key is
+ a URI for a capability supported by the server. The value for
+ each of these keys is an object with further information about the
+ server's capabilities in relation to that capability.
+
+ The client MUST ignore any properties it does not understand.
+
+
+
+
+
+Jenkins & Newman Standards Track [Page 9]
+
+RFC 8620 JMAP July 2019
+
+
+ The capabilities object MUST include a property called
+ "urn:ietf:params:jmap:core". The value of this property is an
+ object that MUST contain the following information on server
+ capabilities (suggested minimum values for limits are supplied
+ that allow clients to make efficient use of the network):
+
+ * maxSizeUpload: "UnsignedInt"
+
+ The maximum file size, in octets, that the server will accept
+ for a single file upload (for any purpose). Suggested minimum:
+ 50,000,000.
+
+ * maxConcurrentUpload: "UnsignedInt"
+
+ The maximum number of concurrent requests the server will
+ accept to the upload endpoint. Suggested minimum: 4.
+
+ * maxSizeRequest: "UnsignedInt"
+
+ The maximum size, in octets, that the server will accept for a
+ single request to the API endpoint. Suggested minimum:
+ 10,000,000.
+
+ * maxConcurrentRequests: "UnsignedInt"
+
+ The maximum number of concurrent requests the server will
+ accept to the API endpoint. Suggested minimum: 4.
+
+ * maxCallsInRequest: "UnsignedInt"
+
+ The maximum number of method calls the server will accept in a
+ single request to the API endpoint. Suggested minimum: 16.
+
+ * maxObjectsInGet: "UnsignedInt"
+
+ The maximum number of objects that the client may request in a
+ single /get type method call. Suggested minimum: 500.
+
+ * maxObjectsInSet: "UnsignedInt"
+
+ The maximum number of objects the client may send to create,
+ update, or destroy in a single /set type method call. This is
+ the combined total, e.g., if the maximum is 10, you could not
+ create 7 objects and destroy 6, as this would be 13 actions,
+ which exceeds the limit. Suggested minimum: 500.
+
+
+
+
+
+
+Jenkins & Newman Standards Track [Page 10]
+
+RFC 8620 JMAP July 2019
+
+
+ * collationAlgorithms: "String[]"
+
+ A list of identifiers for algorithms registered in the
+ collation registry, as defined in [RFC4790], that the server
+ supports for sorting when querying records.
+
+ Specifications for future capabilities will define their own
+ properties on the capabilities object.
+
+ Servers MAY advertise vendor-specific JMAP extensions, as
+ described in Section 1.8. To avoid conflict, an identifier for a
+ vendor-specific extension MUST be a URL with a domain owned by the
+ vendor. Clients MUST opt in to any capability it wishes to use
+ (see Section 3.3).
+
+ o accounts: "Id[Account]"
+
+ A map of an account id to an Account object for each account (see
+ Section 1.6.2) the user has access to. An *Account* object has
+ the following properties:
+
+ * name: "String"
+
+ A user-friendly string to show when presenting content from
+ this account, e.g., the email address representing the owner of
+ the account.
+
+ * isPersonal: "Boolean"
+
+ This is true if the account belongs to the authenticated user
+ rather than a group account or a personal account of another
+ user that has been shared with them.
+
+ * isReadOnly: "Boolean"
+
+ This is true if the entire account is read-only.
+
+ * accountCapabilities: "String[Object]"
+
+ The set of capability URIs for the methods supported in this
+ account. Each key is a URI for a capability that has methods
+ you can use with this account. The value for each of these
+ keys is an object with further information about the account's
+ permissions and restrictions with respect to this capability,
+ as defined in the capability's specification.
+
+ The client MUST ignore any properties it does not understand.
+
+
+
+
+Jenkins & Newman Standards Track [Page 11]
+
+RFC 8620 JMAP July 2019
+
+
+ The server advertises the full list of capabilities it supports
+ in the capabilities object, as defined above. If the
+ capability defines new methods, the server MUST include it in
+ the accountCapabilities object if the user may use those
+ methods with this account. It MUST NOT include it in the
+ accountCapabilities object if the user cannot use those methods
+ with this account.
+
+ For example, you may have access to your own account with mail,
+ calendars, and contacts data and also a shared account that
+ only has contacts data (a business address book, for example).
+ In this case, the accountCapabilities property on the first
+ account would include something like
+ "urn:ietf:params:jmap:mail", "urn:ietf:params:jmap:calendars",
+ and "urn:ietf:params:jmap:contacts", while the second account
+ would just have the last of these.
+
+ Attempts to use the methods defined in a capability with one of
+ the accounts that does not support that capability are rejected
+ with an "accountNotSupportedByMethod" error (see "Method-Level
+ Errors", Section 3.6.2).
+
+ o primaryAccounts: "String[Id]"
+
+ A map of capability URIs (as found in accountCapabilities) to the
+ account id that is considered to be the user's main or default
+ account for data pertaining to that capability. If no account
+ being returned belongs to the user, or in any other way there is
+ no appropriate way to determine a default account, there MAY be no
+ entry for a particular URI, even though that capability is
+ supported by the server (and in the capabilities object).
+ "urn:ietf:params:jmap:core" SHOULD NOT be present.
+
+ o username: "String"
+
+ The username associated with the given credentials, or the empty
+ string if none.
+
+ o apiUrl: "String"
+
+ The URL to use for JMAP API requests.
+
+
+
+
+
+
+
+
+
+
+Jenkins & Newman Standards Track [Page 12]
+
+RFC 8620 JMAP July 2019
+
+
+ o downloadUrl: "String"
+
+ The URL endpoint to use when downloading files, in URI Template
+ (level 1) format [RFC6570]. The URL MUST contain variables called
+ "accountId", "blobId", "type", and "name". The use of these
+ variables is described in Section 6.2. Due to potential encoding
+ issues with slashes in content types, it is RECOMMENDED to put the
+ "type" variable in the query section of the URL.
+
+ o uploadUrl: "String"
+
+ The URL endpoint to use when uploading files, in URI Template
+ (level 1) format [RFC6570]. The URL MUST contain a variable
+ called "accountId". The use of this variable is described in
+ Section 6.1.
+
+ o eventSourceUrl: "String"
+
+ The URL to connect to for push events, as described in
+ Section 7.3, in URI Template (level 1) format [RFC6570]. The URL
+ MUST contain variables called "types", "closeafter", and "ping".
+ The use of these variables is described in Section 7.3.
+
+ o state: "String"
+
+ A (preferably short) string representing the state of this object
+ on the server. If the value of any other property on the Session
+ object changes, this string will change. The current value is
+ also returned on the API Response object (see Section 3.4),
+ allowing clients to quickly determine if the session information
+ has changed (e.g., an account has been added or removed), so they
+ need to refetch the object.
+
+ To ensure future compatibility, other properties MAY be included on
+ the Session object. Clients MUST ignore any properties they are not
+ expecting.
+
+ Implementors must take care to avoid inappropriate caching of the
+ Session object at the HTTP layer. Since the client should only
+ refetch when it detects there is a change (via the sessionState
+ property of an API response), it is RECOMMENDED to disable HTTP
+ caching altogether, for example, by setting "Cache-Control: no-cache,
+ no-store, must-revalidate" on the response.
+
+
+
+
+
+
+
+
+Jenkins & Newman Standards Track [Page 13]
+
+RFC 8620 JMAP July 2019
+
+
+2.1. Example
+
+ In the following example Session object, the user has access to their
+ own mail and contacts via JMAP, as well as read-only access to shared
+ mail from another user. The server is advertising a custom
+ "https://example.com/apis/foobar" capability.
+
+ {
+ "capabilities": {
+ "urn:ietf:params:jmap:core": {
+ "maxSizeUpload": 50000000,
+ "maxConcurrentUpload": 8,
+ "maxSizeRequest": 10000000,
+ "maxConcurrentRequest": 8,
+ "maxCallsInRequest": 32,
+ "maxObjectsInGet": 256,
+ "maxObjectsInSet": 128,
+ "collationAlgorithms": [
+ "i;ascii-numeric",
+ "i;ascii-casemap",
+ "i;unicode-casemap"
+ ]
+ },
+ "urn:ietf:params:jmap:mail": {}
+ "urn:ietf:params:jmap:contacts": {},
+ "https://example.com/apis/foobar": {
+ "maxFoosFinangled": 42
+ }
+ },
+ "accounts": {
+ "A13824": {
+ "name": "john@example.com",
+ "isPersonal": true,
+ "isReadOnly": false,
+ "accountCapabilities": {
+ "urn:ietf:params:jmap:mail": {
+ "maxMailboxesPerEmail": null,
+ "maxMailboxDepth": 10,
+ ...
+ },
+ "urn:ietf:params:jmap:contacts": {
+ ...
+ }
+ }
+ },
+
+
+
+
+
+
+Jenkins & Newman Standards Track [Page 14]
+
+RFC 8620 JMAP July 2019
+
+
+ "A97813": {
+ "name": "jane@example.com",
+ "isPersonal": false,
+ "isReadOnly": true,
+ "accountCapabilities": {
+ "urn:ietf:params:jmap:mail": {
+ "maxMailboxesPerEmail": 1,
+ "maxMailboxDepth": 10,
+ ...
+ }
+ }
+ }
+ },
+ "primaryAccounts": {
+ "urn:ietf:params:jmap:mail": "A13824",
+ "urn:ietf:params:jmap:contacts": "A13824"
+ },
+ "username": "john@example.com",
+ "apiUrl": "https://jmap.example.com/api/",
+ "downloadUrl": "https://jmap.example.com
+ /download/{accountId}/{blobId}/{name}?accept={type}",
+ "uploadUrl": "https://jmap.example.com/upload/{accountId}/",
+ "eventSourceUrl": "https://jmap.example.com
+ /eventsource/?types={types}&closeafter={closeafter}&ping={ping}",
+ "state": "75128aab4b1b"
+ }
+
+2.2. Service Autodiscovery
+
+ There are two standardised autodiscovery methods in use for Internet
+ protocols:
+
+ o DNS SRV (see [RFC2782], [RFC6186], and [RFC6764])
+
+ o .well-known/servicename (see [RFC8615])
+
+ A JMAP-supporting host for the domain "example.com" SHOULD publish a
+ SRV record "_jmap._tcp.example.com" that gives a hostname and port
+ (usually port "443"). The JMAP Session resource is then
+ "https://${hostname}[:${port}]/.well-known/jmap" (following any
+ redirects).
+
+ If the client has a username in the form of an email address, it MAY
+ use the domain portion of this to attempt autodiscovery of the JMAP
+ server.
+
+
+
+
+
+
+Jenkins & Newman Standards Track [Page 15]
+
+RFC 8620 JMAP July 2019
+
+
+3. Structured Data Exchange
+
+ The client may make an API request to the server to get or set
+ structured data. This request consists of an ordered series of
+ method calls. These are processed by the server, which then returns
+ an ordered series of responses.
+
+3.1. Making an API Request
+
+ To make an API request, the client makes an authenticated POST
+ request to the API resource, which is defined by the "apiUrl"
+ property in the Session object (see Section 2).
+
+ The request MUST be of type "application/json" and consist of a
+ single JSON-encoded "Request" object, as defined in Section 3.3. If
+ successful, the response MUST also be of type "application/json" and
+ consist of a single "Response" object, as defined in Section 3.4.
+
+3.2. The Invocation Data Type
+
+ Method calls and responses are represented by the *Invocation* data
+ type. This is a tuple, represented as a JSON array containing three
+ elements:
+
+ 1. A "String" *name* of the method to call or of the response.
+
+ 2. A "String[*]" object containing named *arguments* for that method
+ or response.
+
+ 3. A "String" *method call id*: an arbitrary string from the client
+ to be echoed back with the responses emitted by that method call
+ (a method may return 1 or more responses, as it may make implicit
+ calls to other methods; all responses initiated by this method
+ call get the same method call id in the response).
+
+3.3. The Request Object
+
+ A *Request* object has the following properties:
+
+ o using: "String[]"
+
+ The set of capabilities the client wishes to use. The client MAY
+ include capability identifiers even if the method calls it makes
+ do not utilise those capabilities. The server advertises the set
+ of specifications it supports in the Session object (see
+ Section 2), as keys on the "capabilities" property.
+
+
+
+
+
+Jenkins & Newman Standards Track [Page 16]
+
+RFC 8620 JMAP July 2019
+
+
+ o methodCalls: "Invocation[]"
+
+ An array of method calls to process on the server. The method
+ calls MUST be processed sequentially, in order.
+
+ o createdIds: "Id[Id]" (optional)
+
+ A map of a (client-specified) creation id to the id the server
+ assigned when a record was successfully created.
+
+ As described later in this specification, some records may have a
+ property that contains the id of another record. To allow more
+ efficient network usage, you can set this property to reference a
+ record created earlier in the same API request. Since the real id
+ is unknown when the request is created, the client can instead
+ specify the creation id it assigned, prefixed with a "#" (see
+ Section 5.3 for more details).
+
+ As the server processes API requests, any time it successfully
+ creates a new record, it adds the creation id to this map (see the
+ "create" argument to /set in Section 5.3), with the server-
+ assigned real id as the value. If it comes across a reference to
+ a creation id in a create/update, it looks it up in the map and
+ replaces the reference with the real id, if found.
+
+ The client can pass an initial value for this map as the
+ "createdIds" property of the Request object. This may be an empty
+ object. If given in the request, the response will also include a
+ createdIds property. This allows proxy servers to easily split a
+ JMAP request into multiple JMAP requests to send to different
+ servers. For example, it could send the first two method calls to
+ server A, then the third to server B, before sending the fourth to
+ server A again. By passing the createdIds of the previous
+ response to the next request, it can ensure all of these still
+ resolve. See Section 5.8 for further discussion of proxy
+ considerations.
+
+ Future specifications MAY add further properties to the Request
+ object to extend the semantics. To ensure forwards compatibility, a
+ server MUST ignore any other properties it does not understand on the
+ JMAP Request object.
+
+
+
+
+
+
+
+
+
+
+Jenkins & Newman Standards Track [Page 17]
+
+RFC 8620 JMAP July 2019
+
+
+3.3.1. Example Request
+
+{
+ "using": [ "urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail" ],
+ "methodCalls": [
+ [ "method1", {
+ "arg1": "arg1data",
+ "arg2": "arg2data"
+ }, "c1" ],
+ [ "method2", {
+ "arg1": "arg1data"
+ }, "c2" ],
+ [ "method3", {}, "c3" ]
+ ]
+}
+
+3.4. The Response Object
+
+ A *Response* object has the following properties:
+
+ o methodResponses: "Invocation[]"
+
+ An array of responses, in the same format as the "methodCalls" on
+ the Request object. The output of the methods MUST be added to
+ the "methodResponses" array in the same order that the methods are
+ processed.
+
+ o createdIds: "Id[Id]" (optional; only returned if given in the
+ request)
+
+ A map of a (client-specified) creation id to the id the server
+ assigned when a record was successfully created. This MUST
+ include all creation ids passed in the original createdIds
+ parameter of the Request object, as well as any additional ones
+ added for newly created records.
+
+ o sessionState: "String"
+
+ The current value of the "state" string on the Session object, as
+ described in Section 2. Clients may use this to detect if this
+ object has changed and needs to be refetched.
+
+ Unless otherwise specified, if the method call completed
+ successfully, its response name is the same as the method name in the
+ request.
+
+
+
+
+
+
+Jenkins & Newman Standards Track [Page 18]
+
+RFC 8620 JMAP July 2019
+
+
+3.4.1. Example Response
+
+ {
+ "methodResponses": [
+ [ "method1", {
+ "arg1": 3,
+ "arg2": "foo"
+ }, "c1" ],
+ [ "method2", {
+ "isBlah": true
+ }, "c2" ],
+ [ "anotherResponseFromMethod2", {
+ "data": 10,
+ "yetmoredata": "Hello"
+ }, "c2"],
+ [ "error", {
+ "type":"unknownMethod"
+ }, "c3" ]
+ ],
+ "sessionState": "75128aab4b1b"
+ }
+
+3.5. Omitting Arguments
+
+ An argument to a method may be specified to have a default value. If
+ omitted by the client, the server MUST treat the method call the same
+ as if the default value had been specified. Similarly, the server
+ MAY omit any argument in a response that has the default value.
+
+ Unless otherwise specified in a method description, null is the
+ default value for any argument in a request or response where this is
+ allowed by the type signature. Other arguments may only be omitted
+ if an explicit default value is defined in the method description.
+
+3.6. Errors
+
+ There are three different levels of granularity at which an error may
+ be returned in JMAP.
+
+ When an API request is made, the request as a whole may be rejected
+ due to rate limiting, malformed JSON, request for an unknown
+ capability, etc. In this case, the entire request is rejected with
+ an appropriate HTTP error response code and an additional JSON body
+ with more detail for the client.
+
+ Provided the request itself is syntactically valid (the JSON is valid
+ and when decoded, it matches the type signature of a Request object),
+ the methods within it are executed sequentially by the server. Each
+
+
+
+Jenkins & Newman Standards Track [Page 19]
+
+RFC 8620 JMAP July 2019
+
+
+ method may individually fail, for example, if invalid arguments are
+ given or an unknown method name is called.
+
+ Finally, methods that make changes to the server state often act upon
+ a number of different records within a single call. Each record
+ change may be separately rejected with a SetError, as described in
+ Section 5.3.
+
+3.6.1. Request-Level Errors
+
+ When an HTTP error response is returned to the client, the server
+ SHOULD return a JSON "problem details" object as the response body,
+ as per [RFC7807].
+
+ The following problem types are defined:
+
+ o "urn:ietf:params:jmap:error:unknownCapability"
+ The client included a capability in the "using" property of the
+ request that the server does not support.
+
+ o "urn:ietf:params:jmap:error:notJSON"
+ The content type of the request was not "application/json" or the
+ request did not parse as I-JSON.
+
+ o "urn:ietf:params:jmap:error:notRequest"
+ The request parsed as JSON but did not match the type signature of
+ the Request object.
+
+ o "urn:ietf:params:jmap:error:limit"
+ The request was not processed as it would have exceeded one of the
+ request limits defined on the capability object, such as
+ maxSizeRequest, maxCallsInRequest, or maxConcurrentRequests. A
+ "limit" property MUST also be present on the "problem details"
+ object, containing the name of the limit being applied.
+
+3.6.1.1. Example
+
+ {
+ "type": "urn:ietf:params:jmap:error:unknownCapability",
+ "status": 400,
+ "detail": "The Request object used capability
+ 'https://example.com/apis/foobar', which is not supported
+ by this server."
+ }
+
+
+
+
+
+
+
+Jenkins & Newman Standards Track [Page 20]
+
+RFC 8620 JMAP July 2019
+
+
+ Another example:
+
+ {
+ "type": "urn:ietf:params:jmap:error:limit",
+ "limit": "maxSizeRequest",
+ "status": 400,
+ "detail": "The request is larger than the server is willing to
+ process."
+ }
+
+3.6.2. Method-Level Errors
+
+ If a method encounters an error, the appropriate "error" response
+ MUST be inserted at the current point in the "methodResponses" array
+ and, unless otherwise specified, further processing MUST NOT happen
+ within that method call.
+
+ Any further method calls in the request MUST then be processed as
+ normal. Errors at the method level MUST NOT generate an HTTP-level
+ error.
+
+ An "error" response looks like this:
+
+ [ "error", {
+ "type": "unknownMethod"
+ }, "call-id" ]
+
+ The response name is "error", and it MUST have a type property.
+ Other properties may be present with further information; these are
+ detailed in the error type descriptions where appropriate.
+
+ With the exception of when the "serverPartialFail" error is returned,
+ the externally visible state of the server MUST NOT have changed if
+ an error is returned at the method level.
+
+ The following error types are defined, which may be returned for any
+ method call where appropriate:
+
+ "serverUnavailable": Some internal server resource was temporarily
+ unavailable. Attempting the same operation later (perhaps after a
+ backoff with a random factor) may succeed.
+
+ "serverFail": An unexpected or unknown error occurred during the
+ processing of the call. A "description" property should provide more
+ details about the error. The method call made no changes to the
+ server's state. Attempting the same operation again is expected to
+ fail again. Contacting the service administrator is likely necessary
+ to resolve this problem if it is persistent.
+
+
+
+Jenkins & Newman Standards Track [Page 21]
+
+RFC 8620 JMAP July 2019
+
+
+ "serverPartialFail": Some, but not all, expected changes described by
+ the method occurred. The client MUST resynchronise impacted data to
+ determine server state. Use of this error is strongly discouraged.
+
+ "unknownMethod": The server does not recognise this method name.
+
+ "invalidArguments": One of the arguments is of the wrong type or is
+ otherwise invalid, or a required argument is missing. A
+ "description" property MAY be present to help debug with an
+ explanation of what the problem was. This is a non-localised string,
+ and it is not intended to be shown directly to end users.
+
+ "invalidResultReference": The method used a result reference for one
+ of its arguments (see Section 3.7), but this failed to resolve.
+
+ "forbidden": The method and arguments are valid, but executing the
+ method would violate an Access Control List (ACL) or other
+ permissions policy.
+
+ "accountNotFound": The accountId does not correspond to a valid
+ account.
+
+ "accountNotSupportedByMethod": The accountId given corresponds to a
+ valid account, but the account does not support this method or data
+ type.
+
+ "accountReadOnly": This method modifies state, but the account is
+ read-only (as returned on the corresponding Account object in the
+ JMAP Session resource).
+
+ Further possible errors for a particular method are specified in the
+ method descriptions.
+
+ Further general errors MAY be defined in future RFCs. Should a
+ client receive an error type it does not understand, it MUST treat it
+ the same as the "serverFail" type.
+
+3.7. References to Previous Method Results
+
+ To allow clients to make more efficient use of the network and avoid
+ round trips, an argument to one method can be taken from the result
+ of a previous method call in the same request.
+
+ To do this, the client prefixes the argument name with "#" (an
+ octothorpe). The value is a ResultReference object as described
+ below. When processing a method call, the server MUST first check
+ the arguments object for any names beginning with "#". If found, the
+ result reference should be resolved and the value used as the "real"
+
+
+
+Jenkins & Newman Standards Track [Page 22]
+
+RFC 8620 JMAP July 2019
+
+
+ argument. The method is then processed as normal. If any result
+ reference fails to resolve, the whole method MUST be rejected with an
+ "invalidResultReference" error. If an arguments object contains the
+ same argument name in normal and referenced form (e.g., "foo" and
+ "#foo"), the method MUST return an "invalidArguments" error.
+
+ A *ResultReference* object has the following properties:
+
+ o resultOf: "String"
+
+ The method call id (see Section 3.2) of a previous method call in
+ the current request.
+
+ o name: "String"
+
+ The required name of a response to that method call.
+
+ o path: "String"
+
+ A pointer into the arguments of the response selected via the name
+ and resultOf properties. This is a JSON Pointer [RFC6901], except
+ it also allows the use of "*" to map through an array (see the
+ description below).
+
+ To resolve:
+
+ 1. Find the first response with a method call id identical to the
+ "resultOf" property of the ResultReference in the
+ "methodResponses" array from previously processed method calls in
+ the same request. If none, evaluation fails.
+
+ 2. If the response name is not identical to the "name" property of
+ the ResultReference, evaluation fails.
+
+ 3. Apply the "path" to the arguments object of the response (the
+ second item in the response array) following the JSON Pointer
+ algorithm [RFC6901], except with the following addition in
+ "Evaluation" (see Section 4):
+
+ If the currently referenced value is a JSON array, the reference
+ token may be exactly the single character "*", making the new
+ referenced value the result of applying the rest of the JSON
+ Pointer tokens to every item in the array and returning the
+ results in the same order in a new array. If the result of
+ applying the rest of the pointer tokens to each item was itself
+ an array, the contents of this array are added to the output
+ rather than the array itself (i.e., the result is flattened from
+ an array of arrays to a single array). If the result of applying
+
+
+
+Jenkins & Newman Standards Track [Page 23]
+
+RFC 8620 JMAP July 2019
+
+
+ the rest of the pointer tokens to a value was itself an array,
+ its items should be included individually in the output rather
+ than including the array itself (i.e., the result is flattened
+ from an array of arrays to a single array).
+
+ As a simple example, suppose we have the following API request
+ "methodCalls":
+
+ [[ "Foo/changes", {
+ "accountId": "A1",
+ "sinceState": "abcdef"
+ }, "t0" ],
+ [ "Foo/get", {
+ "accountId": "A1",
+ "#ids": {
+ "resultOf": "t0",
+ "name": "Foo/changes",
+ "path": "/created"
+ }
+ }, "t1" ]]
+
+ After executing the first method call, the "methodResponses" array
+ is:
+
+ [[ "Foo/changes", {
+ "accountId": "A1",
+ "oldState": "abcdef",
+ "newState": "123456",
+ "hasMoreChanges": false,
+ "created": [ "f1", "f4" ],
+ "updated": [],
+ "destroyed": []
+ }, "t0" ]]
+
+ To execute the "Foo/get" call, we look through the arguments and find
+ there is one with a "#" prefix. To resolve this, we apply the
+ algorithm above:
+
+ 1. Find the first response with method call id "t0". The "Foo/
+ changes" response fulfils this criterion.
+
+ 2. Check that the response name is the same as in the result
+ reference. It is, so this is fine.
+
+ 3. Apply the "path" as a JSON Pointer to the arguments object. This
+ simply selects the "created" property, so the result of
+ evaluating is: [ "f1", "f4" ].
+
+
+
+
+Jenkins & Newman Standards Track [Page 24]
+
+RFC 8620 JMAP July 2019
+
+
+ The JMAP server now continues to process the "Foo/get" call as though
+ the arguments were:
+
+ {
+ "accountId": "A1",
+ "ids": [ "f1", "f4" ]
+ }
+
+ Now, a more complicated example using the JMAP Mail data model: fetch
+ the "from"/"date"/"subject" for every Email in the first 10 Threads
+ in the inbox (sorted newest first):
+
+ [[ "Email/query", {
+ "accountId": "A1",
+ "filter": { "inMailbox": "id_of_inbox" },
+ "sort": [{ "property": "receivedAt", "isAscending": false }],
+ "collapseThreads": true,
+ "position": 0,
+ "limit": 10,
+ "calculateTotal": true
+ }, "t0" ],
+ [ "Email/get", {
+ "accountId": "A1",
+ "#ids": {
+ "resultOf": "t0",
+ "name": "Email/query",
+ "path": "/ids"
+ },
+ "properties": [ "threadId" ]
+ }, "t1" ],
+ [ "Thread/get", {
+ "accountId": "A1",
+ "#ids": {
+ "resultOf": "t1",
+ "name": "Email/get",
+ "path": "/list/*/threadId"
+ }
+ }, "t2" ],
+ [ "Email/get", {
+ "accountId": "A1",
+ "#ids": {
+ "resultOf": "t2",
+ "name": "Thread/get",
+ "path": "/list/*/emailIds"
+ },
+ "properties": [ "from", "receivedAt", "subject" ]
+ }, "t3" ]]
+
+
+
+
+Jenkins & Newman Standards Track [Page 25]
+
+RFC 8620 JMAP July 2019
+
+
+ After executing the first 3 method calls, the "methodResponses" array
+ might be:
+
+ [[ "Email/query", {
+ "accountId": "A1",
+ "queryState": "abcdefg",
+ "canCalculateChanges": true,
+ "position": 0,
+ "total": 101,
+ "ids": [ "msg1023", "msg223", "msg110", "msg93", "msg91",
+ "msg38", "msg36", "msg33", "msg11", "msg1" ]
+ }, "t0" ],
+ [ "Email/get", {
+ "accountId": "A1",
+ "state": "123456",
+ "list": [{
+ "id": "msg1023",
+ "threadId": "trd194"
+ }, {
+ "id": "msg223",
+ "threadId": "trd114"
+ },
+ ...
+ ],
+ "notFound": []
+ }, "t1" ],
+ [ "Thread/get", {
+ "accountId": "A1",
+ "state": "123456",
+ "list": [{
+ "id": "trd194",
+ "emailIds": [ "msg1020", "msg1021", "msg1023" ]
+ }, {
+ "id": "trd114",
+ "emailIds": [ "msg201", "msg223" ]
+ },
+ ...
+ ],
+ "notFound": []
+ }, "t2" ]]
+
+ To execute the final "Email/get" call, we look through the arguments
+ and find there is one with a "#" prefix. To resolve this, we apply
+ the algorithm:
+
+ 1. Find the first response with method call id "t2". The "Thread/
+ get" response fulfils this criterion.
+
+
+
+
+Jenkins & Newman Standards Track [Page 26]
+
+RFC 8620 JMAP July 2019
+
+
+ 2. "Thread/get" is the name specified in the result reference, so
+ this is fine.
+
+ 3. Apply the "path" as a JSON Pointer to the arguments object.
+ Token by token:
+
+ 1. "list": get the array of thread objects
+
+ 2. "*": for each of the items in the array:
+
+ a. "emailIds": get the array of Email ids
+
+ b. Concatenate these into a single array of all the ids in
+ the result.
+
+ The JMAP server now continues to process the "Email/get" call as
+ though the arguments were:
+
+{
+ "accountId": "A1",
+ "ids": [ "msg1020", "msg1021", "msg1023", "msg201", "msg223", ... ],
+ "properties": [ "from", "receivedAt", "subject" ]
+}
+
+ The ResultReference performs a similar role to that of the creation
+ id, in that it allows a chained method call to refer to information
+ not available when the request is generated. However, they are
+ different things and not interchangeable; the only commonality is the
+ octothorpe used to indicate them.
+
+3.8. Localisation of User-Visible Strings
+
+ If returning a custom string to be displayed to the user, for
+ example, an error message, the server SHOULD use information from the
+ Accept-Language header of the request (as defined in Section 5.3.5 of
+ [RFC7231]) to choose the best available localisation. The Content-
+ Language header of the response (see Section 3.1.3.2 of [RFC7231])
+ SHOULD indicate the language being used for user-visible strings.
+
+ For example, suppose a request was made with the following header:
+
+ Accept-Language: fr-CH, fr;q=0.9, de;q=0.8, en;q=0.7, *;q=0.5
+
+ and a method generated an error to display to the user. The server
+ has translations of the error message in English and German. Looking
+ at the Accept-Language header, the user's preferred language is
+ French. Since we don't have a translation for this, we look at the
+
+
+
+
+Jenkins & Newman Standards Track [Page 27]
+
+RFC 8620 JMAP July 2019
+
+
+ next most preferred, which is German. We have a German translation,
+ so the server returns this and indicates the language chosen in a
+ Content-Language header like so:
+
+ Content-Language: de
+
+3.9. Security
+
+ As always, the server must be strict about data received from the
+ client. Arguments need to be checked for validity; a malicious user
+ could attempt to find an exploit through the API. In case of invalid
+ arguments (unknown/insufficient/wrong type for data, etc.), the
+ method MUST return an "invalidArguments" error and terminate.
+
+3.10. Concurrency
+
+ Method calls within a single request MUST be executed in order.
+ However, method calls from different concurrent API requests may be
+ interleaved. This means that the data on the server may change
+ between two method calls within a single API request.
+
+4. The Core/echo Method
+
+ The "Core/echo" method returns exactly the same arguments as it is
+ given. It is useful for testing if you have a valid authenticated
+ connection to a JMAP API endpoint.
+
+4.1. Example
+
+ Request:
+
+ [[ "Core/echo", {
+ "hello": true,
+ "high": 5
+ }, "b3ff" ]]
+
+ Response:
+
+ [[ "Core/echo", {
+ "hello": true,
+ "high": 5
+ }, "b3ff" ]]
+
+
+
+
+
+
+
+
+
+Jenkins & Newman Standards Track [Page 28]
+
+RFC 8620 JMAP July 2019
+
+
+5. Standard Methods and Naming Convention
+
+ JMAP provides a uniform interface for creating, retrieving, updating,
+ and deleting objects of a particular type. For a "Foo" data type,
+ records of that type would be fetched via a "Foo/get" call and
+ modified via a "Foo/set" call. Delta updates may be fetched via a
+ "Foo/changes" call. These methods all follow a standard format as
+ described below.
+
+ Some types may not have all these methods. Specifications defining
+ types MUST specify which methods are available for the type.
+
+5.1. /get
+
+ Objects of type Foo are fetched via a call to "Foo/get".
+
+ It takes the following arguments:
+
+ o accountId: "Id"
+
+ The id of the account to use.
+
+ o ids: "Id[]|null"
+
+ The ids of the Foo objects to return. If null, then *all* records
+ of the data type are returned, if this is supported for that data
+ type and the number of records does not exceed the
+ "maxObjectsInGet" limit.
+
+ o properties: "String[]|null"
+
+ If supplied, only the properties listed in the array are returned
+ for each Foo object. If null, all properties of the object are
+ returned. The id property of the object is *always* returned,
+ even if not explicitly requested. If an invalid property is
+ requested, the call MUST be rejected with an "invalidArguments"
+ error.
+
+ The response has the following arguments:
+
+ o accountId: "Id"
+
+ The id of the account used for the call.
+
+
+
+
+
+
+
+
+Jenkins & Newman Standards Track [Page 29]
+
+RFC 8620 JMAP July 2019
+
+
+ o state: "String"
+
+ A (preferably short) string representing the state on the server
+ for *all* the data of this type in the account (not just the
+ objects returned in this call). If the data changes, this string
+ MUST change. If the Foo data is unchanged, servers SHOULD return
+ the same state string on subsequent requests for this data type.
+ When a client receives a response with a different state string to
+ a previous call, it MUST either throw away all currently cached
+ objects for the type or call "Foo/changes" to get the exact
+ changes.
+
+ o list: "Foo[]"
+
+ An array of the Foo objects requested. This is the *empty array*
+ if no objects were found or if the "ids" argument passed in was
+ also an empty array. The results MAY be in a different order to
+ the "ids" in the request arguments. If an identical id is
+ included more than once in the request, the server MUST only
+ include it once in either the "list" or the "notFound" argument of
+ the response.
+
+ o notFound: "Id[]"
+
+ This array contains the ids passed to the method for records that
+ do not exist. The array is empty if all requested ids were found
+ or if the "ids" argument passed in was either null or an empty
+ array.
+
+ The following additional error may be returned instead of the "Foo/
+ get" response:
+
+ "requestTooLarge": The number of ids requested by the client exceeds
+ the maximum number the server is willing to process in a single
+ method call.
+
+5.2. /changes
+
+ When the state of the set of Foo records in an account changes on the
+ server (whether due to creation, updates, or deletion), the "state"
+ property of the "Foo/get" response will change. The "Foo/changes"
+ method allows a client to efficiently update the state of its Foo
+ cache to match the new state on the server. It takes the following
+ arguments:
+
+ o accountId: "Id"
+
+ The id of the account to use.
+
+
+
+Jenkins & Newman Standards Track [Page 30]
+
+RFC 8620 JMAP July 2019
+
+
+ o sinceState: "String"
+
+ The current state of the client. This is the string that was
+ returned as the "state" argument in the "Foo/get" response. The
+ server will return the changes that have occurred since this
+ state.
+
+ o maxChanges: "UnsignedInt|null"
+
+ The maximum number of ids to return in the response. The server
+ MAY choose to return fewer than this value but MUST NOT return
+ more. If not given by the client, the server may choose how many
+ to return. If supplied by the client, the value MUST be a
+ positive integer greater than 0. If a value outside of this range
+ is given, the server MUST reject the call with an
+ "invalidArguments" error.
+
+ The response has the following arguments:
+
+ o accountId: "Id"
+
+ The id of the account used for the call.
+
+ o oldState: "String"
+
+ This is the "sinceState" argument echoed back; it's the state from
+ which the server is returning changes.
+
+ o newState: "String"
+
+ This is the state the client will be in after applying the set of
+ changes to the old state.
+
+ o hasMoreChanges: "Boolean"
+
+ If true, the client may call "Foo/changes" again with the
+ "newState" returned to get further updates. If false, "newState"
+ is the current server state.
+
+ o created: "Id[]"
+
+ An array of ids for records that have been created since the old
+ state.
+
+ o updated: "Id[]"
+
+ An array of ids for records that have been updated since the old
+ state.
+
+
+
+Jenkins & Newman Standards Track [Page 31]
+
+RFC 8620 JMAP July 2019
+
+
+ o destroyed: "Id[]"
+
+ An array of ids for records that have been destroyed since the old
+ state.
+
+ If a record has been created AND updated since the old state, the
+ server SHOULD just return the id in the "created" list but MAY return
+ it in the "updated" list as well.
+
+ If a record has been updated AND destroyed since the old state, the
+ server SHOULD just return the id in the "destroyed" list but MAY
+ return it in the "updated" list as well.
+
+ If a record has been created AND destroyed since the old state, the
+ server SHOULD remove the id from the response entirely. However, it
+ MAY include it in just the "destroyed" list or in both the
+ "destroyed" and "created" lists.
+
+ If a "maxChanges" is supplied, or set automatically by the server,
+ the server MUST ensure the number of ids returned across "created",
+ "updated", and "destroyed" does not exceed this limit. If there are
+ more changes than this between the client's state and the current
+ server state, the server SHOULD generate an update to take the client
+ to an intermediate state, from which the client can continue to call
+ "Foo/changes" until it is fully up to date. If it is unable to
+ calculate an intermediate state, it MUST return a
+ "cannotCalculateChanges" error response instead.
+
+ When generating intermediate states, the server may choose how to
+ divide up the changes. For many types, it will provide a better user
+ experience to return the more recent changes first, as this is more
+ likely to be what the user is most interested in. The client can
+ then continue to page in the older changes while the user is viewing
+ the newer data. For example, suppose a server went through the
+ following states:
+
+ A -> B -> C -> D -> E
+
+ And a client asks for changes from state "B". The server might first
+ get the ids of records created, updated, or destroyed between states
+ D and E, returning them with:
+
+ state: "B-D-E"
+ hasMoreChanges: true
+
+
+
+
+
+
+
+Jenkins & Newman Standards Track [Page 32]
+
+RFC 8620 JMAP July 2019
+
+
+ The client will then ask for the change from state "B-D-E", and the
+ server can return the changes between states C and D, returning:
+
+ state: "B-C-E"
+ hasMoreChanges: true
+
+ Finally, the client will request the changes from "B-C-E", and the
+ server can return the changes between states B and C, returning:
+
+ state: "E"
+ hasMoreChanges: false
+
+ Should the state on the server be modified in the middle of all this
+ (to "F"), the server still does the same, but now when the update to
+ state "E" is returned, it would indicate that it still has more
+ changes for the client to fetch.
+
+ Where multiple changes to a record are split across different
+ intermediate states, the server MUST NOT return a record as created
+ after a response that deems it as updated or destroyed, and it MUST
+ NOT return a record as destroyed before a response that deems it as
+ created or updated. The server may have to coalesce multiple changes
+ to a record to satisfy this requirement.
+
+ The following additional errors may be returned instead of the "Foo/
+ changes" response:
+
+ "cannotCalculateChanges": The server cannot calculate the changes
+ from the state string given by the client. Usually, this is due to
+ the client's state being too old or the server being unable to
+ produce an update to an intermediate state when there are too many
+ updates. The client MUST invalidate its Foo cache.
+
+ Maintaining state to allow calculation of "Foo/changes" can be
+ expensive for the server, but always returning
+ "cannotCalculateChanges" severely increases network traffic and
+ resource usage for the client. To allow efficient sync, servers
+ SHOULD be able to calculate changes from any state string that was
+ given to a client within the last 30 days (but of course may support
+ calculating updates from states older than this).
+
+
+
+
+
+
+
+
+
+
+
+Jenkins & Newman Standards Track [Page 33]
+
+RFC 8620 JMAP July 2019
+
+
+5.3. /set
+
+ Modifying the state of Foo objects on the server is done via the
+ "Foo/set" method. This encompasses creating, updating, and
+ destroying Foo records. This allows the server to sort out ordering
+ and dependencies that may exist if doing multiple operations at once
+ (for example, to ensure there is always a minimum number of a certain
+ record type).
+
+ The "Foo/set" method takes the following arguments:
+
+ o accountId: "Id"
+
+ The id of the account to use.
+
+ o ifInState: "String|null"
+
+ This is a state string as returned by the "Foo/get" method
+ (representing the state of all objects of this type in the
+ account). If supplied, the string must match the current state;
+ otherwise, the method will be aborted and a "stateMismatch" error
+ returned. If null, any changes will be applied to the current
+ state.
+
+ o create: "Id[Foo]|null"
+
+ A map of a *creation id* (a temporary id set by the client) to Foo
+ objects, or null if no objects are to be created.
+
+ The Foo object type definition may define default values for
+ properties. Any such property may be omitted by the client.
+
+ The client MUST omit any properties that may only be set by the
+ server (for example, the "id" property on most object types).
+
+ o update: "Id[PatchObject]|null"
+
+ A map of an id to a Patch object to apply to the current Foo
+ object with that id, or null if no objects are to be updated.
+
+ A *PatchObject* is of type "String[*]" and represents an unordered
+ set of patches. The keys are a path in JSON Pointer format
+ [RFC6901], with an implicit leading "/" (i.e., prefix each key
+ with "/" before applying the JSON Pointer evaluation algorithm).
+
+ All paths MUST also conform to the following restrictions; if
+ there is any violation, the update MUST be rejected with an
+ "invalidPatch" error:
+
+
+
+Jenkins & Newman Standards Track [Page 34]
+
+RFC 8620 JMAP July 2019
+
+
+ * The pointer MUST NOT reference inside an array (i.e., you MUST
+ NOT insert/delete from an array; the array MUST be replaced in
+ its entirety instead).
+
+ * All parts prior to the last (i.e., the value after the final
+ slash) MUST already exist on the object being patched.
+
+ * There MUST NOT be two patches in the PatchObject where the
+ pointer of one is the prefix of the pointer of the other, e.g.,
+ "alerts/1/offset" and "alerts".
+
+ The value associated with each pointer determines how to apply
+ that patch:
+
+ * If null, set to the default value if specified for this
+ property; otherwise, remove the property from the patched
+ object. If the key is not present in the parent, this a no-op.
+
+ * Anything else: The value to set for this property (this may be
+ a replacement or addition to the object being patched).
+
+ Any server-set properties MAY be included in the patch if their
+ value is identical to the current server value (before applying
+ the patches to the object). Otherwise, the update MUST be
+ rejected with an "invalidProperties" SetError.
+
+ This patch definition is designed such that an entire Foo object
+ is also a valid PatchObject. The client may choose to optimise
+ network usage by just sending the diff or may send the whole
+ object; the server processes it the same either way.
+
+ o destroy: "Id[]|null"
+
+ A list of ids for Foo objects to permanently delete, or null if no
+ objects are to be destroyed.
+
+ Each creation, modification, or destruction of an object is
+ considered an atomic unit. It is permissible for the server to
+ commit changes to some objects but not others; however, it MUST NOT
+ only commit part of an update to a single record (e.g., update a
+ "name" property but not a "count" property, if both are supplied in
+ the update object).
+
+ The final state MUST be valid after the "Foo/set" is finished;
+ however, the server may have to transition through invalid
+ intermediate states (not exposed to the client) while processing the
+ individual create/update/destroy requests. For example, suppose
+ there is a "name" property that must be unique. A single method call
+
+
+
+Jenkins & Newman Standards Track [Page 35]
+
+RFC 8620 JMAP July 2019
+
+
+ could rename an object A => B and simultaneously rename another
+ object B => A. If the final state is valid, this is allowed.
+ Otherwise, each creation, modification, or destruction of an object
+ should be processed sequentially and accepted/rejected based on the
+ current server state.
+
+ If a create, update, or destroy is rejected, the appropriate error
+ MUST be added to the notCreated/notUpdated/notDestroyed property of
+ the response, and the server MUST continue to the next create/update/
+ destroy. It does not terminate the method.
+
+ If an id given cannot be found, the update or destroy MUST be
+ rejected with a "notFound" set error.
+
+ The server MAY skip an update (rejecting it with a "willDestroy"
+ SetError) if that object is destroyed in the same /set request.
+
+ Some records may hold references to other records (foreign keys).
+ That reference may be set (via create or update) in the same request
+ as the referenced record is created. To do this, the client refers
+ to the new record using its creation id prefixed with a "#". The
+ order of the method calls in the request by the client MUST be such
+ that the record being referenced is created in the same or an earlier
+ call. Thus, the server never has to look ahead. Instead, while
+ processing a request, the server MUST keep a simple map for the
+ duration of the request of creation id to record id for each newly
+ created record, so it can substitute in the correct value if
+ necessary in later method calls. In the case of records with
+ references to the same type, the server MUST order the creates and
+ updates within a single method call so that creates happen before
+ their creation ids are referenced by another create/update/destroy in
+ the same call.
+
+ Creation ids are not scoped by type but are a single map for all
+ types. A client SHOULD NOT reuse a creation id anywhere in the same
+ API request. If a creation id is reused, the server MUST map the
+ creation id to the most recently created item with that id. To allow
+ easy proxying of API requests, an initial set of creation id to real
+ id values may be passed with a request (see "The Request Object",
+ Section 3.3) and the final state of the map passed out with the
+ response (see "The Response Object", Section 3.4).
+
+ The response has the following arguments:
+
+ o accountId: "Id"
+
+ The id of the account used for the call.
+
+
+
+
+Jenkins & Newman Standards Track [Page 36]
+
+RFC 8620 JMAP July 2019
+
+
+ o oldState: "String|null"
+
+ The state string that would have been returned by "Foo/get" before
+ making the requested changes, or null if the server doesn't know
+ what the previous state string was.
+
+ o newState: "String"
+
+ The state string that will now be returned by "Foo/get".
+
+ o created: "Id[Foo]|null"
+
+ A map of the creation id to an object containing any properties of
+ the created Foo object that were not sent by the client. This
+ includes all server-set properties (such as the "id" in most
+ object types) and any properties that were omitted by the client
+ and thus set to a default by the server.
+
+ This argument is null if no Foo objects were successfully created.
+
+ o updated: "Id[Foo|null]|null"
+
+ The keys in this map are the ids of all Foos that were
+ successfully updated.
+
+ The value for each id is a Foo object containing any property that
+ changed in a way *not* explicitly requested by the PatchObject
+ sent to the server, or null if none. This lets the client know of
+ any changes to server-set or computed properties.
+
+ This argument is null if no Foo objects were successfully updated.
+
+ o destroyed: "Id[]|null"
+
+ A list of Foo ids for records that were successfully destroyed, or
+ null if none.
+
+ o notCreated: "Id[SetError]|null"
+
+ A map of the creation id to a SetError object for each record that
+ failed to be created, or null if all successful.
+
+ o notUpdated: "Id[SetError]|null"
+
+ A map of the Foo id to a SetError object for each record that
+ failed to be updated, or null if all successful.
+
+
+
+
+
+Jenkins & Newman Standards Track [Page 37]
+
+RFC 8620 JMAP July 2019
+
+
+ o notDestroyed: "Id[SetError]|null"
+
+ A map of the Foo id to a SetError object for each record that
+ failed to be destroyed, or null if all successful.
+
+ A *SetError* object has the following properties:
+
+ o type: "String"
+
+ The type of error.
+
+ o description: "String|null"
+
+ A description of the error to help with debugging that includes an
+ explanation of what the problem was. This is a non-localised
+ string and is not intended to be shown directly to end users.
+
+ The following SetError types are defined and may be returned for set
+ operations on any record type where appropriate:
+
+ o "forbidden": (create; update; destroy). The create/update/destroy
+ would violate an ACL or other permissions policy.
+
+ o "overQuota": (create; update). The create would exceed a server-
+ defined limit on the number or total size of objects of this type.
+
+ o "tooLarge": (create; update). The create/update would result in
+ an object that exceeds a server-defined limit for the maximum size
+ of a single object of this type.
+
+ o "rateLimit": (create). Too many objects of this type have been
+ created recently, and a server-defined rate limit has been
+ reached. It may work if tried again later.
+
+ o "notFound": (update; destroy). The id given to update/destroy
+ cannot be found.
+
+ o "invalidPatch": (update). The PatchObject given to update the
+ record was not a valid patch (see the patch description).
+
+ o "willDestroy": (update). The client requested that an object be
+ both updated and destroyed in the same /set request, and the
+ server has decided to therefore ignore the update.
+
+
+
+
+
+
+
+
+Jenkins & Newman Standards Track [Page 38]
+
+RFC 8620 JMAP July 2019
+
+
+ o "invalidProperties": (create; update). The record given is
+ invalid in some way. For example:
+
+ * It contains properties that are invalid according to the type
+ specification of this record type.
+
+ * It contains a property that may only be set by the server
+ (e.g., "id") and is different to the current value. Note, to
+ allow clients to pass whole objects back, it is not an error to
+ include a server-set property in an update as long as the value
+ is identical to the current value on the server.
+
+ * There is a reference to another record (foreign key), and the
+ given id does not correspond to a valid record.
+
+ The SetError object SHOULD also have a property called
+ "properties" of type "String[]" that lists *all* the properties
+ that were invalid.
+
+ Individual methods MAY specify more specific errors for certain
+ conditions that would otherwise result in an invalidProperties
+ error. If the condition of one of these is met, it MUST be
+ returned instead of the invalidProperties error.
+
+ o "singleton": (create; destroy). This is a singleton type, so you
+ cannot create another one or destroy the existing one.
+
+ Other possible SetError types MAY be given in specific method
+ descriptions. Other properties MAY also be present on the SetError
+ object, as described in the relevant methods.
+
+ The following additional errors may be returned instead of the "Foo/
+ set" response:
+
+ "requestTooLarge": The total number of objects to create, update, or
+ destroy exceeds the maximum number the server is willing to process
+ in a single method call.
+
+ "stateMismatch": An "ifInState" argument was supplied, and it does
+ not match the current state.
+
+
+
+
+
+
+
+
+
+
+
+Jenkins & Newman Standards Track [Page 39]
+
+RFC 8620 JMAP July 2019
+
+
+5.4. /copy
+
+ The only way to move Foo records *between* two different accounts is
+ to copy them using the "Foo/copy" method; once the copy has
+ succeeded, delete the original. The "onSuccessDestroyOriginal"
+ argument allows you to try to do this in one method call; however,
+ note that the two different actions are not atomic, so it is possible
+ for the copy to succeed but the original not to be destroyed for some
+ reason.
+
+ The copy is conceptually in three phases:
+
+ 1. Reading the current values from the "from" account.
+
+ 2. Writing the new copies to the other account.
+
+ 3. Destroying the originals in the "from" account, if requested.
+
+ Data may change in between phases due to concurrent requests.
+
+ The "Foo/copy" method takes the following arguments:
+
+ o fromAccountId: "Id"
+
+ The id of the account to copy records from.
+
+ o ifFromInState: "String|null"
+
+ This is a state string as returned by the "Foo/get" method. If
+ supplied, the string must match the current state of the account
+ referenced by the fromAccountId when reading the data to be
+ copied; otherwise, the method will be aborted and a
+ "stateMismatch" error returned. If null, the data will be read
+ from the current state.
+
+ o accountId: "Id"
+
+ The id of the account to copy records to. This MUST be different
+ to the "fromAccountId".
+
+ o ifInState: "String|null"
+
+ This is a state string as returned by the "Foo/get" method. If
+ supplied, the string must match the current state of the account
+ referenced by the accountId; otherwise, the method will be aborted
+ and a "stateMismatch" error returned. If null, any changes will
+ be applied to the current state.
+
+
+
+
+Jenkins & Newman Standards Track [Page 40]
+
+RFC 8620 JMAP July 2019
+
+
+ o create: "Id[Foo]"
+
+ A map of the *creation id* to a Foo object. The Foo object MUST
+ contain an "id" property, which is the id (in the fromAccount) of
+ the record to be copied. When creating the copy, any other
+ properties included are used instead of the current value for that
+ property on the original.
+
+ o onSuccessDestroyOriginal: "Boolean" (default: false)
+
+ If true, an attempt will be made to destroy the original records
+ that were successfully copied: after emitting the "Foo/copy"
+ response, but before processing the next method, the server MUST
+ make a single call to "Foo/set" to destroy the original of each
+ successfully copied record; the output of this is added to the
+ responses as normal, to be returned to the client.
+
+ o destroyFromIfInState: "String|null"
+
+ This argument is passed on as the "ifInState" argument to the
+ implicit "Foo/set" call, if made at the end of this request to
+ destroy the originals that were successfully copied.
+
+ Each record copy is considered an atomic unit that may succeed or
+ fail individually.
+
+ The response has the following arguments:
+
+ o fromAccountId: "Id"
+
+ The id of the account records were copied from.
+
+ o accountId: "Id"
+
+ The id of the account records were copied to.
+
+ o oldState: "String|null"
+
+ The state string that would have been returned by "Foo/get" on the
+ account records that were copied to before making the requested
+ changes, or null if the server doesn't know what the previous
+ state string was.
+
+ o newState: "String"
+
+ The state string that will now be returned by "Foo/get" on the
+ account records were copied to.
+
+
+
+
+Jenkins & Newman Standards Track [Page 41]
+
+RFC 8620 JMAP July 2019
+
+
+ o created: "Id[Foo]|null"
+
+ A map of the creation id to an object containing any properties of
+ the copied Foo object that are set by the server (such as the "id"
+ in most object types; note, the id is likely to be different to
+ the id of the object in the account it was copied from).
+
+ This argument is null if no Foo objects were successfully copied.
+
+ o notCreated: "Id[SetError]|null"
+
+ A map of the creation id to a SetError object for each record that
+ failed to be copied, or null if none.
+
+ The SetError may be any of the standard set errors returned for a
+ create or update. In addition, the following SetError is defined:
+
+ "alreadyExists": The server forbids duplicates, and the record
+ already exists in the target account. An "existingId" property of
+ type "Id" MUST be included on the SetError object with the id of the
+ existing record.
+
+ The following additional errors may be returned instead of the "Foo/
+ copy" response:
+
+ "fromAccountNotFound": The "fromAccountId" does not correspond to a
+ valid account.
+
+ "fromAccountNotSupportedByMethod": The "fromAccountId" given
+ corresponds to a valid account, but the account does not support this
+ data type.
+
+ "stateMismatch": An "ifInState" argument was supplied and it does not
+ match the current state, or an "ifFromInState" argument was supplied
+ and it does not match the current state in the from account.
+
+5.5. /query
+
+ For data sets where the total amount of data is expected to be very
+ small, clients can just fetch the complete set of data and then do
+ any sorting/filtering locally. However, for large data sets (e.g.,
+ multi-gigabyte mailboxes), the client needs to be able to
+ search/sort/window the data type on the server.
+
+ A query on the set of Foos in an account is made by calling "Foo/
+ query". This takes a number of arguments to determine which records
+ to include, how they should be sorted, and which part of the result
+
+
+
+
+Jenkins & Newman Standards Track [Page 42]
+
+RFC 8620 JMAP July 2019
+
+
+ should be returned (the full list may be *very* long). The result is
+ returned as a list of Foo ids.
+
+ A call to "Foo/query" takes the following arguments:
+
+ o accountId: "Id"
+
+ The id of the account to use.
+
+ o filter: "FilterOperator|FilterCondition|null"
+
+ Determines the set of Foos returned in the results. If null, all
+ objects in the account of this type are included in the results.
+ A *FilterOperator* object has the following properties:
+
+ * operator: "String"
+
+ This MUST be one of the following strings:
+
+ + "AND": All of the conditions must match for the filter to
+ match.
+
+ + "OR": At least one of the conditions must match for the
+ filter to match.
+
+ + "NOT": None of the conditions must match for the filter to
+ match.
+
+ * conditions: "(FilterOperator|FilterCondition)[]"
+
+ The conditions to evaluate against each record.
+
+ A *FilterCondition* is an "object" whose allowed properties and
+ semantics depend on the data type and is defined in the /query
+ method specification for that type. It MUST NOT have an
+ "operator" property.
+
+ o sort: "Comparator[]|null"
+
+ Lists the names of properties to compare between two Foo records,
+ and how to compare them, to determine which comes first in the
+ sort. If two Foo records have an identical value for the first
+ comparator, the next comparator will be considered, and so on. If
+ all comparators are the same (this includes the case where an
+ empty array or null is given as the "sort" argument), the sort
+ order is server dependent, but it MUST be stable between calls to
+ "Foo/query". A *Comparator* has the following properties:
+
+
+
+
+Jenkins & Newman Standards Track [Page 43]
+
+RFC 8620 JMAP July 2019
+
+
+ * property: "String"
+
+ The name of the property on the Foo objects to compare.
+
+ * isAscending: "Boolean" (optional; default: true)
+
+ If true, sort in ascending order. If false, reverse the
+ comparator's results to sort in descending order.
+
+ * collation: "String" (optional; default is server-dependent)
+
+ The identifier, as registered in the collation registry defined
+ in [RFC4790], for the algorithm to use when comparing the order
+ of strings. The algorithms the server supports are advertised
+ in the capabilities object returned with the Session object
+ (see Section 2).
+
+ If omitted, the default algorithm is server dependent, but:
+
+ 1. It MUST be unicode-aware.
+
+ 2. It MAY be selected based on an Accept-Language header in
+ the request (as defined in [RFC7231], Section 5.3.5) or
+ out-of-band information about the user's language/locale.
+
+ 3. It SHOULD be case insensitive where such a concept makes
+ sense for a language/locale. Where the user's language is
+ unknown, it is RECOMMENDED to follow the advice in
+ Section 5.2.3 of [RFC8264].
+
+ The "i;unicode-casemap" collation [RFC5051] and the Unicode
+ Collation Algorithm (<http://www.unicode.org/reports/tr10/>)
+ are two examples that fulfil these criterion and provide
+ reasonable behaviour for a large number of languages.
+
+ When the property being compared is not a string, the
+ "collation" property is ignored, and the following comparison
+ rules apply based on the type. In ascending order:
+
+ + "Boolean": false comes before true.
+
+ + "Number": A lower number comes before a higher number.
+
+ + "Date"/"UTCDate": The earlier date comes first.
+
+ The Comparator object may also have additional properties as
+ required for specific sort operations defined in a type's /query
+ method.
+
+
+
+Jenkins & Newman Standards Track [Page 44]
+
+RFC 8620 JMAP July 2019
+
+
+ o position: "Int" (default: 0)
+
+ The zero-based index of the first id in the full list of results
+ to return.
+
+ If a negative value is given, it is an offset from the end of the
+ list. Specifically, the negative value MUST be added to the total
+ number of results given the filter, and if still negative, it's
+ clamped to "0". This is now the zero-based index of the first id
+ to return.
+
+ If the index is greater than or equal to the total number of
+ objects in the results list, then the "ids" array in the response
+ will be empty, but this is not an error.
+
+ o anchor: "Id|null"
+
+ A Foo id. If supplied, the "position" argument is ignored. The
+ index of this id in the results will be used in combination with
+ the "anchorOffset" argument to determine the index of the first
+ result to return (see below for more details).
+
+ o anchorOffset: "Int" (default: 0)
+
+ The index of the first result to return relative to the index of
+ the anchor, if an anchor is given. This MAY be negative. For
+ example, "-1" means the Foo immediately preceding the anchor is
+ the first result in the list returned (see below for more
+ details).
+
+ o limit: "UnsignedInt|null"
+
+ The maximum number of results to return. If null, no limit
+ presumed. The server MAY choose to enforce a maximum "limit"
+ argument. In this case, if a greater value is given (or if it is
+ null), the limit is clamped to the maximum; the new limit is
+ returned with the response so the client is aware. If a negative
+ value is given, the call MUST be rejected with an
+ "invalidArguments" error.
+
+ o calculateTotal: "Boolean" (default: false)
+
+ Does the client wish to know the total number of results in the
+ query? This may be slow and expensive for servers to calculate,
+ particularly with complex filters, so clients should take care to
+ only request the total when needed.
+
+
+
+
+
+Jenkins & Newman Standards Track [Page 45]
+
+RFC 8620 JMAP July 2019
+
+
+ If an "anchor" argument is given, the anchor is looked for in the
+ results after filtering and sorting. If found, the "anchorOffset" is
+ then added to its index. If the resulting index is now negative, it
+ is clamped to 0. This index is now used exactly as though it were
+ supplied as the "position" argument. If the anchor is not found, the
+ call is rejected with an "anchorNotFound" error.
+
+ If an "anchor" is specified, any position argument supplied by the
+ client MUST be ignored. If no "anchor" is supplied, any
+ "anchorOffset" argument MUST be ignored.
+
+ A client can use "anchor" instead of "position" to find the index of
+ an id within a large set of results.
+
+ The response has the following arguments:
+
+ o accountId: "Id"
+
+ The id of the account used for the call.
+
+ o queryState: "String"
+
+ A string encoding the current state of the query on the server.
+ This string MUST change if the results of the query (i.e., the
+ matching ids and their sort order) have changed. The queryState
+ string MAY change if something has changed on the server, which
+ means the results may have changed but the server doesn't know for
+ sure.
+
+ The queryState string only represents the ordered list of ids that
+ match the particular query (including its sort/filter). There is
+ no requirement for it to change if a property on an object
+ matching the query changes but the query results are unaffected
+ (indeed, it is more efficient if the queryState string does not
+ change in this case). The queryState string only has meaning when
+ compared to future responses to a query with the same type/sort/
+ filter or when used with /queryChanges to fetch changes.
+
+ Should a client receive back a response with a different
+ queryState string to a previous call, it MUST either throw away
+ the currently cached query and fetch it again (note, this does not
+ require fetching the records again, just the list of ids) or call
+ "Foo/queryChanges" to get the difference.
+
+
+
+
+
+
+
+
+Jenkins & Newman Standards Track [Page 46]
+
+RFC 8620 JMAP July 2019
+
+
+ o canCalculateChanges: "Boolean"
+
+ This is true if the server supports calling "Foo/queryChanges"
+ with these "filter"/"sort" parameters. Note, this does not
+ guarantee that the "Foo/queryChanges" call will succeed, as it may
+ only be possible for a limited time afterwards due to server
+ internal implementation details.
+
+ o position: "UnsignedInt"
+
+ The zero-based index of the first result in the "ids" array within
+ the complete list of query results.
+
+ o ids: "Id[]"
+
+ The list of ids for each Foo in the query results, starting at the
+ index given by the "position" argument of this response and
+ continuing until it hits the end of the results or reaches the
+ "limit" number of ids. If "position" is >= "total", this MUST be
+ the empty list.
+
+ o total: "UnsignedInt" (only if requested)
+
+ The total number of Foos in the results (given the "filter").
+ This argument MUST be omitted if the "calculateTotal" request
+ argument is not true.
+
+ o limit: "UnsignedInt" (if set by the server)
+
+ The limit enforced by the server on the maximum number of results
+ to return. This is only returned if the server set a limit or
+ used a different limit than that given in the request.
+
+ The following additional errors may be returned instead of the "Foo/
+ query" response:
+
+ "anchorNotFound": An anchor argument was supplied, but it cannot be
+ found in the results of the query.
+
+ "unsupportedSort": The "sort" is syntactically valid, but it includes
+ a property the server does not support sorting on or a collation
+ method it does not recognise.
+
+ "unsupportedFilter": The "filter" is syntactically valid, but the
+ server cannot process it. If the filter was the result of a user's
+ search input, the client SHOULD suggest that the user simplify their
+ search.
+
+
+
+
+Jenkins & Newman Standards Track [Page 47]
+
+RFC 8620 JMAP July 2019
+
+
+5.6. /queryChanges
+
+ The "Foo/queryChanges" method allows a client to efficiently update
+ the state of a cached query to match the new state on the server. It
+ takes the following arguments:
+
+ o accountId: "Id"
+
+ The id of the account to use.
+
+ o filter: "FilterOperator|FilterCondition|null"
+
+ The filter argument that was used with "Foo/query".
+
+ o sort: "Comparator[]|null"
+
+ The sort argument that was used with "Foo/query".
+
+ o sinceQueryState: "String"
+
+ The current state of the query in the client. This is the string
+ that was returned as the "queryState" argument in the "Foo/query"
+ response with the same sort/filter. The server will return the
+ changes made to the query since this state.
+
+ o maxChanges: "UnsignedInt|null"
+
+ The maximum number of changes to return in the response. See
+ error descriptions below for more details.
+
+ o upToId: "Id|null"
+
+ The last (highest-index) id the client currently has cached from
+ the query results. When there are a large number of results, in a
+ common case, the client may have only downloaded and cached a
+ small subset from the beginning of the results. If the sort and
+ filter are both only on immutable properties, this allows the
+ server to omit changes after this point in the results, which can
+ significantly increase efficiency. If they are not immutable,
+ this argument is ignored.
+
+ o calculateTotal: "Boolean" (default: false)
+
+ Does the client wish to know the total number of results now in
+ the query? This may be slow and expensive for servers to
+ calculate, particularly with complex filters, so clients should
+ take care to only request the total when needed.
+
+
+
+
+Jenkins & Newman Standards Track [Page 48]
+
+RFC 8620 JMAP July 2019
+
+
+ The response has the following arguments:
+
+ o accountId: "Id"
+
+ The id of the account used for the call.
+
+ o oldQueryState: "String"
+
+ This is the "sinceQueryState" argument echoed back; that is, the
+ state from which the server is returning changes.
+
+ o newQueryState: "String"
+
+ This is the state the query will be in after applying the set of
+ changes to the old state.
+
+ o total: "UnsignedInt" (only if requested)
+
+ The total number of Foos in the results (given the "filter").
+ This argument MUST be omitted if the "calculateTotal" request
+ argument is not true.
+
+ o removed: "Id[]"
+
+ The "id" for every Foo that was in the query results in the old
+ state and that is not in the results in the new state.
+
+ If the server cannot calculate this exactly, the server MAY return
+ the ids of extra Foos in addition that may have been in the old
+ results but are not in the new results.
+
+ If the sort and filter are both only on immutable properties and
+ an "upToId" is supplied and exists in the results, any ids that
+ were removed but have a higher index than "upToId" SHOULD be
+ omitted.
+
+ If the "filter" or "sort" includes a mutable property, the server
+ MUST include all Foos in the current results for which this
+ property may have changed. The position of these may have moved
+ in the results, so they must be reinserted by the client to ensure
+ its query cache is correct.
+
+
+
+
+
+
+
+
+
+
+Jenkins & Newman Standards Track [Page 49]
+
+RFC 8620 JMAP July 2019
+
+
+ o added: "AddedItem[]"
+
+ The id and index in the query results (in the new state) for every
+ Foo that has been added to the results since the old state AND
+ every Foo in the current results that was included in the
+ "removed" array (due to a filter or sort based upon a mutable
+ property).
+
+ If the sort and filter are both only on immutable properties and
+ an "upToId" is supplied and exists in the results, any ids that
+ were added but have a higher index than "upToId" SHOULD be
+ omitted.
+
+ The array MUST be sorted in order of index, with the lowest index
+ first.
+
+ An *AddedItem* object has the following properties:
+
+ * id: "Id"
+
+ * index: "UnsignedInt"
+
+ The result of this is that if the client has a cached sparse array of
+ Foo ids corresponding to the results in the old state, then:
+
+ fooIds = [ "id1", "id2", null, null, "id3", "id4", null, null, null ]
+
+ If it *splices out* all ids in the removed array that it has in its
+ cached results, then:
+
+ removed = [ "id2", "id31", ... ];
+ fooIds => [ "id1", null, null, "id3", "id4", null, null, null ]
+
+ and *splices in* (one by one in order, starting with the lowest
+ index) all of the ids in the added array:
+
+ added = [{ id: "id5", index: 0, ... }];
+ fooIds => [ "id5", "id1", null, null, "id3", "id4", null, null, null ]
+
+ and *truncates* or *extends* to the new total length, then the
+ results will now be in the new state.
+
+ Note: splicing in adds the item at the given index, incrementing the
+ index of all items previously at that or a higher index. Splicing
+ out is the inverse, removing the item and decrementing the index of
+ every item after it in the array.
+
+
+
+
+
+Jenkins & Newman Standards Track [Page 50]
+
+RFC 8620 JMAP July 2019
+
+
+ The following additional errors may be returned instead of the "Foo/
+ queryChanges" response:
+
+ "tooManyChanges": There are more changes than the client's
+ "maxChanges" argument. Each item in the removed or added array is
+ considered to be one change. The client may retry with higher max
+ changes or invalidate its cache of the query results.
+
+ "cannotCalculateChanges": The server cannot calculate the changes
+ from the queryState string given by the client, usually due to the
+ client's state being too old. The client MUST invalidate its cache
+ of the query results.
+
+5.7. Examples
+
+ Suppose we have a type *Todo* with the following properties:
+
+ o id: "Id" (immutable; server-set)
+
+ The id of the object.
+
+ o title: "String"
+
+ A brief summary of what is to be done.
+
+ o keywords: "String[Boolean]" (default: {})
+
+ A set of keywords that apply to the Todo. The set is represented
+ as an object, with the keys being the "keywords". The value for
+ each key in the object MUST be true. (This format allows you to
+ update an individual key using patch syntax rather than having to
+ update the whole set of keywords as one, which a "String[]"
+ representation would require.)
+
+ o neuralNetworkTimeEstimation: "Number" (server-set)
+
+ The title and keywords are fed into the server's state-of-the-art
+ neural network to get an estimation of how long this Todo will
+ take, in seconds.
+
+ o subTodoIds: "Id[]|null"
+
+ The ids of a list of other Todos to complete as part of this Todo.
+
+ Suppose also that all the standard methods are defined for this type
+ and the FilterCondition object supports a "hasKeyword" property to
+ match Todos with the given keyword.
+
+
+
+
+Jenkins & Newman Standards Track [Page 51]
+
+RFC 8620 JMAP July 2019
+
+
+ A client might want to display the list of Todos with either a
+ "music" keyword or a "video" keyword, so it makes the following
+ method call:
+
+ [[ "Todo/query", {
+ "accountId": "x",
+ "filter": {
+ "operator": "OR",
+ "conditions": [
+ { "hasKeyword": "music" },
+ { "hasKeyword": "video" }
+ ]
+ },
+ "sort": [{ "property": "title" }],
+ "position": 0,
+ "limit": 10
+ }, "0" ],
+ [ "Todo/get", {
+ "accountId": "x",
+ "#ids": {
+ "resultOf": "0",
+ "name": "Todo/query",
+ "path": "/ids"
+ }
+ }, "1" ]]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Jenkins & Newman Standards Track [Page 52]
+
+RFC 8620 JMAP July 2019
+
+
+ This would query the server for the set of Todos with a keyword of
+ either "music" or "video", sorted by title, and limited to the first
+ 10 results. It fetches the full object for each of these Todos using
+ back-references to reference the result of the query. The response
+ might look something like:
+
+ [[ "Todo/query", {
+ "accountId": "x",
+ "queryState": "y13213",
+ "canCalculateChanges": true,
+ "position": 0,
+ "ids": [ "a", "b", "c", "d", "e", "f", "g", "h", "i", "j" ]
+ }, "0" ],
+ [ "Todo/get", {
+ "accountId": "x",
+ "state": "10324",
+ "list": [{
+ "id": "a",
+ "title": "Practise Piano",
+ "keywords": {
+ "music": true,
+ "beethoven": true,
+ "mozart": true,
+ "liszt": true,
+ "rachmaninov": true
+ },
+ "neuralNetworkTimeEstimation": 3600
+ }, {
+ "id": "b",
+ "title": "Watch Daft Punk music video",
+ "keywords": {
+ "music": true,
+ "video": true,
+ "trance": true
+ },
+ "neuralNetworkTimeEstimation": 18000
+ },
+ ...
+ ]
+ }, "1" ]]
+
+
+
+
+
+
+
+
+
+
+
+Jenkins & Newman Standards Track [Page 53]
+
+RFC 8620 JMAP July 2019
+
+
+ Now, suppose the user adds a keyword "chopin" and removes the keyword
+ "mozart" from the "Practise Piano" task. The client may send the
+ whole object to the server, as this is a valid PatchObject:
+
+ [[ "Todo/set", {
+ "accountId": "x",
+ "ifInState": "10324",
+ "update": {
+ "a": {
+ "id": "a",
+ "title": "Practise Piano",
+ "keywords": {
+ "music": true,
+ "beethoven": true,
+ "chopin": true,
+ "liszt": true,
+ "rachmaninov": true
+ },
+ "neuralNetworkTimeEstimation": 360
+ }
+ }
+ }, "0" ]]
+
+ or it may send a minimal patch:
+
+ [[ "Todo/set", {
+ "accountId": "x",
+ "ifInState": "10324",
+ "update": {
+ "a": {
+ "keywords/chopin": true,
+ "keywords/mozart": null
+ }
+ }
+ }, "0" ]]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Jenkins & Newman Standards Track [Page 54]
+
+RFC 8620 JMAP July 2019
+
+
+ The effect is exactly the same on the server in either case, and
+ presuming the server is still in state "10324", it will probably
+ return success:
+
+ [[ "Todo/set", {
+ "accountId": "x",
+ "oldState": "10324",
+ "newState": "10329",
+ "updated": {
+ "a": {
+ "neuralNetworkTimeEstimation": 5400
+ }
+ }
+ }, "0" ]]
+
+ The server changed the "neuralNetworkTimeEstimation" property on the
+ object as part of this change; as this changed in a way *not*
+ explicitly requested by the PatchObject sent to the server, it is
+ returned with the "updated" confirmation.
+
+ Let us now add a sub-Todo to our new "Practise Piano" Todo. In this
+ example, we can see the use of a reference to a creation id to allow
+ us to set a foreign key reference to a record created in the same
+ request:
+
+ [[ "Todo/set", {
+ "accountId": "x",
+ "create": {
+ "k15": {
+ "title": "Warm up with scales"
+ }
+ },
+ "update": {
+ "a": {
+ "subTodoIds": [ "#k15" ]
+ }
+ }
+ }, "0" ]]
+
+
+
+
+
+
+
+
+
+
+
+
+
+Jenkins & Newman Standards Track [Page 55]
+
+RFC 8620 JMAP July 2019
+
+
+ Now, suppose another user deleted the "Listen to Daft Punk" Todo.
+ The first user will receive a push notification (see Section 7) with
+ the changed state string for the "Todo" type. Since the new string
+ does not match its current state, it knows it needs to check for
+ updates. It may make a request like:
+
+ [[ "Todo/changes", {
+ "accountId": "x",
+ "sinceState": "10324",
+ "maxChanges": 50
+ }, "0" ],
+ [ "Todo/queryChanges", {
+ "accountId": "x",
+ "filter": {
+ "operator": "OR",
+ "conditions": [
+ { "hasKeyword": "music" },
+ { "hasKeyword": "video" }
+ ]
+ },
+ "sort": [{ "property": "title" }],
+ "sinceQueryState": "y13213",
+ "maxChanges": 50
+ }, "1" ]]
+
+ and receive in response:
+
+ [[ "Todo/changes", {
+ "accountId": "x",
+ "oldState": "10324",
+ "newState": "871903",
+ "hasMoreChanges": false,
+ "created": [],
+ "updated": [],
+ "destroyed": ["b"]
+ }, "0" ],
+ [ "Todo/queryChanges", {
+ "accountId": "x",
+ "oldQueryState": "y13213",
+ "newQueryState": "y13218",
+ "removed": ["b"],
+ "added": null
+ }, "1" ]]
+
+
+
+
+
+
+
+
+Jenkins & Newman Standards Track [Page 56]
+
+RFC 8620 JMAP July 2019
+
+
+ Suppose the user has access to another account "y", for example, a
+ team account shared between multiple users. To move an existing Todo
+ from account "x", the client would call:
+
+ [[ "Todo/copy", {
+ "fromAccountId": "x",
+ "accountId": "y",
+ "create": {
+ "k5122": {
+ "id": "a"
+ }
+ },
+ "onSuccessDestroyOriginal": true
+ }, "0" ]]
+
+ The server successfully copies the Todo to a new account (where it
+ receives a new id) and deletes the original. Due to the implicit
+ call to "Todo/set", there are two responses to the single method
+ call, both with the same method call id:
+
+ [[ "Todo/copy", {
+ "fromAccountId": "x",
+ "accountId": "y",
+ "created": {
+ "k5122": {
+ "id": "DAf97"
+ }
+ },
+ "oldState": "c1d64ecb038c",
+ "newState": "33844835152b"
+ }, "0" ],
+ [ "Todo/set", {
+ "accountId": "x",
+ "oldState": "871903",
+ "newState": "871909",
+ "destroyed": [ "a" ],
+ ...
+ }, "0" ]]
+
+
+
+
+
+
+
+
+
+
+
+
+
+Jenkins & Newman Standards Track [Page 57]
+
+RFC 8620 JMAP July 2019
+
+
+5.8. Proxy Considerations
+
+ JMAP has been designed to allow an API endpoint to easily proxy
+ through to one or more JMAP servers. This may be useful for load
+ balancing, augmenting capabilities, or presenting a single endpoint
+ to accounts hosted on different JMAP servers (splitting the request
+ based on each method's "accountId" argument). The proxy need only
+ understand the general structure of a JMAP Request object; it does
+ not need to know anything specifically about the methods and
+ arguments it will pass through to other servers.
+
+ If splitting up the methods in a request to call them on different
+ backend servers, the proxy must do two things to ensure back-
+ references and creation-id references resolve the same as if the
+ entire request were processed on a single server:
+
+ 1. It must pass a "createdIds" property with each subrequest. If
+ this is not given by the client, an empty object should be used
+ for the first subrequest. The "createdIds" property of each
+ subresponse should be passed on in the next subrequest.
+
+ 2. It must resolve back-references to previous method results that
+ were processed on a different server. This is a relatively
+ simple syntactic substitution, described in Section 3.7.
+
+ When splitting a request based on accountId, proxy implementors do
+ need to be aware of "/copy" methods that copy between accounts. If
+ the accounts are on different servers, the proxy will have to
+ implement this functionality directly.
+
+6. Binary Data
+
+ Binary data is referenced by a *blobId* in JMAP and uploaded/
+ downloaded separately to the core API. The blobId solely represents
+ the raw bytes of data, not any associated metadata such as a file
+ name or content type. Such metadata is stored alongside the blobId
+ in the object referencing it. The data represented by a blobId is
+ immutable.
+
+ Any blobId that exists within an account may be used when creating/
+ updating another object in that account. For example, an Email type
+ may have a blobId that represents the object in Internet Message
+ Format [RFC5322]. A client could create a new Email object with an
+ attachment and use this blobId, in effect attaching the old message
+ to the new one. Similarly, it could attach any existing attachment
+ of an old message without having to download and upload it again.
+
+
+
+
+
+Jenkins & Newman Standards Track [Page 58]
+
+RFC 8620 JMAP July 2019
+
+
+ When the client uses a blobId in a create/update, the server MAY
+ assign a new blobId to refer to the same binary data within the new/
+ updated object. If it does so, it MUST return any properties that
+ contain a changed blobId in the created/updated response, so the
+ client gets the new ids.
+
+ A blob that is not referenced by a JMAP object (e.g., as a message
+ attachment) MAY be deleted by the server to free up resources.
+ Uploads (see below) are initially unreferenced blobs. To ensure
+ interoperability:
+
+ o The server SHOULD use a separate quota for unreferenced blobs to
+ the account's usual quota. In the case of shared accounts, this
+ quota SHOULD be separate per user.
+
+ o This quota SHOULD be at least the maximum total size that a single
+ object can reference on this server. For example, if supporting
+ JMAP Mail, this should be at least the maximum total attachments
+ size for a message.
+
+ o When an upload would take the user over quota, the server MUST
+ delete unreferenced blobs in date order, oldest first, until there
+ is room for the new blob.
+
+ o Except where quota restrictions force early deletion, an
+ unreferenced blob MUST NOT be deleted for at least 1 hour from the
+ time of upload; if reuploaded, the same blobId MAY be returned,
+ but this SHOULD reset the expiry time.
+
+ o A blob MUST NOT be deleted during the method call that removed the
+ last reference, so that a client can issue a create and a destroy
+ that both reference the blob within the same method call.
+
+6.1. Uploading Binary Data
+
+ There is a single endpoint that handles all file uploads for an
+ account, regardless of what they are to be used for. The Session
+ object (see Section 2) has an "uploadUrl" property in URI Template
+ (level 1) format [RFC6570], which MUST contain a variable called
+ "accountId". The client may use this template in combination with an
+ "accountId" to get the URL of the file upload resource.
+
+ To upload a file, the client submits an authenticated POST request to
+ the file upload resource.
+
+
+
+
+
+
+
+Jenkins & Newman Standards Track [Page 59]
+
+RFC 8620 JMAP July 2019
+
+
+ A successful request MUST return a single JSON object with the
+ following properties as the response:
+
+ o accountId: "Id"
+
+ The id of the account used for the call.
+
+ o blobId: "Id"
+
+ The id representing the binary data uploaded. The data for this
+ id is immutable. The id *only* refers to the binary data, not any
+ metadata.
+
+ o type: "String"
+
+ The media type of the file (as specified in [RFC6838],
+ Section 4.2) as set in the Content-Type header of the upload HTTP
+ request.
+
+ o size: "UnsignedInt"
+
+ The size of the file in octets.
+
+ If identical binary content to an existing blob in the account is
+ uploaded, the existing blobId MAY be returned.
+
+ Clients should use the blobId returned in a timely manner. Under
+ rare circumstances, the server may have deleted the blob before the
+ client uses it; the client should keep a reference to the local file
+ so it can upload it again in such a situation.
+
+ When an HTTP error response is returned to the client, the server
+ SHOULD return a JSON "problem details" object as the response body,
+ as per [RFC7807].
+
+ As access controls are often determined by the object holding the
+ reference to a blob, unreferenced blobs MUST only be accessible to
+ the uploader, even in shared accounts.
+
+6.2. Downloading Binary Data
+
+ The Session object (see Section 2) has a "downloadUrl" property,
+ which is in URI Template (level 1) format [RFC6570]. The URL MUST
+ contain variables called "accountId", "blobId", "type", and "name".
+
+
+
+
+
+
+
+Jenkins & Newman Standards Track [Page 60]
+
+RFC 8620 JMAP July 2019
+
+
+ To download a file, the client makes an authenticated GET request to
+ the download URL with the appropriate variables substituted in:
+
+ o "accountId": The id of the account to which the record with the
+ blobId belongs.
+
+ o "blobId": The blobId representing the data of the file to
+ download.
+
+ o "type": The type for the server to set in the "Content-Type"
+ header of the response; the blobId only represents the binary data
+ and does not have a content-type innately associated with it.
+
+ o "name": The name for the file; the server MUST return this as the
+ filename if it sets a "Content-Disposition" header.
+
+ As the data for a particular blobId is immutable, and thus the
+ response in the generated download URL is too, implementors are
+ recommended to set long cache times and use the "immutable" Cache-
+ Control extension [RFC8246] for successful responses, for example,
+ "Cache-Control: private, immutable, max-age=31536000".
+
+ When an HTTP error response is returned to the client, the server
+ SHOULD return a JSON "problem details" object as the response body,
+ as per [RFC7807].
+
+6.3. Blob/copy
+
+ Binary data may be copied *between* two different accounts using the
+ "Blob/copy" method rather than having to download and then reupload
+ on the client.
+
+ The "Blob/copy" method takes the following arguments:
+
+ o fromAccountId: "Id"
+
+ The id of the account to copy blobs from.
+
+ o accountId: "Id"
+
+ The id of the account to copy blobs to.
+
+ o blobIds: "Id[]"
+
+ A list of ids of blobs to copy to the other account.
+
+
+
+
+
+
+Jenkins & Newman Standards Track [Page 61]
+
+RFC 8620 JMAP July 2019
+
+
+ The response has the following arguments:
+
+ o fromAccountId: "Id"
+
+ The id of the account blobs were copied from.
+
+ o accountId: "Id"
+
+ The id of the account blobs were copied to.
+
+ o copied: "Id[Id]|null"
+
+ A map of the blobId in the fromAccount to the id for the blob in
+ the account it was copied to, or null if none were successfully
+ copied.
+
+ o notCopied: "Id[SetError]|null"
+
+ A map of blobId to a SetError object for each blob that failed to
+ be copied, or null if none.
+
+ The SetError may be any of the standard set errors that may be
+ returned for a create, as defined in Section 5.3. In addition, the
+ "notFound" SetError error may be returned if the blobId to be copied
+ cannot be found.
+
+ The following additional method-level error may be returned instead
+ of the "Blob/copy" response:
+
+ "fromAccountNotFound": The "fromAccountId" included with the request
+ does not correspond to a valid account.
+
+7. Push
+
+ Push notifications allow clients to efficiently update (almost)
+ instantly to stay in sync with data changes on the server. The
+ general model for push is simple and sends minimal data over the push
+ channel: just enough for the client to know whether it needs to
+ resync. The format allows multiple changes to be coalesced into a
+ single push update and the frequency of pushes to be rate limited by
+ the server. It doesn't matter if some push events are dropped before
+ they reach the client; the next time it gets/sets any records of a
+ changed type, it will discover the data has changed and still sync
+ all changes.
+
+
+
+
+
+
+
+Jenkins & Newman Standards Track [Page 62]
+
+RFC 8620 JMAP July 2019
+
+
+ There are two different mechanisms by which a client can receive push
+ notifications, to allow for the different environments in which a
+ client may exist. An event source resource (see Section 7.3) allows
+ clients that can hold transport connections open to receive push
+ notifications directly from the JMAP server. This is simple and
+ avoids third parties, but it is often not feasible on constrained
+ platforms such as mobile devices. Alternatively, clients can make
+ use of any push service supported by their environment. A URL for
+ the push service is registered with the JMAP server (see
+ Section 7.2); the server then POSTs each notification to that URL.
+ The push service is then responsible for routing these to the client.
+
+7.1. The StateChange Object
+
+ When something changes on the server, the server pushes a StateChange
+ object to the client. A *StateChange* object has the following
+ properties:
+
+ o @type: "String"
+
+ This MUST be the string "StateChange".
+
+ o changed: "Id[TypeState]"
+
+ A map of an "account id" to an object encoding the state of data
+ types that have changed for that account since the last
+ StateChange object was pushed, for each of the accounts to which
+ the user has access and for which something has changed.
+
+ A *TypeState* object is a map. The keys are the type name "Foo"
+ (e.g., "Mailbox" or "Email"), and the value is the "state"
+ property that would currently be returned by a call to "Foo/get".
+
+ The client can compare the new state strings with its current
+ values to see whether it has the current data for these types. If
+ not, the changes can then be efficiently fetched in a single
+ standard API request (using the /changes type methods).
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Jenkins & Newman Standards Track [Page 63]
+
+RFC 8620 JMAP July 2019
+
+
+7.1.1. Example
+
+ In this example, the server has amalgamated a few changes together
+ across two different accounts the user has access to, before pushing
+ the following StateChange object to the client:
+
+ {
+ "@type": "StateChange",
+ "changed": {
+ "a3123": {
+ "Email": "d35ecb040aab",
+ "EmailDelivery": "428d565f2440",
+ "CalendarEvent": "87accfac587a"
+ },
+ "a43461d": {
+ "Mailbox": "0af7a512ce70",
+ "CalendarEvent": "7a4297cecd76"
+ }
+ }
+ }
+
+ The client can compare the state strings with its current state for
+ the Email, CalendarEvent, etc., object types in the appropriate
+ accounts to see if it needs to fetch changes.
+
+ If the client is itself making changes, it may receive a StateChange
+ object while the /set API call is in flight. It can wait until the
+ call completes and then compare if the new state string after the
+ /set is the same as was pushed in the StateChange object; if so, and
+ the old state of the /set response matches the client's previous
+ state, it does not need to waste a request asking for changes it
+ already knows.
+
+7.2. PushSubscription
+
+ Clients may create a PushSubscription to register a URL with the JMAP
+ server. The JMAP server will then make an HTTP POST request to this
+ URL for each push notification it wishes to send to the client.
+
+ As a push subscription causes the JMAP server to make a number of
+ requests to a previously unknown endpoint, it can be used as a vector
+ for launching a denial-of-service attack. To prevent this, when a
+ subscription is created, the JMAP server immediately sends a
+ PushVerification object to that URL (see Section 7.2.2). The JMAP
+ server MUST NOT make any further requests to the URL until the client
+ receives the push and updates the subscription with the correct
+ verification code.
+
+
+
+
+Jenkins & Newman Standards Track [Page 64]
+
+RFC 8620 JMAP July 2019
+
+
+ A *PushSubscription* object has the following properties:
+
+ o id: "Id" (immutable; server-set)
+
+ The id of the push subscription.
+
+ o deviceClientId: "String" (immutable)
+
+ An id that uniquely identifies the client + device it is running
+ on. The purpose of this is to allow clients to identify which
+ PushSubscription objects they created even if they lose their
+ local state, so they can revoke or update them. This string MUST
+ be different on different devices and be different from apps from
+ other vendors. It SHOULD be easy to regenerate and not depend on
+ persisted state. It is RECOMMENDED to use a secure hash of a
+ string that contains:
+
+ 1. A unique identifier associated with the device where the JMAP
+ client is running, normally supplied by the device's operating
+ system.
+
+ 2. A custom vendor/app id, including a domain controlled by the
+ vendor of the JMAP client.
+
+ To protect the privacy of the user, the deviceClientId id MUST NOT
+ contain an unobfuscated device id.
+
+ o url: "String" (immutable)
+
+ An absolute URL where the JMAP server will POST the data for the
+ push message. This MUST begin with "https://".
+
+ o keys: "Object|null" (immutable)
+
+ Client-generated encryption keys. If supplied, the server MUST
+ use them as specified in [RFC8291] to encrypt all data sent to the
+ push subscription. The object MUST have the following properties:
+
+ * p256dh: "String"
+
+ The P-256 Elliptic Curve Diffie-Hellman (ECDH) public key as
+ described in [RFC8291], encoded in URL-safe base64
+ representation as defined in [RFC4648].
+
+ * auth: "String"
+
+ The authentication secret as described in [RFC8291], encoded in
+ URL-safe base64 representation as defined in [RFC4648].
+
+
+
+Jenkins & Newman Standards Track [Page 65]
+
+RFC 8620 JMAP July 2019
+
+
+ o verificationCode: "String|null"
+
+ This MUST be null (or omitted) when the subscription is created.
+ The JMAP server then generates a verification code and sends it in
+ a push message, and the client updates the PushSubscription object
+ with the code; see Section 7.2.2 for details.
+
+ o expires: "UTCDate|null"
+
+ The time this push subscription expires. If specified, the JMAP
+ server MUST NOT make further requests to this resource after this
+ time. It MAY automatically destroy the push subscription at or
+ after this time.
+
+ The server MAY choose to set an expiry if none is given by the
+ client or modify the expiry time given by the client to a shorter
+ duration.
+
+ o types: "String[]|null"
+
+ A list of types the client is interested in (using the same names
+ as the keys in the TypeState object defined in the previous
+ section). A StateChange notification will only be sent if the
+ data for one of these types changes. Other types are omitted from
+ the TypeState object. If null, changes will be pushed for all
+ types.
+
+ The POST request MUST have a content type of "application/json" and
+ contain the UTF-8 JSON-encoded object as the body. The request MUST
+ have a "TTL" header and MAY have "Urgency" and/or "Topic" headers, as
+ specified in Section 5 of [RFC8030]. The JMAP server is expected to
+ understand and handle HTTP status responses in a reasonable manner.
+ A "429" (Too Many Requests) response MUST cause the JMAP server to
+ reduce the frequency of pushes; the JMAP push structure allows
+ multiple changes to be coalesced into a single minimal StateChange
+ object. See the security considerations in Section 8.6 for a
+ discussion of the risks in connecting to unknown servers.
+
+ The JMAP server acts as an application server as defined in
+ [RFC8030]. A client MAY use the rest of [RFC8030] in combination
+ with its own push service to form a complete end-to-end solution, or
+ it MAY rely on alternative mechanisms to ensure the delivery of the
+ pushed data after it leaves the JMAP server.
+
+ The push subscription is tied to the credentials used to authenticate
+ the API request that created it. Should these credentials expire or
+ be revoked, the push subscription MUST be destroyed by the JMAP
+
+
+
+
+Jenkins & Newman Standards Track [Page 66]
+
+RFC 8620 JMAP July 2019
+
+
+ server. Only subscriptions created by these credentials are returned
+ when the client fetches existing subscriptions.
+
+ When these credentials have their own expiry (i.e., it is a session
+ with a timeout), the server SHOULD NOT set or bound the expiry time
+ for the push subscription given by the client but MUST expire it when
+ the session expires.
+
+ When these credentials are not time bounded (e.g., Basic
+ authentication [RFC7617]), the server SHOULD set an expiry time for
+ the push subscription if none is given and limit the expiry time if
+ set too far in the future. This maximum expiry time MUST be at least
+ 48 hours in the future and SHOULD be at least 7 days in the future.
+ An app running on a mobile device may only be able to refresh the
+ push subscription lifetime when it is in the foreground, so this
+ gives a reasonable time frame to allow this to happen.
+
+ In the case of separate access and refresh credentials, as in Oauth
+ 2.0 [RFC6749], the server SHOULD tie the push subscription to the
+ validity of the refresh token rather than the access token and behave
+ according to whether this is time-limited or not.
+
+ When a push subscription is destroyed, the server MUST securely erase
+ the URL and encryption keys from memory and storage as soon as
+ possible.
+
+7.2.1. PushSubscription/get
+
+ Standard /get method as described in Section 5.1, except it does
+ *not* take or return an "accountId" argument, as push subscriptions
+ are not tied to specific accounts. It also does *not* return a
+ "state" argument. The "ids" argument may be null to fetch all at
+ once.
+
+ The server MUST only return push subscriptions that were created
+ using the same authentication credentials as for this
+ "PushSubscription/get" request.
+
+ As the "url" and "keys" properties may contain data that is private
+ to a particular device, the values for these properties MUST NOT be
+ returned. If the "properties" argument is null or omitted, the
+ server MUST default to all properties excluding these two. If one of
+ them is explicitly requested, the method call MUST be rejected with a
+ "forbidden" error.
+
+
+
+
+
+
+
+Jenkins & Newman Standards Track [Page 67]
+
+RFC 8620 JMAP July 2019
+
+
+7.2.2. PushSubscription/set
+
+ Standard /set method as described in Section 5.3, except it does
+ *not* take or return an "accountId" argument, as push subscriptions
+ are not tied to specific accounts. It also does *not* take an
+ "ifInState" argument or return "oldState" or "newState" arguments.
+
+ The "url" and "keys" properties are immutable; if the client wishes
+ to change these, it must destroy the current push subscription and
+ create a new one.
+
+ When a PushSubscription is created, the server MUST immediately push
+ a *PushVerification* object to the URL. It has the following
+ properties:
+
+ o @type: "String"
+
+ This MUST be the string "PushVerification".
+
+ o pushSubscriptionId: "String"
+
+ The id of the push subscription that was created.
+
+ o verificationCode: "String"
+
+ The verification code to add to the push subscription. This MUST
+ contain sufficient entropy to avoid the client being able to guess
+ the code via brute force.
+
+ The client MUST update the push subscription with the correct
+ verification code before the server makes any further requests to the
+ subscription's URL. Attempts to update the subscription with an
+ invalid verification code MUST be rejected by the server with an
+ "invalidProperties" SetError.
+
+ The client may update the "expires" property to extend (or, less
+ commonly, shorten) the lifetime of a push subscription. The server
+ MAY modify the proposed new expiry time to enforce server-defined
+ limits. Extending the lifetime does not require the subscription to
+ be verified again.
+
+ Clients SHOULD NOT update or destroy a push subscription that they
+ did not create (i.e., has a "deviceClientId" that they do not
+ recognise).
+
+
+
+
+
+
+
+Jenkins & Newman Standards Track [Page 68]
+
+RFC 8620 JMAP July 2019
+
+
+7.2.3. Example
+
+ At "2018-07-06T02:14:29Z", a client with deviceClientId "a889-ffea-
+ 910" fetches the set of push subscriptions currently on the server,
+ making an API request with:
+
+ [[ "PushSubscription/get", {
+ "ids": null
+ }, "0" ]]
+
+ Which returns:
+
+ [[ "PushSubscription/get", {
+ "list": [{
+ "id": "e50b2c1d-9553-41a3-b0a7-a7d26b599ee1",
+ "deviceClientId": "b37ff8001ca0",
+ "verificationCode": "b210ef734fe5f439c1ca386421359f7b",
+ "expires": "2018-07-31T00:13:21Z",
+ "types": [ "Todo" ]
+ }, {
+ "id": "f2d0aab5-e976-4e8b-ad4b-b380a5b987e4",
+ "deviceClientId": "X8980fc",
+ "verificationCode": "f3d4618a9ae15c8b7f5582533786d531",
+ "expires": "2018-07-12T05:55:00Z",
+ "types": [ "Mailbox", "Email", "EmailDelivery" ]
+ }],
+ "notFound": []
+ }, "0" ]]
+
+ Since neither of the returned push subscription objects have the
+ client's deviceClientId, it knows it does not have a current push
+ subscription active on the server. So it creates one, sending this
+ request:
+
+[[ "PushSubscription/set", {
+ "create": {
+ "4f29": {
+ "deviceClientId": "a889-ffea-910",
+ "url": "https://example.com/push/?device=X8980fc&client=12c6d086",
+ "types": null
+ }
+ }
+}, "0" ]]
+
+
+
+
+
+
+
+
+Jenkins & Newman Standards Track [Page 69]
+
+RFC 8620 JMAP July 2019
+
+
+ The server creates the push subscription but limits the expiry time
+ to 7 days in the future, returning this response:
+
+ [[ "PushSubscription/set", {
+ "created": {
+ "4f29": {
+ "id": "P43dcfa4-1dd4-41ef-9156-2c89b3b19c60",
+ "keys": null,
+ "expires": "2018-07-13T02:14:29Z"
+ }
+ }
+ }, "0" ]]
+
+ The server also immediately makes a POST request to
+ "https://example.com/push/?device=X8980fc&client=12c6d086" with the
+ data:
+
+ {
+ "@type": "PushVerification",
+ "pushSubscriptionId": "P43dcfa4-1dd4-41ef-9156-2c89b3b19c60",
+ "verificationCode": "da1f097b11ca17f06424e30bf02bfa67"
+ }
+
+ The client receives this and updates the subscription with the
+ verification code (note there is a potential race condition here; the
+ client MUST be able to handle receiving the push while the request
+ creating the subscription is still in progress):
+
+ [[ "PushSubscription/set", {
+ "update": {
+ "P43dcfa4-1dd4-41ef-9156-2c89b3b19c60": {
+ "verificationCode": "da1f097b11ca17f06424e30bf02bfa67"
+ }
+ }
+ }, "0" ]]
+
+ The server confirms the update was successful and will now make
+ requests to the registered URL when the state changes.
+
+
+
+
+
+
+
+
+
+
+
+
+
+Jenkins & Newman Standards Track [Page 70]
+
+RFC 8620 JMAP July 2019
+
+
+ Two days later, the client updates the subscription to extend its
+ lifetime, sending this request:
+
+ [[ "PushSubscription/set", {
+ "update": {
+ "P43dcfa4-1dd4-41ef-9156-2c89b3b19c60": {
+ "expires": "2018-08-13T00:00:00Z"
+ }
+ }
+ }, "0" ]]
+
+ The server extends the expiry time, but only again to its maximum
+ limit of 7 days in the future, returning this response:
+
+ [[ "PushSubscription/set", {
+ "updated": {
+ "P43dcfa4-1dd4-41ef-9156-2c89b3b19c60": {
+ "expires": "2018-07-15T02:22:50Z"
+ }
+ }
+ }, "0" ]]
+
+7.3. Event Source
+
+ Clients that can hold transport connections open can connect directly
+ to the JMAP server to receive push notifications via a "text/event-
+ stream" resource, as described in [EventSource]. This is a long
+ running HTTP request, where the server can push data to the client by
+ appending data without ending the response.
+
+ When a change occurs in the data on the server, it pushes an event
+ called "state" to any connected clients, with the StateChange object
+ as the data.
+
+ The server SHOULD also send a new event id that encodes the entire
+ server state visible to the user immediately after sending a "state"
+ event. When a new connection is made to the event-source endpoint, a
+ client following the server-sent events specification will send a
+ Last-Event-ID HTTP header field with the last id it saw, which the
+ server can use to work out whether the client has missed some
+ changes. If so, it SHOULD send these changes immediately on
+ connection.
+
+ The Session object (see Section 2) has an "eventSourceUrl" property,
+ which is in URI Template (level 1) format [RFC6570]. The URL MUST
+ contain variables called "types", "closeafter", and "ping".
+
+
+
+
+
+Jenkins & Newman Standards Track [Page 71]
+
+RFC 8620 JMAP July 2019
+
+
+ To connect to the resource, the client makes an authenticated GET
+ request to the event-source URL with the appropriate variables
+ substituted in:
+
+ o "types": This MUST be either:
+
+ * A comma-separated list of type names, e.g.,
+ "Email,CalendarEvent". The server MUST only push changes for
+ the types in this list.
+
+ * The single character: "*". Changes to all types are pushed.
+
+ o "closeafter": This MUST be one of the following values:
+
+ * "state": The server MUST end the HTTP response after pushing a
+ state event. This can be used by clients in environments where
+ buffering proxies prevent the pushed data from arriving
+ immediately, or indeed at all, when operating in the usual
+ mode.
+
+ * "no": The connection is persisted by the server as a standard
+ event-source resource.
+
+ o "ping": A positive integer value representing a length of time in
+ seconds, e.g., "300". If non-zero, the server MUST send an event
+ called "ping" whenever this time elapses since the previous event
+ was sent. This MUST NOT set a new event id. If the value is "0",
+ the server MUST NOT send ping events.
+
+ The server MAY modify a requested ping interval to be subject to a
+ minimum and/or maximum value. For interoperability, servers MUST
+ NOT have a minimum allowed value higher than 30 or a maximum
+ allowed value less than 300.
+
+ The data for the ping event MUST be a JSON object containing an
+ "interval" property, the value (type "UnsignedInt") being the
+ interval in seconds the server is using to send pings (this may be
+ different to the requested value if the server clamped it to be
+ within a min/max value).
+
+ Clients can monitor for the ping event to help determine when the
+ closeafter mode may be required.
+
+ A client MAY hold open multiple connections to the event-source
+ resource, although it SHOULD try to use a single connection for
+ efficiency.
+
+
+
+
+
+Jenkins & Newman Standards Track [Page 72]
+
+RFC 8620 JMAP July 2019
+
+
+8. Security Considerations
+
+8.1. Transport Confidentiality
+
+ To ensure the confidentiality and integrity of data sent and received
+ via JMAP, all requests MUST use TLS 1.2 [RFC5246] [RFC8446] or later,
+ following the recommendations in [RFC7525]. Servers SHOULD support
+ TLS 1.3 [RFC8446] or later.
+
+ Clients MUST validate TLS certificate chains to protect against
+ man-in-the-middle attacks [RFC5280].
+
+8.2. Authentication Scheme
+
+ A number of HTTP authentication schemes have been standardised (see
+ <https://www.iana.org/assignments/http-authschemes/>). Servers
+ should take care to assess the security characteristics of different
+ schemes in relation to their needs when deciding what to implement.
+
+ Use of the Basic authentication scheme is NOT RECOMMENDED. Services
+ that choose to use it are strongly recommended to require generation
+ of a unique "app password" via some external mechanism for each
+ client they wish to connect. This allows connections from different
+ devices to be differentiated by the server and access to be
+ individually revoked.
+
+8.3. Service Autodiscovery
+
+ Unless secured by something like DNSSEC, autodiscovery of server
+ details using SRV DNS records is vulnerable to a DNS poisoning
+ attack, which can lead to the client talking to an attacker's server
+ instead of the real JMAP server. The attacker may then intercept
+ requests to execute man-in-the-middle attacks and, depending on the
+ authentication scheme, steal credentials to generate its own
+ requests.
+
+ Clients that do not support SRV lookups are likely to try just using
+ the "/.well-known/jmap" path directly against the domain of the
+ username over HTTPS. Servers SHOULD ensure this path resolves or
+ redirects to the correct JMAP Session resource to allow this to work.
+ If this is not feasible, servers MUST ensure this path cannot be
+ controlled by an attacker, as again it may be used to steal
+ credentials.
+
+
+
+
+
+
+
+
+Jenkins & Newman Standards Track [Page 73]
+
+RFC 8620 JMAP July 2019
+
+
+8.4. JSON Parsing
+
+ The Security Considerations of [RFC8259] apply to the use of JSON as
+ the data interchange format.
+
+ As for any serialization format, parsers need to thoroughly check the
+ syntax of the supplied data. JSON uses opening and closing tags for
+ several types and structures, and it is possible that the end of the
+ supplied data will be reached when scanning for a matching closing
+ tag; this is an error condition, and implementations need to stop
+ scanning at the end of the supplied data.
+
+ JSON also uses a string encoding with some escape sequences to encode
+ special characters within a string. Care is needed when processing
+ these escape sequences to ensure that they are fully formed before
+ the special processing is triggered, with special care taken when the
+ escape sequences appear adjacent to other (non-escaped) special
+ characters or adjacent to the end of data (as in the previous
+ paragraph).
+
+ If parsing JSON into a non-textual structured data format,
+ implementations may need to allocate storage to hold JSON string
+ elements. Since JSON does not use explicit string lengths, the risk
+ of denial of service due to resource exhaustion is small, but
+ implementations may still wish to place limits on the size of
+ allocations they are willing to make in any given context, to avoid
+ untrusted data causing excessive memory allocation.
+
+8.5. Denial of Service
+
+ A small request may result in a very large response and require
+ considerable work on the server if resource limits are not enforced.
+ JMAP provides mechanisms for advertising and enforcing a wide variety
+ of limits for mitigating this threat, including limits on the number
+ of objects fetched in a single method call, number of methods in a
+ single request, number of concurrent requests, etc.
+
+ JMAP servers MUST implement sensible limits to mitigate against
+ resource exhaustion attacks.
+
+8.6. Connection to Unknown Push Server
+
+ When a push subscription is registered, the application server will
+ make POST requests to the given URL. There are a number of security
+ considerations that MUST be considered when implementing this.
+
+
+
+
+
+
+Jenkins & Newman Standards Track [Page 74]
+
+RFC 8620 JMAP July 2019
+
+
+ The server MUST ensure the URL is externally resolvable to avoid
+ server-side request forgery, where the server makes a request to a
+ resource on its internal network.
+
+ A malicious client may use the push subscription to attempt to flood
+ a third party server with requests, creating a denial-of-service
+ attack and masking the attacker's true identity. There is no
+ guarantee that the URL given to the JMAP server is actually a valid
+ push server. Upon creation of a push subscription, the JMAP server
+ sends a PushVerification object to the URL and MUST NOT send any
+ further requests until the client verifies it has received the
+ initial push. The verification code MUST contain sufficient entropy
+ to prevent the client from being able to verify the subscription via
+ brute force.
+
+ The verification code does not guarantee the URL is a valid push
+ server, only that the client is able to access the data submitted to
+ it. While the verification step significantly reduces the set of
+ potential targets, there is still a risk that the server is unrelated
+ to the client and being targeted for a denial-of-service attack.
+
+ The server MUST limit the number of push subscriptions any one user
+ may have to ensure the user cannot cause the server to send a large
+ number of push notifications at once, which could again be used as
+ part of a denial-of-service attack. The rate of creation MUST also
+ be limited to minimise the ability to abuse the verification request
+ as an attack vector.
+
+8.7. Push Encryption
+
+ When data changes, a small object is pushed with the new state
+ strings for the types that have changed. While the data here is
+ minimal, a passive man-in-the-middle attacker may be able to gain
+ useful information. To ensure confidentiality and integrity, if the
+ push is sent via a third party outside of the control of the client
+ and JMAP server, the client MUST specify encryption keys when
+ establishing the PushSubscription and ignore any push notification
+ received that is not encrypted with those keys.
+
+ The privacy and security considerations of [RFC8030] and [RFC8291]
+ also apply to the use of the PushSubscription mechanism.
+
+ As there is no crypto algorithm agility in Web Push Encryption
+ [RFC8291], a new specification will be needed to provide this if new
+ algorithms are required in the future.
+
+
+
+
+
+
+Jenkins & Newman Standards Track [Page 75]
+
+RFC 8620 JMAP July 2019
+
+
+8.8. Traffic Analysis
+
+ While the data is encrypted, a passive observer with the ability to
+ monitor network traffic may be able to glean information from the
+ timing of API requests and push notifications. For example, suppose
+ an email or calendar invitation is sent from User A (hosted on Server
+ X) to User B (hosted on Server Y). If Server X hosts data for many
+ users, a passive observer can see that the two servers connected but
+ does not know who the data was for. However, if a push notification
+ is immediately sent to User B and the attacker can observe this as
+ well, they may reasonably conclude that someone on Server X is
+ connecting to User B.
+
+9. IANA Considerations
+
+9.1. Assignment of jmap Service Name
+
+ IANA has assigned the 'jmap' service name in the "Service Name and
+ Transport Protocol Port Number Registry" [RFC6335].
+
+ Service Name: jmap
+
+ Transport Protocol(s): tcp
+
+ Assignee: IESG
+
+ Contact: IETF Chair
+
+ Description: JSON Meta Application Protocol
+
+ Reference: RFC 8620
+
+ Assignment Notes: This service name was previously assigned under the
+ name "JSON Mail Access Protocol". This has been de-assigned and
+ re-assigned with the approval of the previous assignee.
+
+9.2. Registration of Well-Known URI Suffix for JMAP
+
+ IANA has registered the following suffix in the "Well-Known URIs"
+ registry for JMAP, as described in [RFC8615]:
+
+ URI Suffix: jmap
+
+ Change Controller: IETF
+
+ Specification Document: RFC 8620, Section 2.2.
+
+
+
+
+
+Jenkins & Newman Standards Track [Page 76]
+
+RFC 8620 JMAP July 2019
+
+
+9.3. Registration of the jmap URN Sub-namespace
+
+ IANA has registered the following URN sub-namespace in the "IETF URN
+ Sub-namespace for Registered Protocol Parameter Identifiers" registry
+ within the "Uniform Resource Name (URN) Namespace for IETF Use"
+ registry as described in [RFC3553].
+
+ Registered Parameter Identifier: jmap
+
+ Reference: RFC 8620, Section 9.4
+
+ IANA Registry Reference: http://www.iana.org/assignments/jmap
+
+9.4. Creation of "JMAP Capabilities" Registry
+
+ IANA has created the "JMAP Capabilities" registry as described in
+ Section 2. JMAP capabilities are advertised in the "capabilities"
+ property of the JMAP Session resource. They are used to extend the
+ functionality of a JMAP server. A capability is referenced by a URI.
+ The JMAP capability URI can be a URN starting with
+ "urn:ietf:params:jmap:" plus a unique suffix that is the index value
+ in the jmap URN sub-namespace. Registration of a JMAP capability
+ with another form of URI has no impact on the jmap URN sub-namespace.
+
+ This registry follows the expert review process unless the "intended
+ use" field is "common" or "placeholder", in which case registration
+ follows the specification required process.
+
+ A JMAP capability registration can have an intended use of "common",
+ "placeholder", "limited", or "obsolete". IANA will list common-use
+ registrations prominently and separately from those with other
+ intended use values.
+
+ The JMAP capability registration procedure is not a formal standards
+ process but rather an administrative procedure intended to allow
+ community comment and sanity checking without excessive time delay.
+
+ A "placeholder" registration reserves part of the jmap URN namespace
+ for another purpose but is typically not included in the
+ "capabilities" property of the JMAP Session resource.
+
+9.4.1. Preliminary Community Review
+
+ Notice of a potential JMAP common-use registration SHOULD be sent to
+ the JMAP mailing list <jmap@ietf.org> for review. This mailing list
+ is appropriate to solicit community feedback on a proposed JMAP
+
+
+
+
+
+Jenkins & Newman Standards Track [Page 77]
+
+RFC 8620 JMAP July 2019
+
+
+ capability. Registrations that are not intended for common use MAY
+ be sent to the list for review as well; doing so is entirely
+ OPTIONAL, but is encouraged.
+
+ The intent of the public posting to this list is to solicit comments
+ and feedback on the choice of the capability name, the unambiguity of
+ the specification document, and a review of any interoperability or
+ security considerations. The submitter may submit a revised
+ registration proposal or abandon the registration completely at any
+ time.
+
+9.4.2. Submit Request to IANA
+
+ Registration requests can be sent to <iana@iana.org>.
+
+9.4.3. Designated Expert Review
+
+ For a limited-use registration, the primary concern of the designated
+ expert (DE) is preventing name collisions and encouraging the
+ submitter to document security and privacy considerations; a
+ published specification is not required. For a common-use
+ registration, the DE is expected to confirm that suitable
+ documentation, as described in Section 4.6 of [RFC8126], is
+ available. The DE should also verify that the capability does not
+ conflict with work that is active or already published within the
+ IETF.
+
+ Before a period of 30 days has passed, the DE will either approve or
+ deny the registration request and publish a notice of the decision to
+ the JMAP WG mailing list or its successor, as well as inform IANA. A
+ denial notice must be justified by an explanation, and, in the cases
+ where it is possible, concrete suggestions on how the request can be
+ modified so as to become acceptable should be provided.
+
+ If the DE does not respond within 30 days, the registrant may request
+ the IESG take action to process the request in a timely manner.
+
+9.4.4. Change Procedures
+
+ Once a JMAP capability has been published by the IANA, the change
+ controller may request a change to its definition. The same
+ procedure that would be appropriate for the original registration
+ request is used to process a change request.
+
+ JMAP capability registrations may not be deleted; capabilities that
+ are no longer believed appropriate for use can be declared obsolete
+ by a change to their "intended use" field; such capabilities will be
+ clearly marked in the lists published by the IANA.
+
+
+
+Jenkins & Newman Standards Track [Page 78]
+
+RFC 8620 JMAP July 2019
+
+
+ Significant changes to a capability's definition should be requested
+ only when there are serious omissions or errors in the published
+ specification. When review is required, a change request may be
+ denied if it renders entities that were valid under the previous
+ definition invalid under the new definition.
+
+ The owner of a JMAP capability may pass responsibility to another
+ person or agency by informing the IANA; this can be done without
+ discussion or review.
+
+ The IESG may reassign responsibility for a JMAP capability. The most
+ common case of this will be to enable changes to be made to
+ capabilities where the author of the registration has died, moved out
+ of contact, or is otherwise unable to make changes that are important
+ to the community.
+
+9.4.5. JMAP Capabilities Registry Template
+
+ Capability name: (see capability property in Section 2)
+
+ Specification document:
+
+ Intended use: (one of common, limited, placeholder, or obsolete)
+
+ Change controller: ("IETF" for Standards Track / BCP RFCs)
+
+ Security and privacy considerations:
+
+9.4.6. Initial Registration for JMAP Core
+
+ Capability Name: "urn:ietf:params:jmap:core"
+
+ Specification document: RFC 8620, Section 2
+
+ Intended use: common
+
+ Change Controller: IETF
+
+ Security and privacy considerations: RFC 8620, Section 8.
+
+
+
+
+
+
+
+
+
+
+
+
+Jenkins & Newman Standards Track [Page 79]
+
+RFC 8620 JMAP July 2019
+
+
+9.4.7. Registration for JMAP Error Placeholder in JMAP Capabilities
+ Registry
+
+ Capability Name: "urn:ietf:params:jmap:error:"
+
+ Specification document: RFC 8620, Section 9.5
+
+ Intended use: placeholder
+
+ Change Controller: IETF
+
+ Security and privacy considerations: RFC 8620, Section 8.
+
+9.5. Creation of "JMAP Error Codes" Registry
+
+ IANA has created the "JMAP Error Codes" registry. JMAP error codes
+ appear in the "type" member of a JSON problem details object (as
+ described in Section 3.6.1), the "type" member in a JMAP error object
+ (as described in Section 3.6.2), or the "type" member of a JMAP
+ method-specific error object (such as SetError in Section 5.3). When
+ used in a problem details object, the prefix
+ "urn:ietf:params:jmap:error:" is always included; when used in JMAP
+ objects, the prefix is always omitted.
+
+ This registry follows the expert review process. Preliminary
+ community review for this registry follows the same procedures as the
+ "JMAP Capabilities" registry, but it is optional. The change
+ procedures for this registry are the same as the change procedures
+ for the "JMAP Capabilities" registry.
+
+9.5.1. Expert Review
+
+ The designated expert should review the following aspects of the
+ registration:
+
+ 1. Verify the error code does not conflict with existing names.
+
+ 2. Verify the error code follows the syntax limitations (does not
+ require URI encoding).
+
+ 3. Encourage the submitter to follow the naming convention of
+ previously registered errors.
+
+ 4. Encourage the submitter to describe client behaviours that are
+ recommended in response to the error code. These may distinguish
+ the error code from other error codes.
+
+
+
+
+
+Jenkins & Newman Standards Track [Page 80]
+
+RFC 8620 JMAP July 2019
+
+
+ 5. Encourage the submitter to describe when the server should issue
+ the error as opposed to some other error code.
+
+ 6. Encourage the submitter to note any security considerations
+ associated with the error, if any (e.g., an error code that might
+ disclose existence of data the authenticated user does not have
+ permission to know about).
+
+ Steps 3-6 are meant to promote a higher-quality registry. However,
+ the expert is encouraged to approve any registration that would not
+ actively harm JMAP interoperability to make this a relatively
+ lightweight process.
+
+9.5.2. JMAP Error Codes Registry Template
+
+ JMAP Error Code:
+
+ Intended use: (one of "common", "limited", "obsolete")
+
+ Change Controller: ("IETF" for Standards Track / BCP RFCs)
+
+ Reference: (Optional. Only required if defined in an RFC.)
+
+ Description:
+
+9.5.3. Initial Contents for the JMAP Error Codes Registry
+
+ o JMAP Error Code: accountNotFound
+ Intended Use: Common
+ Change Controller: IETF
+ Reference: RFC 8620, Section 3.6.2
+ Description: The accountId does not correspond to a valid account.
+
+ o JMAP Error Code: accountNotSupportedByMethod
+ Intended Use: Common
+ Change Controller: IETF
+ Reference: RFC 8620, Section 3.6.2
+ Description: The accountId given corresponds to a valid account,
+ but the account does not support this method or data type.
+
+ o JMAP Error Code: accountReadOnly
+ Intended Use: Common
+ Change Controller: IETF
+ Reference: RFC 8620, Section 3.6.2
+ Description: This method modifies state, but the account is read-
+ only (as returned on the corresponding Account object in the JMAP
+ Session resource).
+
+
+
+
+Jenkins & Newman Standards Track [Page 81]
+
+RFC 8620 JMAP July 2019
+
+
+ o JMAP Error Code: anchorNotFound
+ Intended Use: Common
+ Change Controller: IETF
+ Reference: RFC 8620, Section 5.5
+ Description: An anchor argument was supplied, but it cannot be
+ found in the results of the query.
+
+ o JMAP Error Code: alreadyExists
+ Intended Use: Common
+ Change Controller: IETF
+ Reference: RFC 8620, Section 5.4
+ Description: The server forbids duplicates, and the record already
+ exists in the target account. An existingId property of type Id
+ MUST be included on the SetError object with the id of the
+ existing record.
+
+ o JMAP Error Code: cannotCalculateChanges
+ Intended Use: Common
+ Change Controller: IETF
+ Reference: RFC 8620, Sections 5.2 and 5.6
+ Description: The server cannot calculate the changes from the
+ state string given by the client.
+
+ o JMAP Error Code: forbidden
+ Intended Use: Common
+ Change Controller: IETF
+ Reference: RFC 8620, Sections 3.6.2, 5.3, and 7.2.1
+ Description: The action would violate an ACL or other permissions
+ policy.
+
+ o JMAP Error Code: fromAccountNotFound
+ Intended Use: Common
+ Change Controller: IETF
+ Reference: RFC 8620, Sections 5.4 and 6.3
+ Description: The fromAccountId does not correspond to a valid
+ account.
+
+ o JMAP Error Code: fromAccountNotSupportedByMethod
+ Intended Use: Common
+ Change Controller: IETF
+ Reference: RFC 8620, Section 5.4
+ Description: The fromAccountId given corresponds to a valid
+ account, but the account does not support this data type.
+
+
+
+
+
+
+
+
+Jenkins & Newman Standards Track [Page 82]
+
+RFC 8620 JMAP July 2019
+
+
+ o JMAP Error Code: invalidArguments
+ Intended Use: Common
+ Change Controller: IETF
+ Reference: RFC 8620, Section 3.6.2
+ Description: One of the arguments is of the wrong type or
+ otherwise invalid, or a required argument is missing.
+
+ o JMAP Error Code: invalidPatch
+ Intended Use: Common
+ Change Controller: IETF
+ Reference: RFC 8620, Section 5.3
+ Description: The PatchObject given to update the record was not a
+ valid patch.
+
+ o JMAP Error Code: invalidProperties
+ Intended Use: Common
+ Change Controller: IETF
+ Reference: RFC 8620, Section 5.3
+ Description: The record given is invalid.
+
+ o JMAP Error Code: notFound
+ Intended Use: Common
+ Change Controller: IETF
+ Reference: RFC 8620, Section 5.3
+ Description: The id given cannot be found.
+
+ o JMAP Error Code: notJSON
+ Intended Use: Common
+ Change Controller: IETF
+ Reference: RFC 8620, Section 3.6.1
+ Description: The content type of the request was not application/
+ json, or the request did not parse as I-JSON.
+
+ o JMAP Error Code: notRequest
+ Intended Use: Common
+ Change Controller: IETF
+ Reference: RFC 8620, Section 3.6.1
+ Description: The request parsed as JSON but did not match the type
+ signature of the Request object.
+
+ o JMAP Error Code: overQuota
+ Intended Use: Common
+ Change Controller: IETF
+ Reference: RFC 8620, Section 5.3
+ Description: The create would exceed a server-defined limit on the
+ number or total size of objects of this type.
+
+
+
+
+
+Jenkins & Newman Standards Track [Page 83]
+
+RFC 8620 JMAP July 2019
+
+
+ o JMAP Error Code: rateLimit
+ Intended Use: Common
+ Change Controller: IETF
+ Reference: RFC 8620, Section 5.3
+ Description: Too many objects of this type have been created
+ recently, and a server-defined rate limit has been reached. It
+ may work if tried again later.
+
+ o JMAP Error Code: requestTooLarge
+ Intended Use: Common
+ Change Controller: IETF
+ Reference: RFC 8620, Sections 5.1 and 5.3
+ Description: The total number of actions exceeds the maximum
+ number the server is willing to process in a single method call.
+
+ o JMAP Error Code: invalidResultReference
+ Intended Use: Common
+ Change Controller: IETF
+ Reference: RFC 8620, Section 3.6.2
+ Description: The method used a result reference for one of its
+ arguments, but this failed to resolve.
+
+ o JMAP Error Code: serverFail
+ Intended Use: Common
+ Change Controller: IETF
+ Reference: RFC 8620, Section 3.6.2
+ Description: An unexpected or unknown error occurred during the
+ processing of the call. The method call made no changes to the
+ server's state.
+
+ o JMAP Error Code: serverPartialFail
+ Intended Use: Limited
+ Change Controller: IETF
+ Reference: RFC 8620, Section 3.6.2
+ Description: Some, but not all, expected changes described by the
+ method occurred. The client MUST resynchronise impacted data to
+ determine the server state. Use of this error is strongly
+ discouraged.
+
+ o JMAP Error Code: serverUnavailable
+ Intended Use: Common
+ Change Controller: IETF
+ Reference: RFC 8620, Section 3.6.2
+ Description: Some internal server resource was temporarily
+ unavailable. Attempting the same operation later (perhaps after a
+ backoff with a random factor) may succeed.
+
+
+
+
+
+Jenkins & Newman Standards Track [Page 84]
+
+RFC 8620 JMAP July 2019
+
+
+ o JMAP Error Code: singleton
+ Intended Use: Common
+ Change Controller: IETF
+ Reference: RFC 8620, Section 5.3
+ Description: This is a singleton type, so you cannot create
+ another one or destroy the existing one.
+
+ o JMAP Error Code: stateMismatch
+ Intended Use: Common
+ Change Controller: IETF
+ Reference: RFC 8620, Section 5.3
+ Description: An ifInState argument was supplied, and it does not
+ match the current state.
+
+ o JMAP Error Code: tooLarge
+ Intended Use: Common
+ Change Controller: IETF
+ Reference: RFC 8620, Section 5.3
+ Description: The action would result in an object that exceeds a
+ server-defined limit for the maximum size of a single object of
+ this type.
+
+ o JMAP Error Code: tooManyChanges
+ Intended Use: Common
+ Change Controller: IETF
+ Reference: RFC 8620, Section 5.6
+ Description: There are more changes than the client's maxChanges
+ argument.
+
+ o JMAP Error Code: unknownCapability
+ Intended Use: Common
+ Change Controller: IETF
+ Reference: RFC 8620, Section 3.6.1
+ Description: The client included a capability in the "using"
+ property of the request that the server does not support.
+
+ o JMAP Error Code: unknownMethod
+ Intended Use: Common
+ Change Controller: IETF
+ Reference: RFC 8620, Section 3.6.2
+ Description: The server does not recognise this method name.
+
+ o JMAP Error Code: unsupportedFilter
+ Intended Use: Common
+ Change Controller: IETF
+ Reference: RFC 8620, Section 5.5
+ Description: The filter is syntactically valid, but the server
+ cannot process it.
+
+
+
+Jenkins & Newman Standards Track [Page 85]
+
+RFC 8620 JMAP July 2019
+
+
+ o JMAP Error Code: unsupportedSort
+ Intended Use: Common
+ Change Controller: IETF
+ Reference: RFC 8620, Section 5.5
+ Description: The sort is syntactically valid but includes a
+ property the server does not support sorting on or a collation
+ method it does not recognise.
+
+ o JMAP Error Code: willDestroy
+ Intended Use: Common
+ Change Controller: IETF
+ Reference: RFC 8620, Section 5.3
+ Description: The client requested an object be both updated and
+ destroyed in the same /set request, and the server has decided to
+ therefore ignore the update.
+
+10. References
+
+10.1. Normative References
+
+ [EventSource]
+ Hickson, I., "Server-Sent Events", World Wide Web
+ Consortium Recommendation REC-eventsource-20150203,
+ February 2015, <https://www.w3.org/TR/eventsource/>.
+
+ [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
+ Requirement Levels", BCP 14, RFC 2119,
+ DOI 10.17487/RFC2119, March 1997,
+ <https://www.rfc-editor.org/info/rfc2119>.
+
+ [RFC2782] Gulbrandsen, A., Vixie, P., and L. Esibov, "A DNS RR for
+ specifying the location of services (DNS SRV)", RFC 2782,
+ DOI 10.17487/RFC2782, February 2000,
+ <https://www.rfc-editor.org/info/rfc2782>.
+
+ [RFC2818] Rescorla, E., "HTTP Over TLS", RFC 2818,
+ DOI 10.17487/RFC2818, May 2000,
+ <https://www.rfc-editor.org/info/rfc2818>.
+
+ [RFC3339] Klyne, G. and C. Newman, "Date and Time on the Internet:
+ Timestamps", RFC 3339, DOI 10.17487/RFC3339, July 2002,
+ <https://www.rfc-editor.org/info/rfc3339>.
+
+ [RFC3553] Mealling, M., Masinter, L., Hardie, T., and G. Klyne, "An
+ IETF URN Sub-namespace for Registered Protocol
+ Parameters", BCP 73, RFC 3553, DOI 10.17487/RFC3553, June
+ 2003, <https://www.rfc-editor.org/info/rfc3553>.
+
+
+
+
+Jenkins & Newman Standards Track [Page 86]
+
+RFC 8620 JMAP July 2019
+
+
+ [RFC3629] Yergeau, F., "UTF-8, a transformation format of ISO
+ 10646", STD 63, RFC 3629, DOI 10.17487/RFC3629, November
+ 2003, <https://www.rfc-editor.org/info/rfc3629>.
+
+ [RFC4648] Josefsson, S., "The Base16, Base32, and Base64 Data
+ Encodings", RFC 4648, DOI 10.17487/RFC4648, October 2006,
+ <https://www.rfc-editor.org/info/rfc4648>.
+
+ [RFC4790] Newman, C., Duerst, M., and A. Gulbrandsen, "Internet
+ Application Protocol Collation Registry", RFC 4790,
+ DOI 10.17487/RFC4790, March 2007,
+ <https://www.rfc-editor.org/info/rfc4790>.
+
+ [RFC5051] Crispin, M., "i;unicode-casemap - Simple Unicode Collation
+ Algorithm", RFC 5051, DOI 10.17487/RFC5051, October 2007,
+ <https://www.rfc-editor.org/info/rfc5051>.
+
+ [RFC5246] Dierks, T. and E. Rescorla, "The Transport Layer Security
+ (TLS) Protocol Version 1.2", RFC 5246,
+ DOI 10.17487/RFC5246, August 2008,
+ <https://www.rfc-editor.org/info/rfc5246>.
+
+ [RFC5280] Cooper, D., Santesson, S., Farrell, S., Boeyen, S.,
+ Housley, R., and W. Polk, "Internet X.509 Public Key
+ Infrastructure Certificate and Certificate Revocation List
+ (CRL) Profile", RFC 5280, DOI 10.17487/RFC5280, May 2008,
+ <https://www.rfc-editor.org/info/rfc5280>.
+
+ [RFC5322] Resnick, P., Ed., "Internet Message Format", RFC 5322,
+ DOI 10.17487/RFC5322, October 2008,
+ <https://www.rfc-editor.org/info/rfc5322>.
+
+ [RFC6186] Daboo, C., "Use of SRV Records for Locating Email
+ Submission/Access Services", RFC 6186,
+ DOI 10.17487/RFC6186, March 2011,
+ <https://www.rfc-editor.org/info/rfc6186>.
+
+ [RFC6335] Cotton, M., Eggert, L., Touch, J., Westerlund, M., and S.
+ Cheshire, "Internet Assigned Numbers Authority (IANA)
+ Procedures for the Management of the Service Name and
+ Transport Protocol Port Number Registry", BCP 165,
+ RFC 6335, DOI 10.17487/RFC6335, August 2011,
+ <https://www.rfc-editor.org/info/rfc6335>.
+
+ [RFC6570] Gregorio, J., Fielding, R., Hadley, M., Nottingham, M.,
+ and D. Orchard, "URI Template", RFC 6570,
+ DOI 10.17487/RFC6570, March 2012,
+ <https://www.rfc-editor.org/info/rfc6570>.
+
+
+
+Jenkins & Newman Standards Track [Page 87]
+
+RFC 8620 JMAP July 2019
+
+
+ [RFC6749] Hardt, D., Ed., "The OAuth 2.0 Authorization Framework",
+ RFC 6749, DOI 10.17487/RFC6749, October 2012,
+ <https://www.rfc-editor.org/info/rfc6749>.
+
+ [RFC6764] Daboo, C., "Locating Services for Calendaring Extensions
+ to WebDAV (CalDAV) and vCard Extensions to WebDAV
+ (CardDAV)", RFC 6764, DOI 10.17487/RFC6764, February 2013,
+ <https://www.rfc-editor.org/info/rfc6764>.
+
+ [RFC6838] Freed, N., Klensin, J., and T. Hansen, "Media Type
+ Specifications and Registration Procedures", BCP 13,
+ RFC 6838, DOI 10.17487/RFC6838, January 2013,
+ <https://www.rfc-editor.org/info/rfc6838>.
+
+ [RFC6901] Bryan, P., Ed., Zyp, K., and M. Nottingham, Ed.,
+ "JavaScript Object Notation (JSON) Pointer", RFC 6901,
+ DOI 10.17487/RFC6901, April 2013,
+ <https://www.rfc-editor.org/info/rfc6901>.
+
+ [RFC7230] Fielding, R., Ed. and J. Reschke, Ed., "Hypertext Transfer
+ Protocol (HTTP/1.1): Message Syntax and Routing",
+ RFC 7230, DOI 10.17487/RFC7230, June 2014,
+ <https://www.rfc-editor.org/info/rfc7230>.
+
+ [RFC7231] Fielding, R., Ed. and J. Reschke, Ed., "Hypertext Transfer
+ Protocol (HTTP/1.1): Semantics and Content", RFC 7231,
+ DOI 10.17487/RFC7231, June 2014,
+ <https://www.rfc-editor.org/info/rfc7231>.
+
+ [RFC7493] Bray, T., Ed., "The I-JSON Message Format", RFC 7493,
+ DOI 10.17487/RFC7493, March 2015,
+ <https://www.rfc-editor.org/info/rfc7493>.
+
+ [RFC7525] Sheffer, Y., Holz, R., and P. Saint-Andre,
+ "Recommendations for Secure Use of Transport Layer
+ Security (TLS) and Datagram Transport Layer Security
+ (DTLS)", BCP 195, RFC 7525, DOI 10.17487/RFC7525, May
+ 2015, <https://www.rfc-editor.org/info/rfc7525>.
+
+ [RFC7617] Reschke, J., "The 'Basic' HTTP Authentication Scheme",
+ RFC 7617, DOI 10.17487/RFC7617, September 2015,
+ <https://www.rfc-editor.org/info/rfc7617>.
+
+ [RFC7807] Nottingham, M. and E. Wilde, "Problem Details for HTTP
+ APIs", RFC 7807, DOI 10.17487/RFC7807, March 2016,
+ <https://www.rfc-editor.org/info/rfc7807>.
+
+
+
+
+
+Jenkins & Newman Standards Track [Page 88]
+
+RFC 8620 JMAP July 2019
+
+
+ [RFC8030] Thomson, M., Damaggio, E., and B. Raymor, Ed., "Generic
+ Event Delivery Using HTTP Push", RFC 8030,
+ DOI 10.17487/RFC8030, December 2016,
+ <https://www.rfc-editor.org/info/rfc8030>.
+
+ [RFC8126] Cotton, M., Leiba, B., and T. Narten, "Guidelines for
+ Writing an IANA Considerations Section in RFCs", BCP 26,
+ RFC 8126, DOI 10.17487/RFC8126, June 2017,
+ <https://www.rfc-editor.org/info/rfc8126>.
+
+ [RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC
+ 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174,
+ May 2017, <https://www.rfc-editor.org/info/rfc8174>.
+
+ [RFC8259] Bray, T., Ed., "The JavaScript Object Notation (JSON) Data
+ Interchange Format", STD 90, RFC 8259,
+ DOI 10.17487/RFC8259, December 2017,
+ <https://www.rfc-editor.org/info/rfc8259>.
+
+ [RFC8264] Saint-Andre, P. and M. Blanchet, "PRECIS Framework:
+ Preparation, Enforcement, and Comparison of
+ Internationalized Strings in Application Protocols",
+ RFC 8264, DOI 10.17487/RFC8264, October 2017,
+ <https://www.rfc-editor.org/info/rfc8264>.
+
+ [RFC8291] Thomson, M., "Message Encryption for Web Push", RFC 8291,
+ DOI 10.17487/RFC8291, November 2017,
+ <https://www.rfc-editor.org/info/rfc8291>.
+
+ [RFC8446] Rescorla, E., "The Transport Layer Security (TLS) Protocol
+ Version 1.3", RFC 8446, DOI 10.17487/RFC8446, August 2018,
+ <https://www.rfc-editor.org/info/rfc8446>.
+
+ [RFC8615] Nottingham, M., "Well-Known Uniform Resource Identifiers
+ (URIs)", RFC 8615, DOI 10.17487/RFC8615, May 2019,
+ <https://www.rfc-editor.org/info/rfc8615>.
+
+10.2. Informative References
+
+ [RFC8246] McManus, P., "HTTP Immutable Responses", RFC 8246,
+ DOI 10.17487/RFC8246, September 2017,
+ <https://www.rfc-editor.org/info/rfc8246>.
+
+
+
+
+
+
+
+
+
+Jenkins & Newman Standards Track [Page 89]
+
+RFC 8620 JMAP July 2019
+
+
+Authors' Addresses
+
+ Neil Jenkins
+ Fastmail
+ PO Box 234, Collins St. West
+ Melbourne, VIC 8007
+ Australia
+
+ Email: neilj@fastmailteam.com
+ URI: https://www.fastmail.com
+
+
+ Chris Newman
+ Oracle
+ 440 E. Huntington Dr., Suite 400
+ Arcadia, CA 91006
+ United States of America
+
+ Email: chris.newman@oracle.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Jenkins & Newman Standards Track [Page 90]
+