Tech-invite3GPPspaceIETFspace
959493929190898887868584838281807978777675747372717069686766656463626160595857565554535251504948474645444342414039383736353433323130292827262524232221201918171615141312111009080706050403020100
in Index   Prev   Next

RFC 8621

The JSON Meta Application Protocol (JMAP) for Mail

Pages: 108
Proposed Standard
Updates:  5788
Part 1 of 5 – Pages 1 to 22
None   None   Next

Top   ToC   RFC8621 - Page 1
Internet Engineering Task Force (IETF)                        N. Jenkins
Request for Comments: 8621                                      Fastmail
Updates: 5788                                                  C. Newman
Category: Standards Track                                         Oracle
ISSN: 2070-1721                                              August 2019


           The JSON Meta Application Protocol (JMAP) for Mail

Abstract

This document specifies a data model for synchronising email data with a server using the JSON Meta Application Protocol (JMAP). Clients can use this to efficiently search, access, organise, and send messages, and to get push notifications for fast resynchronisation when new messages are delivered or a change is made in another client. 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/rfc8621. 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.
Top   ToC   RFC8621 - Page 2

Table of Contents

1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 4 1.1. Notational Conventions . . . . . . . . . . . . . . . . . 4 1.2. Terminology . . . . . . . . . . . . . . . . . . . . . . . 5 1.3. Additions to the Capabilities Object . . . . . . . . . . 5 1.3.1. urn:ietf:params:jmap:mail . . . . . . . . . . . . . . 5 1.3.2. urn:ietf:params:jmap:submission . . . . . . . . . . . 7 1.3.3. urn:ietf:params:jmap:vacationresponse . . . . . . . . 8 1.4. Data Type Support in Different Accounts . . . . . . . . . 8 1.5. Push . . . . . . . . . . . . . . . . . . . . . . . . . . 8 1.5.1. Example . . . . . . . . . . . . . . . . . . . . . . . 9 1.6. Ids . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 2. Mailboxes . . . . . . . . . . . . . . . . . . . . . . . . . . 9 2.1. Mailbox/get . . . . . . . . . . . . . . . . . . . . . . . 14 2.2. Mailbox/changes . . . . . . . . . . . . . . . . . . . . . 14 2.3. Mailbox/query . . . . . . . . . . . . . . . . . . . . . . 14 2.4. Mailbox/queryChanges . . . . . . . . . . . . . . . . . . 15 2.5. Mailbox/set . . . . . . . . . . . . . . . . . . . . . . . 16 2.6. Example . . . . . . . . . . . . . . . . . . . . . . . . . 17 3. Threads . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 3.1. Thread/get . . . . . . . . . . . . . . . . . . . . . . . 22 3.1.1. Example . . . . . . . . . . . . . . . . . . . . . . . 22 3.2. Thread/changes . . . . . . . . . . . . . . . . . . . . . 22 4. Emails . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 4.1. Properties of the Email Object . . . . . . . . . . . . . 23 4.1.1. Metadata . . . . . . . . . . . . . . . . . . . . . . 24 4.1.2. Header Fields Parsed Forms . . . . . . . . . . . . . 26 4.1.3. Header Fields Properties . . . . . . . . . . . . . . 32 4.1.4. Body Parts . . . . . . . . . . . . . . . . . . . . . 35 4.2. Email/get . . . . . . . . . . . . . . . . . . . . . . . . 42 4.2.1. Example . . . . . . . . . . . . . . . . . . . . . . . 44 4.3. Email/changes . . . . . . . . . . . . . . . . . . . . . . 45 4.4. Email/query . . . . . . . . . . . . . . . . . . . . . . . 45 4.4.1. Filtering . . . . . . . . . . . . . . . . . . . . . . 46 4.4.2. Sorting . . . . . . . . . . . . . . . . . . . . . . . 49 4.4.3. Thread Collapsing . . . . . . . . . . . . . . . . . . 50 4.5. Email/queryChanges . . . . . . . . . . . . . . . . . . . 51 4.6. Email/set . . . . . . . . . . . . . . . . . . . . . . . . 51 4.7. Email/copy . . . . . . . . . . . . . . . . . . . . . . . 53 4.8. Email/import . . . . . . . . . . . . . . . . . . . . . . 54 4.9. Email/parse . . . . . . . . . . . . . . . . . . . . . . . 56 4.10. Examples . . . . . . . . . . . . . . . . . . . . . . . . 58 5. Search Snippets . . . . . . . . . . . . . . . . . . . . . . . 68 5.1. SearchSnippet/get . . . . . . . . . . . . . . . . . . . . 69 5.2. Example . . . . . . . . . . . . . . . . . . . . . . . . . 71
Top   ToC   RFC8621 - Page 3
   6.  Identities  . . . . . . . . . . . . . . . . . . . . . . . . .  72
     6.1.  Identity/get  . . . . . . . . . . . . . . . . . . . . . .  73
     6.2.  Identity/changes  . . . . . . . . . . . . . . . . . . . .  73
     6.3.  Identity/set  . . . . . . . . . . . . . . . . . . . . . .  73
     6.4.  Example . . . . . . . . . . . . . . . . . . . . . . . . .  73
   7.  Email Submission  . . . . . . . . . . . . . . . . . . . . . .  74
     7.1.  EmailSubmission/get . . . . . . . . . . . . . . . . . . .  80
     7.2.  EmailSubmission/changes . . . . . . . . . . . . . . . . .  80
     7.3.  EmailSubmission/query . . . . . . . . . . . . . . . . . .  80
     7.4.  EmailSubmission/queryChanges  . . . . . . . . . . . . . .  81
     7.5.  EmailSubmission/set . . . . . . . . . . . . . . . . . . .  81
       7.5.1.  Example . . . . . . . . . . . . . . . . . . . . . . .  84
   8.  Vacation Response . . . . . . . . . . . . . . . . . . . . . .  86
     8.1.  VacationResponse/get  . . . . . . . . . . . . . . . . . .  87
     8.2.  VacationResponse/set  . . . . . . . . . . . . . . . . . .  88
   9.  Security Considerations . . . . . . . . . . . . . . . . . . .  88
     9.1.  EmailBodyPart Value . . . . . . . . . . . . . . . . . . .  88
     9.2.  HTML Email Display  . . . . . . . . . . . . . . . . . . .  88
     9.3.  Multiple Part Display . . . . . . . . . . . . . . . . . .  91
     9.4.  Email Submission  . . . . . . . . . . . . . . . . . . . .  91
     9.5.  Partial Account Access  . . . . . . . . . . . . . . . . .  92
     9.6.  Permission to Send from an Address  . . . . . . . . . . .  92
   10. IANA Considerations . . . . . . . . . . . . . . . . . . . . .  93
     10.1.  JMAP Capability Registration for "mail"  . . . . . . . .  93
     10.2.  JMAP Capability Registration for "submission"  . . . . .  93
     10.3.  JMAP Capability Registration for "vacationresponse"  . .  94
     10.4.  IMAP and JMAP Keywords Registry  . . . . . . . . . . . .  94
       10.4.1.  Registration of JMAP Keyword "$draft"  . . . . . . .  95
       10.4.2.  Registration of JMAP Keyword "$seen" . . . . . . . .  96
       10.4.3.  Registration of JMAP Keyword "$flagged"  . . . . . .  97
       10.4.4.  Registration of JMAP Keyword "$answered" . . . . . .  98
       10.4.5.  Registration of "$recent" Keyword  . . . . . . . . .  99
     10.5.  IMAP Mailbox Name Attributes Registry  . . . . . . . . .  99
       10.5.1.  Registration of "inbox" Role . . . . . . . . . . . .  99
     10.6.  JMAP Error Codes Registry  . . . . . . . . . . . . . . . 100
       10.6.1.  mailboxHasChild  . . . . . . . . . . . . . . . . . . 100
       10.6.2.  mailboxHasEmail  . . . . . . . . . . . . . . . . . . 100
       10.6.3.  blobNotFound . . . . . . . . . . . . . . . . . . . . 100
       10.6.4.  tooManyKeywords  . . . . . . . . . . . . . . . . . . 101
       10.6.5.  tooManyMailboxes . . . . . . . . . . . . . . . . . . 101
       10.6.6.  invalidEmail . . . . . . . . . . . . . . . . . . . . 101
       10.6.7.  tooManyRecipients  . . . . . . . . . . . . . . . . . 102
       10.6.8.  noRecipients . . . . . . . . . . . . . . . . . . . . 102
       10.6.9.  invalidRecipients  . . . . . . . . . . . . . . . . . 102
       10.6.10. forbiddenMailFrom  . . . . . . . . . . . . . . . . . 103
       10.6.11. forbiddenFrom  . . . . . . . . . . . . . . . . . . . 103
       10.6.12. forbiddenToSend  . . . . . . . . . . . . . . . . . . 103
