draft-ietf-jmap-mail-07.txt   draft-ietf-jmap-mail-08.txt 
JMAP N. Jenkins JMAP N. Jenkins
Internet-Draft FastMail Internet-Draft FastMail
Updates: 5788 (if approved) C. Newman Updates: 5788 (if approved) C. Newman
Intended status: Standards Track Oracle Intended status: Standards Track Oracle
Expires: February 8, 2019 August 7, 2018 Expires: March 14, 2019 September 10, 2018
JMAP for Mail JMAP for Mail
draft-ietf-jmap-mail-07 draft-ietf-jmap-mail-08
Abstract Abstract
This document specifies a data model for synchronising email data This document specifies a data model for synchronising email data
with a server using JMAP. with a server using JMAP.
Status of This Memo Status of This Memo
This Internet-Draft is submitted in full conformance with the This Internet-Draft is submitted in full conformance with the
provisions of BCP 78 and BCP 79. provisions of BCP 78 and BCP 79.
skipping to change at page 1, line 32 skipping to change at page 1, line 32
Internet-Drafts are working documents of the Internet Engineering Internet-Drafts are working documents of the Internet Engineering
Task Force (IETF). Note that other groups may also distribute Task Force (IETF). Note that other groups may also distribute
working documents as Internet-Drafts. The list of current Internet- working documents as Internet-Drafts. The list of current Internet-
Drafts is at https://datatracker.ietf.org/drafts/current/. Drafts is at https://datatracker.ietf.org/drafts/current/.
Internet-Drafts are draft documents valid for a maximum of six months Internet-Drafts are draft documents valid for a maximum of six months
and may be updated, replaced, or obsoleted by other documents at any and may be updated, replaced, or obsoleted by other documents at any
time. It is inappropriate to use Internet-Drafts as reference time. It is inappropriate to use Internet-Drafts as reference
material or to cite them other than as "work in progress." material or to cite them other than as "work in progress."
This Internet-Draft will expire on February 8, 2019. This Internet-Draft will expire on March 14, 2019.
Copyright Notice Copyright Notice
Copyright (c) 2018 IETF Trust and the persons identified as the Copyright (c) 2018 IETF Trust and the persons identified as the
document authors. All rights reserved. document authors. All rights reserved.
This document is subject to BCP 78 and the IETF Trust's Legal This document is subject to BCP 78 and the IETF Trust's Legal
Provisions Relating to IETF Documents Provisions Relating to IETF Documents
(https://trustee.ietf.org/license-info) in effect on the date of (https://trustee.ietf.org/license-info) in effect on the date of
publication of this document. Please review these documents publication of this document. Please review these documents
skipping to change at page 2, line 12 skipping to change at page 2, line 12
the Trust Legal Provisions and are provided without warranty as the Trust Legal Provisions and are provided without warranty as
described in the Simplified BSD License. described in the Simplified BSD License.
Table of Contents Table of Contents
1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 4 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 4
1.1. Notational conventions . . . . . . . . . . . . . . . . . 4 1.1. Notational conventions . . . . . . . . . . . . . . . . . 4
1.2. Terminology . . . . . . . . . . . . . . . . . . . . . . . 4 1.2. Terminology . . . . . . . . . . . . . . . . . . . . . . . 4
1.3. Additions to the capabilities object . . . . . . . . . . 4 1.3. Additions to the capabilities object . . . . . . . . . . 4
1.3.1. urn:ietf:params:jmap:mail . . . . . . . . . . . . . . 5 1.3.1. urn:ietf:params:jmap:mail . . . . . . . . . . . . . . 5
1.3.2. urn:ietf:params:jmap:submission . . . . . . . . . . . 5 1.3.2. urn:ietf:params:jmap:submission . . . . . . . . . . . 6
1.3.3. urn:ietf:params:jmap:vacationresponse . . . . . . . . 6 1.3.3. urn:ietf:params:jmap:vacationresponse . . . . . . . . 6
1.4. Data type support in different accounts . . . . . . . . . 6 1.4. Data type support in different accounts . . . . . . . . . 7
1.5. Push . . . . . . . . . . . . . . . . . . . . . . . . . . 7 1.5. Push . . . . . . . . . . . . . . . . . . . . . . . . . . 7
2. Mailboxes . . . . . . . . . . . . . . . . . . . . . . . . . . 7 2. Mailboxes . . . . . . . . . . . . . . . . . . . . . . . . . . 7
2.1. Mailbox/get . . . . . . . . . . . . . . . . . . . . . . . 10 2.1. Mailbox/get . . . . . . . . . . . . . . . . . . . . . . . 11
2.2. Mailbox/changes . . . . . . . . . . . . . . . . . . . . . 10 2.2. Mailbox/changes . . . . . . . . . . . . . . . . . . . . . 11
2.3. Mailbox/query . . . . . . . . . . . . . . . . . . . . . . 11 2.3. Mailbox/query . . . . . . . . . . . . . . . . . . . . . . 11
2.4. Mailbox/queryChanges . . . . . . . . . . . . . . . . . . 11 2.4. Mailbox/queryChanges . . . . . . . . . . . . . . . . . . 12
2.5. Mailbox/set . . . . . . . . . . . . . . . . . . . . . . . 12 2.5. Mailbox/set . . . . . . . . . . . . . . . . . . . . . . . 12
2.6. Example . . . . . . . . . . . . . . . . . . . . . . . . . 12 2.6. Example . . . . . . . . . . . . . . . . . . . . . . . . . 12
3. Threads . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 3. Threads . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
3.1. Thread/get . . . . . . . . . . . . . . . . . . . . . . . 17 3.1. Thread/get . . . . . . . . . . . . . . . . . . . . . . . 17
3.1.1. Example . . . . . . . . . . . . . . . . . . . . . . . 17 3.1.1. Example . . . . . . . . . . . . . . . . . . . . . . . 17
3.2. Thread/changes . . . . . . . . . . . . . . . . . . . . . 18 3.2. Thread/changes . . . . . . . . . . . . . . . . . . . . . 18
4. Emails . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 4. Emails . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
4.1. Properties of the Email object . . . . . . . . . . . . . 18 4.1. Properties of the Email object . . . . . . . . . . . . . 18
4.1.1. Metadata . . . . . . . . . . . . . . . . . . . . . . 19 4.1.1. Metadata . . . . . . . . . . . . . . . . . . . . . . 19
4.1.2. Header fields parsed forms . . . . . . . . . . . . . 21 4.1.2. Header fields parsed forms . . . . . . . . . . . . . 21
skipping to change at page 3, line 30 skipping to change at page 3, line 30
10. IANA considerations . . . . . . . . . . . . . . . . . . . . . 75 10. IANA considerations . . . . . . . . . . . . . . . . . . . . . 75
10.1. JMAP capability registration for "mail" . . . . . . . . 75 10.1. JMAP capability registration for "mail" . . . . . . . . 75
10.2. JMAP capability registration for "submission" . . . . . 76 10.2. JMAP capability registration for "submission" . . . . . 76
10.3. JMAP capability registration for "vacationresponse" . . 76 10.3. JMAP capability registration for "vacationresponse" . . 76
10.4. IMAP and JMAP keywords registry . . . . . . . . . . . . 76 10.4. IMAP and JMAP keywords registry . . . . . . . . . . . . 76
10.4.1. Registration of JMAP keyword '$draft' . . . . . . . 77 10.4.1. Registration of JMAP keyword '$draft' . . . . . . . 77
10.4.2. Registration of JMAP keyword '$seen' . . . . . . . . 78 10.4.2. Registration of JMAP keyword '$seen' . . . . . . . . 78
10.4.3. Registration of JMAP keyword '$flagged' . . . . . . 79 10.4.3. Registration of JMAP keyword '$flagged' . . . . . . 79
10.4.4. Registration of JMAP keyword '$answered' . . . . . . 79 10.4.4. Registration of JMAP keyword '$answered' . . . . . . 79
10.4.5. Registration of '$recent' keyword . . . . . . . . . 80 10.4.5. Registration of '$recent' keyword . . . . . . . . . 80
10.5. JMAP Error Codes registry . . . . . . . . . . . . . . . 81 10.5. Registration of "inbox" role in . . . . . . . . . . . . 81
10.5.1. mailboxHasChild . . . . . . . . . . . . . . . . . . 81 10.6. JMAP Error Codes registry . . . . . . . . . . . . . . . 81
10.5.2. mailboxHasEmail . . . . . . . . . . . . . . . . . . 81 10.6.1. mailboxHasChild . . . . . . . . . . . . . . . . . . 81
10.5.3. blobNotFound . . . . . . . . . . . . . . . . . . . . 81 10.6.2. mailboxHasEmail . . . . . . . . . . . . . . . . . . 81
10.5.4. tooManyKeywords . . . . . . . . . . . . . . . . . . 81 10.6.3. blobNotFound . . . . . . . . . . . . . . . . . . . . 82
10.5.5. tooManyMailboxes . . . . . . . . . . . . . . . . . . 82 10.6.4. tooManyKeywords . . . . . . . . . . . . . . . . . . 82
10.5.6. emailNotFound . . . . . . . . . . . . . . . . . . . 82 10.6.5. tooManyMailboxes . . . . . . . . . . . . . . . . . . 82
10.5.7. emailTooLarge . . . . . . . . . . . . . . . . . . . 82 10.6.6. emailNotFound . . . . . . . . . . . . . . . . . . . 82
10.5.8. invalidEmail . . . . . . . . . . . . . . . . . . . . 82 10.6.7. emailTooLarge . . . . . . . . . . . . . . . . . . . 82
10.5.9. tooManyRecipients . . . . . . . . . . . . . . . . . 83 10.6.8. invalidEmail . . . . . . . . . . . . . . . . . . . . 83
10.5.10. noRecipients . . . . . . . . . . . . . . . . . . . . 83 10.6.9. tooManyRecipients . . . . . . . . . . . . . . . . . 83
10.5.11. invalidRecipients . . . . . . . . . . . . . . . . . 83 10.6.10. noRecipients . . . . . . . . . . . . . . . . . . . . 83
10.5.12. forbiddenMailFrom . . . . . . . . . . . . . . . . . 83 10.6.11. invalidRecipients . . . . . . . . . . . . . . . . . 83
10.5.13. forbiddenFrom . . . . . . . . . . . . . . . . . . . 83 10.6.12. forbiddenMailFrom . . . . . . . . . . . . . . . . . 83
10.5.14. forbiddenToSend . . . . . . . . . . . . . . . . . . 84 10.6.13. forbiddenFrom . . . . . . . . . . . . . . . . . . . 84
10.6.14. forbiddenToSend . . . . . . . . . . . . . . . . . . 84
11. References . . . . . . . . . . . . . . . . . . . . . . . . . 84 11. References . . . . . . . . . . . . . . . . . . . . . . . . . 84
11.1. Normative References . . . . . . . . . . . . . . . . . . 84 11.1. Normative References . . . . . . . . . . . . . . . . . . 84
11.2. URIs . . . . . . . . . . . . . . . . . . . . . . . . . . 87 11.2. URIs . . . . . . . . . . . . . . . . . . . . . . . . . . 87
Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . 87 Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . 87
1. Introduction 1. Introduction
JMAP <https://tools.ietf.org/html/draft-ietf-jmap-core-05> is a JMAP <https://tools.ietf.org/html/draft-ietf-jmap-core-05> is a
generic protocol for synchronising data, such as mail, calendars or generic protocol for synchronising data, such as mail, calendars or
contacts, between a client and a server. It is optimised for mobile contacts, between a client and a server. It is optimised for mobile
skipping to change at page 5, line 19 skipping to change at page 5, line 19
This represents support for the Mailbox, Thread, Email, and This represents support for the Mailbox, Thread, Email, and
SearchSnippet data types and associated API methods. The value of SearchSnippet data types and associated API methods. The value of
this property is an object which MUST contain the following this property is an object which MUST contain the following
information on server capabilities: information on server capabilities:
o *maxMailboxesPerEmail*: "PositiveInt|null" The maximum number of o *maxMailboxesPerEmail*: "PositiveInt|null" The maximum number of
mailboxes that can be can assigned to a single email. This MUST mailboxes that can be can assigned to a single email. This MUST
be an integer >= 1, or "null" for no limit (or rather, the limit be an integer >= 1, or "null" for no limit (or rather, the limit
is always the number of mailboxes in the account). is always the number of mailboxes in the account).
o *maxMailboxDepth*: "PositiveInt|null" The maximum depth of the
mailbox hierarchy (i.e. one less than the maximum number of
ancestors a mailbox may have), or "null" for no limit.
o *maxSizeMailboxName*: "PositiveInt" The maximum length, in (UTF-8)
octets, allowed for the name of a mailbox. This MUST be >= 255.
o *maxSizeAttachmentsPerEmail*: "PositiveInt" The maximum total size o *maxSizeAttachmentsPerEmail*: "PositiveInt" The maximum total size
of attachments, in octets, allowed for a single email. A server of attachments, in octets, allowed for a single email. A server
MAY still reject import or creation of emails with a lower MAY still reject import or creation of emails with a lower
attachment size total (for example, if the body includes several attachment size total (for example, if the body includes several
megabytes of text, causing the size of the encoded MIME structure megabytes of text, causing the size of the encoded MIME structure
to be over some server-defined limit). Note, this limit is for to be over some server-defined limit). Note, this limit is for
the sum of unencoded attachment sizes. Users are generally not the sum of unencoded attachment sizes. Users are generally not
knowledgeable about encoding overhead etc., nor should they need knowledgeable about encoding overhead etc., nor should they need
to be, so services marketing and help materials normally tells to be, so services marketing and help materials normally tells
them the "max size attachments". This is the unencoded size they them the "max size attachments". This is the unencoded size they
skipping to change at page 7, line 41 skipping to change at page 7, line 50
For compatibility with IMAP, an email MUST belong to one or more For compatibility with IMAP, an email MUST belong to one or more
mailboxes. The email id does not change if the email changes mailboxes. The email id does not change if the email changes
mailboxes. mailboxes.
A *Mailbox* object has the following properties: A *Mailbox* object has the following properties:
o *id*: "String" (immutable; server-set) The id of the mailbox. o *id*: "String" (immutable; server-set) The id of the mailbox.
o *name*: "String" User-visible name for the mailbox, e.g. "Inbox". o *name*: "String" User-visible name for the mailbox, e.g. "Inbox".
This may be any Net-Unicode string ([RFC5198]) of at least 1 This may be any Net-Unicode string ([RFC5198]) of at least 1
character in length and maximum 255 octets in size. Servers MUST character in length, subject to the maximum size given in the
forbid sibling Mailboxes with the same name. Servers MAY reject capability object. Servers MUST forbid sibling Mailboxes with the
names that violate server policy (e.g., names containing slash (/) same name. Servers MAY reject names that violate server policy
or control characters). (e.g., names containing slash (/) or control characters).
o *parentId*: "String|null" (default: null) The mailbox id for the o *parentId*: "String|null" (default: null) The mailbox id for the
parent of this mailbox, or "null" if this mailbox is at the top parent of this mailbox, or "null" if this mailbox is at the top
level. Mailboxes form acyclic graphs (forests) directed by the level. Mailboxes form acyclic graphs (forests) directed by the
child-to-parent relationship. There MUST NOT be a loop. child-to-parent relationship. There MUST NOT be a loop.
o *role*: "String|null" (default: null) Identifies mailboxes that o *role*: "String|null" (default: null) Identifies mailboxes that
have a particular common purpose (e.g. the "inbox"), regardless of have a particular common purpose (e.g. the "inbox"), regardless of
the _name_ (which may be localised). This value is shared with the _name_ (which may be localised). This value is shared with
IMAP (exposed in IMAP via the [RFC6154] SPECIAL-USE extension). IMAP (exposed in IMAP via the [RFC6154] SPECIAL-USE extension).
However, unlike in IMAP, a mailbox may only have a single role, However, unlike in IMAP, a mailbox may only have a single role,
and no two mailboxes in the same account may have the same role. and no two mailboxes in the same account may have the same role.
The value MUST be one of the mailbox attribute names listed in the The value MUST be one of the mailbox attribute names listed in the
IANA Mailbox Name Attributes Registry [1], as established in IANA IMAP Mailbox Name Attributes Registry [1], as established in
[TODO:being established in EXTRA], converted to lower-case. New [RFC8457], converted to lower-case. New roles may be established
roles may be established here in the future. An account is not here in the future. An account is not required to have mailboxes
required to have mailboxes with any particular roles. with any particular roles.
o *sortOrder*: "PositiveInt" (default: 0) Defines the sort order of o *sortOrder*: "PositiveInt" (default: 0) Defines the sort order of
mailboxes when presented in the client's UI, so it is consistent mailboxes when presented in the client's UI, so it is consistent
between devices. The number MUST be an integer in the range 0 <= between devices. The number MUST be an integer in the range 0 <=
sortOrder < 2^31. A mailbox with a lower order should be sortOrder < 2^31. A mailbox with a lower order should be
displayed before a mailbox with a higher order (that has the same displayed before a mailbox with a higher order (that has the same
parent) in any mailbox listing in the client's UI. Mailboxes with parent) in any mailbox listing in the client's UI. Mailboxes with
equal order SHOULD be sorted in alphabetical order by name. The equal order SHOULD be sorted in alphabetical order by name. The
sorting SHOULD take into account locale-specific character order sorting SHOULD take into account locale-specific character order
convention. convention.
skipping to change at page 8, line 37 skipping to change at page 8, line 44
o *totalEmails*: "PositiveInt" (server-set) The number of emails in o *totalEmails*: "PositiveInt" (server-set) The number of emails in
this mailbox. this mailbox.
o *unreadEmails*: "PositiveInt" (server-set) The number of emails in o *unreadEmails*: "PositiveInt" (server-set) The number of emails in
this mailbox that have neither the "$seen" keyword nor the this mailbox that have neither the "$seen" keyword nor the
"$draft" keyword. "$draft" keyword.
o *totalThreads*: "PositiveInt" (server-set) The number of threads o *totalThreads*: "PositiveInt" (server-set) The number of threads
where at least one email in the thread is in this mailbox. where at least one email in the thread is in this mailbox.
o *unreadThreads*: "PositiveInt" (server-set) The number of threads o *unreadThreads*: "PositiveInt" (server-set) An indication of the
where at least one email in the thread has neither the "$seen" number of "unread" threads in the mailbox. This may be presented
keyword nor the "$draft" keyword AND at least one email in the by the client as a badge or marker associated with the mailbox.
thread is in this mailbox (but see below for special case handling For compatibility with existing implementations, the way "unread
of Trash). Note, the unread email does not need to be the one in threads" is determined is not mandated in this document. The
this mailbox. 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 make 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 messages 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, 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") is
treated specially:
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.
So 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.
o *myRights*: "MailboxRights" (server-set) The set of rights (ACLs) o *myRights*: "MailboxRights" (server-set) The set of rights (ACLs)
the user has in relation to this mailbox. A _MailboxRights_ the user has in relation to this mailbox. A _MailboxRights_
object has the following properties: object has the following properties:
* *mayReadItems*: "Boolean" If true, the user may use this * *mayReadItems*: "Boolean" If true, the user may use this
mailbox as part of a filter in a _Email/query_ call and the mailbox as part of a filter in a _Email/query_ call and the
mailbox may be included in the _mailboxIds_ set of _Email_ mailbox may be included in the _mailboxIds_ set of _Email_
objects. If a sub-mailbox is shared but not the parent objects. If a sub-mailbox is shared but not the parent
mailbox, this may be "false". Corresponds to IMAP ACLs "lr". mailbox, this may be "false". Corresponds to IMAP ACLs "lr".
skipping to change at page 10, line 5 skipping to change at page 10, line 41
number of shared accounts, or a shared account with a very 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 set of mailboxes, but only be interested in the contents of a few
of these. Clients may choose only to display mailboxes to the of these. Clients may choose only to display mailboxes to the
user that have the "isSubscribed" property set to "true", and user that have the "isSubscribed" property set to "true", and
offer a separate UI to allow the user to see and subscribe/ offer a separate UI to allow the user to see and subscribe/
unsubscribe from the full set of mailboxes. However, clients MAY unsubscribe from the full set of mailboxes. However, clients MAY
choose to ignore this property, either entirely, for ease of choose to ignore this property, either entirely, for ease of
implementation, or just for the primary account (which is normally implementation, or just for the primary account (which is normally
the user's own, rather than a shared account). the user's own, rather than a shared account).
The Trash mailbox (that is a mailbox with "role == "trash"") MUST be
treated specially for the purpose of unread counts:
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.
So for example, suppose you have an account where the entire contents
is a single conversation 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.
For IMAP compatibility, an email in both the Trash and another For IMAP compatibility, an email in both the Trash and another
mailbox SHOULD be treated by the client as existing in both places mailbox SHOULD be treated by the client as existing in both places
(i.e. when emptying the trash, the client SHOULD just remove the (i.e. when emptying the trash, the client SHOULD just remove the
Trash mailbox and leave it in the other mailbox). Trash mailbox and leave it in the other mailbox).
The following JMAP methods are supported: The following JMAP methods are supported:
2.1. Mailbox/get 2.1. Mailbox/get
Standard "/get" method. The _ids_ argument may be "null" to fetch Standard "/get" method. The _ids_ argument may be "null" to fetch
skipping to change at page 17, line 27 skipping to change at page 17, line 27
3.1. Thread/get 3.1. Thread/get
Standard "/get" method. Standard "/get" method.
3.1.1. Example 3.1.1. Example
Request: Request:
[[ "Thread/get", { [[ "Thread/get", {
"accountId": "acme",
"ids": ["f123u4", "f41u44"], "ids": ["f123u4", "f41u44"],
}, "#1" ]] }, "#1" ]]
with response: with response:
[[ "Thread/get", { [[ "Thread/get", {
"accountId": "acme", "accountId": "acme",
"state": "f6a7e214", "state": "f6a7e214",
"list": [ "list": [
{ {
skipping to change at page 43, line 4 skipping to change at page 43, line 4
Standard "/set" method. The _Email/set_ method encompasses: Standard "/set" method. The _Email/set_ method encompasses:
o Creating a draft o Creating a draft
o Changing the keywords of an email (e.g. unread/flagged status) o Changing the keywords of an email (e.g. unread/flagged status)
o Adding/removing an email to/from mailboxes (moving a message) o Adding/removing an email to/from mailboxes (moving a message)
o Deleting emails o Deleting emails
The format of the keywords/mailboxIds properties means that when
updating an email you can either replace the entire set of keywords/
mailboxes (by setting the full value of the property) or add/remove
individual ones using the JMAP patch syntax (see RFC XXXX, section
5.3 for the specification and section 5.7 for an example).
Due to the format of the Email object, when creating an email there Due to the format of the Email object, when creating an email there
are a number of ways to specify the same information. To ensure that are a number of ways to specify the same information. To ensure that
the RFC5322 email to create is unambiguous, the following constraints the RFC5322 email to create is unambiguous, the following constraints
apply to Email objects submitted for creation: apply to Email objects submitted for creation:
o The _headers_ property MUST NOT be given, on either the top-level o The _headers_ property MUST NOT be given, on either the top-level
email or an EmailBodyPart - the client must set each header field email or an EmailBodyPart - the client must set each header field
as an individual property. as an individual property.
o There MUST NOT be two properties that represent the same header o There MUST NOT be two properties that represent the same header
skipping to change at page 45, line 16 skipping to change at page 45, line 21
exceed a server-defined maximum. exceed a server-defined maximum.
4.7. Email/copy 4.7. Email/copy
Standard "/copy" method, except only the _mailboxIds_, _keywords_ and Standard "/copy" method, except only the _mailboxIds_, _keywords_ and
_receivedAt_ properties may be set during the copy. This method _receivedAt_ properties may be set during the copy. This method
cannot modify the RFC5322 representation of an email. cannot modify the RFC5322 representation of an email.
The server MAY forbid two email objects with the same exact [RFC5322] The server MAY forbid two email objects with the same exact [RFC5322]
content, or even just with the same [RFC5322] Message-ID, to coexist content, or even just with the same [RFC5322] Message-ID, to coexist
within an account. If duplicates are allowed though, the "from" within an account; if the target account already has the email the
account may be the same as the "to" account to copy emails within an copy will be rejected with a standard "alreadyExists" error.
account.
For successfully copied Email objects, the _created_ response For successfully copied Email objects, the _created_ response
contains the _id_, _blobId_, _threadId_ and _size_ properties of the contains the _id_, _blobId_, _threadId_ and _size_ properties of the
new object. new object.
4.8. Email/import 4.8. Email/import
The _Email/import_ method adds [RFC5322] messages to a user's set of The _Email/import_ method adds [RFC5322] messages to a user's set of
emails. The messages must first be uploaded as a file using the emails. The messages must first be uploaded as a file using the
standard upload mechanism. It takes the following arguments: standard upload mechanism. It takes the following arguments:
o *accountId*: "String|null" The id of the account to use for this o *accountId*: "String" The id of the account to use.
call. If "null", defaults to the "urn:ietf:params:jmap:mail"
primary account.
o *emails*: "String[EmailImport]" A map of creation id (client o *emails*: "String[EmailImport]" A map of creation id (client
specified) to EmailImport objects specified) to EmailImport objects
An *EmailImport* object has the following properties: An *EmailImport* object has the following properties:
o *blobId*: "String" The id of the blob containing the raw [RFC5322] o *blobId*: "String" The id of the blob containing the raw [RFC5322]
message. message.
o *mailboxIds*: "String[Boolean]" The ids of the mailboxes to assign o *mailboxIds*: "String[Boolean]" The ids of the mailboxes to assign
skipping to change at page 46, line 11 skipping to change at page 46, line 14
Each email to import is considered an atomic unit which may succeed Each email to import is considered an atomic unit which may succeed
or fail individually. Importing successfully creates a new email or fail individually. Importing successfully creates a new email
object from the data referenced by the blobId and applies the given object from the data referenced by the blobId and applies the given
mailboxes, keywords and receivedAt date. mailboxes, keywords and receivedAt date.
The server MAY forbid two email objects with the same exact [RFC5322] The server MAY forbid two email objects with the same exact [RFC5322]
content, or even just with the same [RFC5322] Message-ID, to coexist content, or even just with the same [RFC5322] Message-ID, to coexist
within an account. In this case, it MUST reject attempts to import within an account. In this case, it MUST reject attempts to import
an email considered a duplicate with an "alreadyExists" SetError. An an email considered a duplicate with an "alreadyExists" SetError. An
_emailId_ property of type "String" MUST be included on the error _existingId_ property of type "String" MUST be included on the error
object with the id of the existing email. object with the id of the existing email. If duplicates are allowed,
the newly created Email object MUST have a separate id and
independent mutable properties to the existing object.
If the _blobId_, _mailboxIds_, or _keywords_ properties are invalid If the _blobId_, _mailboxIds_, or _keywords_ properties are invalid
(e.g. missing, wrong type, id not found), the server MUST reject the (e.g. missing, wrong type, id not found), the server MUST reject the
import with an "invalidProperties" SetError. import with an "invalidProperties" SetError.
If the email cannot be imported because it would take the account If the email cannot be imported because it would take the account
over quota, the import should be rejected with a "overQuota" over quota, the import should be rejected with an "overQuota"
SetError. SetError.
If the blob referenced is not a valid [RFC5322] message, the server If the blob referenced is not a valid [RFC5322] message, the server
MAY modify the message to fix errors (such as removing NUL octets or MAY modify the message to fix errors (such as removing NUL octets or
fixing invalid headers). If it does this, the _blobId_ on the fixing invalid headers). If it does this, the _blobId_ on the
response MUST represent the new representation and therefore be response MUST represent the new representation and therefore be
different to the _blobId_ on the EmailImport object. Alternatively, different to the _blobId_ on the EmailImport object. Alternatively,
the server MAY reject the import with an "invalidEmail" SetError. the server MAY reject the import with an "invalidEmail" SetError.
The response has the following arguments: The response has the following arguments:
skipping to change at page 47, line 16 skipping to change at page 47, line 22
o keywords o keywords
o receivedAt o receivedAt
The _threadId_ property of the Email MAY be present if the server can The _threadId_ property of the Email MAY be present if the server can
calculate which thread the Email would be assigned to were it to be calculate which thread the Email would be assigned to were it to be
imported. Otherwise, this too is "null" if fetched. imported. Otherwise, this too is "null" if fetched.
The _Email/parse_ method takes the following arguments: The _Email/parse_ method takes the following arguments:
o *accountId*: "String|null" The id of the Account to use. If o *accountId*: "String" The id of the account to use.
"null", the primary account is used.
o *blobIds*: "String[]" The ids of the blobs to parse. o *blobIds*: "String[]" The ids of the blobs to parse.
o *properties*: "String[]" If supplied, only the properties listed o *properties*: "String[]" If supplied, only the properties listed
in the array are returned for each Email object. If omitted, in the array are returned for each Email object. If omitted,
defaults to: [ "messageId", "inReplyTo", "references", "sender", defaults to: [ "messageId", "inReplyTo", "references", "sender",
"from", "to", "cc", "bcc", "replyTo", "subject", "sentAt", "from", "to", "cc", "bcc", "replyTo", "subject", "sentAt",
"hasAttachment", "preview", "bodyValues", "textBody", "htmlBody", "hasAttachment", "preview", "bodyValues", "textBody", "htmlBody",
"attachments" ] "attachments" ]
skipping to change at page 57, line 15 skipping to change at page 57, line 15
Note, unlike most data types, a SearchSnippet DOES NOT have a Note, unlike most data types, a SearchSnippet DOES NOT have a
property called "id". property called "id".
The following JMAP method is supported: The following JMAP method is supported:
5.1. SearchSnippet/get 5.1. SearchSnippet/get
To fetch search snippets, make a call to "SearchSnippet/get". It To fetch search snippets, make a call to "SearchSnippet/get". It
takes the following arguments: takes the following arguments:
o *accountId*: "String|null" The id of the account to use for this o *accountId*: "String" The id of the account to use.
call. If "null", defaults to the "urn:ietf:params:jmap:mail"
primary account.
o *filter*: "FilterOperator|FilterCondition|null" The same filter as o *filter*: "FilterOperator|FilterCondition|null" The same filter as
passed to Email/query; see the description of this method for passed to Email/query; see the description of this method for
details. details.
o *emailIds*: "String[]" The list of ids of emails to fetch the o *emailIds*: "String[]" The list of ids of emails to fetch the
snippets for. snippets for.
The response has the following arguments: The response has the following arguments:
skipping to change at page 60, line 30 skipping to change at page 60, line 30
For *create*: For *create*:
o "forbiddenFrom": The user is not allowed to send from the address o "forbiddenFrom": The user is not allowed to send from the address
given as the _email_ property of the identity. given as the _email_ property of the identity.
6.4. Example 6.4. Example
Request: Request:
[ "Identity/get", {}, "0" ] [ "Identity/get", {
"accountId": "acme",
}, "0" ]
with response: with response:
[ "Identity/get", { [ "Identity/get", {
"accountId": "acme", "accountId": "acme",
"state": "99401312ae-11-333", "state": "99401312ae-11-333",
"list": [ "list": [
{ {
"id": "3301-222-11_22AAz", "id": "3301-222-11_22AAz",
"name": "Joe Bloggs", "name": "Joe Bloggs",
skipping to change at page 68, line 5 skipping to change at page 68, line 5
EmailSubmission object is created, this MUST NOT change the behaviour EmailSubmission object is created, this MUST NOT change the behaviour
of the email submission (i.e. it does not cancel a future send). of the email submission (i.e. it does not cancel a future send).
Similarly, destroying a EmailSubmission object MUST NOT affect the Similarly, destroying a EmailSubmission object MUST NOT affect the
deliveries it represents. It purely removes the record of the email deliveries it represents. It purely removes the record of the email
submission. The server MAY automatically destroy EmailSubmission submission. The server MAY automatically destroy EmailSubmission
objects after a certain time or in response to other triggers, and objects after a certain time or in response to other triggers, and
MAY forbid the client from manually destroying EmailSubmission MAY forbid the client from manually destroying EmailSubmission
objects. objects.
The following extra _SetError_ types are defined: If the email to be sent is larger than the server supports sending, a
standard "tooLarge" SetError MUST be returned. A _maxSize_
"PositiveInt" property MUST be present on the SetError specifying the
maximum size of an email that may be sent, in octets.
For *create*: If the email or identity id given cannot be found, the submission
creation is rejected with a standard "invalidProperties" SetError.
o "emailNotFound" - The _emailId_ is not a valid id for an email in The following extra _SetError_ types are defined:
the account.
o "emailTooLarge" - The email size is larger than the server For *create*:
supports sending. A _maxSize_ "PositiveInt" property MUST be
present on the SetError specifying the maximum size of an email
that may be sent, in octets.
o "invalidEmail" - The email to be sent is invalid in some way. The o "invalidEmail" - The email to be sent is invalid in some way. The
SetError SHOULD contain a property called _properties_ of type SetError SHOULD contain a property called _properties_ of type
"String[]" that lists *all* the properties of the email that were "String[]" that lists *all* the properties of the email that were
invalid. invalid.
o "tooManyRecipients" - The envelope (supplied or generated) has o "tooManyRecipients" - The envelope (supplied or generated) has
more recipients than the server allows. A _maxRecipients_ more recipients than the server allows. A _maxRecipients_
"PositiveInt" property MUST also be present on the SetError "PositiveInt" property MUST also be present on the SetError
specifying the maximum number of allowed recipients. specifying the maximum number of allowed recipients.
skipping to change at page 70, line 21 skipping to change at page 70, line 21
"id": "3bab7f9a-623e-4acf-99a5-2e67facb02a0" "id": "3bab7f9a-623e-4acf-99a5-2e67facb02a0"
} }
}, },
"notCreated": null, "notCreated": null,
"updated": null, "updated": null,
"notUpdated": null, "notUpdated": null,
"destroyed": null, "destroyed": null,
"notDestroyed": null "notDestroyed": null
}, "0" ], }, "0" ],
[ "Email/set", { [ "Email/set", {
"accountId": "neilj@fastmail.fm", "accountId": "ue411d190",
"oldState": "778193", "oldState": "778193",
"newState": "778197", "newState": "778197",
"created": null, "created": null,
"notCreated": null, "notCreated": null,
"updated": { "updated": {
"M7f6ed5bcfd7e2604d1753f6c": null "M7f6ed5bcfd7e2604d1753f6c": null
}, },
"notUpdated": null, "notUpdated": null,
"destroyed": null, "destroyed": null,
"notDestroyed": null "notDestroyed": null
skipping to change at page 72, line 18 skipping to change at page 72, line 18
There MUST only be exactly one VacationResponse object in an account. There MUST only be exactly one VacationResponse object in an account.
It MUST have the id "singleton". It MUST have the id "singleton".
8.2. VacationResponse/set 8.2. VacationResponse/set
Standard "/set" method. Standard "/set" method.
9. Security considerations 9. Security considerations
All security considerations of JMAP {TODO: insert RFC ref} apply to All security considerations of JMAP (RFC XXXX) apply to this
this specification. specification.
9.1. EmailBodyPart value 9.1. EmailBodyPart value
Service providers typically perform security filtering on incoming Service providers typically perform security filtering on incoming
email and it's important the detection of content-type and charset email and it's important the detection of content-type and charset
for the security filter aligns with the heuristics performed by JMAP for the security filter aligns with the heuristics performed by JMAP
servers. Servers that apply heuristics to determine the content-type servers. Servers that apply heuristics to determine the content-type
or charset for _EmailBodyValue_ SHOULD document the heuristics and or charset for _EmailBodyValue_ SHOULD document the heuristics and
provide a mechanism to turn them off in the event they are misaligned provide a mechanism to turn them off in the event they are misaligned
with the security filter used at a particular mailbox host. with the security filter used at a particular mailbox host.
skipping to change at page 81, line 12 skipping to change at page 81, line 12
Purpose (description): This keyword is not used to avoid confusion Purpose (description): This keyword is not used to avoid confusion
with the IMAP \Recent system flag. with the IMAP \Recent system flag.
Published specification (recommended): this document Published specification (recommended): this document
Person & email address to contact for further information: (editor- Person & email address to contact for further information: (editor-
contact-goes-here) contact-goes-here)
Owner/Change controller: IESG Owner/Change controller: IESG
10.5. JMAP Error Codes registry 10.5. Registration of "inbox" role in
This registers the JMAP-only "inbox" attribute in the "IMAP Mailbox
Name Attributes Registry", as established in [RFC8457].
Attribute Name: Inbox
Description: New mail is delivered here by default.
Reference: This document, section 10.5.
Usage Notes: JMAP only
10.6. JMAP Error Codes registry
The following sub-sections register several new error codes in the The following sub-sections register several new error codes in the
JMAP Error Codes registry, as defined in RFC XXXX. JMAP Error Codes registry, as defined in RFC XXXX.
10.5.1. mailboxHasChild 10.6.1. mailboxHasChild
JMAP Error Code: mailboxHasChild JMAP Error Code: mailboxHasChild
Intended use: common Intended use: common
Change controller: IETF Change controller: IETF
Reference: This document, section 2.5 Reference: This document, section 2.5
10.5.2. mailboxHasEmail 10.6.2. mailboxHasEmail
JMAP Error Code: mailboxHasEmail JMAP Error Code: mailboxHasEmail
Intended use: common Intended use: common
Change controller: IETF Change controller: IETF
Reference: This document, section 2.5 Reference: This document, section 2.5
10.5.3. blobNotFound 10.6.3. blobNotFound
JMAP Error Code: blobNotFound JMAP Error Code: blobNotFound
Intended use: common Intended use: common
Change controller: IETF Change controller: IETF
Reference: This document, section 4.6 Reference: This document, section 4.6
10.5.4. tooManyKeywords 10.6.4. tooManyKeywords
JMAP Error Code: tooManyKeywords JMAP Error Code: tooManyKeywords
Intended use: common Intended use: common
Change controller: IETF Change controller: IETF
Reference: This document, section 4.6 Reference: This document, section 4.6
10.5.5. tooManyMailboxes 10.6.5. tooManyMailboxes
JMAP Error Code: tooManyMailboxes JMAP Error Code: tooManyMailboxes
Intended use: common Intended use: common
Change controller: IETF Change controller: IETF
Reference: This document, section 4.6 Reference: This document, section 4.6
10.5.6. emailNotFound 10.6.6. emailNotFound
JMAP Error Code: emailNotFound JMAP Error Code: emailNotFound
Intended use: common Intended use: common
Change controller: IETF Change controller: IETF
Reference: This document, section 7.5 Reference: This document, section 7.5
10.5.7. emailTooLarge 10.6.7. emailTooLarge
JMAP Error Code: emailTooLarge JMAP Error Code: emailTooLarge
Intended use: common Intended use: common
Change controller: IETF Change controller: IETF
Reference: This document, section 7.5 Reference: This document, section 7.5
10.5.8. invalidEmail 10.6.8. invalidEmail
JMAP Error Code: invalidEmail JMAP Error Code: invalidEmail
Intended use: common Intended use: common
Change controller: IETF Change controller: IETF
Reference: This document, section 7.5 Reference: This document, section 7.5
10.5.9. tooManyRecipients 10.6.9. tooManyRecipients
JMAP Error Code: tooManyRecipients JMAP Error Code: tooManyRecipients
Intended use: common Intended use: common
Change controller: IETF Change controller: IETF
Reference: This document, section 7.5 Reference: This document, section 7.5
10.5.10. noRecipients 10.6.10. noRecipients
JMAP Error Code: noRecipients JMAP Error Code: noRecipients
Intended use: common Intended use: common
Change controller: IETF Change controller: IETF
Reference: This document, section 7.5 Reference: This document, section 7.5
10.5.11. invalidRecipients 10.6.11. invalidRecipients
JMAP Error Code: invalidRecipients JMAP Error Code: invalidRecipients
Intended use: common Intended use: common
Change controller: IETF Change controller: IETF
Reference: This document, section 7.5 Reference: This document, section 7.5
10.5.12. forbiddenMailFrom 10.6.12. forbiddenMailFrom
JMAP Error Code: forbiddenMailFrom JMAP Error Code: forbiddenMailFrom
Intended use: common Intended use: common
Change controller: IETF Change controller: IETF
Reference: This document, section 7.5 Reference: This document, section 7.5
10.5.13. forbiddenFrom 10.6.13. forbiddenFrom
JMAP Error Code: forbiddenFrom JMAP Error Code: forbiddenFrom
Intended use: common Intended use: common
Change controller: IETF Change controller: IETF
Reference: This document, sections 6.3 and 7.5 Reference: This document, sections 6.3 and 7.5
10.5.14. forbiddenToSend 10.6.14. forbiddenToSend
JMAP Error Code: forbiddenToSend JMAP Error Code: forbiddenToSend
Intended use: common Intended use: common
Change controller: IETF Change controller: IETF
Reference: This document, section 7.5 Reference: This document, section 7.5
11. References 11. References
skipping to change at page 87, line 15 skipping to change at page 87, line 24
[RFC6710] Melnikov, A. and K. Carlberg, "Simple Mail Transfer [RFC6710] Melnikov, A. and K. Carlberg, "Simple Mail Transfer
Protocol Extension for Message Transfer Priorities", Protocol Extension for Message Transfer Priorities",
RFC 6710, DOI 10.17487/RFC6710, August 2012, RFC 6710, DOI 10.17487/RFC6710, August 2012,
<https://www.rfc-editor.org/info/rfc6710>. <https://www.rfc-editor.org/info/rfc6710>.
[RFC8314] Moore, K. and C. Newman, "Cleartext Considered Obsolete: [RFC8314] Moore, K. and C. Newman, "Cleartext Considered Obsolete:
Use of Transport Layer Security (TLS) for Email Submission Use of Transport Layer Security (TLS) for Email Submission
and Access", RFC 8314, DOI 10.17487/RFC8314, January 2018, and Access", RFC 8314, DOI 10.17487/RFC8314, January 2018,
<https://www.rfc-editor.org/info/rfc8314>. <https://www.rfc-editor.org/info/rfc8314>.
[RFC8457] Leiba, B., Ed., "IMAP "$Important" Keyword and
"\Important" Special-Use Attribute", RFC 8457,
DOI 10.17487/RFC8457, September 2018,
<https://www.rfc-editor.org/info/rfc8457>.
11.2. URIs 11.2. URIs
[1] TODO [1] https://www.iana.org/assignments/imap-mailbox-name-attributes/
imap-mailbox-name-attributes.xhtml
[2] https://www.iana.org/assignments/imap-keywords/imap- [2] https://www.iana.org/assignments/imap-keywords/imap-
keywords.xhtml keywords.xhtml
[3] https://www.w3.org/TR/CSP3/ [3] https://www.w3.org/TR/CSP3/
[4] https://www.w3.org/TR/referrer-policy/ [4] https://www.w3.org/TR/referrer-policy/
Authors' Addresses Authors' Addresses
 End of changes. 49 change blocks. 
102 lines changed or deleted 142 lines changed or added

This html diff was produced by rfcdiff 1.47. The latest version is available from http://tools.ietf.org/tools/rfcdiff/