draft-ietf-jmap-mail-00.txt   draft-ietf-jmap-mail-01.txt 
JMAP N. Jenkins JMAP N. Jenkins
Internet-Draft FastMail Internet-Draft FastMail
Intended status: Standards Track March 28, 2017 Updates: 5788 (if approved) July 16, 2017
Expires: September 29, 2017 Intended status: Standards Track
Expires: January 17, 2018
JMAP for Mail JMAP for Mail
draft-ietf-jmap-mail-00 draft-ietf-jmap-mail-01
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 31 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 http://datatracker.ietf.org/drafts/current/. Drafts is at http://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 September 29, 2017. This Internet-Draft will expire on January 17, 2018.
Copyright Notice Copyright Notice
Copyright (c) 2017 IETF Trust and the persons identified as the Copyright (c) 2017 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
(http://trustee.ietf.org/license-info) in effect on the date of (http://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 19 skipping to change at page 2, line 19
1.2. Terminology . . . . . . . . . . . . . . . . . . . . . . . 4 1.2. Terminology . . . . . . . . . . . . . . . . . . . . . . . 4
1.3. Addition to the capabilities object . . . . . . . . . . . 4 1.3. Addition to the capabilities object . . . . . . . . . . . 4
2. Mailboxes . . . . . . . . . . . . . . . . . . . . . . . . . . 4 2. Mailboxes . . . . . . . . . . . . . . . . . . . . . . . . . . 4
2.1. getMailboxes . . . . . . . . . . . . . . . . . . . . . . 7 2.1. getMailboxes . . . . . . . . . . . . . . . . . . . . . . 7
2.2. getMailboxUpdates . . . . . . . . . . . . . . . . . . . . 8 2.2. getMailboxUpdates . . . . . . . . . . . . . . . . . . . . 8
2.3. setMailboxes . . . . . . . . . . . . . . . . . . . . . . 10 2.3. setMailboxes . . . . . . . . . . . . . . . . . . . . . . 10
2.3.1. Ordering of changes . . . . . . . . . . . . . . . . . 11 2.3.1. Ordering of changes . . . . . . . . . . . . . . . . . 11
2.3.2. Creating mailboxes . . . . . . . . . . . . . . . . . 11 2.3.2. Creating mailboxes . . . . . . . . . . . . . . . . . 11
2.3.3. Updating mailboxes . . . . . . . . . . . . . . . . . 12 2.3.3. Updating mailboxes . . . . . . . . . . . . . . . . . 12
2.3.4. Destroying mailboxes . . . . . . . . . . . . . . . . 13 2.3.4. Destroying mailboxes . . . . . . . . . . . . . . . . 13
2.3.5. Response . . . . . . . . . . . . . . . . . . . . . . 14 2.3.5. Response . . . . . . . . . . . . . . . . . . . . . . 13
3. MessageLists . . . . . . . . . . . . . . . . . . . . . . . . 15 3. MessageLists . . . . . . . . . . . . . . . . . . . . . . . . 15
3.1. getMessageList . . . . . . . . . . . . . . . . . . . . . 16 3.1. getMessageList . . . . . . . . . . . . . . . . . . . . . 16
3.1.1. Filtering . . . . . . . . . . . . . . . . . . . . . . 17 3.1.1. Filtering . . . . . . . . . . . . . . . . . . . . . . 17
3.1.2. Sorting . . . . . . . . . . . . . . . . . . . . . . . 20 3.1.2. Sorting . . . . . . . . . . . . . . . . . . . . . . . 20
3.1.3. Thread collapsing . . . . . . . . . . . . . . . . . . 21 3.1.3. Thread collapsing . . . . . . . . . . . . . . . . . . 21
3.1.4. Windowing . . . . . . . . . . . . . . . . . . . . . . 22 3.1.4. Windowing . . . . . . . . . . . . . . . . . . . . . . 22
3.1.5. Response . . . . . . . . . . . . . . . . . . . . . . 22 3.1.5. Response . . . . . . . . . . . . . . . . . . . . . . 22
3.2. getMessageListUpdates . . . . . . . . . . . . . . . . . . 24 3.2. getMessageListUpdates . . . . . . . . . . . . . . . . . . 24
4. Threads . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 4. Threads . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
4.1. getThreads . . . . . . . . . . . . . . . . . . . . . . . 27 4.1. getThreads . . . . . . . . . . . . . . . . . . . . . . . 27
4.2. getThreadUpdates . . . . . . . . . . . . . . . . . . . . 29 4.2. getThreadUpdates . . . . . . . . . . . . . . . . . . . . 29
5. Messages . . . . . . . . . . . . . . . . . . . . . . . . . . 31 5. Messages . . . . . . . . . . . . . . . . . . . . . . . . . . 31
5.1. getMessages . . . . . . . . . . . . . . . . . . . . . . . 35 5.1. getMessages . . . . . . . . . . . . . . . . . . . . . . . 36
5.2. getMessageUpdates . . . . . . . . . . . . . . . . . . . . 37 5.2. getMessageUpdates . . . . . . . . . . . . . . . . . . . . 38
5.3. setMessages . . . . . . . . . . . . . . . . . . . . . . . 39 5.3. setMessages . . . . . . . . . . . . . . . . . . . . . . . 40
5.3.1. Saving a draft . . . . . . . . . . . . . . . . . . . 40 5.3.1. Saving a draft . . . . . . . . . . . . . . . . . . . 41
5.3.2. Updating messages . . . . . . . . . . . . . . . . . . 43 5.3.2. Updating messages . . . . . . . . . . . . . . . . . . 43
5.3.3. Sending messages . . . . . . . . . . . . . . . . . . 44 5.3.3. Sending messages . . . . . . . . . . . . . . . . . . 44
5.3.4. Cancelling a send . . . . . . . . . . . . . . . . . . 44 5.3.4. Cancelling a send . . . . . . . . . . . . . . . . . . 45
5.3.5. Destroying messages . . . . . . . . . . . . . . . . . 44 5.3.5. Destroying messages . . . . . . . . . . . . . . . . . 45
5.3.6. Response . . . . . . . . . . . . . . . . . . . . . . 45 5.3.6. Response . . . . . . . . . . . . . . . . . . . . . . 45
5.4. importMessages . . . . . . . . . . . . . . . . . . . . . 46 5.4. importMessages . . . . . . . . . . . . . . . . . . . . . 47
5.5. copyMessages . . . . . . . . . . . . . . . . . . . . . . 48 5.5. copyMessages . . . . . . . . . . . . . . . . . . . . . . 48
5.6. reportMessages . . . . . . . . . . . . . . . . . . . . . 49
6. Identities . . . . . . . . . . . . . . . . . . . . . . . . . 50 6. Identities . . . . . . . . . . . . . . . . . . . . . . . . . 50
6.1. getIdentities . . . . . . . . . . . . . . . . . . . . . . 51 6.1. getIdentities . . . . . . . . . . . . . . . . . . . . . . 50
6.2. getIdentityUpdates . . . . . . . . . . . . . . . . . . . 52 6.2. getIdentityUpdates . . . . . . . . . . . . . . . . . . . 51
6.3. setIdentities . . . . . . . . . . . . . . . . . . . . . . 54 6.3. setIdentities . . . . . . . . . . . . . . . . . . . . . . 53
7. SearchSnippets . . . . . . . . . . . . . . . . . . . . . . . 57 7. SearchSnippets . . . . . . . . . . . . . . . . . . . . . . . 56
7.1. getSearchSnippets . . . . . . . . . . . . . . . . . . . . 58 7.1. getSearchSnippets . . . . . . . . . . . . . . . . . . . . 57
8. Vacation Response . . . . . . . . . . . . . . . . . . . . . . 59 8. Vacation Response . . . . . . . . . . . . . . . . . . . . . . 58
8.1. getVacationResponse . . . . . . . . . . . . . . . . . . . 60 8.1. getVacationResponse . . . . . . . . . . . . . . . . . . . 59
8.2. setVacationResponse . . . . . . . . . . . . . . . . . . . 60 8.2. setVacationResponse . . . . . . . . . . . . . . . . . . . 59
9. References . . . . . . . . . . . . . . . . . . . . . . . . . 61 9. References . . . . . . . . . . . . . . . . . . . . . . . . . 61
9.1. Normative References . . . . . . . . . . . . . . . . . . 61 9.1. Normative References . . . . . . . . . . . . . . . . . . 61
9.2. URIs . . . . . . . . . . . . . . . . . . . . . . . . . . 62 9.2. URIs . . . . . . . . . . . . . . . . . . . . . . . . . . 61
Author's Address . . . . . . . . . . . . . . . . . . . . . . . . 62 Author's Address . . . . . . . . . . . . . . . . . . . . . . . . 61
1. Introduction 1. Introduction
JMAP is a generic protocol for synchronising data, such as mail, JMAP is a generic protocol for synchronising data, such as mail,
calendars or contacts, between a client and a server. It is calendars or contacts, between a client and a server. It is
optimised for mobile and web environments, and aims to provide a optimised for mobile and web environments, and aims to provide a
consistent interface to different data types. consistent interface to different data types.
This specification defines a data model for synchronising mail This specification defines a data model for synchronising mail
between a client and a server using JMAP. between a client and a server using JMAP.
skipping to change at page 4, line 39 skipping to change at page 4, line 39
o *messageListSortOptions*: "String[]" A list of all the message o *messageListSortOptions*: "String[]" A list of all the message
properties the server supports for sorting by. This MAY include properties the server supports for sorting by. This MAY include
properties the client does not recognise (for example custom properties the client does not recognise (for example custom
properties specified in a vendor extension). Clients MUST ignore properties specified in a vendor extension). Clients MUST ignore
any unknown properties in the list. any unknown properties in the list.
2. Mailboxes 2. Mailboxes
A mailbox represents a named set of emails. This is the primary A mailbox represents a named set of emails. This is the primary
mechanism for organising messages within an account. It is analogous mechanism for organising messages within an account. It is analogous
to a folder in IMAP or a label in other systems. A mailbox may to a folder or a label in other systems. A mailbox may perform a
perform a certain role in the system; see below for more details. certain role in the system; see below for more details.
For compatibility with IMAP, a message MUST belong to one or more For compatibility with IMAP, a message MUST belong to one or more
mailboxes. The message id does not change if the message changes mailboxes. The message id does not change if the message changes
mailboxes. mailboxes.
A *Mailbox* object has the following properties: A *Mailbox* object has the following properties:
o *id*: "String" The id of the mailbox. This property is immutable. o *id*: "String" The id of the mailbox. This property is immutable.
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 UTF-8 string of at least 1 character in length and This may be any UTF-8 string ([RFC3629]) of at least 1 character
maximum 256 bytes in size. Servers SHOULD forbid sibling in length and maximum 256 bytes in size. Servers SHOULD forbid
Mailboxes with the same name. sibling Mailboxes with the same name.
o *parentId*: "String|null" The mailbox id for the parent of this o *parentId*: "String|null" The mailbox id for the parent of this
mailbox, or "null" if this mailbox is at the top level. Mailboxes mailbox, or "null" if this mailbox is at the top level. Mailboxes
form acyclic graphs (forests) directed by the child-to-parent form acyclic graphs (forests) directed by the child-to-parent
relationship. There MUST NOT be a loop. relationship. There MUST NOT be a loop.
o *role*: "String|null" Identifies system mailboxes. This property o *role*: "String|null" Identifies system mailboxes. This property
can only be set on create. After the record has been created, can only be set on create. After the record has been created,
this property is immutable. The following values MUST be used for this property is immutable. The following values MUST be used for
the relevant mailboxes: the relevant mailboxes:
skipping to change at page 5, line 30 skipping to change at page 5, line 30
* "archive" - messages the user does not need right now, but does * "archive" - messages the user does not need right now, but does
not wish to delete. not wish to delete.
* "drafts" - messages the user is currently writing and are not * "drafts" - messages the user is currently writing and are not
yet sent. yet sent.
* "outbox" - messages the user has finished writing and wishes to * "outbox" - messages the user has finished writing and wishes to
send (see the "setMessages" method description for more send (see the "setMessages" method description for more
information). A mailbox with this role MUST be present if the information). A mailbox with this role MUST be present if the
user is allowed to send mail through an account. If not user is allowed to send mail through an account. If not
present, the user MAY NOT send mail with that account. present, the user cannot send mail with that account.
* "sent" - messages the user has sent. * "sent" - messages the user has sent.
* "trash" - messages the user has deleted. * "trash" - messages the user has deleted.
* "spam" - messages considered spam by the server. * "spam" - messages considered spam by the server.
* "templates" - drafts which should be used as templates (i.e. * "templates" - drafts which should be used as templates (i.e.
used as the basis for creating new drafts). used as the basis for creating new drafts).
skipping to change at page 6, line 42 skipping to change at page 6, line 42
this mailbox as its parent. this mailbox as its parent.
o *mayRename*: "Boolean" The user may rename the mailbox or make it o *mayRename*: "Boolean" The user may rename the mailbox or make it
a child of another mailbox. a child of another mailbox.
o *mayDelete*: "Boolean" The user may delete the mailbox itself. o *mayDelete*: "Boolean" The user may delete the mailbox itself.
o *totalMessages*: "Number" The number of messages in this mailbox. o *totalMessages*: "Number" The number of messages in this mailbox.
o *unreadMessages*: "Number" The number of messages in this mailbox o *unreadMessages*: "Number" The number of messages in this mailbox
where the _isUnread_ property of the message is "true" and the that have neither the "$Seen" keyword nor the "$Draft" keyword.
_isDraft_ property is "false".
o *totalThreads*: "Number" The number of threads where at least one o *totalThreads*: "Number" The number of threads where at least one
message in the thread is in this mailbox. message in the thread is in this mailbox.
o *unreadThreads*: "Number" The number of threads where at least one o *unreadThreads*: "Number" The number of threads where at least one
message in the thread has "isUnread == true" and "isDraft == message in the thread has neither the "$Seen" keyword nor the
false" AND at least one message in the thread is in this mailbox "$Draft" keyword AND at least one message in the thread is in this
(but see below for special case handling of Trash). Note, the mailbox (but see below for special case handling of Trash). Note,
unread message does not need to be the one in this mailbox. the unread message does not need to be the one in this mailbox.
The Trash mailbox (that is a mailbox with "role == "trash"") MUST be The Trash mailbox (that is a mailbox with "role == "trash"") MUST be
treated specially for the purpose of unread counts: treated specially for the purpose of unread counts:
1. Messages that are *only* in the Trash (and no other mailbox) are 1. Messages that are *only* in the Trash (and no other mailbox) are
ignored when calculating the "unreadThreads" count of other ignored when calculating the "unreadThreads" count of other
mailboxes. mailboxes.
2. Messages that are *not* in the Trash are ignored when calculating 2. Messages that are *not* in the Trash are ignored when calculating
the "unreadThreads" count for the Trash mailbox. the "unreadThreads" count for the Trash mailbox.
skipping to change at page 7, line 26 skipping to change at page 7, line 26
though they are in a separate thread for the purposes of unread though they are in a separate thread for the purposes of unread
counts. It is expected that clients will hide messages in the Trash counts. It is expected that clients will hide messages in the Trash
when viewing a thread in another mailbox and vice versa. This allows when viewing a thread in another mailbox and vice versa. This allows
you to delete a single message to the Trash out of a thread. you to delete a single message to the Trash out of a thread.
So for example, suppose you have an account where the entire contents So for example, suppose you have an account where the entire contents
is a single conversation with 2 messages: an unread message in the is a single conversation with 2 messages: an unread message in the
Trash and a read message in the Inbox. The "unreadThreads" count Trash and a read message in the Inbox. The "unreadThreads" count
would be "1" for the Trash and "0" for the Inbox. would be "1" for the Trash and "0" for the Inbox.
For IMAP compatability, a message in both the Trash and another For IMAP compatibility, a message 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).
2.1. getMailboxes 2.1. getMailboxes
Mailboxes can either be fetched explicitly by id, or all of them at Mailboxes can either be fetched explicitly by id, or all of them at
once. To fetch mailboxes, make a call to "getMailboxes". It takes once. To fetch mailboxes, make a call to "getMailboxes". It takes
the following arguments: the following arguments:
skipping to change at page 13, line 44 skipping to change at page 13, line 44
If the mailbox has "mayDeleteMailbox == false", the destruction MUST If the mailbox has "mayDeleteMailbox == false", the destruction MUST
be rejected with a "forbidden" error. be rejected with a "forbidden" error.
A mailbox MUST NOT be destroyed if it still has any child mailboxes. A mailbox MUST NOT be destroyed if it still has any child mailboxes.
Attempts to do so MUST be rejected with a "mailboxHasChild" error. Attempts to do so MUST be rejected with a "mailboxHasChild" error.
A mailbox MUST NOT be destroyed if it has any messages assigned to A mailbox MUST NOT be destroyed if it has any messages assigned to
it. Attempts to do so MUST be rejected with a "mailboxHasMessage" it. Attempts to do so MUST be rejected with a "mailboxHasMessage"
error. error.
There MUST always be *at least one* mailbox. It is expected that the
server will enforce this by setting "mayDeleteMailbox == false" on at
least the Inbox, if not all system mailboxes. However, if this is
not the case, an attempt to destroy the last mailbox MUST still be
rejected with a "mailboxRequired" error.
2.3.5. Response 2.3.5. Response
The response to _setMailboxes_ is called _mailboxesSet_. It has the The response to _setMailboxes_ is called _mailboxesSet_. It has the
following arguments: following arguments:
o *accountId*: "String" The id of the account used for the call. o *accountId*: "String" The id of the account used for the call.
o *oldState*: "String|null" The state string that would have been o *oldState*: "String|null" The state string that would have been
returned by "getMailboxes" before making the requested changes, or returned by "getMailboxes" before making the requested changes, or
"null" if the server doesn't know what the previous state string "null" if the server doesn't know what the previous state string
skipping to change at page 18, line 30 skipping to change at page 18, line 28
condition. condition.
o *minSize*: "Number|null" The size of the message in bytes (as o *minSize*: "Number|null" The size of the message in bytes (as
returned on the Message object) must be equal to or greater than returned on the Message object) must be equal to or greater than
this number to match the condition. this number to match the condition.
o *maxSize*: "Number|null" The size of the message in bytes (as o *maxSize*: "Number|null" The size of the message in bytes (as
returned on the Message object) must be less than this number to returned on the Message object) must be less than this number to
match the condition. match the condition.
o *threadIsFlagged*: "Boolean|null" If "true", the condition is o *allInThreadHaveKeyword*: "String" All messages (including this
matched if the "isFlagged" property of _any_ message in the same one) in the same thread as this message must have the given
thread as the message being examined is "true". If "false", the keyword to match the condition.
"isFlagged" property of _every_ message in the same thread as the
message being examined must be "false" to match the condition.
o *threadIsUnread*: "Boolean|null" If "true", the condition is
matched if the "isUnread" property of _any_ message in the same
thread as the message being examined is "true". If "false", the
"isUnread" property of _every_ message in the same thread as the
message being examined must be "false" to match the condition.
o *isFlagged*: "Boolean|null" The "isFlagged" property of the o *someInThreadHaveKeyword*: "String" At least one message (possibly
message must be identical to the value given to match the this one) in the same thread as this message must have the given
condition. keyword to match the condition.
o *isUnread*: "Boolean|null" The "isUnread" property of the message o *noneInThreadHaveKeyword*: "String" All messages (including this
must be identical to the value given to match the condition. one) in the same thread as this message must *not* have the given
keyword to match the condition.
o *isAnswered*: "Boolean|null" The "isAnswered" property of the o *hasKeyword*: "String" This message must have the given keyword to
message must be identical to the value given to match the match the condition.
condition.
o *isDraft*: "Boolean|null" The "isDraft" property of the message o *notKeyword*: "String" This message must not have the given
must be identical to the value given to match the condition. keyword to match the condition.
o *hasAttachment*: "Boolean|null" The "hasAttachment" property of o *hasAttachment*: "Boolean|null" The "hasAttachment" property of
the message must be identical to the value given to match the the message must be identical to the value given to match the
condition. condition.
o *text*: "String|null" Looks for the text in the _from_, _to_, o *text*: "String|null" Looks for the text in the _from_, _to_,
_cc_, _bcc_, _subject_, _textBody_ or _htmlBody_ properties of the _cc_, _bcc_, _subject_, _textBody_ or _htmlBody_ properties of the
message. message.
o *from*: "String|null" Looks for the text in the _from_ property of o *from*: "String|null" Looks for the text in the _from_ property of
skipping to change at page 21, line 15 skipping to change at page 20, line 51
o *to* - This is taken to be either the "name" part of the *first* o *to* - This is taken to be either the "name" part of the *first*
Emailer object, or if none then the "email" part of the *first* Emailer object, or if none then the "email" part of the *first*
Emailer object (see the definition of the to property in the Emailer object (see the definition of the to property in the
Message object). If still none, consider the value to be the Message object). If still none, consider the value to be the
empty string. empty string.
o *subject* - This is taken to be the subject of the Message with o *subject* - This is taken to be the subject of the Message with
any ignoring any leading "Fwd:"s or "Re:"s (case-insensitive any ignoring any leading "Fwd:"s or "Re:"s (case-insensitive
match). match).
o *threadIsFlagged* - This value MUST be considered "true" for the o *keyword:*"$keyword" - This value MUST be considered "true" if the
message if *any* of the messages in the same thread (regardless of message has the keyword, or "false" otherwise.
mailbox) have "isFlagged: true".
o *threadIsUnread* - This value MUST be considered "true" for the
message if *any* of the messages in the same thread (regardless of
mailbox) have "isUnread: true".
o *isFlagged* - The "isFlagged" state of the message (only). o *allThreadKeyword:*"$keyword" - This value MUST be considered
"true" for the message if *all* of the messages in the same thread
(regardless of mailbox) have the keyword.
o *isUnread* - The "isUnread" state of the message (only). o *someThreadKeyword:*"$keyword" - This value MUST be considered
"true" for the message if *any* of the messages in the same thread
(regardless of mailbox) have the keyword.
The server MAY support sorting based on other properties as well. A The server MAY support sorting based on other properties as well. A
client can discover which properties are supported by inspecting the client can discover which properties are supported by inspecting the
server's _capabilities_ object (see section 1). server's _capabilities_ object (see section 1).
The method of comparison depends on the type of the property: The method of comparison depends on the type of the property:
o "String": Comparison function is server-dependent. It SHOULD be o "String": Comparison function is server-dependent. It SHOULD be
case-insensitive and SHOULD take into account locale-specific case-insensitive and SHOULD take into account locale-specific
conventions if known for the user. However, the server MAY choose conventions if known for the user. However, the server MAY choose
to just sort based on unicode code point, after best-effort to just sort based on unicode code point, after best-effort
translation to lower-case. translation to lower-case.
o "Date": If sorting in ascending order, the earlier date MUST come o "Date": If sorting in ascending order, the earlier date MUST come
first. first.
o "Boolean": If sorting in ascending order, a "false" value MUST o "Boolean": If sorting in ascending order, a "false" value MUST
come before a "true" value. come before a "true" value.
Example sort:
`[ "someThreadKeyword:$Flagged desc", "date desc" ]
This would sort messages in flagged threads first (the thread is
considered flagged if any message within it is flagged), and then in
date order, newest first. If two messages have both identical
flagged status and date, the order is server-dependent but must be
stable.
3.1.3. Thread collapsing 3.1.3. Thread collapsing
When "collapseThreads == true", then after filtering and sorting the When "collapseThreads == true", then after filtering and sorting the
message list, the list is further winnowed by removing any messages message list, the list is further winnowed by removing any messages
for a thread id that has already been seen (when passing through the for a thread id that has already been seen (when passing through the
list sequentially). A thread will therefore only appear *once* in list sequentially). A thread will therefore only appear *once* in
the "threadIds" list of the result, at the position of the first the "threadIds" list of the result, at the position of the first
message in the list that belongs to the thread. message in the list that belongs to the thread.
3.1.4. Windowing 3.1.4. Windowing
skipping to change at page 25, line 28 skipping to change at page 25, line 28
o *total*: "Number" The total number of messages in the message list o *total*: "Number" The total number of messages in the message list
(given the filter and collapseThreads arguments). (given the filter and collapseThreads arguments).
o *removed*: "RemovedItem[]" The _messageId_ and _threadId_ for o *removed*: "RemovedItem[]" The _messageId_ and _threadId_ for
every message that was in the list in the old state and is not in every message that was in the list in the old state and is not in
the list in the new state. If the server cannot calculate this the list in the new state. If the server cannot calculate this
exactly, the server MAY return extra messages in addition that MAY exactly, the server MAY return extra messages in addition that MAY
have been in the old list but are not in the new list. If an have been in the old list but are not in the new list. If an
_uptoMessageId_ was given AND this id was found in the list, only _uptoMessageId_ was given AND this id was found in the list, only
messages positioned before this message that were removed need be messages positioned before this message that were removed need be
returned. In addition, if the sort includes the property returned. In addition, if the sort includes a keyword, the server
_isUnread_ or _isFlagged_, the server MUST include all messages in MUST include all messages in the current list for which this
the current list for which this property MAY have changed. If keyword MAY have changed. If the sort includes a "some/all-in-
"collapseThreads == true", then the server MUST include all thread-keyword", then the server MUST include all messages in the
messages in the current list for which this property MAY have current list for which this keyword MAY have changed *on any of
changed *on any of the messages in the thread*. the messages in the thread*.
o *added*: "AddedItem[]" The messageId and threadId and index in the o *added*: "AddedItem[]" The messageId and threadId and index in the
list (in the new state) for every message that has been added to list (in the new state) for every message that has been added to
the list since the old state AND every message in the current list the list since the old state AND every message in the current list
that was included in the _removed_ array (due to a filter or sort that was included in the _removed_ array (due to a filter or sort
based upon a mutable property). The array MUST be sorted in order based upon a mutable property). The array MUST be sorted in order
of index, lowest index first. If an _uptoMessageId_ was given AND of index, lowest index first. If an _uptoMessageId_ was given AND
this id was found in the list, only messages positioned before this id was found in the list, only messages positioned before
this message that have been added need be returned. this message that have been added need be returned.
skipping to change at page 27, line 33 skipping to change at page 27, line 33
this by deleting and reinserting (with a new message id) the messages this by deleting and reinserting (with a new message id) the messages
that change threadId. that change threadId.
A *Thread* object has the following properties: A *Thread* object has the following properties:
o *id*: "String" The id of the thread. This property is immutable. o *id*: "String" The id of the thread. This property is immutable.
o *messageIds*: "String[]" The ids of the messages in the thread, o *messageIds*: "String[]" The ids of the messages in the thread,
sorted such that: sorted such that:
* Any message with "isDraft == true" and an _inReplyToMessageId_ * Any message with the "$Draft" keyword that has an "In-Reply-To"
property that corresponds to another message in the thread header is sorted after the _first_ non-draft message in the
comes immediately after that message in the sort order. thread with the corresponding "Message-Id" header, but before
any subsequent non-draft messages.
* Other than that, everything is sorted in date order (the same * Other than that, everything is sorted in _date_ order (as
as the _date_ property on the Message object), oldest first. determined by the date property on the _Message_ object),
oldest first.
* If two messages are identical under the above two conditions,
the sort is server-dependent but MUST be stable (sorting by id
is recommended).
4.1. getThreads 4.1. getThreads
Threads can only be fetched explicitly by id. To fetch threads, make Threads can only be fetched explicitly by id. To fetch threads, make
a call to _getThreads_. It takes the following arguments: a call to _getThreads_. It takes the following arguments:
o *accountId*: "String|null" The id of the account to use for this o *accountId*: "String|null" The id of the account to use for this
call. If not given, defaults to the primary account. call. If not given, defaults to the primary account.
o *ids*: "String[]" An array of ids for the threads to fetch. o *ids*: "String[]" An array of ids for the threads to fetch.
skipping to change at page 30, line 45 skipping to change at page 31, line 4
messages within the thread has changed since the old state, and messages within the thread has changed since the old state, and
there are now no messages in the thread. there are now no messages in the thread.
If a _maxChanges_ is supplied, or set automatically by the server, If a _maxChanges_ is supplied, or set automatically by the server,
the server MUST ensure the number of ids returned across _changed_ the server MUST ensure the number of ids returned across _changed_
and _removed_ does not exceed this limit. If there are more changes and _removed_ does not exceed this limit. If there are more changes
than this between the client's state and the current server state, than this between the client's state and the current server state,
the update returned SHOULD generate an update to take the client to the update returned SHOULD generate an update to take the client to
an intermediate state, from which the client can continue to call an intermediate state, from which the client can continue to call
_getThreadUpdates_ until it is fully up to date. If it is unable to _getThreadUpdates_ until it is fully up to date. If it is unable to
calculat an intermediate state, it MUST return a calculate an intermediate state, it MUST return a
"cannotCalculateChanges" error response instead. "cannotCalculateChanges" error response instead.
If a thread has been modified AND deleted since the oldState, the If a thread has been modified AND deleted since the oldState, the
server SHOULD just return the id in the _removed_ response, but MAY server SHOULD just return the id in the _removed_ response, but MAY
return it in the changed response as well. If a thread has been return it in the changed response as well. If a thread has been
created AND deleted since the oldState, the server SHOULD remove the created AND deleted since the oldState, the server SHOULD remove the
thread id from the response entirely, but MAY include it in the thread id from the response entirely, but MAY include it in the
_removed_ response. _removed_ response.
The following errors may be returned instead of the _threadUpdates_ The following errors may be returned instead of the _threadUpdates_
skipping to change at page 31, line 38 skipping to change at page 31, line 45
5. Messages 5. Messages
Just like in IMAP, a message is *immutable* except for the boolean Just like in IMAP, a message is *immutable* except for the boolean
"isXXX" status properties and the set of mailboxes it is in. This "isXXX" status properties and the set of mailboxes it is in. This
allows for more efficient caching of messages, and gives easier allows for more efficient caching of messages, and gives easier
backwards compatibility for servers implementing an IMAP interface to backwards compatibility for servers implementing an IMAP interface to
the same data. the same data.
JMAP completely hides the complexities of MIME. All special JMAP completely hides the complexities of MIME. All special
encodings of either headers or the body, such as base64 [2], or RFC encodings of either headers or textual body parts, such as base64
2047 [3] encoding of non-ASCII characters, MUST be fully decoded into [2], or RFC 2047 [3] encoding of non-ASCII characters, MUST be fully
standard UTF-8. decoded into UTF-8.
A *Message* object has the following properties: A *Message* object has the following properties:
o *id*: "String" The id of the message. o *id*: "String" The id of the message.
o *blobId*: "String" The id representing the raw [RFC5322] message. o *blobId*: "String" The id representing the raw [RFC5322] message.
This may be used to download the original message or to attach it This may be used to download the original message or to attach it
directly to another message etc. directly to another message etc.
o *threadId*: "String" The id of the thread to which this message o *threadId*: "String" The id of the thread to which this message
belongs. belongs.
o *mailboxIds*: "String[]" (Mutable) The ids of the mailboxes the o *mailboxIds*: "String[]" (Mutable) The ids of the mailboxes the
message is in. A message MUST belong to one or more mailboxes at message is in. A message MUST belong to one or more mailboxes at
all times (until it is deleted). all times (until it is deleted).
o *inReplyToMessageId*: "String|null" The id of the Message this o *keywords*: "String[Boolean]" (Mutable) A set of keywords that
message is a reply to. This is primarily for drafts, but the apply to the message. The set is represented as an object, with
server MAY support this for received messages as well by looking the keys being the _keywords_. The value for each key in the
up the [RFC5322] Message-Id referenced in the "In-Reply-To" header object MUST be "true". Keywords are shared with IMAP. The six
and searching for this message in the user's mail. system keywords from IMAP are treated specially. The following
four keywords have their first character changed from "\" in IMAP
to "$" in JMAP and have particular semantic meaning:
o *isUnread*: "Boolean" (Mutable) Has the message not yet been read? * "$Draft": The message is a draft the user is composing.
This corresponds to the *opposite* of the "\Seen" system flag in
IMAP.
o *isFlagged*: "Boolean" (Mutable) Is the message flagged? This * "$Seen": The message has been read.
corresponds to the "\Flagged" system flag in IMAP.
o *isAnswered*: "Boolean" (Mutable) Has the message been replied to? * "$Flagged": The message has been flagged for urgent/special
This corresponds to the "\Answered" system flag in IMAP. attention.
o *isDraft*: "Boolean" (Mutable by the server only) Is the message a * "$Answered": The message has been replied to.
draft? This corresponds to the "\Draft" system flag in IMAP.
The IMAP "\Recent" keyword is not exposed via JMAP. The IMAP
"\Deleted" keyword is also not present: IMAP uses a delete+expunge
model, which JMAP does not. Any message with the "\Deleted"
keyword MUST NOT be visible via JMAP. Users may add arbitrary
keywords to a message. For compatibility with IMAP, a keyword is
a (case-sensitive) string of 1-255 characters in the ASCII subset
%x21-%x127 (excludes control chars and space), and MUST NOT
include any of these characters: "()]{%*"\" The IANA Keyword
Registry [4] as established in [RFC5788] assigns semantic meaning
to some other keywords in common use. New keywords may be
established here in the future. In particular, note:
* "$Forwarded": The message has been forwarded.
* "$Phishing": The message is highly likely to be phishing.
Clients SHOULD warn users to take care when viewing this
message and disable links and attachments.
* "$Junk": The message is definitely spam. Clients SHOULD set
this flag when users report spam to help train automated spam-
detection systems.
* "$NotJunk": The message is definitely not spam. Clients SHOULD
set this flag when users indicate a message is legitimate, to
help train automated spam-detection systems.
o *hasAttachment*: "Boolean" Does the message have any attachments? o *hasAttachment*: "Boolean" Does the message have any attachments?
o *headers*: "String[String]" A map of lower-cased header name to o *headers*: "String[String]" A map of lower-cased header name to
(decoded) header value for all headers in the message. For (decoded) header value for all headers in the message. For
headers that occur multiple times (e.g. "Received"), the values headers that occur multiple times (e.g. "Received"), the values
are concatenated with a single new line ("\n") character in are concatenated with a single new line ("\n") character in
between each one. between each one.
o *sender*: "Emailer|null" An Emailer object (see below) containing o *sender*: "Emailer|null" An Emailer object (see below) containing
skipping to change at page 33, line 42 skipping to change at page 34, line 26
o *preview*: "String" Up to 256 characters of the beginning of a o *preview*: "String" Up to 256 characters of the beginning of a
plain text version of the message body. This is intended to be plain text version of the message body. This is intended to be
shown as a preview line on a mailbox listing, and the server may shown as a preview line on a mailbox listing, and the server may
choose to skip quoted sections or salutations to return a more choose to skip quoted sections or salutations to return a more
useful preview. useful preview.
o *textBody*: "String" The plain text body part for the message. If o *textBody*: "String" The plain text body part for the message. If
there is only an HTML version of the body, a plain text version there is only an HTML version of the body, a plain text version
MUST be generated from this; the exact method of conversion in MUST be generated from this; the exact method of conversion in
this case is not defined and is server-specific. this case is not defined and is server-specific. If there is
neither a "text/plain" nor a "text/html" body part, this MUST be
the empty string.
o *htmlBody*: "String|null" The HTML body part for the message if o *htmlBody*: "String|null" The HTML body part for the message if
present. present.
o *attachments*: "Attachment[]|null" An array of attachment objects o *attachments*: "Attachment[]|null" An array of attachment objects
(see below) detailing all the attachments to the message. (see below) detailing all the attachments to the message.
o *attachedMessages*: "String[Message]|null" An object mapping o *attachedMessages*: "String[Message]|null" An object mapping
attachment id (as found in the "attachments" property) to a attachment id (as found in the "attachments" property) to a
*Message* object with the following properties, for each [RFC5322] *Message* object with the following properties, for each [RFC5322]
skipping to change at page 35, line 31 skipping to change at page 36, line 12
decoded (i.e. the number of bytes in the file the user would decoded (i.e. the number of bytes in the file the user would
download). download).
o *cid*: "String|null" The id used within the message body to o *cid*: "String|null" The id used within the message body to
reference this attachment. This is only unique when paired with reference this attachment. This is only unique when paired with
the message id, and has no meaning without reference to that. the message id, and has no meaning without reference to that.
o *isInline*: "Boolean" True if the attachment is referenced by a o *isInline*: "Boolean" True if the attachment is referenced by a
"cid:" link from within the HTML body of the message. "cid:" link from within the HTML body of the message.
o *width*: "Number|null" The width (in px) of the image, if the o *width*: "Number|null" (optional, server MAY omit if not
attachment is an image. supported) The width (in px) of the image, if the attachment is an
image.
o *height*: "Number|null" The height (in px) of the image, if the o *height*: "Number|null" (optional, server MAY omit if not
attachment is an image. supported) The height (in px) of the image, if the attachment is
an image.
5.1. getMessages 5.1. getMessages
Messages can only be fetched explicitly by id. To fetch messages, Messages can only be fetched explicitly by id. To fetch messages,
make a call to "getMessages". It takes the following arguments: make a call to "getMessages". It takes the following arguments:
o *accountId*: "String|null" The id of the account to use for this o *accountId*: "String|null" The id of the account to use for this
call. If not given, defaults to the primary account. call. If not given, defaults to the primary account.
o *ids*: "String[]" An array of ids for the messages to fetch. o *ids*: "String[]" An array of ids for the messages to fetch.
skipping to change at page 39, line 9 skipping to change at page 39, line 41
o *removed*: "String[]" An array of message ids for messages that o *removed*: "String[]" An array of message ids for messages that
have been deleted since the oldState. have been deleted since the oldState.
If a _maxChanges_ is supplied, or set automatically by the server, If a _maxChanges_ is supplied, or set automatically by the server,
the server MUST ensure the number of ids returned across _changed_ the server MUST ensure the number of ids returned across _changed_
and _removed_ does not exceed this limit. If there are more changes and _removed_ does not exceed this limit. If there are more changes
than this between the client's state and the current server state, than this between the client's state and the current server state,
the update returned SHOULD generate an update to take the client to the update returned SHOULD generate an update to take the client to
an intermediate state, from which the client can continue to call an intermediate state, from which the client can continue to call
_getMessageUpdates_ until it is fully up to date. If it is unable to _getMessageUpdates_ until it is fully up to date. If it is unable to
calculat an intermediate state, it MUST return a calculate an intermediate state, it MUST return a
"cannotCalculateChanges" error response instead. "cannotCalculateChanges" error response instead.
If a message has been modified AND deleted since the oldState, the If a message has been modified AND deleted since the oldState, the
server SHOULD just return the id in the _removed_ response, but MAY server SHOULD just return the id in the _removed_ response, but MAY
return it in the changed response as well. If a message has been return it in the changed response as well. If a message has been
created AND deleted since the oldState, the server SHOULD remove the created AND deleted since the oldState, the server SHOULD remove the
message id from the response entirely, but MAY include it in the message id from the response entirely, but MAY include it in the
_removed_ response, and (if in the _removed_ response) MAY included _removed_ response, and (if in the _removed_ response) MAY included
it in the _changed_ response as well. it in the _changed_ response as well.
skipping to change at page 40, line 32 skipping to change at page 41, line 18
o *update*: "String[Message]|null" A map of message id to objects o *update*: "String[Message]|null" A map of message id to objects
containing the properties to update for that Message. containing the properties to update for that Message.
o *destroy*: "String[]|null" A list of ids for Message objects to o *destroy*: "String[]|null" A list of ids for Message objects to
permanently delete. permanently delete.
Each create, update or destroy is considered an atomic unit. It is Each create, update or destroy is considered an atomic unit. It is
permissible for the server to commit some of the changes but not permissible for the server to commit some of the changes but not
others, however it is not permissible to only commit part of an others, however it is not permissible to only commit part of an
update to a single record (e.g. update the _isFlagged_ field but not update to a single record (e.g. update the _keywords_ field but not
the _mailboxIds_ field, if both are supplied in the update object for the _mailboxIds_ field, if both are supplied in the update object for
a message). a message).
If a create, update or destroy is rejected, the appropriate error If a create, update or destroy is rejected, the appropriate error
MUST be added to the notCreated/notUpdated/notDestroyed property of MUST be added to the notCreated/notUpdated/notDestroyed property of
the response and the server MUST continue to the next create/update/ the response and the server MUST continue to the next create/update/
destroy. It does not terminate the method. destroy. It does not terminate the method.
If an id given cannot be found, the update or destroy MUST be If an id given cannot be found, the update or destroy MUST be
rejected with a "notFound" set error. rejected with a "notFound" set error.
skipping to change at page 41, line 20 skipping to change at page 42, line 5
o *threadId*: This property MUST NOT be included. It is set by the o *threadId*: This property MUST NOT be included. It is set by the
server upon creation. server upon creation.
o *mailboxIds*: This property MUST be included. The value MUST o *mailboxIds*: This property MUST be included. The value MUST
include the id of either the mailbox with "role == "drafts"" (to include the id of either the mailbox with "role == "drafts"" (to
save a draft) or the mailbox with "role == "outbox"" (to send the save a draft) or the mailbox with "role == "outbox"" (to send the
message). If this mailbox does not have "mustBeOnlyMailbox == message). If this mailbox does not have "mustBeOnlyMailbox ==
true", others may be included too. true", others may be included too.
o *inReplyToMessageId*: Optional. If included, the server will look o *keywords*: This property MUST be included. It MUST include the
up this message and if found set appropriate "References" and "In- "$Draft" keyword and SHOULD also include "$Seen".
Reply-To" headers. These will override any such headers supplied
in the _headers_ property. If not found, the creation MUST be
rejected with an "inReplyToNotFound" error.
o *isUnread*: Optional, defaults to "false". If included this MUST
be "false".
o *isFlagged*: Optional, defaults to "false".
o *isAnswered*: Optional, defaults to "false". If included this
MUST be "false".
o *isDraft*: Optional, defaults to "true". If included this MUST be
"true".
o *hasAttachment*: This property MUST NOT be included. It is set by o *hasAttachment*: This property MUST NOT be included. It is set by
the server upon creation based on the attachments property. the server upon creation based on the attachments property.
o *headers*: Optional. The keys MUST only contain the characters o *headers*: Optional. The keys MUST only contain the characters
a-z (lower-case only), 0-9 and hyphens. a-z (lower-case only), 0-9 and hyphens.
o *from*: Optional. Overrides a "From" in the _headers_. o *from*: Optional. Overrides a "From" in the _headers_.
o *to*: Optional. Overrides a "To" in the _headers_. o *to*: Optional. Overrides a "To" in the _headers_.
skipping to change at page 43, line 21 skipping to change at page 43, line 39
mail storage quota, the creation MUST be rejected with a mail storage quota, the creation MUST be rejected with a
"maxQuotaReached" error. "maxQuotaReached" error.
5.3.2. Updating messages 5.3.2. Updating messages
Messages are mainly immutable, so to update a draft the client must Messages are mainly immutable, so to update a draft the client must
create a new message and delete the old one. This ensures that if create a new message and delete the old one. This ensures that if
the draft is also being edited elsewhere, the two will split into two the draft is also being edited elsewhere, the two will split into two
different drafts to avoid data loss. different drafts to avoid data loss.
Only the following properties may be modified: Only the _mailboxIds_ and _keywords_ properties may be modified, and
they are subject to the following constraints:
o *mailboxIds*: The server MUST reject any attempt to add a message o *mailboxIds*: The server MUST reject any attempt to add a message
with "isDraft == false" to the outbox. The server MAY reject to the outbox that does not have the "$Draft" keyword with an
attempts to add a draft message to a mailbox that does not have a "invalidProperties" error.
role of "drafts", "outbox" or "templates".
o *isFlagged*
o *isUnread*
o *isAnswered* o *keywords*: The server MUST reject any attempt to add or remove
the "$Draft" flag in an update with an "invalidProperties" error.
The server MAY have a maximum number of keywords it supports; if
the change would exceed this, it MUST be rejected with a
"tooManyKeywords" error.
Note, a mailbox id may be a _creation id_ (see "setFoos" for a Note, a mailbox id may be a _creation id_ (see "setFoos" for a
description of how this works). description of how this works).
If any of the properties in the update are invalid (immutable and If any of the properties in the update are invalid (immutable and
different to the current server value, wrong type, invalid value for different to the current server value, wrong type, invalid value for
the property - like a mailbox id for non-existent mailbox), the the property - like a mailbox id for non-existent mailbox), the
server MUST reject the update with an "invalidProperties" error. The server MUST reject the update with an "invalidProperties" error. The
Error object SHOULD contain a property called _properties_ of type Error object SHOULD contain a property called _properties_ of type
"String[]" that lists *all* the properties that were invalid. The "String[]" that lists *all* the properties that were invalid. The
skipping to change at page 44, line 28 skipping to change at page 44, line 47
with a user-friendly description of the problems to present to the with a user-friendly description of the problems to present to the
user. user.
If the message is accepted, the server SHOULD *asynchronously* If the message is accepted, the server SHOULD *asynchronously*
schedule the message to be sent *after* this method call is complete schedule the message to be sent *after* this method call is complete
(note, this MAY occur before the next method in the same API request (note, this MAY occur before the next method in the same API request
or after the whole API request is complete). This means that the or after the whole API request is complete). This means that the
"newState" string in the response represents a state where the "newState" string in the response represents a state where the
message is still in the outbox. message is still in the outbox.
When the message is sent, the server MUST delete the message from the When the message is sent, the server MUST remove the message from the
*outbox* and SHOULD create a *new* copy of the sent message (with a *outbox* and add it to the *sent* mailbox, unless the user has
new id) in the *sent* mailbox, unless the user has indicated another indicated another preference. The version added to the sent mailbox
preference. If "inReplyToMessageId" was set, the server SHOULD mark MAY be different (for example have extra headers added by the
this message as "isAnswered: true" at this point, if found. The server), and so have a different id to the version that was in the
server is responsible for either reporting an error (normally a outbox. If the message has an "In-Reply-To" header, the server
SHOULD add the "$Answered" keyword to all messages with the
coresponding "Message-Id" header at this point. If the message has
an "X-Forwarded-Message-Id" header, the server SHOULD add the
"$Forwarded" keyword to all messages with the coresponding "Message-
Id" header at this point.
The server is responsible for either reporting an error (normally a
"bounce" email), or ensuring delivery of the message to the next hop. "bounce" email), or ensuring delivery of the message to the next hop.
5.3.4. Cancelling a send 5.3.4. Cancelling a send
A message may be moved out of the *outbox* and back to the *drafts* A message may be moved out of the *outbox* and back to the *drafts*
mailbox using the standard update message mechanism, if it has not mailbox using the standard update message mechanism, if it has not
yet been sent at the time the method is called. This MUST cancel the yet been sent at the time the method is called. This MUST cancel the
queued send. If the message has already been sent then it will have queued send. If the message has already been sent then it will have
been deleted from the outbox, so the update will fail with a standard been deleted from the outbox, so the update will fail with a standard
"notFound" error. "notFound" error.
skipping to change at page 46, line 45 skipping to change at page 47, line 25
specified) to MessageImport objects specified) to MessageImport objects
An *MessageImport* object has the following properties: An *MessageImport* object has the following properties:
o *blobId*: "String" The id representing the raw [RFC5322] message o *blobId*: "String" The id representing the raw [RFC5322] message
(see the file upload section). (see the file upload section).
o *mailboxIds* "String[]" The ids of the mailbox(es) to assign this o *mailboxIds* "String[]" The ids of the mailbox(es) to assign this
message to. message to.
o *isUnread*: "Boolean" o *keywords*: "String[Boolean]"
o *isFlagged*: "Boolean"
o *isAnswered*: "Boolean"
o *isDraft*: "Boolean" Adding to the outbox will send the message, as described in the
If "isDraft == true", the mailboxes MUST include the drafts or outbox _setMessages_ section. The "$Draft" keyword MUST also be included if
mailbox. Adding to the outbox will send the message, as described in the message is being imported to the outbox.
the _setMessages_ section (it will NOT automatically mark any other
message as _isAnswered_).
The response to _importMessages_ is called _messagesImported_. It has The response to _importMessages_ is called _messagesImported_. It has
the following arguments: the following arguments:
o *accountId*: "String" The id of the account used for this call. o *accountId*: "String" The id of the account used for this call.
o *created*: "String[Message]" A map of the creation id to an object o *created*: "String[Message]" A map of the creation id to an object
containing the _id_, _blobId_, _threadId_ and _size_ properties containing the _id_, _blobId_, _threadId_ and _size_ properties
for each successfully imported Message. for each successfully imported Message.
skipping to change at page 48, line 28 skipping to change at page 48, line 44
MessageCopy object. MessageCopy object.
A *MessageCopy* object has the following properties: A *MessageCopy* object has the following properties:
o *messageId*: "String" The id of the message to be copied in the o *messageId*: "String" The id of the message to be copied in the
"from" account. "from" account.
o *mailboxIds*: "String[]" The ids of the mailboxes (in the "to" o *mailboxIds*: "String[]" The ids of the mailboxes (in the "to"
account) to add the copied message to. account) to add the copied message to.
o *isUnread*: "Boolean" The _isUnread_ property for the copy. o *keywords*: "String[Boolean]" The _keywords_ property for the
copy.
o *isFlagged*: "Boolean" The _isFlagged_ property for the copy.
o *isAnswered*: "Boolean" The _isAnswered_ property for the copy.
o *isDraft*: "Boolean" The _isDraft_ property for the copy.
The "from" account may be the same as the "to" account to copy The "from" account may be the same as the "to" account to copy
messages within an account. messages within an account.
The response to _copyMessages_ is called _messagesCopied_. It has the The response to _copyMessages_ is called _messagesCopied_. It has the
following arguments: following arguments:
o *fromAccountId*: "String" The id of the account messages were o *fromAccountId*: "String" The id of the account messages were
copied from. copied from.
skipping to change at page 49, line 44 skipping to change at page 50, line 5
a valid account, but does not contain any mail data. a valid account, but does not contain any mail data.
"accountReadOnly": Returned if the "to" account has "isReadOnly == "accountReadOnly": Returned if the "to" account has "isReadOnly ==
true". true".
"invalidArguments": Returned if one of the arguments is of the wrong "invalidArguments": Returned if one of the arguments is of the wrong
type, or otherwise invalid. A "description" property MAY be present type, or otherwise invalid. A "description" property MAY be present
on the response object to help debug with an explanation of what the on the response object to help debug with an explanation of what the
problem was. problem was.
5.6. reportMessages
Messages can be reported as spam or non-spam to help train the user's
spam filter. This MUST NOT affect the state of the Message objects
(it DOES NOT move a message into or out of the Spam mailbox).
To report messages, make a call to _reportMessages_. It takes the
following arguments:
o *accountId*: "String|null" The id of the account to use for this
call. If not given, defaults to the primary account.
o *messageIds*: "String[]" The list of ids of messages to report.
o *asSpam*: "Boolean" If "true", learn these messages as spam. If
"false", learn as non-spam.
The response to _reportMessages_ is called _messagesReported_. It has
the following arguments:
o *accountId*: "String" The id of the account used for this call.
o *asSpam*: "Boolean" Echoed back from the call
o *reported*: "String[]" The ids of each message successfully
reported.
o *notFound*: "String[]|null" An array of message ids requested
which could not be found, or "null" if all ids were found.
The following errors may be returned instead of the
_messagesReported_ response:
"accountNotFound": Returned if an _accountId_ was explicitly included
with the request, but it does not correspond to a valid account.
"accountNotSupportedByMethod": Returned if the _accountId_ given
corresponds to a valid account, but the account does not support this
data type.
"accountReadOnly": Returned if the account has "isReadOnly == true".
"requestTooLarge": Returned if 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.
"invalidArguments": Returned if one of the arguments is of the wrong
type, or otherwise invalid. A "description" property MAY be present
on the response object to help debug with an explanation of what the
problem was.
6. Identities 6. Identities
A *Identity* object stores information about an email address (or A *Identity* object stores information about an email address (or
domain) the user may send from. It has the following properties: domain) the user may send from. It has the following properties:
o *id*: "String" The id of the identity. This property is o *id*: "String" The id of the identity. This property is
immutable. immutable.
o *name*: "String" The "From" _name_ the client SHOULD use when o *name*: "String" The "From" _name_ the client SHOULD use when
creating a new message from this identity. creating a new message from this identity.
skipping to change at page 58, line 28 skipping to change at page 57, line 35
details. details.
The response to "getSearchSnippets" is called "searchSnippets". It The response to "getSearchSnippets" is called "searchSnippets". It
has the following arguments: has the following arguments:
o *accountId*: "String" The id of the account used for the call. o *accountId*: "String" The id of the account used for the call.
o *filter*: "FilterCondition|FilterOperator|null" Echoed back from o *filter*: "FilterCondition|FilterOperator|null" Echoed back from
the call. the call.
o *list*: "SearchSnippet[]" An array of SearchSnippets objects for o *list*: "SearchSnippet[]" An array of SearchSnippet objects for
the requested message ids. This may not be in the same order as the requested message ids. This may not be in the same order as
the ids that were in the request. the ids that were in the request.
o *notFound*: "String[]|null" An array of message ids requested o *notFound*: "String[]|null" An array of message ids requested
which could not be found, or "null" if all ids were found. which could not be found, or "null" if all ids were found.
Since snippets are only based on immutable properties, there is no Since snippets are only based on immutable properties, there is no
state string or update mechanism needed. state string or update mechanism needed.
The following errors may be returned instead of the _searchSnippets_ The following errors may be returned instead of the _searchSnippets_
skipping to change at page 62, line 10 skipping to change at page 61, line 14
9. References 9. References
9.1. Normative References 9.1. Normative References
[RFC2119] Bradner, S., "Key words for use in RFCs to Indicate [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
Requirement Levels", BCP 14, RFC 2119, Requirement Levels", BCP 14, RFC 2119,
DOI 10.17487/RFC2119, March 1997, DOI 10.17487/RFC2119, March 1997,
<http://www.rfc-editor.org/info/rfc2119>. <http://www.rfc-editor.org/info/rfc2119>.
[RFC3629] Yergeau, F., "UTF-8, a transformation format of ISO
10646", STD 63, RFC 3629, DOI 10.17487/RFC3629, November
2003, <http://www.rfc-editor.org/info/rfc3629>.
[RFC5322] Resnick, P., Ed., "Internet Message Format", RFC 5322, [RFC5322] Resnick, P., Ed., "Internet Message Format", RFC 5322,
DOI 10.17487/RFC5322, October 2008, DOI 10.17487/RFC5322, October 2008,
<http://www.rfc-editor.org/info/rfc5322>. <http://www.rfc-editor.org/info/rfc5322>.
[RFC5788] Melnikov, A. and D. Cridland, "IMAP4 Keyword Registry",
RFC 5788, DOI 10.17487/RFC5788, March 2010,
<http://www.rfc-editor.org/info/rfc5788>.
[RFC7159] Bray, T., Ed., "The JavaScript Object Notation (JSON) Data [RFC7159] Bray, T., Ed., "The JavaScript Object Notation (JSON) Data
Interchange Format", RFC 7159, DOI 10.17487/RFC7159, March Interchange Format", RFC 7159, DOI 10.17487/RFC7159, March
2014, <http://www.rfc-editor.org/info/rfc7159>. 2014, <http://www.rfc-editor.org/info/rfc7159>.
9.2. URIs 9.2. URIs
[1] server.html [1] server.html
[2] https://tools.ietf.org/html/rfc4648 [2] https://tools.ietf.org/html/rfc4648
[3] http://tools.ietf.org/html/rfc2047 [3] http://tools.ietf.org/html/rfc2047
[4] https://www.iana.org/assignments/imap-keywords/imap-
keywords.xhtml
Author's Address Author's Address
Neil Jenkins Neil Jenkins
FastMail FastMail
Level 1, 91 William St Level 1, 91 William St
Melbourne VIC 3000 Melbourne VIC 3000
Australia Australia
Email: neilj@fastmail.com Email: neilj@fastmail.com
URI: https://www.fastmail.com URI: https://www.fastmail.com
 End of changes. 54 change blocks. 
209 lines changed or deleted 178 lines changed or added

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