Top   ToC   RFC8621 - Page 4
   11. References  . . . . . . . . . . . . . . . . . . . . . . . . . 104
     11.1.  Normative References . . . . . . . . . . . . . . . . . . 104
     11.2.  Informative References . . . . . . . . . . . . . . . . . 107
   Authors' Addresses  . . . . . . . . . . . . . . . . . . . . . . . 108

1. Introduction

The JSON Meta Application Protocol (JMAP) [RFC8620] is a generic protocol for synchronising data, such as mail, calendars, or contacts between a client and a server. It is optimised for mobile and web environments and aims to provide a consistent interface to different data types. This specification defines a data model for accessing a mail store over JMAP, allowing you to query, read, organise, and submit mail for sending. The data model is designed to allow a server to provide consistent access to the same data via IMAP [RFC3501] as well as JMAP. As in IMAP, a message must belong to a mailbox; however, in JMAP, its id does not change if you move it between mailboxes, and the server may allow it to belong to multiple mailboxes simultaneously (often exposed in a user agent as labels rather than folders). As in IMAP, messages may also be assigned zero or more keywords: short arbitrary strings. These are primarily intended to store metadata to inform client display, such as unread status or whether a message has been replied to. An IANA registry allows common semantics to be shared between clients and extended easily in the future. A message and its replies are linked on the server by a common Thread id. Clients may fetch the list of messages with a particular Thread id to more easily present a threaded or conversational interface. Permissions for message access happen on a per-mailbox basis. Servers may give the user restricted permissions for certain mailboxes, for example, if another user's inbox has been shared as read-only with them.

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.
Top   ToC   RFC8621 - Page 5
   Type signatures, examples, and property descriptions in this document
   follow the conventions established in Section 1.1 of [RFC8620].  Data
   types defined in the core specification are also used in this
   document.

   Servers MUST support all properties specified for the new data types
   defined in this document.

1.2. Terminology

This document uses the same terminology as in the core JMAP specification. The terms Mailbox, Thread, Email, SearchSnippet, EmailSubmission and VacationResponse (with that specific capitalisation) are used to refer to the data types defined in this document and instances of those data types. The term message refers to a document in Internet Message Format, as described in [RFC5322]. The Email data type represents messages in the mail store and associated metadata.

1.3. Additions to the Capabilities Object

The capabilities object is returned as part of the JMAP Session object; see [RFC8620], Section 2. This document defines three additional capability URIs.

1.3.1. urn:ietf:params:jmap:mail

This represents support for the Mailbox, Thread, Email, and SearchSnippet data types and associated API methods. The value of this property in the JMAP session "capabilities" property is an empty object. The value of this property in an account's "accountCapabilities" property is an object that MUST contain the following information on server capabilities and permissions for that account: o maxMailboxesPerEmail: "UnsignedInt|null" The maximum number of Mailboxes (see Section 2) that can be can assigned to a single Email object (see Section 4). This MUST be an integer >= 1, or null for no limit (or rather, the limit is always the number of Mailboxes in the account).
Top   ToC   RFC8621 - Page 6
   o  maxMailboxDepth: "UnsignedInt|null"

      The maximum depth of the Mailbox hierarchy (i.e., one more than
      the maximum number of ancestors a Mailbox may have), or null for
      no limit.

   o  maxSizeMailboxName: "UnsignedInt"

      The maximum length, in (UTF-8) octets, allowed for the name of a
      Mailbox.  This MUST be at least 100, although it is recommended
      servers allow more.

   o  maxSizeAttachmentsPerEmail: "UnsignedInt"

      The maximum total size of attachments, in octets, allowed for a
      single Email object.  A server MAY still reject the import or
      creation of an Email with a lower attachment size total (for
      example, if the body includes several megabytes of text, causing
      the size of the encoded MIME structure to be over some server-
      defined limit).

      Note that this limit is for the sum of unencoded attachment sizes.
      Users are generally not knowledgeable about encoding overhead,
      etc., nor should they need to be, so marketing and help materials
      normally tell them the "max size attachments".  This is the
      unencoded size they see on their hard drive, so this capability
      matches that and allows the client to consistently enforce what
      the user understands as the limit.

      The server may separately have a limit for the total size of the
      message [RFC5322], created by combining the attachments (often
      base64 encoded) with the message headers and bodies.  For example,
      suppose the server advertises "maxSizeAttachmentsPerEmail:
      50000000" (50 MB).  The enforced server limit may be for a message
      size of 70000000 octets.  Even with base64 encoding and a 2 MB
      HTML body, 50 MB attachments would fit under this limit.

   o  emailQuerySortOptions: "String[]"

      A list of all the values the server supports for the "property"
      field of the Comparator object in an "Email/query" sort (see
      Section 4.4.2).  This MAY include properties the client does not
      recognise (for example, custom properties specified in a vendor
      extension).  Clients MUST ignore any unknown properties in the
      list.
Top   ToC   RFC8621 - Page 7
   o  mayCreateTopLevelMailbox: "Boolean"

      If true, the user may create a Mailbox (see Section 2) in this
      account with a null parentId.  (Permission for creating a child of
      an existing Mailbox is given by the "myRights" property on that
      Mailbox.)

1.3.2. urn:ietf:params:jmap:submission

This represents support for the Identity and EmailSubmission data types and associated API methods. The value of this property in the JMAP session "capabilities" property is an empty object. The value of this property in an account's "accountCapabilities" property is an object that MUST contain the following information on server capabilities and permissions for that account: o maxDelayedSend: "UnsignedInt" The number in seconds of the maximum delay the server supports in sending (see the EmailSubmission object description). This is 0 if the server does not support delayed send. o submissionExtensions: "String[String[]]" The set of SMTP submission extensions supported by the server, which the client may use when creating an EmailSubmission object (see Section 7). Each key in the object is the "ehlo-name", and the value is a list of "ehlo-args". A JMAP implementation that talks to a submission server [RFC6409] SHOULD have a configuration setting that allows an administrator to modify the set of submission EHLO capabilities it may expose on this property. This allows a JMAP server to easily add access to a new submission extension without code changes. By default, the JMAP server should hide EHLO capabilities that have to do with the transport mechanism and thus are only relevant to the JMAP server (for example, PIPELINING, CHUNKING, or STARTTLS). Examples of Submission extensions to include: * FUTURERELEASE [RFC4865] * SIZE [RFC1870] * DSN [RFC3461] * DELIVERYBY [RFC2852]
Top   ToC   RFC8621 - Page 8
      *  MT-PRIORITY [RFC6710]

      A JMAP server MAY advertise an extension and implement the
      semantics of that extension locally on the JMAP server even if a
      submission server used by JMAP doesn't implement it.

      The full IANA registry of submission extensions can be found at
      <https://www.iana.org/assignments/mail-parameters>.

1.3.3. urn:ietf:params:jmap:vacationresponse

This represents support for the VacationResponse data type and associated API methods. The value of this property is an empty object in both the JMAP session "capabilities" property and an account's "accountCapabilities" property.

1.4. Data Type Support in Different Accounts

The server MUST include the appropriate capability strings as keys in the "accountCapabilities" property of any account with which the user may use the data types represented by that URI. Supported data types may differ between accounts the user has access to. For example, in the user's personal account, they may have access to all three sets of data, but in a shared account, they may only have data for "urn:ietf:params:jmap:mail". This means they can access Mailbox/Thread/Email data in the shared account but are not allowed to send as that account (and so do not have access to Identity/ EmailSubmission objects) or view/set its VacationResponse.

1.5. Push

Servers MUST support the JMAP push mechanisms, as specified in [RFC8620], Section 7, to receive notifications when the state changes for any of the types defined in this specification. In addition, servers that implement the "urn:ietf:params:jmap:mail" capability MUST support pushing state changes for a type called "EmailDelivery". There are no methods to act on this type; it only exists as part of the push mechanism. The state string for this MUST change whenever a new Email is added to the store, but it SHOULD NOT change upon any other change to the Email objects, for example, if one is marked as read or deleted. Clients in battery-constrained environments may wish to delay fetching changes initiated by the user but fetch new Emails immediately so they can notify the user. To do this, they can register for pushes for the EmailDelivery type rather than the Email type (as defined in Section 4).
Top   ToC   RFC8621 - Page 9

1.5.1. Example

The client has registered for push notifications (see [RFC8620]) just for the EmailDelivery type. The user marks an Email as read on another device, causing the state string for the Email type to change; however, as nothing new was added to the store, the EmailDelivery state does not change and nothing is pushed to the client. A new message arrives in the user's inbox, again causing the Email state to change. This time, the EmailDelivery state also changes, and a StateChange object is pushed to the client with the new state string. The client may then resync to fetch the new Email immediately.

1.6. Ids

If a JMAP Mail server also provides an IMAP interface to the data and supports IMAP Extension for Object Identifiers [RFC8474], the ids SHOULD be the same for Mailbox, Thread, and Email objects in JMAP.

2. Mailboxes

A Mailbox represents a named set of Email objects. This is the primary mechanism for organising messages within an account. It is analogous to a folder or a label in other systems. A Mailbox may perform a certain role in the system; see below for more details. For compatibility with IMAP, an Email MUST belong to one or more Mailboxes. The Email id does not change if the Email changes Mailboxes. A *Mailbox* object has the following properties: o id: "Id" (immutable; server-set) The id of the Mailbox. o name: "String" User-visible name for the Mailbox, e.g., "Inbox". This MUST be a Net-Unicode string [RFC5198] of at least 1 character in length, subject to the maximum size given in the capability object. There MUST NOT be two sibling Mailboxes with both the same parent and the same name. Servers MAY reject names that violate server policy (e.g., names containing a slash (/) or control characters).
Top   ToC   RFC8621 - Page 10
   o  parentId: "Id|null" (default: null)

      The Mailbox id for the parent of this Mailbox, or null if this
      Mailbox is at the top level.  Mailboxes form acyclic graphs
      (forests) directed by the child-to-parent relationship.  There
      MUST NOT be a loop.

   o  role: "String|null" (default: null)

      Identifies Mailboxes that have a particular common purpose (e.g.,
      the "inbox"), regardless of the "name" property (which may be
      localised).

      This value is shared with IMAP (exposed in IMAP via the SPECIAL-
      USE extension [RFC6154]).  However, unlike in IMAP, a Mailbox MUST
      only have a single role, and there MUST NOT be two Mailboxes in
      the same account with the same role.  Servers providing IMAP
      access to the same data are encouraged to enforce these extra
      restrictions in IMAP as well.  Otherwise, modifying the IMAP
      attributes to ensure compliance when exposing the data over JMAP
      is implementation dependent.

      The value MUST be one of the Mailbox attribute names listed in the
      IANA "IMAP Mailbox Name Attributes" registry at
      <https://www.iana.org/assignments/imap-mailbox-name-attributes/>,
      as established in [RFC8457], converted to lowercase.  New roles
      may be established here in the future.

      An account is not required to have Mailboxes with any particular
      roles.

   o  sortOrder: "UnsignedInt" (default: 0)

      Defines the sort order of Mailboxes when presented in the client's
      UI, so it is consistent between devices.  The number MUST be an
      integer in the range 0 <= sortOrder < 2^31.

      A Mailbox with a lower order should be displayed before a Mailbox
      with a higher order (that has the same parent) in any Mailbox
      listing in the client's UI.  Mailboxes with equal order SHOULD be
      sorted in alphabetical order by name.  The sorting should take
      into account locale-specific character order convention.

   o  totalEmails: "UnsignedInt" (server-set)

      The number of Emails in this Mailbox.
Top   ToC   RFC8621 - Page 11
   o  unreadEmails: "UnsignedInt" (server-set)

      The number of Emails in this Mailbox that have neither the "$seen"
      keyword nor the "$draft" keyword.

   o  totalThreads: "UnsignedInt" (server-set)

      The number of Threads where at least one Email in the Thread is in
      this Mailbox.

   o  unreadThreads: "UnsignedInt" (server-set)

      An indication of the number of "unread" Threads in the Mailbox.

      For compatibility with existing implementations, the way "unread
      Threads" is determined is not mandated in this document.  The
      simplest solution to implement is simply the number of Threads
      where at least one Email in the Thread is both in this Mailbox and
      has neither the "$seen" nor "$draft" keywords.

      However, a quality implementation will return the number of unread
      items the user would see if they opened that Mailbox.  A Thread is
      shown as unread if it contains any unread Emails that will be
      displayed when the Thread is opened.  Therefore, "unreadThreads"
      should be the number of Threads where at least one Email in the
      Thread has neither the "$seen" nor the "$draft" keyword AND at
      least one Email in the Thread is in this Mailbox.  Note that the
      unread Email does not need to be the one in this Mailbox.  In
      addition, the trash Mailbox (that is, a Mailbox whose "role" is
      "trash") requires special treatment:

      1.  Emails that are *only* in the trash (and no other Mailbox) are
          ignored when calculating the "unreadThreads" count of other
          Mailboxes.

      2.  Emails that are *not* in the trash are ignored when
          calculating the "unreadThreads" count for the trash Mailbox.

      The result of this is that Emails in the trash are treated as
      though they are in a separate Thread for the purposes of unread
      counts.  It is expected that clients will hide Emails in the trash
      when viewing a Thread in another Mailbox, and vice versa.  This
      allows you to delete a single Email to the trash out of a Thread.

      For example, suppose you have an account where the entire contents
      is a single Thread with 2 Emails: an unread Email in the trash and
      a read Email in the inbox.  The "unreadThreads" count would be 1
      for the trash and 0 for the inbox.
Top   ToC   RFC8621 - Page 12
   o  myRights: "MailboxRights" (server-set)

      The set of rights (Access Control Lists (ACLs)) the user has in
      relation to this Mailbox.  These are backwards compatible with
      IMAP ACLs, as defined in [RFC4314].  A *MailboxRights* object has
      the following properties:

      *  mayReadItems: "Boolean"

         If true, the user may use this Mailbox as part of a filter in
         an "Email/query" call, and the Mailbox may be included in the
         "mailboxIds" property of Email objects.  Email objects may be
         fetched if they are in *at least one* Mailbox with this
         permission.  If a sub-Mailbox is shared but not the parent
         Mailbox, this may be false.  Corresponds to IMAP ACLs "lr" (if
         mapping from IMAP, both are required for this to be true).

      *  mayAddItems: "Boolean"

         The user may add mail to this Mailbox (by either creating a new
         Email or moving an existing one).  Corresponds to IMAP ACL "i".

      *  mayRemoveItems: "Boolean"

         The user may remove mail from this Mailbox (by either changing
         the Mailboxes of an Email or destroying the Email).
         Corresponds to IMAP ACLs "te" (if mapping from IMAP, both are
         required for this to be true).

      *  maySetSeen: "Boolean"

         The user may add or remove the "$seen" keyword to/from an
         Email.  If an Email belongs to multiple Mailboxes, the user may
         only modify "$seen" if they have this permission for *all* of
         the Mailboxes.  Corresponds to IMAP ACL "s".

      *  maySetKeywords: "Boolean"

         The user may add or remove any keyword other than "$seen" to/
         from an Email.  If an Email belongs to multiple Mailboxes, the
         user may only modify keywords if they have this permission for
         *all* of the Mailboxes.  Corresponds to IMAP ACL "w".

      *  mayCreateChild: "Boolean"

         The user may create a Mailbox with this Mailbox as its parent.
         Corresponds to IMAP ACL "k".
Top   ToC   RFC8621 - Page 13
      *  mayRename: "Boolean"

         The user may rename the Mailbox or make it a child of another
         Mailbox.  Corresponds to IMAP ACL "x" (although this covers
         both rename and delete permissions).

      *  mayDelete: "Boolean"

         The user may delete the Mailbox itself.  Corresponds to IMAP
         ACL "x" (although this covers both rename and delete
         permissions).

      *  maySubmit: "Boolean"

         Messages may be submitted directly to this Mailbox.
         Corresponds to IMAP ACL "p".

   o  isSubscribed: "Boolean"

      Has the user indicated they wish to see this Mailbox in their
      client?  This SHOULD default to false for Mailboxes in shared
      accounts the user has access to and true for any new Mailboxes
      created by the user themself.  This MUST be stored separately per
      user where multiple users have access to a shared Mailbox.

      A user may have permission to access a large number of shared
      accounts, or a shared account with a very large set of Mailboxes,
      but only be interested in the contents of a few of these.  Clients
      may choose to only display Mailboxes where the "isSubscribed"
      property is set to true, and offer a separate UI to allow the user
      to see and subscribe/unsubscribe from the full set of Mailboxes.
      However, clients MAY choose to ignore this property, either
      entirely for ease of implementation or just for an account where
      "isPersonal" is true (indicating it is the user's own rather than
      a shared account).

      This property corresponds to IMAP [RFC3501] mailbox subscriptions.

   For IMAP compatibility, an Email in both the trash and another
   Mailbox SHOULD be treated by the client as existing in both places
   (i.e., when emptying the trash, the client should just remove it from
   the trash Mailbox and leave it in the other Mailbox).

   The following JMAP methods are supported.
Top   ToC   RFC8621 - Page 14

2.1. Mailbox/get

This is a standard "/get" method as described in [RFC8620], Section 5.1. The "ids" argument may be "null" to fetch all at once.

2.2. Mailbox/changes

This is a standard "/changes" method as described in [RFC8620], Section 5.2 but with one extra argument to the response: o updatedProperties: "String[]|null" If only the "totalEmails", "unreadEmails", "totalThreads", and/or "unreadThreads" Mailbox properties have changed since the old state, this will be the list of properties that may have changed. If the server is unable to tell if only counts have changed, it MUST just be null. Since counts frequently change but other properties are generally only changed rarely, the server can help the client optimise data transfer by keeping track of changes to Email/Thread counts separate from other state changes. The "updatedProperties" array may be used directly via a back-reference in a subsequent "Mailbox/get" call in the same request, so only these properties are returned if nothing else has changed.

2.3. Mailbox/query

This is a standard "/query" method as described in [RFC8620], Section 5.5 but with the following additional request argument: o sortAsTree: "Boolean" (default: false) If true, when sorting the query results and comparing Mailboxes A and B: * If A is an ancestor of B, it always comes first regardless of the sort comparators. Similarly, if A is descendant of B, then B always comes first. * Otherwise, if A and B do not share a "parentId", find the nearest ancestors of each that do have the same "parentId" and compare the sort properties on those Mailboxes instead. The result of this is that the Mailboxes are sorted as a tree according to the parentId properties, with each set of children with a common parent sorted according to the standard sort comparators.
Top   ToC   RFC8621 - Page 15
   o  filterAsTree: "Boolean" (default: false)

      If true, a Mailbox is only included in the query if all its
      ancestors are also included in the query according to the filter.

   A *FilterCondition* object has the following properties, any of which
   may be omitted:

   o  parentId: "Id|null"

      The Mailbox "parentId" property must match the given value
      exactly.

   o  name: "String"

      The Mailbox "name" property contains the given string.

   o  role: "String|null"

      The Mailbox "role" property must match the given value exactly.

   o  hasAnyRole: "Boolean"

      If true, a Mailbox matches if it has any non-null value for its
      "role" property.

   o  isSubscribed: "Boolean"

      The "isSubscribed" property of the Mailbox must be identical to
      the value given to match the condition.

   A Mailbox object matches the FilterCondition if and only if all of
   the given conditions match.  If zero properties are specified, it is
   automatically true for all objects.

   The following Mailbox properties MUST be supported for sorting:

   o  "sortOrder"

   o  "name"

2.4. Mailbox/queryChanges

This is a standard "/queryChanges" method as described in [RFC8620], Section 5.6.
Top   ToC   RFC8621 - Page 16

2.5. Mailbox/set

This is a standard "/set" method as described in [RFC8620], Section 5.3 but with the following additional request argument: o onDestroyRemoveEmails: "Boolean" (default: false) If false, any attempt to destroy a Mailbox that still has Emails in it will be rejected with a "mailboxHasEmail" SetError. If true, any Emails that were in the Mailbox will be removed from it, and if in no other Mailboxes, they will be destroyed when the Mailbox is destroyed. The following extra SetError types are defined: For "destroy": o "mailboxHasChild": The Mailbox still has at least one child Mailbox. The client MUST remove these before it can delete the parent Mailbox. o "mailboxHasEmail": The Mailbox has at least one Email assigned to it, and the "onDestroyRemoveEmails" argument was false.
Top   ToC   RFC8621 - Page 17

2.6. Example

Fetching all Mailboxes in an account: [[ "Mailbox/get", { "accountId": "u33084183", "ids": null }, "0" ]] And the response: [[ "Mailbox/get", { "accountId": "u33084183", "state": "78540", "list": [{ "id": "MB23cfa8094c0f41e6", "name": "Inbox", "parentId": null, "role": "inbox", "sortOrder": 10, "totalEmails": 16307, "unreadEmails": 13905, "totalThreads": 5833, "unreadThreads": 5128, "myRights": { "mayAddItems": true, "mayRename": false, "maySubmit": true, "mayDelete": false, "maySetKeywords": true, "mayRemoveItems": true, "mayCreateChild": true, "maySetSeen": true, "mayReadItems": true }, "isSubscribed": true }, { "id": "MB674cc24095db49ce", "name": "Important mail", ... }, ... ], "notFound": [] }, "0" ]]
Top   ToC   RFC8621 - Page 18
   Now suppose an Email is marked read, and we get a push update that
   the Mailbox state has changed.  You might fetch the updates like
   this:

                     [[ "Mailbox/changes", {
                       "accountId": "u33084183",
                       "sinceState": "78540"
                     }, "0" ],
                     [ "Mailbox/get", {
                       "accountId": "u33084183",
                       "#ids": {
                         "resultOf": "0",
                         "name": "Mailbox/changes",
                         "path": "/created"
                       }
                     }, "1" ],
                     [ "Mailbox/get", {
                       "accountId": "u33084183",
                       "#ids": {
                         "resultOf": "0",
                         "name": "Mailbox/changes",
                         "path": "/updated"
                       },
                       "#properties": {
                         "resultOf": "0",
                         "name": "Mailbox/changes",
                         "path": "/updatedProperties"
                       }
                     }, "2" ]]
Top   ToC   RFC8621 - Page 19
   This fetches the list of ids for created/updated/destroyed Mailboxes,
   then using back-references, it fetches the data for just the created/
   updated Mailboxes in the same request.  The response may look
   something like this:

                   [[ "Mailbox/changes", {
                     "accountId": "u33084183",
                     "oldState": "78541",
                     "newState": "78542",
                     "hasMoreChanges": false,
                     "updatedProperties": [
                       "totalEmails", "unreadEmails",
                       "totalThreads", "unreadThreads"
                     ],
                     "created": [],
                     "updated": ["MB23cfa8094c0f41e6"],
                     "destroyed": []
                   }, "0" ],
                   [ "Mailbox/get", {
                     "accountId": "u33084183",
                     "state": "78542",
                     "list": [],
                     "notFound": []
                   }, "1" ],
                   [ "Mailbox/get", {
                     "accountId": "u33084183",
                     "state": "78542",
                     "list": [{
                       "id": "MB23cfa8094c0f41e6",
                       "totalEmails": 16307,
                       "unreadEmails": 13903,
                       "totalThreads": 5833,
                       "unreadThreads": 5127
                     }],
                     "notFound": []
                   }, "2" ]]
Top   ToC   RFC8621 - Page 20
   Here's an example where we try to rename one Mailbox and destroy
   another:

                   [[ "Mailbox/set", {
                     "accountId": "u33084183",
                     "ifInState": "78542",
                     "update": {
                       "MB674cc24095db49ce": {
                         "name": "Maybe important mail"
                       }
                     },
                     "destroy": [ "MB23cfa8094c0f41e6" ]
                   }, "0" ]]

   Suppose the rename succeeds, but we don't have permission to destroy
   the Mailbox we tried to destroy; we might get back:

                     [[ "Mailbox/set", {
                       "accountId": "u33084183",
                       "oldState": "78542",
                       "newState": "78549",
                       "updated": {
                           "MB674cc24095db49ce": null
                       },
                       "notDestroyed": {
                         "MB23cfa8094c0f41e6": {
                           "type": "forbidden"
                         }
                       }
                     }, "0" ]]

3. Threads

Replies are grouped together with the original message to form a Thread. In JMAP, a Thread is simply a flat list of Emails, ordered by date. Every Email MUST belong to a Thread, even if it is the only Email in the Thread. The exact algorithm for determining whether two Emails belong to the same Thread is not mandated in this spec to allow for compatibility with different existing systems. For new implementations, it is suggested that two messages belong in the same Thread if both of the following conditions apply: 1. An identical message id [RFC5322] appears in both messages in any of the Message-Id, In-Reply-To, and References header fields.
Top   ToC   RFC8621 - Page 21
   2.  After stripping automatically added prefixes such as "Fwd:",
       "Re:", "[List-Tag]", etc., and ignoring white space, the subjects
       are the same.  This avoids the situation where a person replies
       to an old message as a convenient way of finding the right
       recipient to send to but changes the subject and starts a new
       conversation.

   If messages are delivered out of order for some reason, a user may
   have two Emails in the same Thread but without headers that associate
   them with each other.  The arrival of a third Email may provide the
   missing references to join them all together into a single Thread.
   Since the "threadId" of an Email is immutable, if the server wishes
   to merge the Threads, it MUST handle this by deleting and reinserting
   (with a new Email id) the Emails that change "threadId".

   A *Thread* object has the following properties:

   o  id: "Id" (immutable; server-set)


      The id of the Thread.

   o  emailIds: "Id[]" (server-set)

      The ids of the Emails in the Thread, sorted by the "receivedAt"
      date of the Email, oldest first.  If two Emails have an identical
      date, the sort is server dependent but MUST be stable (sorting by
      id is recommended).

   The following JMAP methods are supported.
Top   ToC   RFC8621 - Page 22

3.1. Thread/get

This is a standard "/get" method as described in [RFC8620], Section 5.1.

3.1.1. Example

Request: [[ "Thread/get", { "accountId": "acme", "ids": ["f123u4", "f41u44"] }, "#1" ]] with response: [[ "Thread/get", { "accountId": "acme", "state": "f6a7e214", "list": [ { "id": "f123u4", "emailIds": [ "eaa623", "f782cbb"] }, { "id": "f41u44", "emailIds": [ "82cf7bb" ] } ], "notFound": [] }, "#1" ]]

3.2. Thread/changes

This is a standard "/changes" method as described in [RFC8620], Section 5.2.


(page 22 continued on part 2)

Next Section