idnits 2.17.1 draft-ietf-jmap-mail-01.txt: Checking boilerplate required by RFC 5378 and the IETF Trust (see https://trustee.ietf.org/license-info): ---------------------------------------------------------------------------- No issues found here. Checking nits according to https://www.ietf.org/id-info/1id-guidelines.txt: ---------------------------------------------------------------------------- No issues found here. Checking nits according to https://www.ietf.org/id-info/checklist : ---------------------------------------------------------------------------- ** The document seems to lack a Security Considerations section. ** The document seems to lack an IANA Considerations section. (See Section 2.2 of https://www.ietf.org/id-info/checklist for how to handle the case when there are no actions for IANA.) ** There are 2 instances of too long lines in the document, the longest one being 2 characters in excess of 72. -- The draft header indicates that this document updates RFC5788, but the abstract doesn't seem to mention this, which it should. Miscellaneous warnings: ---------------------------------------------------------------------------- == The copyright year in the IETF Trust and authors Copyright Line does not match the current year == Using lowercase 'not' together with uppercase 'MUST', 'SHALL', 'SHOULD', or 'RECOMMENDED' is not an accepted usage according to RFC 2119. Please use uppercase 'NOT' together with RFC 2119 keywords (if that is what you mean). Found 'MUST not' in this paragraph: o *headers.property*: Instead of requesting all the headers (by requesting the ""headers"" property, the client may specify the particular headers it wants using the "headers.property-name" syntax, e.g. ""headers.x-spam-score", "headers.x-spam-hits""). The server will return a _headers_ property but with just the requested headers in the object rather than all headers. If ""headers"" is requested, the server MUST ignore the individual header requests and just return all headers. If a requested header is not present in the message, it MUST not be present in the _headers_ object. Header names are case-insensitive. (Using the creation date from RFC5788, updated by this document, for RFC5378 checks: 2002-06-21) -- The document seems to lack a disclaimer for pre-RFC5378 work, but may have content which was first submitted before 10 November 2008. If you have contacted all the original authors and they are all willing to grant the BCP78 rights to the IETF Trust, then this is fine, and you can ignore this comment. If not, you may need to add the pre-RFC5378 disclaimer. (See the Legal Provisions document at https://trustee.ietf.org/license-info for more information.) -- The document date (July 16, 2017) is 2473 days in the past. Is this intentional? Checking references for intended status: Proposed Standard ---------------------------------------------------------------------------- (See RFCs 3967 and 4897 for information about using normative references to lower-maturity documents in RFCs) -- Looks like a reference, but probably isn't: '1' on line 2888 -- Looks like a reference, but probably isn't: '2' on line 2890 -- Looks like a reference, but probably isn't: '3' on line 2892 -- Looks like a reference, but probably isn't: '4' on line 2894 ** Obsolete normative reference: RFC 7159 (Obsoleted by RFC 8259) Summary: 4 errors (**), 0 flaws (~~), 2 warnings (==), 7 comments (--). Run idnits with the --verbose option for more detailed information about the items above. -------------------------------------------------------------------------------- 2 JMAP N. Jenkins 3 Internet-Draft FastMail 4 Updates: 5788 (if approved) July 16, 2017 5 Intended status: Standards Track 6 Expires: January 17, 2018 8 JMAP for Mail 9 draft-ietf-jmap-mail-01 11 Abstract 13 This document specifies a data model for synchronising email data 14 with a server using JMAP. 16 Status of This Memo 18 This Internet-Draft is submitted in full conformance with the 19 provisions of BCP 78 and BCP 79. 21 Internet-Drafts are working documents of the Internet Engineering 22 Task Force (IETF). Note that other groups may also distribute 23 working documents as Internet-Drafts. The list of current Internet- 24 Drafts is at http://datatracker.ietf.org/drafts/current/. 26 Internet-Drafts are draft documents valid for a maximum of six months 27 and may be updated, replaced, or obsoleted by other documents at any 28 time. It is inappropriate to use Internet-Drafts as reference 29 material or to cite them other than as "work in progress." 31 This Internet-Draft will expire on January 17, 2018. 33 Copyright Notice 35 Copyright (c) 2017 IETF Trust and the persons identified as the 36 document authors. All rights reserved. 38 This document is subject to BCP 78 and the IETF Trust's Legal 39 Provisions Relating to IETF Documents 40 (http://trustee.ietf.org/license-info) in effect on the date of 41 publication of this document. Please review these documents 42 carefully, as they describe your rights and restrictions with respect 43 to this document. Code Components extracted from this document must 44 include Simplified BSD License text as described in Section 4.e of 45 the Trust Legal Provisions and are provided without warranty as 46 described in the Simplified BSD License. 48 Table of Contents 50 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 3 51 1.1. Notational Conventions . . . . . . . . . . . . . . . . . 3 52 1.2. Terminology . . . . . . . . . . . . . . . . . . . . . . . 4 53 1.3. Addition to the capabilities object . . . . . . . . . . . 4 54 2. Mailboxes . . . . . . . . . . . . . . . . . . . . . . . . . . 4 55 2.1. getMailboxes . . . . . . . . . . . . . . . . . . . . . . 7 56 2.2. getMailboxUpdates . . . . . . . . . . . . . . . . . . . . 8 57 2.3. setMailboxes . . . . . . . . . . . . . . . . . . . . . . 10 58 2.3.1. Ordering of changes . . . . . . . . . . . . . . . . . 11 59 2.3.2. Creating mailboxes . . . . . . . . . . . . . . . . . 11 60 2.3.3. Updating mailboxes . . . . . . . . . . . . . . . . . 12 61 2.3.4. Destroying mailboxes . . . . . . . . . . . . . . . . 13 62 2.3.5. Response . . . . . . . . . . . . . . . . . . . . . . 13 63 3. MessageLists . . . . . . . . . . . . . . . . . . . . . . . . 15 64 3.1. getMessageList . . . . . . . . . . . . . . . . . . . . . 16 65 3.1.1. Filtering . . . . . . . . . . . . . . . . . . . . . . 17 66 3.1.2. Sorting . . . . . . . . . . . . . . . . . . . . . . . 20 67 3.1.3. Thread collapsing . . . . . . . . . . . . . . . . . . 21 68 3.1.4. Windowing . . . . . . . . . . . . . . . . . . . . . . 22 69 3.1.5. Response . . . . . . . . . . . . . . . . . . . . . . 22 70 3.2. getMessageListUpdates . . . . . . . . . . . . . . . . . . 24 71 4. Threads . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 72 4.1. getThreads . . . . . . . . . . . . . . . . . . . . . . . 27 73 4.2. getThreadUpdates . . . . . . . . . . . . . . . . . . . . 29 74 5. Messages . . . . . . . . . . . . . . . . . . . . . . . . . . 31 75 5.1. getMessages . . . . . . . . . . . . . . . . . . . . . . . 36 76 5.2. getMessageUpdates . . . . . . . . . . . . . . . . . . . . 38 77 5.3. setMessages . . . . . . . . . . . . . . . . . . . . . . . 40 78 5.3.1. Saving a draft . . . . . . . . . . . . . . . . . . . 41 79 5.3.2. Updating messages . . . . . . . . . . . . . . . . . . 43 80 5.3.3. Sending messages . . . . . . . . . . . . . . . . . . 44 81 5.3.4. Cancelling a send . . . . . . . . . . . . . . . . . . 45 82 5.3.5. Destroying messages . . . . . . . . . . . . . . . . . 45 83 5.3.6. Response . . . . . . . . . . . . . . . . . . . . . . 45 84 5.4. importMessages . . . . . . . . . . . . . . . . . . . . . 47 85 5.5. copyMessages . . . . . . . . . . . . . . . . . . . . . . 48 86 6. Identities . . . . . . . . . . . . . . . . . . . . . . . . . 50 87 6.1. getIdentities . . . . . . . . . . . . . . . . . . . . . . 50 88 6.2. getIdentityUpdates . . . . . . . . . . . . . . . . . . . 51 89 6.3. setIdentities . . . . . . . . . . . . . . . . . . . . . . 53 90 7. SearchSnippets . . . . . . . . . . . . . . . . . . . . . . . 56 91 7.1. getSearchSnippets . . . . . . . . . . . . . . . . . . . . 57 92 8. Vacation Response . . . . . . . . . . . . . . . . . . . . . . 58 93 8.1. getVacationResponse . . . . . . . . . . . . . . . . . . . 59 94 8.2. setVacationResponse . . . . . . . . . . . . . . . . . . . 59 95 9. References . . . . . . . . . . . . . . . . . . . . . . . . . 61 96 9.1. Normative References . . . . . . . . . . . . . . . . . . 61 97 9.2. URIs . . . . . . . . . . . . . . . . . . . . . . . . . . 61 98 Author's Address . . . . . . . . . . . . . . . . . . . . . . . . 61 100 1. Introduction 102 JMAP is a generic protocol for synchronising data, such as mail, 103 calendars or contacts, between a client and a server. It is 104 optimised for mobile and web environments, and aims to provide a 105 consistent interface to different data types. 107 This specification defines a data model for synchronising mail 108 between a client and a server using JMAP. 110 1.1. Notational Conventions 112 The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", 113 "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this 114 document are to be interpreted as described in [RFC2119]. 116 The underlying format used for this specification is JSON. 117 Consequently, the terms "object" and "array" as well as the four 118 primitive types (strings, numbers, booleans, and null) are to be 119 interpreted as described in Section 1 of [RFC7159]. 121 Some examples in this document contain "partial" JSON documents used 122 for illustrative purposes. In these examples, three periods "..." 123 are used to indicate a portion of the document that has been removed 124 for compactness. 126 Types signatures are given for all JSON objects in this document. 127 The following conventions are used: 129 o "Boolean|String" - The value is either a JSON "Boolean" value, or 130 a JSON "String" value. 132 o "Foo" - Any name that is not a native JSON type means an object 133 for which the properties (and their types) are defined elsewhere 134 within this document. 136 o "Foo[]" - An array of objects of type "Foo". 138 o "String[Foo]" - A JSON "Object" being used as a map (associative 139 array), where all the values are of type "Foo". 141 1.2. Terminology 143 The same terminology is used in this document as in the core JMAP 144 specification. 146 1.3. Addition to the capabilities object 148 The capabilities object is returned as part of the standard JMAP 149 authentication response; see the JMAP spec. Servers supporting 150 _this_ specification MUST add a property called "{TODO: URI for this 151 spec}" to the capabilities object. The value of this property is an 152 object which SHOULD contain the following information on server 153 capabilities: 155 o *maxSizeMessageAttachments*: "Number" The maximum total size of 156 attachments, in bytes, allowed for messages. A server MAY still 157 reject messages with a lower attachment size total (for example, 158 if the body includes several megabytes of text, causing the size 159 of the encoded MIME structure to be over some server-defined 160 limit). 162 o *canDelaySend*: "Boolean" Does the server support inserting a 163 message into the outbox to be sent later at a user-specified time? 165 o *messageListSortOptions*: "String[]" A list of all the message 166 properties the server supports for sorting by. This MAY include 167 properties the client does not recognise (for example custom 168 properties specified in a vendor extension). Clients MUST ignore 169 any unknown properties in the list. 171 2. Mailboxes 173 A mailbox represents a named set of emails. This is the primary 174 mechanism for organising messages within an account. It is analogous 175 to a folder or a label in other systems. A mailbox may perform a 176 certain role in the system; see below for more details. 178 For compatibility with IMAP, a message MUST belong to one or more 179 mailboxes. The message id does not change if the message changes 180 mailboxes. 182 A *Mailbox* object has the following properties: 184 o *id*: "String" The id of the mailbox. This property is immutable. 186 o *name*: "String" User-visible name for the mailbox, e.g. "Inbox". 187 This may be any UTF-8 string ([RFC3629]) of at least 1 character 188 in length and maximum 256 bytes in size. Servers SHOULD forbid 189 sibling Mailboxes with the same name. 191 o *parentId*: "String|null" The mailbox id for the parent of this 192 mailbox, or "null" if this mailbox is at the top level. Mailboxes 193 form acyclic graphs (forests) directed by the child-to-parent 194 relationship. There MUST NOT be a loop. 196 o *role*: "String|null" Identifies system mailboxes. This property 197 can only be set on create. After the record has been created, 198 this property is immutable. The following values MUST be used for 199 the relevant mailboxes: 201 * "inbox" - the mailbox to which new mail is delivered by 202 default, unless diverted by a rule or spam filter etc. 204 * "archive" - messages the user does not need right now, but does 205 not wish to delete. 207 * "drafts" - messages the user is currently writing and are not 208 yet sent. 210 * "outbox" - messages the user has finished writing and wishes to 211 send (see the "setMessages" method description for more 212 information). A mailbox with this role MUST be present if the 213 user is allowed to send mail through an account. If not 214 present, the user cannot send mail with that account. 216 * "sent" - messages the user has sent. 218 * "trash" - messages the user has deleted. 220 * "spam" - messages considered spam by the server. 222 * "templates" - drafts which should be used as templates (i.e. 223 used as the basis for creating new drafts). 225 No two mailboxes may have the same role. Mailboxes without a 226 known purpose MUST have a role of "null". An account is not 227 required to have mailboxes with any of the above roles. A client 228 MAY create new mailboxes with a role property to help them keep 229 track of a use-case not covered by the above list. To avoid 230 potential conflict with any special behaviour a server might apply 231 to mailboxes with certain roles in the future, any roles not in 232 the above list created by the client must begin with ""x-"". The 233 client MAY attempt to create mailboxes with the standard roles if 234 not already present, but the server MAY reject these. 236 o *sortOrder*: "Number" Defines the sort order of mailboxes when 237 presented in the client's UI, so it is consistent between devices. 238 The number MUST be an integer in the range 0 <= sortOrder < 2^31. 239 A mailbox with a lower order should be displayed before a mailbox 240 with a higher order (that has the same parent) in any mailbox 241 listing in the client's UI. Mailboxes with equal order SHOULD be 242 sorted in alphabetical order by name. The sorting SHOULD take 243 into account locale-specific character order convention. 245 o *mustBeOnlyMailbox*: "Boolean" If "true", messages in this mailbox 246 may not also be in any other mailbox that also has 247 "mustBeOnlyMailbox: true". If "false", messages may be added to 248 this mailbox in addition to any other mailbox (i.e. it's a label). 249 This property is immutable. 251 o *mayReadItems*: "Boolean" If true, may use this mailbox as part of 252 a filter in a _getMessageList_ call. If a submailbox is shared 253 but not the parent mailbox, this may be "false". 255 o *mayAddItems*: "Boolean" The user may add messages to this mailbox 256 (by either creating a new message or moving an existing one). 258 o *mayRemoveItems*: "Boolean" The user may remove messages from this 259 mailbox (by either changing the mailboxes of a message or deleting 260 it). 262 o *mayCreateChild*: "Boolean" The user may create a mailbox with 263 this mailbox as its parent. 265 o *mayRename*: "Boolean" The user may rename the mailbox or make it 266 a child of another mailbox. 268 o *mayDelete*: "Boolean" The user may delete the mailbox itself. 270 o *totalMessages*: "Number" The number of messages in this mailbox. 272 o *unreadMessages*: "Number" The number of messages in this mailbox 273 that have neither the "$Seen" keyword nor the "$Draft" keyword. 275 o *totalThreads*: "Number" The number of threads where at least one 276 message in the thread is in this mailbox. 278 o *unreadThreads*: "Number" The number of threads where at least one 279 message in the thread has neither the "$Seen" keyword nor the 280 "$Draft" keyword AND at least one message in the thread is in this 281 mailbox (but see below for special case handling of Trash). Note, 282 the unread message does not need to be the one in this mailbox. 284 The Trash mailbox (that is a mailbox with "role == "trash"") MUST be 285 treated specially for the purpose of unread counts: 287 1. Messages that are *only* in the Trash (and no other mailbox) are 288 ignored when calculating the "unreadThreads" count of other 289 mailboxes. 291 2. Messages that are *not* in the Trash are ignored when calculating 292 the "unreadThreads" count for the Trash mailbox. 294 The result of this is that messages in the Trash are treated as 295 though they are in a separate thread for the purposes of unread 296 counts. It is expected that clients will hide messages in the Trash 297 when viewing a thread in another mailbox and vice versa. This allows 298 you to delete a single message to the Trash out of a thread. 300 So for example, suppose you have an account where the entire contents 301 is a single conversation with 2 messages: an unread message in the 302 Trash and a read message in the Inbox. The "unreadThreads" count 303 would be "1" for the Trash and "0" for the Inbox. 305 For IMAP compatibility, a message in both the Trash and another 306 mailbox SHOULD be treated by the client as existing in both places 307 (i.e. when emptying the trash, the client SHOULD just remove the 308 Trash mailbox and leave it in the other mailbox). 310 2.1. getMailboxes 312 Mailboxes can either be fetched explicitly by id, or all of them at 313 once. To fetch mailboxes, make a call to "getMailboxes". It takes 314 the following arguments: 316 o *accountId*: "String|null" The Account to fetch the mailboxes for. 317 If "null", the primary account is used. 319 o *ids*: "String[]|null" The ids of the mailboxes to fetch. If 320 "null", all mailboxes in the account are returned. 322 o *properties*: "String[]|null" The properties of each mailbox to 323 fetch. If "null", all properties are returned. The id of the 324 mailbox will *always* be returned, even if not explicitly 325 requested. 327 The response to _getMailboxes_ is called _mailboxes_. It has the 328 following arguments: 330 o *accountId*: "String" The id of the account used for the call. 332 o *state*: "String" A string representing the state on the server 333 for *all* mailboxes. If the state of a mailbox changes, or a new 334 mailbox is created, or a mailbox is destroyed, this string will 335 change. It is used to get delta updates. 337 o *list*: "Mailbox[]" An array of the Mailbox objects requested. 338 This will be the *empty array* if the _ids_ argument was the empty 339 array, or contained only ids for mailboxes that could not be 340 found. 342 o *notFound*: "String[]|null" This array contains the ids passed to 343 the method for mailboxes that do not exist, or "null" if all 344 requested ids were found. It MUST be "null" if the _ids_ argument 345 in the call was "null". 347 The following errors may be returned instead of the _mailboxes_ 348 response: 350 "accountNotFound": Returned if an _accountId_ was explicitly included 351 with the request, but it does not correspond to a valid account. 353 "accountNotSupportedByMethod": Returned if the _accountId_ given 354 corresponds to a valid account, but the account does not support this 355 data type. 357 "requestTooLarge": Returned if the number of _ids_ requested by the 358 client exceeds the maximum number the server is willing to process in 359 a single method call. 361 "invalidArguments": Returned if the request does not include one of 362 the required arguments, or one of the arguments is of the wrong type, 363 or otherwise invalid. A "description" property MAY be present on the 364 response object to help debug with an explanation of what the problem 365 was. 367 2.2. getMailboxUpdates 369 The _getMailboxUpdates_ call allows a client to efficiently update 370 the state of its cached mailboxes to match the new state on the 371 server. It takes the following arguments: 373 o *accountId*: "String|null" The id of the account to use for this 374 call. If "null", the primary account will be used. 376 o *sinceState*: "String" The current state of the client. This is 377 the string that was returned as the _state_ argument in the 378 _mailboxes_ response. The server will return the changes made 379 since this state. 381 o *fetchRecords*: "Boolean|null" If "true", immediately after 382 outputting a _mailboxUpdates_ response, an implicit call will be 383 made to _getMailboxes_ with the _changed_ property of the response 384 as the _ids_ argument, and the _fetchRecordProperties_ argument as 385 the _properties_ argument. If "false" or "null", no implicit call 386 will be made. 388 o *fetchRecordProperties*: "String[]|null" If "null", all Mailbox 389 properties will be fetched unless _onlyCountsChanged_ in the 390 _mailboxUpdates_ response is "true", in which case only the 4 391 counts properties will be returned (_totalMessages_, 392 _unreadMessages_, _totalThreads_ and _unreadThreads_). If not 393 "null", this value will be passed through to the _getMailboxes_ 394 call regardless of the _onlyCountsChanged_ value in the 395 _mailboxUpdates_ response. 397 The response to _getMailboxUpdates_ is called _mailboxUpdates_. It 398 has the following arguments: 400 o *accountId*: "String" The id of the account used for the call. 402 o *oldState*: "String" This is the _sinceState_ argument echoed 403 back; the state from which the server is returning changes. 405 o *newState*: "String" This is the state the client will be in after 406 applying the set of changes to the old state. 408 o *changed*: "String[]" An array of Mailbox ids where a property of 409 the mailbox has changed between the old state and the new state, 410 or the mailbox has been created, and the mailbox has not been 411 destroyed. 413 o *removed*: "String[]" An array of Mailbox ids for mailboxes which 414 have been destroyed since the old state. 416 o *onlyCountsChanged*: "Boolean" Indicates that only the mailbox 417 counts (unread/total messages/threads) have changed since the old 418 state. The client can then use this to optimise its data transfer 419 and only fetch the counts. If the server is unable to tell if 420 only counts have changed, it should just always return "false". 422 If a mailbox has been modified AND deleted since the oldState, the 423 server should just return the id in the _removed_ array, but MAY 424 return it in the _changed_ array as well. If a mailbox has been 425 created AND deleted since the oldState, the server SHOULD remove the 426 mailbox id from the response entirely, but MAY include it in the 427 _removed_ array. 429 The following errors may be returned instead of the "mailboxUpdates" 430 response: 432 "accountNotFound": Returned if an _accountId_ was explicitly included 433 with the request, but it does not correspond to a valid account. 435 "accountNotSupportedByMethod": Returned if the _accountId_ given 436 corresponds to a valid account, but the account does not support this 437 data type. 439 "invalidArguments": Returned if the request does not include one of 440 the required arguments, or one of the arguments is of the wrong type, 441 or otherwise invalid. A "description" property MAY be present on the 442 response object to help debug with an explanation of what the problem 443 was. 445 "cannotCalculateChanges": Returned if the server cannot calculate the 446 changes from the state string given by the client. Usually due to 447 the client's state being too old. The client MUST invalidate its 448 Mailbox cache. 450 2.3. setMailboxes 452 Mailboxes can be created, updated and destroyed using the 453 _setMailboxes_ method. The method takes the following arguments: 455 o *accountId*: "String|null" The id of the account to use for this 456 call. If "null", defaults to the primary account. 458 o *ifInState*: "String|null" This is a state string as returned by 459 the _getMailboxes_ method. If supplied, the string must match the 460 current state, otherwise the method will be aborted and a 461 "stateMismatch" error returned. If "null", any changes will be 462 applied to the current state. 464 o *create*: "String[Mailbox]|null" A map of _creation id_ (an 465 arbitrary string set by the client) to Mailbox objects. If 466 "null", no objects will be created. 468 o *update*: "String[Mailbox]|null" A map of mailbox id to objects 469 containing the properties to update for that Mailbox. If "null", 470 no objects will be updated. 472 o *destroy*: "String[]|null" A list of ids for Mailboxes to 473 permanently delete. If "null", no objects will be deleted. 475 If a create, update or destroy is rejected, the appropriate error 476 MUST be added to the notCreated/notUpdated/notDestroyed property of 477 the response and the server MUST continue to the next create/update/ 478 destroy. It does not terminate the method. 480 2.3.1. Ordering of changes 482 Each create, update or destroy is considered an atomic unit. The 483 server MAY commit some of the changes but not others, however MUST 484 NOT only commit part of an update to a single record (e.g. update the 485 _name_ field but not the _parentId_ field, if both are supplied in 486 the update object). 488 The final state MUST be valid after the setMailboxes is finished, 489 however the server MAY have to transition through invalid 490 intermediate states (not exposed to the client) while processing the 491 individual create/update/destroy requests. For example, a single 492 method call could rename Mailbox A => B, and simultaneously rename 493 Mailbox B => A. The final state is valid, so this is allowed, 494 however if processed sequentially there will be an internal state 495 where temporarily both mailboxes have the same name. 497 A Mailbox may reference another Mailbox object as a parent. When a 498 Mailbox is created or modified, it may reference another Mailbox 499 being created _in the same API request_ by using the creation id 500 prefixed with a "#". The order of the method calls in the request by 501 the client MUST be such that the mailbox being referenced is created 502 in *either the same or an earlier method call*. If within the same 503 method call, the server MUST process the parent create first, as if 504 this fails the create/update that references it will also fail. 506 Creation ids sent by the client SHOULD be unique within the single 507 API request for a particular data type. If a creation id is reused, 508 the server MUST map the creation id to the most recently created item 509 with that id. 511 2.3.2. Creating mailboxes 513 The properties of the Mailbox object submitted for creation MUST 514 conform to the following conditions: 516 o The _id_ property MUST NOT be present. 518 o The _parentId_ property MUST be either "null" or be a valid id for 519 a mailbox for which the "mayCreateChild" property is "true". 521 o The _role_ property MUST be either "null", a valid role as listed 522 in the Mailbox object specification, or prefixed by ""x-"". 524 o The _mustBeOnlyMailbox_ property MUST NOT be present. This is 525 server dependent and will be set by the server. 527 o The _mayXXX_ properties MUST NOT be present. Restrictions may 528 only be set by the server for system mailboxes, or when sharing 529 mailboxes with other users (setting sharing is not defined yet in 530 this spec). 532 o The _totalMessages_, _unreadMessages_, _totalThreads_ and 533 _unreadThreads_ properties MUST NOT be present. 535 If any of the properties are invalid, the server MUST reject the 536 create with an "invalidProperties" error. The Error object SHOULD 537 contain a property called _properties_ of type "String[]" that lists 538 *all* the properties that were invalid. The object MAY also contain 539 a _description_ property of type "String" with a user-friendly 540 description of the problems. 542 There may be a maximum number of mailboxes allowed on the server. If 543 this is reached, any attempt at creation will be rejected with a 544 "maxQuotaReached" error. 546 2.3.3. Updating mailboxes 548 If the _id_ given does not correspond to a Mailbox in the given 549 account, the update MUST be rejected with a "notFound" error. 551 All properties being updated must be of the correct type, not 552 immutable or server-set-only, and the new value must obey all 553 conditions of the property. In particular, note the following 554 conditions: 556 o The _name_ property MUST be a valid UTF-8 string of at least 1 557 character in length and maximum 256 bytes in size. 559 o The _parentId_ property MUST be either "null" or be a valid id for 560 _another_ mailbox that is *not a descendant* of this mailbox, and 561 for which the "mayCreateChild" property is "true". 563 o These properties are immutable or may only be set by the server: 565 * id 567 * role 569 * mustBeOnlyMailbox 571 * mayReadItems 572 * mayAddItems 574 * mayRemoveItems 576 * mayCreateChild 578 * mayRename 580 * mayDelete 582 * totalMessages 584 * unreadMessages 586 * totalThreads 588 * unreadThreads 590 If any of the properties are invalid, the server MUST reject the 591 update with an "invalidProperties" error. The Error object SHOULD 592 contain a property called _properties_ of type "String[]" that lists 593 *all* the properties that were invalid. The object MAY also contain 594 a _description_ property of type "String" with a user-friendly 595 description of the problems. 597 2.3.4. Destroying mailboxes 599 If the _id_ given does not correspond to a Mailbox in the given 600 account, the destruction MUST be rejected with a "notFound" error. 602 If the mailbox has "mayDeleteMailbox == false", the destruction MUST 603 be rejected with a "forbidden" error. 605 A mailbox MUST NOT be destroyed if it still has any child mailboxes. 606 Attempts to do so MUST be rejected with a "mailboxHasChild" error. 608 A mailbox MUST NOT be destroyed if it has any messages assigned to 609 it. Attempts to do so MUST be rejected with a "mailboxHasMessage" 610 error. 612 2.3.5. Response 614 The response to _setMailboxes_ is called _mailboxesSet_. It has the 615 following arguments: 617 o *accountId*: "String" The id of the account used for the call. 619 o *oldState*: "String|null" The state string that would have been 620 returned by "getMailboxes" before making the requested changes, or 621 "null" if the server doesn't know what the previous state string 622 was. 624 o *newState*: "String" The state string that will now be returned by 625 "getMailboxes". 627 o *created*: "String[Mailbox]" A map of the creation id to an object 628 containing all server-set properties for each successfully created 629 Mailbox: _id_, _mustBeOnlyMailbox_, all _mayXXX_ properties, 630 _totalMessages_, _unreadMessages_, _totalThreads_ and 631 _unreadThreads_. 633 o *updated*: "String[Mailbox|null]" The _keys_ in this map are the 634 ids of all mailboxes that were successfully updated. If the 635 server made any other changes to the record beyond those 636 explicitly requested by the client, the _value_ for the 637 corresponding id in the map is an object containing the updated 638 value of each property the *server changed*. Otherwise (if no 639 properties changed on the server other than those explicitly 640 updated by the client), the value is "null". 642 o *destroyed*: "String[]" A list of ids for Mailboxes that were 643 successfully destroyed. 645 o *notCreated*: "String[SetError]" A map of creation id to a 646 SetError object for each Mailbox that failed to be created. The 647 possible errors are defined above. 649 o *notUpdated*: "String[SetError]" A map of Mailbox id to a SetError 650 object for each Mailbox that failed to be updated. The possible 651 errors are defined above. 653 o *notDestroyed*: "String[SetError]" A map of Mailbox id to a 654 SetError object for each Mailbox that failed to be destroyed. The 655 possible errors are defined above. 657 The following errors may be returned instead of the _mailboxesSet_ 658 response: 660 "accountNotFound": Returned if an _accountId_ was explicitly included 661 with the request, but it does not correspond to a valid account. 663 "accountNotSupportedByMethod": Returned if the _accountId_ given 664 corresponds to a valid account, but the account does not support this 665 data type. 667 "accountReadOnly": Returned if the account has "isReadOnly == true". 669 "requestTooLarge": Returned if the total number of objects to create, 670 update or destroy exceeds the maximum number the server is willing to 671 process in a single method call. 673 "invalidArguments": Returned if one of the arguments is of the wrong 674 type, or otherwise invalid. A _description_ property MAY be present 675 on the response object to help debug with an explanation of what the 676 problem was. 678 "stateMismatch": Returned if an "ifInState" argument was supplied and 679 it does not match the current state. 681 Example request: 683 [ "setMailboxes", { 684 "ifInState": "ms4123", 685 "update": { 686 "f3": { 687 "name": "The new name" 688 } 689 }, 690 "destroy": [ "f5" ] 691 }, "#0" ] 693 3. MessageLists 695 A *MessageList* is a sorted query on the set of messages in a user's 696 account. Since it can be very long, the client must specify what 697 section of the list to return. The client can optionally also fetch 698 the threads and/or messages for this part of the list. 700 The same message may appear in multiple messages lists. For example, 701 it may belong to multiple mailboxes, and of course it can appear in 702 searches. Since messages have an immutable id, a client can easily 703 tell if it already has a message cached and only fetch the ones it 704 needs. 706 When the state changes on the server, a delta update can be requested 707 to efficiently update the client's cache of this list to the new 708 state. If the server doesn't support this, the client still only 709 needs to fetch the message list again, not the messages themselves. 711 3.1. getMessageList 713 To fetch a message list, make a call to _getMessageList_. It takes 714 the following arguments: 716 o *accountId*: "String|null" The id of the account to use for this 717 call. If "null", the primary account will be used. 719 o *filter*: "FilterCondition|FilterOperator|null" Determines the set 720 of messages returned in the results. See the "Filtering" section 721 below for allowed values and semantics. 723 o *sort*: "String[]|null" A list of Message property names to sort 724 by. See the "Sorting" section below for allowed values and 725 semantics. 727 o *collapseThreads*: "Boolean|null" If true, each thread will only 728 be returned once in the resulting list, at the position of the 729 first message in the list (given the filter and sort order) 730 belonging to the thread. If "false" or "null", threads may be 731 returned multiple times. 733 o *position*: "Number|null" The 0-based index of the first result in 734 the list to return. If a negative value is given, the call MUST 735 be rejected with an "invalidArguments" error. If "null", 0 is 736 used. 738 o *anchor*: "String|null" A Message id. The index of this message 739 id will be used in combination with the "anchorOffset" argument to 740 determine the index of the first result to return (see the 741 "Windowing" section below for more details). 743 o *anchorOffset*: "Number|null" The index of the anchor message 744 relative to the index of the first result to return. This MAY be 745 negative. For example, "-1" means the first message after the 746 anchor message should be the first result in the results returned 747 (see the "Windowing" section below for more details). 749 o *limit*: "Number|null" The maximum number of results to return. 750 If "null", no limit is presumed. The server MAY choose to enforce 751 a maximum "limit" argument. In this case, if a greater value is 752 given, the limit should be clamped to the maximum; since the total 753 number of results in the list is returned, the client should not 754 be relying on how many results are returned to determine if it has 755 reached the end of the list. If a negative value is given, the 756 call MUST be rejected with an "invalidArguments" error. 758 o *fetchThreads*: "Boolean|null" If "true", after outputting a 759 _messageList_ response, an implicit call will be made to 760 _getThreads_ with the _threadIds_ array in the response as the 761 _ids_ argument, and the _fetchMessages_ and 762 _fetchMessageProperties_ arguments passed straight through from 763 the call to _getMessageList_. If "false" or "null", no implicit 764 call will be made. 766 o *fetchMessages*: "Boolean|null" If "true" and "fetchThreads == 767 false", then after outputting a _messageList_ response, an 768 implicit call will be made to _getMessages_ with the "messageIds" 769 array in the response as the _ids_ argument, and the 770 _fetchMessageProperties_ argument as the _properties_ argument. 771 If "false" or "null", no implicit call will be made. 773 o *fetchMessageProperties*: "String[]|null" The list of properties 774 to fetch on any fetched messages. See _getMessages_ for a full 775 description. 777 o *fetchSearchSnippets*: "Boolean|null" If "true", then after 778 outputting a _messageList_ and making any other implicit calls, an 779 implicit call will be made to _getSearchSnippets_. The 780 _messageIds_ array from the response will be used as the 781 _messageIds_ argument, and the _filter_ argument will be passed 782 straight through. If "false" or "null", no implicit call will be 783 made. 785 3.1.1. Filtering 787 A *FilterOperator* object has the following properties: 789 o *operator*: "String" This MUST be one of the following strings: 790 "AND"/"OR"/"NOT": 792 * *AND*: all of the conditions must match for the filter to 793 match. 795 * *OR*: at least one of the conditions must match for the filter 796 to match. 798 * *NOT*: none of the conditions must match for the filter to 799 match. 801 o *conditions*: "(FilterCondition|FilterOperator)[]" The conditions 802 to evaluate against each message. 804 A *FilterCondition* object has the following properties: 806 o *inMailbox*: "String|null" A mailbox id. A message must be in 807 this mailbox to match the condition. 809 o *inMailboxOtherThan*: "String|null" A mailbox id. A message be in 810 any mailbox other than this one to match the condition. This is 811 to allow messages solely in trash/spam to be easily excluded from 812 a search. 814 o *before*: "Date|null" The date of the message (as returned on the 815 Message object) must be before this date to match the condition. 817 o *after*: "Date|null" The date of the message (as returned on the 818 Message object) must be on or after this date to match the 819 condition. 821 o *minSize*: "Number|null" The size of the message in bytes (as 822 returned on the Message object) must be equal to or greater than 823 this number to match the condition. 825 o *maxSize*: "Number|null" The size of the message in bytes (as 826 returned on the Message object) must be less than this number to 827 match the condition. 829 o *allInThreadHaveKeyword*: "String" All messages (including this 830 one) in the same thread as this message must have the given 831 keyword to match the condition. 833 o *someInThreadHaveKeyword*: "String" At least one message (possibly 834 this one) in the same thread as this message must have the given 835 keyword to match the condition. 837 o *noneInThreadHaveKeyword*: "String" All messages (including this 838 one) in the same thread as this message must *not* have the given 839 keyword to match the condition. 841 o *hasKeyword*: "String" This message must have the given keyword to 842 match the condition. 844 o *notKeyword*: "String" This message must not have the given 845 keyword to match the condition. 847 o *hasAttachment*: "Boolean|null" The "hasAttachment" property of 848 the message must be identical to the value given to match the 849 condition. 851 o *text*: "String|null" Looks for the text in the _from_, _to_, 852 _cc_, _bcc_, _subject_, _textBody_ or _htmlBody_ properties of the 853 message. 855 o *from*: "String|null" Looks for the text in the _from_ property of 856 the message. 858 o *to*: "String|null" Looks for the text in the _to_ property of the 859 message. 861 o *cc*: "String|null" Looks for the text in the _cc_ property of the 862 message. 864 o *bcc*: "String|null" Looks for the text in the _bcc_ property of 865 the message. 867 o *subject*: "String|null" Looks for the text in the _subject_ 868 property of the message. 870 o *body*: "String|null" Looks for the text in the _textBody_ or 871 _htmlBody_ property of the message. 873 o *header*: "String[]|null" The array MUST contain either one or two 874 elements. The first element is the name of the header to match 875 against. The second (optional) element is the text to look for in 876 the header. If not supplied, the message matches simply if it 877 _has_ a header of the given name. 879 If zero properties are specified on the FilterCondition, the 880 condition MUST always evaluate to "true". If multiple properties are 881 specified, ALL must apply for the condition to be "true" (it is 882 equivalent to splitting the object into one-property conditions and 883 making them all the child of an AND filter operator). 885 The exact semantics for matching "String" fields is *deliberately not 886 defined* to allow for flexibility in indexing implementation, subject 887 to the following: 889 o Text SHOULD be matched in a case-insensitive manner. 891 o Text contained in either (but matched) single or double quotes 892 SHOULD be treated as a *phrase search*, that is a match is 893 required for that exact word or sequence of words, excluding the 894 surrounding quotation marks. Use "\"", "\'" and "\\" to match a 895 literal """, "'" and "\" respectively in a phrase. 897 o Outside of a phrase, white-space SHOULD be treated as dividing 898 separate tokens that may be searched for separately in the 899 message, but MUST all be present for the message to match the 900 filter. 902 o Tokens MAY be matched on a whole-word basis using stemming (so for 903 example a text search for "bus" would match "buses" but not 904 "business"). 906 o When searching inside the _htmlBody_ property, HTML tags and 907 attributes SHOULD be ignored. 909 3.1.2. Sorting 911 The "sort" argument lists the properties to compare between two 912 messages to determine which comes first in the sort. If two messages 913 have an identical value for the first property, the next property 914 will be considered and so on. If all properties are the same (this 915 includes the case where an empty array or "null" is given as the 916 argument), the sort order is server-dependent, but MUST be stable 917 between calls to "getMessageList". 919 Following the property name there MUST be a space and then either the 920 string "asc" or "desc" to specify ascending or descending sort for 921 that property. 923 The following properties MUST be supported for sorting: 925 o *id* - The id as returned in the Message object. 927 o *date* - The date as returned in the Message object. 929 The following properties SHOULD be supported for sorting: 931 o *size* - The size as returned in the Message object. 933 o *from* - This is taken to be either the "name" part of the Emailer 934 object, or if none then the "email" part of the Emailer object 935 (see the definition of the from property in the Message object). 936 If still none, consider the value to be the empty string. 938 o *to* - This is taken to be either the "name" part of the *first* 939 Emailer object, or if none then the "email" part of the *first* 940 Emailer object (see the definition of the to property in the 941 Message object). If still none, consider the value to be the 942 empty string. 944 o *subject* - This is taken to be the subject of the Message with 945 any ignoring any leading "Fwd:"s or "Re:"s (case-insensitive 946 match). 948 o *keyword:*"$keyword" - This value MUST be considered "true" if the 949 message has the keyword, or "false" otherwise. 951 o *allThreadKeyword:*"$keyword" - This value MUST be considered 952 "true" for the message if *all* of the messages in the same thread 953 (regardless of mailbox) have the keyword. 955 o *someThreadKeyword:*"$keyword" - This value MUST be considered 956 "true" for the message if *any* of the messages in the same thread 957 (regardless of mailbox) have the keyword. 959 The server MAY support sorting based on other properties as well. A 960 client can discover which properties are supported by inspecting the 961 server's _capabilities_ object (see section 1). 963 The method of comparison depends on the type of the property: 965 o "String": Comparison function is server-dependent. It SHOULD be 966 case-insensitive and SHOULD take into account locale-specific 967 conventions if known for the user. However, the server MAY choose 968 to just sort based on unicode code point, after best-effort 969 translation to lower-case. 971 o "Date": If sorting in ascending order, the earlier date MUST come 972 first. 974 o "Boolean": If sorting in ascending order, a "false" value MUST 975 come before a "true" value. 977 Example sort: 979 `[ "someThreadKeyword:$Flagged desc", "date desc" ] 981 This would sort messages in flagged threads first (the thread is 982 considered flagged if any message within it is flagged), and then in 983 date order, newest first. If two messages have both identical 984 flagged status and date, the order is server-dependent but must be 985 stable. 987 3.1.3. Thread collapsing 989 When "collapseThreads == true", then after filtering and sorting the 990 message list, the list is further winnowed by removing any messages 991 for a thread id that has already been seen (when passing through the 992 list sequentially). A thread will therefore only appear *once* in 993 the "threadIds" list of the result, at the position of the first 994 message in the list that belongs to the thread. 996 3.1.4. Windowing 998 If a _position_ offset is supplied, then this is the 0-based index of 999 the first result to return in the list of messages after filtering, 1000 sorting and collapsing threads. If the index is greater than or 1001 equal to the total number of messages in the list, then there are no 1002 results to return, but this DOES NOT generate an error. If 1003 _position_ is "null" (or, equivalently, omitted) this MUST be 1004 interpreted as "position: 0". 1006 Alternatively, a message id, called the *anchor* may be given. In 1007 this case, after filtering, sorting and collapsing threads, the 1008 anchor is searched for in the message list. If found, the *anchor 1009 offset* is then subtracted from this index. If the resulting index 1010 is now negative, it is clamped to 0. This index is now used exactly 1011 as though it were supplied as the "position" argument. If the anchor 1012 is not found, the call is rejected with an "anchorNotFound" error. 1014 If an _anchor_ is specified, any position argument supplied by the 1015 client MUST be ignored. If _anchorOffset_ is "null", it defaults to 1016 "0". If no _anchor_ is supplied, any anchor offset argument MUST be 1017 ignored. 1019 3.1.5. Response 1021 The response to a call to _getMessageList_ is called _messageList_. 1022 It has the following arguments: 1024 o *accountId*: "String" The id of the account used for the call. 1026 o *filter*: "FilterCondition|FilterOperator|null" The filter of the 1027 message list. Echoed back from the call. 1029 o *sort*: "String[]|null" A list of Message property names used to 1030 sort by. Echoed back from the call. 1032 o *collapseThreads*: "Boolean|null" Echoed back from the call. 1034 o *state*: "String" A string encoding the current state on the 1035 server. This string will change if the results of the message 1036 list MAY have changed (for example, there has been a change to the 1037 state of the set of Messages; it does not guarantee that anything 1038 in the list has changed). It may be passed to 1039 _getMessageListUpdates_ to efficiently get the set of changes from 1040 the previous state. Should a client receive back a response with 1041 a different state string to a previous call, it MUST either throw 1042 away the currently cached list and fetch it again (note, this does 1043 not require fetching the messages again, just the list of ids) or, 1044 if the server supports it, call _getMessageListUpdates_ to get the 1045 delta difference. 1047 o *canCalculateUpdates*: "Boolean" This is "true" if the server 1048 supports calling "getMessageListUpdates" with these 1049 "filter"/"sort"/"collapseThreads" parameters. Note, this does not 1050 guarantee that the getMessageListUpdates call will succeed, as it 1051 may only be possible for a limited time afterwards due to server 1052 internal implementation details. 1054 o *position*: "Number" The 0-based index of the first result in the 1055 "threadIds" array within the complete list. 1057 o *total*: "Number" The total number of messages in the message list 1058 (given the _filter_ and _collapseThreads_ arguments). 1060 o *threadIds*: "String[]" The list of Thread ids for each message in 1061 the list after filtering, sorting and collapsing threads, starting 1062 at the index given by the _position_ argument of this response, 1063 and continuing until it hits the end of the list or reaches the 1064 "limit" number of ids. 1066 o *messageIds*: "String[]" The list of Message ids for each message 1067 in the list after filtering, sorting and collapsing threads, 1068 starting at the index given by the _position_ argument of this 1069 response, and continuing until it hits the end of the list or 1070 reaches the "limit" number of ids. 1072 The following errors may be returned instead of the "messageList" 1073 response: 1075 "accountNotFound": Returned if an _accountId_ was explicitly included 1076 with the request, but it does not correspond to a valid account. 1078 "accountNotSupportedByMethod": Returned if the _accountId_ given 1079 corresponds to a valid account, but the account does not support this 1080 data type. 1082 "unsupportedSort": Returned if the _sort_ includes a property the 1083 server does not support sorting on. 1085 "cannotDoFilter": Returned if the server is unable to process the 1086 given _filter_ for any reason. 1088 "invalidArguments": Returned if the request does not include one of 1089 the required arguments, or one of the arguments is of the wrong type, 1090 or otherwise invalid. A "description" property MAY be present on the 1091 response object to help debug with an explanation of what the problem 1092 was. 1094 "anchorNotFound": Returned if an anchor argument was supplied, but it 1095 cannot be found in the message list. 1097 3.2. getMessageListUpdates 1099 The "getMessageListUpdates" call allows a client to efficiently 1100 update the state of any cached message list to match the new state on 1101 the server. It takes the following arguments: 1103 o *accountId*: "String|null" The id of the account to use for this 1104 call. If "null", the primary account will be used. 1106 o *filter*: "FilterCondition|FilterOperator|null" The filter 1107 argument that was used with _getMessageList_. 1109 o *sort*: "String[]|null" The sort argument that was used with 1110 _getMessageList_. 1112 o *collapseThreads*: "Boolean|null" The _collapseThreads_ argument 1113 that was used with _getMessageList_. 1115 o *sinceState*: "String" The current state of the client. This is 1116 the string that was returned as the _state_ argument in the 1117 _messageList_ response. The server will return the changes made 1118 since this state. 1120 o *uptoMessageId*: "String|null" The message id of the last message 1121 in the list that the client knows about. In the common case of 1122 the client only having the first X ids cached, this allows the 1123 server to ignore changes further down the list the client doesn't 1124 care about. 1126 o *maxChanges*: "Number|null" The maximum number of changes to 1127 return in the response. See below for a more detailed 1128 description. 1130 The response to _getMessageListUpdates_ is called 1131 _messageListUpdates_ It has the following arguments: 1133 o *accountId*: "String" The id of the account used for the call. 1135 o *filter*: "FilterCondition|FilterOperator|null" The filter of the 1136 message list. Echoed back from the call. 1138 o *sort*: "String[]|null" A list of Message property names used to 1139 sort by. Echoed back from the call. 1141 o *collapseThreads*: "Boolean|null" Echoed back from the call. 1143 o *oldState*: "String" This is the "sinceState" argument echoed 1144 back; the state from which the server is returning changes. 1146 o *newState*: "String" This is the state the client will be in after 1147 applying the set of changes to the old state. 1149 o *uptoMessageId*: "String|null" Echoed back from the call. 1151 o *total*: "Number" The total number of messages in the message list 1152 (given the filter and collapseThreads arguments). 1154 o *removed*: "RemovedItem[]" The _messageId_ and _threadId_ for 1155 every message that was in the list in the old state and is not in 1156 the list in the new state. If the server cannot calculate this 1157 exactly, the server MAY return extra messages in addition that MAY 1158 have been in the old list but are not in the new list. If an 1159 _uptoMessageId_ was given AND this id was found in the list, only 1160 messages positioned before this message that were removed need be 1161 returned. In addition, if the sort includes a keyword, the server 1162 MUST include all messages in the current list for which this 1163 keyword MAY have changed. If the sort includes a "some/all-in- 1164 thread-keyword", then the server MUST include all messages in the 1165 current list for which this keyword MAY have changed *on any of 1166 the messages in the thread*. 1168 o *added*: "AddedItem[]" The messageId and threadId and index in the 1169 list (in the new state) for every message that has been added to 1170 the list since the old state AND every message in the current list 1171 that was included in the _removed_ array (due to a filter or sort 1172 based upon a mutable property). The array MUST be sorted in order 1173 of index, lowest index first. If an _uptoMessageId_ was given AND 1174 this id was found in the list, only messages positioned before 1175 this message that have been added need be returned. 1177 A *RemovedItem* object has the following properties: 1179 o *messageId*: "String" 1181 o *threadId*: "String" 1183 An *AddedItem* object has the following properties: 1185 o *messageId*: "String" 1186 o *threadId*: "String" 1188 o *index*: "Number" 1190 The result of this should be that if the client has a cached sparse 1191 array of message ids in the list in the old state: 1193 messageIds = [ "id1", "id2", null, null, "id3", "id4", null, null, null ] 1195 then if it *splices out* all messages in the removed array: 1197 removed = [{ messageId: "id2", ... }]; 1198 messageIds => [ "id1", null, null, "id3", "id4", null, null, null ] 1200 and *splices in* (in order) all of the messages in the added array: 1202 added = [{ messageId: "id5", index: 0, ... }]; 1203 messageIds => [ "id5", "id1", null, null, "id3", "id4", null, null, null ] 1205 then the message list will now be in the new state. 1207 The following errors may be returned instead of the 1208 "messageListUpdates" response: 1210 "accountNotFound": Returned if an _accountId_ was explicitly included 1211 with the request, but it does not correspond to a valid account. 1213 "accountNotSupportedByMethod": Returned if the _accountId_ given 1214 corresponds to a valid account, but the account does not support this 1215 data type. 1217 "invalidArguments": Returned if the request does not include one of 1218 the required arguments, or one of the arguments is of the wrong type, 1219 or otherwise invalid. A _description_ property MAY be present on the 1220 response object to help debug with an explanation of what the problem 1221 was. 1223 "tooManyChanges": Returned if there are more changes the the client's 1224 _maxChanges_ argument. Each item in the removed or added array is 1225 considered as one change. The client may retry with a higher max 1226 changes or invalidate its cache of the message list. 1228 "cannotCalculateChanges": Returned if the server cannot calculate the 1229 changes from the state string given by the client. Usually due to 1230 the client's state being too old. The client MUST invalidate its 1231 cache of the message list. 1233 4. Threads 1235 Replies are grouped together with the original message to form a 1236 thread. In JMAP, a thread is simply a flat list of messages, ordered 1237 by date. Every message MUST belong to a thread, even if it is the 1238 only message in the thread. 1240 The JMAP spec does not require the server to use any particular 1241 algorithm for determining whether two messages belong to the same 1242 thread, however there is a recommended algorithm in the 1243 implementation guide [1]. 1245 If messages are delivered out of order for some reason, a user may 1246 receive two messages in the same thread but without headers that 1247 associate them with each other. The arrival of a third message in 1248 the thread may provide the missing references to join them all 1249 together into a single thread. Since the "threadId" of a message is 1250 immutable, if the server wishes to merge the threads, it MUST handle 1251 this by deleting and reinserting (with a new message id) the messages 1252 that change threadId. 1254 A *Thread* object has the following properties: 1256 o *id*: "String" The id of the thread. This property is immutable. 1258 o *messageIds*: "String[]" The ids of the messages in the thread, 1259 sorted such that: 1261 * Any message with the "$Draft" keyword that has an "In-Reply-To" 1262 header is sorted after the _first_ non-draft message in the 1263 thread with the corresponding "Message-Id" header, but before 1264 any subsequent non-draft messages. 1266 * Other than that, everything is sorted in _date_ order (as 1267 determined by the date property on the _Message_ object), 1268 oldest first. 1270 * If two messages are identical under the above two conditions, 1271 the sort is server-dependent but MUST be stable (sorting by id 1272 is recommended). 1274 4.1. getThreads 1276 Threads can only be fetched explicitly by id. To fetch threads, make 1277 a call to _getThreads_. It takes the following arguments: 1279 o *accountId*: "String|null" The id of the account to use for this 1280 call. If not given, defaults to the primary account. 1282 o *ids*: "String[]" An array of ids for the threads to fetch. 1284 o *fetchMessages*: "Boolean|null" If true, after outputting a 1285 _threads_ response, an implicit call will be made to _getMessages_ 1286 with a list of all message ids in the returned threads as the 1287 _ids_ argument, and the _fetchMessageProperties_ argument as the 1288 _properties_ argument. If "false" or "null", no implicit call 1289 will be made. 1291 o *fetchMessageProperties*: "String[]|null" The list of properties 1292 to fetch on any fetched messages. See _getMessages_ for a full 1293 description. 1295 The response to _getThreads_ is called _threads_. It has the 1296 following arguments: 1298 o *accountId*: "String" The id of the account used for the call. 1300 o *state*: "String" A string encoding the current state on the 1301 server. This string will change if any threads change (that is, 1302 new messages arrive, or messages are deleted, as these are the 1303 only two events that change thread membership). It can be passed 1304 to _getThreadUpdates_ to efficiently get the list of changes from 1305 the previous state. 1307 o *list*: "Thread[]" An array of Thread objects for the requested 1308 thread ids. This may not be in the same order as the ids were in 1309 the request. 1311 o *notFound*: "String[]|null" An array of thread ids requested which 1312 could not be found, or "null" if all ids were found. 1314 The following errors may be returned instead of the "threads" 1315 response: 1317 "accountNotFound": Returned if an _accountId_ was explicitly included 1318 with the request, but it does not correspond to a valid account. 1320 "accountNotSupportedByMethod": Returned if the _accountId_ given 1321 corresponds to a valid account, but the account does not support this 1322 data type. 1324 "requestTooLarge": Returned if the number of _ids_ requested by the 1325 client exceeds the maximum number the server is willing to process in 1326 a single method call. 1328 "invalidArguments": Returned if the request does not include one of 1329 the required arguments, or one of the arguments is of the wrong type, 1330 or otherwise invalid. A _description_ property MAY be present on the 1331 response object to help debug with an explanation of what the problem 1332 was. 1334 Example of a successful request: 1336 [ "getThreads", { 1337 "ids": ["f123u4", "f41u44"], 1338 "fetchMessages": false, 1339 "fetchMessageProperties": null 1340 }, "#1" ] 1342 and response: 1344 [ "threads", { 1345 "state": "f6a7e214", 1346 "list": [ 1347 { 1348 "id": "f123u4", 1349 "messageIds": [ "eaa623", "f782cbb"] 1350 }, 1351 { 1352 "id": "f41u44", 1353 "messageIds": [ "82cf7bb" ] 1354 } 1355 ], 1356 "notFound": null 1357 }, "#1" ] 1359 4.2. getThreadUpdates 1361 When messages are created or deleted, new threads may be created, or 1362 the set of messages belonging to an existing thread may change. If a 1363 call to _getThreads_ returns with a different _state_ string in the 1364 response to a previous call, the state of the threads has changed on 1365 the server and the client needs to work out which part of its cache 1366 is now invalid. 1368 The _getThreadUpdates_ call allows a client to efficiently update the 1369 state of any cached threads to match the new state on the server. It 1370 takes the following arguments: 1372 o *accountId*: "String|null" The id of the account to use for this 1373 call. If not given, defaults to the primary account. 1375 o *sinceState*: "String" The current state of the client. This is 1376 the string that was returned as the _state_ argument in the 1377 _threads_ response. The server will return the changes made since 1378 this state. 1380 o *maxChanges*: "Number|null" The maximum number of Thread ids to 1381 return in the response. The server MAY choose to clamp this value 1382 to a particular maximum or set a maximum if none is given by the 1383 client. If supplied by the client, the value MUST be a positive 1384 integer greater than 0. If a value outside of this range is 1385 given, the server MUST reject the call with an "invalidArguments" 1386 error. 1388 o *fetchRecords*: "Boolean|null" If "true", immediately after 1389 outputting a _threadUpdates_ response, an implicit call will be 1390 made to _getThreads_ with the _changed_ property of the response 1391 as the _ids_ argument, and _fetchMessages_ equal to "false". 1393 The response to _getThreadUpdates_ is called _threadUpdates_. It has 1394 the following arguments: 1396 o *accountId*: "String" The id of the account used for the call. 1398 o *oldState*: "String" This is the _sinceState_ argument echoed 1399 back; the state from which the server is returning changes. 1401 o *newState*: "String" This is the state the client will be in after 1402 applying the set of changes to the old state. 1404 o *hasMoreUpdates*: "Boolean" If "true", the client may call 1405 _getThreadUpdates_ again with the _newState_ returned to get 1406 further updates. If "false", _newState_ is the current server 1407 state. 1409 o *changed*: "String[]" An array of thread ids where the list of 1410 messages within the thread has changed between the old state and 1411 the new state, and the thread currently has at least one message 1412 in it. 1414 o *removed*: "String[]" An array of thread ids where the list of 1415 messages within the thread has changed since the old state, and 1416 there are now no messages in the thread. 1418 If a _maxChanges_ is supplied, or set automatically by the server, 1419 the server MUST ensure the number of ids returned across _changed_ 1420 and _removed_ does not exceed this limit. If there are more changes 1421 than this between the client's state and the current server state, 1422 the update returned SHOULD generate an update to take the client to 1423 an intermediate state, from which the client can continue to call 1424 _getThreadUpdates_ until it is fully up to date. If it is unable to 1425 calculate an intermediate state, it MUST return a 1426 "cannotCalculateChanges" error response instead. 1428 If a thread has been modified AND deleted since the oldState, the 1429 server SHOULD just return the id in the _removed_ response, but MAY 1430 return it in the changed response as well. If a thread has been 1431 created AND deleted since the oldState, the server SHOULD remove the 1432 thread id from the response entirely, but MAY include it in the 1433 _removed_ response. 1435 The following errors may be returned instead of the _threadUpdates_ 1436 response: 1438 "accountNotFound": Returned if an _accountId_ was explicitly included 1439 with the request, but it does not correspond to a valid account. 1441 "accountNotSupportedByMethod": Returned if the _accountId_ given 1442 corresponds to a valid account, but the account does not support this 1443 data type. 1445 "invalidArguments": Returned if the request does not include one of 1446 the required arguments, or one of the arguments is of the wrong type, 1447 or otherwise invalid. A _description_ property MAY be present on the 1448 response object to help debug with an explanation of what the problem 1449 was. 1451 "cannotCalculateChanges": Returned if the server cannot calculate the 1452 changes from the state string given by the client. Usually due to 1453 the client's state being too old, or the server being unable to 1454 produce an update to an intermediate state when there are too many 1455 updates. The client MUST invalidate its Thread cache. 1457 5. Messages 1459 Just like in IMAP, a message is *immutable* except for the boolean 1460 "isXXX" status properties and the set of mailboxes it is in. This 1461 allows for more efficient caching of messages, and gives easier 1462 backwards compatibility for servers implementing an IMAP interface to 1463 the same data. 1465 JMAP completely hides the complexities of MIME. All special 1466 encodings of either headers or textual body parts, such as base64 1467 [2], or RFC 2047 [3] encoding of non-ASCII characters, MUST be fully 1468 decoded into UTF-8. 1470 A *Message* object has the following properties: 1472 o *id*: "String" The id of the message. 1474 o *blobId*: "String" The id representing the raw [RFC5322] message. 1475 This may be used to download the original message or to attach it 1476 directly to another message etc. 1478 o *threadId*: "String" The id of the thread to which this message 1479 belongs. 1481 o *mailboxIds*: "String[]" (Mutable) The ids of the mailboxes the 1482 message is in. A message MUST belong to one or more mailboxes at 1483 all times (until it is deleted). 1485 o *keywords*: "String[Boolean]" (Mutable) A set of keywords that 1486 apply to the message. The set is represented as an object, with 1487 the keys being the _keywords_. The value for each key in the 1488 object MUST be "true". Keywords are shared with IMAP. The six 1489 system keywords from IMAP are treated specially. The following 1490 four keywords have their first character changed from "\" in IMAP 1491 to "$" in JMAP and have particular semantic meaning: 1493 * "$Draft": The message is a draft the user is composing. 1495 * "$Seen": The message has been read. 1497 * "$Flagged": The message has been flagged for urgent/special 1498 attention. 1500 * "$Answered": The message has been replied to. 1502 The IMAP "\Recent" keyword is not exposed via JMAP. The IMAP 1503 "\Deleted" keyword is also not present: IMAP uses a delete+expunge 1504 model, which JMAP does not. Any message with the "\Deleted" 1505 keyword MUST NOT be visible via JMAP. Users may add arbitrary 1506 keywords to a message. For compatibility with IMAP, a keyword is 1507 a (case-sensitive) string of 1-255 characters in the ASCII subset 1508 %x21-%x127 (excludes control chars and space), and MUST NOT 1509 include any of these characters: "()]{%*"\" The IANA Keyword 1510 Registry [4] as established in [RFC5788] assigns semantic meaning 1511 to some other keywords in common use. New keywords may be 1512 established here in the future. In particular, note: 1514 * "$Forwarded": The message has been forwarded. 1516 * "$Phishing": The message is highly likely to be phishing. 1517 Clients SHOULD warn users to take care when viewing this 1518 message and disable links and attachments. 1520 * "$Junk": The message is definitely spam. Clients SHOULD set 1521 this flag when users report spam to help train automated spam- 1522 detection systems. 1524 * "$NotJunk": The message is definitely not spam. Clients SHOULD 1525 set this flag when users indicate a message is legitimate, to 1526 help train automated spam-detection systems. 1528 o *hasAttachment*: "Boolean" Does the message have any attachments? 1530 o *headers*: "String[String]" A map of lower-cased header name to 1531 (decoded) header value for all headers in the message. For 1532 headers that occur multiple times (e.g. "Received"), the values 1533 are concatenated with a single new line ("\n") character in 1534 between each one. 1536 o *sender*: "Emailer|null" An Emailer object (see below) containing 1537 the name/email from the parsed "Sender" header of the email. If 1538 the email doesn't have a "Sender" header, this is "null". 1540 o *from*: "Emailer[]|null" An array of name/email objects (see 1541 below) representing the parsed "From" header of the email, in the 1542 same order as they appear in the header. If the email doesn't 1543 have a "From" header, this is "null". If the header exists but 1544 does not have any content, the response is an array of zero 1545 length. 1547 o *to*: "Emailer[]|null" An array of name/email objects (see below) 1548 representing the parsed "To" header of the email, in the same 1549 order as they appear in the header. If the email doesn't have a 1550 "To" header, this is "null". If the header exists but does not 1551 have any content, the response is an array of zero length. 1553 o *cc*: "Emailer[]|null" An array of name/email objects (see below) 1554 representing the parsed "Cc" header of the email, in the same 1555 order as they appear in the header. If the email doesn't have a 1556 "Cc" header, this is "null". If the header exists but does not 1557 have any content, the response is an array of zero length. 1559 o *bcc*: "Emailer[]|null" An array of name/email objects (see below) 1560 representing the parsed "Bcc" header of the email. If the email 1561 doesn't have a "Bcc" header (which will be true for most emails 1562 outside of the Sent mailbox), this is "null". If the header 1563 exists but does not have any content, the response is an array of 1564 zero length. 1566 o *replyTo*: "Emailer[]|null" An array of name/email objects (see 1567 below) representing the parsed "Reply-To" header of the email, in 1568 the same order as they appear in the header. If the email doesn't 1569 have a "Reply-To" header, this is "null". If the header exists 1570 but does not have any content, the response is an array of zero 1571 length. 1573 o *subject*: "String" The subject of the message. 1575 o *date*: "Date" The date the message was sent (or saved, if the 1576 message is a draft). 1578 o *size*: "Number" The size in bytes of the whole message as counted 1579 by the server towards the user's quota. 1581 o *preview*: "String" Up to 256 characters of the beginning of a 1582 plain text version of the message body. This is intended to be 1583 shown as a preview line on a mailbox listing, and the server may 1584 choose to skip quoted sections or salutations to return a more 1585 useful preview. 1587 o *textBody*: "String" The plain text body part for the message. If 1588 there is only an HTML version of the body, a plain text version 1589 MUST be generated from this; the exact method of conversion in 1590 this case is not defined and is server-specific. If there is 1591 neither a "text/plain" nor a "text/html" body part, this MUST be 1592 the empty string. 1594 o *htmlBody*: "String|null" The HTML body part for the message if 1595 present. 1597 o *attachments*: "Attachment[]|null" An array of attachment objects 1598 (see below) detailing all the attachments to the message. 1600 o *attachedMessages*: "String[Message]|null" An object mapping 1601 attachment id (as found in the "attachments" property) to a 1602 *Message* object with the following properties, for each [RFC5322] 1603 message attached to this one: 1605 * headers 1607 * from 1609 * to 1611 * cc 1613 * bcc 1615 * replyTo 1616 * subject 1618 * date 1620 * textBody 1622 * htmlBody 1624 * attachments 1626 * attachedMessages 1628 An *Emailer* object has the following properties: 1630 o *name*: "String" The name of the sender/recipient. If a name 1631 cannot be extracted for an email, this property SHOULD be the 1632 empty string. 1634 o *email*: "String" The email address of the sender/recipient. This 1635 MUST be of the form ""@"" If a "host" or even 1636 "mailbox" cannot be extracted for an email, the empty string 1637 SHOULD be used for this part (so the result MUST always still 1638 contain an ""@"" character). 1640 Group information and comments from the RFC 5322 header MUST be 1641 discarded when converting into an Emailer object. 1643 Example array of Emailer objects: 1645 [ 1646 {name:"Joe Bloggs", email:"joeb@example.com"}, 1647 {name:"", email:"john@example.com"}, 1648 {name:"John Smith", email: "john@"} 1649 ] 1651 An *Attachment* object has the following properties: 1653 o *blobId*: "String" The id of the binary data. 1655 o *type*: "String" The content-type of the attachment. 1657 o *name*: "String|null" The full file name, e.g. 1658 "myworddocument.doc", if available. 1660 o *size*: "Number" The size, in bytes, of the attachment when fully 1661 decoded (i.e. the number of bytes in the file the user would 1662 download). 1664 o *cid*: "String|null" The id used within the message body to 1665 reference this attachment. This is only unique when paired with 1666 the message id, and has no meaning without reference to that. 1668 o *isInline*: "Boolean" True if the attachment is referenced by a 1669 "cid:" link from within the HTML body of the message. 1671 o *width*: "Number|null" (optional, server MAY omit if not 1672 supported) The width (in px) of the image, if the attachment is an 1673 image. 1675 o *height*: "Number|null" (optional, server MAY omit if not 1676 supported) The height (in px) of the image, if the attachment is 1677 an image. 1679 5.1. getMessages 1681 Messages can only be fetched explicitly by id. To fetch messages, 1682 make a call to "getMessages". It takes the following arguments: 1684 o *accountId*: "String|null" The id of the account to use for this 1685 call. If not given, defaults to the primary account. 1687 o *ids*: "String[]" An array of ids for the messages to fetch. 1689 o *properties*: "String[]|null" A list of properties to fetch for 1690 each message. If "null", all properties will be fetched. 1692 The "id" property is always returned, regardless of whether it is in 1693 the list of requested properties. The possible values for 1694 "properties" can be found above in the description of the Message 1695 object. In addition to this, the client may request the following 1696 special values: 1698 o *body*: If ""body"" is included in the list of requested 1699 properties, it will be interpreted by the server as a request for 1700 ""htmlBody"" if the message has an HTML part, or ""textBody"" 1701 otherwise. 1703 o *headers.property*: Instead of requesting all the headers (by 1704 requesting the ""headers"" property, the client may specify the 1705 particular headers it wants using the "headers.property-name" 1706 syntax, e.g. ""headers.x-spam-score", "headers.x-spam-hits""). 1707 The server will return a _headers_ property but with just the 1708 requested headers in the object rather than all headers. If 1709 ""headers"" is requested, the server MUST ignore the individual 1710 header requests and just return all headers. If a requested 1711 header is not present in the message, it MUST not be present in 1712 the _headers_ object. Header names are case-insensitive. 1714 The response to _getMessages_ is called _messages_. It has the 1715 following arguments: 1717 o *accountId*: "String" The id of the account used for the call. 1719 o *state*: "String" A string encoding the current state on the 1720 server. This string will change if any messages change (that is, 1721 a new message arrives, a change is made to one of the mutable 1722 properties, or a message is deleted). It can be passed to 1723 _getMessageUpdates_ to efficiently get the list of changes from 1724 the previous state. 1726 o *list*: "Message[]" An array of Message objects for the requested 1727 message ids. This may not be in the same order as the ids were in 1728 the request. 1730 o *notFound*: "String[]|null" An array of message ids requested 1731 which could not be found, or "null" if all ids were found. 1733 The following errors may be returned instead of the _messages_ 1734 response: 1736 "accountNotFound": Returned if an _accountId_ was explicitly included 1737 with the request, but it does not correspond to a valid account. 1739 "accountNotSupportedByMethod": Returned if the _accountId_ given 1740 corresponds to a valid account, but the account does not support this 1741 data type. 1743 "requestTooLarge": Returned if the number of _ids_ requested by the 1744 client exceeds the maximum number the server is willing to process in 1745 a single method call. 1747 "invalidArguments": Returned if the request does not include one of 1748 the required arguments, or one of the arguments is of the wrong type, 1749 or otherwise invalid. A _description_ property MAY be present on the 1750 response object to help debug with an explanation of what the problem 1751 was. 1753 Example request: 1755 ["getMessages", { 1756 "ids": [ "f123u456", "f123u457" ], 1757 "properties": [ "threadId", "mailboxIds", "from", "subject", "date" ] 1758 }, "#1"] 1759 and response: 1761 ["messages", { 1762 "state": "41234123231", 1763 "list": [ 1764 { 1765 messageId: "f123u457", 1766 threadId: "ef1314a", 1767 mailboxIds: [ "f123" ], 1768 from: [{name: "Joe Bloggs", email: "joe@bloggs.com"}], 1769 subject: "Dinner on Thursday?", 1770 date: "2013-10-13T14:12:00Z" 1771 } 1772 ], 1773 notFound: [ "f123u456" ] 1774 }, "#1"] 1776 5.2. getMessageUpdates 1778 If a call to _getMessages_ returns with a different _state_ string in 1779 the response to a previous call, the state of the messages has 1780 changed on the server. For example, a new message may have been 1781 delivered, or an existing message may have changed mailboxes. 1783 The _getMessageUpdates_ call allows a client to efficiently update 1784 the state of any cached messages to match the new state on the 1785 server. It takes the following arguments: 1787 o *accountId*: "String|null" The id of the account to use for this 1788 call. If not given, defaults to the primary account. 1790 o *sinceState*: "String" The current state of the client. This is 1791 the string that was returned as the _state_ argument in the 1792 _messages_ response. The server will return the changes made 1793 since this state. 1795 o *maxChanges*: "Number|null" The maximum number of changed messages 1796 to return in the response. The server MAY choose to clamp this 1797 value to a particular maximum or set a maximum if none is given by 1798 the client. If supplied by the client, the value MUST be a 1799 positive integer greater than 0. If a value outside of this range 1800 is given, the server MUST reject the call with an 1801 "invalidArguments" error. 1803 o *fetchRecords*: "Boolean|null" If true, immediately after 1804 outputting a _messageUpdates_ response, an implicit call will be 1805 made to _getMessages_ with a list of all message ids in the 1806 _changed_ argument of the response as the _ids_ argument, and the 1807 _fetchRecordProperties_ argument as the _properties_ argument. 1809 o *fetchRecordProperties*: "String[]|null" The list of properties to 1810 fetch on any fetched messages. See _getMessages_ for a full 1811 description. 1813 The response to _getMessageUpdates_ is called _messageUpdates_. It 1814 has the following arguments: 1816 o *accountId*: "String" The id of the account used for the call. 1818 o *oldState*: "String" This is the _sinceState_ argument echoed 1819 back; the state from which the server is returning changes. 1821 o *newState*: "String" This is the state the client will be in after 1822 applying the set of changes to the old state. 1824 o *hasMoreUpdates*: "Boolean" If "true", the client may call 1825 _getMessageUpdates_ again with the _newState_ returned to get 1826 further updates. If "false", _newState_ is the current server 1827 state. 1829 o *changed*: "String[]" An array of message ids for messages that 1830 have either been created or had their state change, and are not 1831 currently deleted. 1833 o *removed*: "String[]" An array of message ids for messages that 1834 have been deleted since the oldState. 1836 If a _maxChanges_ is supplied, or set automatically by the server, 1837 the server MUST ensure the number of ids returned across _changed_ 1838 and _removed_ does not exceed this limit. If there are more changes 1839 than this between the client's state and the current server state, 1840 the update returned SHOULD generate an update to take the client to 1841 an intermediate state, from which the client can continue to call 1842 _getMessageUpdates_ until it is fully up to date. If it is unable to 1843 calculate an intermediate state, it MUST return a 1844 "cannotCalculateChanges" error response instead. 1846 If a message has been modified AND deleted since the oldState, the 1847 server SHOULD just return the id in the _removed_ response, but MAY 1848 return it in the changed response as well. If a message has been 1849 created AND deleted since the oldState, the server SHOULD remove the 1850 message id from the response entirely, but MAY include it in the 1851 _removed_ response, and (if in the _removed_ response) MAY included 1852 it in the _changed_ response as well. 1854 The following errors may be returned instead of the _messageUpdates_ 1855 response: 1857 "accountNotFound": Returned if an _accountId_ was explicitly included 1858 with the request, but it does not correspond to a valid account. 1860 "accountNotSupportedByMethod": Returned if the _accountId_ given 1861 corresponds to a valid account, but the account does not support this 1862 data type. 1864 "invalidArguments": Returned if the request does not include one of 1865 the required arguments, or one of the arguments is of the wrong type, 1866 or otherwise invalid. A _description_ property MAY be present on the 1867 response object to help debug with an explanation of what the problem 1868 was. 1870 "cannotCalculateChanges": Returned if the server cannot calculate the 1871 changes from the state string given by the client. Usually due to 1872 the client's state being too old, or the server being unable to 1873 produce an update to an intermediate state when there are too many 1874 updates. The client MUST invalidate its Message cache. 1876 5.3. setMessages 1878 The _setMessages_ method encompasses: 1880 o Creating a draft message 1882 o Sending a message 1884 o Changing the flags of a message (unread/flagged status) 1886 o Adding/removing a message to/from mailboxes (moving a message) 1888 o Deleting messages 1890 It takes the following arguments: 1892 o *accountId*: "String|null" The id of the account to use for this 1893 call. If not given, defaults to the primary account. 1895 o *ifInState*: "String|null" This is a state string as returned by 1896 the _getMessages_ method. If supplied, the string must match the 1897 current state, otherwise the method will be aborted and a 1898 "stateMismatch" error returned. If "null", any changes will be 1899 applied to the current state. 1901 o *create*: "String[Message]|null" A map of _creation id_ (an 1902 arbitrary string set by the client) to Message objects (see below 1903 for a detailed description). 1905 o *update*: "String[Message]|null" A map of message id to objects 1906 containing the properties to update for that Message. 1908 o *destroy*: "String[]|null" A list of ids for Message objects to 1909 permanently delete. 1911 Each create, update or destroy is considered an atomic unit. It is 1912 permissible for the server to commit some of the changes but not 1913 others, however it is not permissible to only commit part of an 1914 update to a single record (e.g. update the _keywords_ field but not 1915 the _mailboxIds_ field, if both are supplied in the update object for 1916 a message). 1918 If a create, update or destroy is rejected, the appropriate error 1919 MUST be added to the notCreated/notUpdated/notDestroyed property of 1920 the response and the server MUST continue to the next create/update/ 1921 destroy. It does not terminate the method. 1923 If an id given cannot be found, the update or destroy MUST be 1924 rejected with a "notFound" set error. 1926 5.3.1. Saving a draft 1928 Creating messages via the _setMessages_ method is only for creating 1929 draft messages and sending them. For delivering/importing a complete 1930 [RFC5322] message, use the "importMessages" method. 1932 The properties of the Message object submitted for creation MUST 1933 conform to the following conditions: 1935 o *id*: This property MUST NOT be included. It is set by the server 1936 upon creation. 1938 o *blobId*: This property MUST NOT be included. It is set by the 1939 server upon creation. 1941 o *threadId*: This property MUST NOT be included. It is set by the 1942 server upon creation. 1944 o *mailboxIds*: This property MUST be included. The value MUST 1945 include the id of either the mailbox with "role == "drafts"" (to 1946 save a draft) or the mailbox with "role == "outbox"" (to send the 1947 message). If this mailbox does not have "mustBeOnlyMailbox == 1948 true", others may be included too. 1950 o *keywords*: This property MUST be included. It MUST include the 1951 "$Draft" keyword and SHOULD also include "$Seen". 1953 o *hasAttachment*: This property MUST NOT be included. It is set by 1954 the server upon creation based on the attachments property. 1956 o *headers*: Optional. The keys MUST only contain the characters 1957 a-z (lower-case only), 0-9 and hyphens. 1959 o *from*: Optional. Overrides a "From" in the _headers_. 1961 o *to*: Optional. Overrides a "To" in the _headers_. 1963 o *cc*: Optional. Overrides a "Cc" in the _headers_. 1965 o *bcc*: Optional. Overrides a "Bcc" in the _headers_. 1967 o *replyTo*: Optional. Overrides a "Reply-To" in the _headers_. 1969 o *subject*: Optional. Defaults to the empty string (""""). 1971 o *date*: Optional. If included, the server SHOULD wait until this 1972 time to send the message (once moved to the outbox mailbox). 1973 Until it is sent, the send may be cancelled by moving the message 1974 back out of the outbox mailbox. If the date is in the past, the 1975 message must be sent immediately. A client may find out if the 1976 server supports delayed sending by querying the server's 1977 _capabilities_ object (see section 1). 1979 o *size*: This MUST NOT be included. It is set by the server upon 1980 creation. 1982 o *preview*: This MUST NOT be included. It is set by the server 1983 upon creation. 1985 o *textBody*: Optional. If not supplied and an htmlBody is, the 1986 server SHOULD generate a text version for the message from the 1987 HTML body. 1989 o *htmlBody*: Optional. 1991 o *attachments*: Optional. An array of Attachment objects detailing 1992 all the attachments to the message. To add an attachment, the 1993 file must first be uploaded using the standard upload mechanism; 1994 this will give the client a blobId that may be used to identify 1995 the file. The "cid" property may be assigned by the client, and 1996 is solely used for matching up with "cid:" links inside the 1997 "htmlBody". The server MAY change the cids upon sending. 1999 If any of the files specified in _attachments_ cannot be found, the 2000 creation MUST be rejected with an "invalidProperties" error. An 2001 extra property SHOULD be included in the error object called 2002 "attachmentsNotFound", of type "String[]", which SHOULD be an array 2003 of the _blobId_ of every attachment that could not be found on the 2004 server. - *attachedMessages*: This MUST NOT be included. 2006 All optional properties default to "null" unless otherwise stated. 2007 Where included, properties MUST conform to the type given in the 2008 Message object definition. 2010 If any of the properties are invalid, the server MUST reject the 2011 create with an "invalidProperties" error. The Error object SHOULD 2012 contain a property called _properties_ of type "String[]" that lists 2013 *all* the properties that were invalid. The object MAY also contain 2014 a _description_ property of type "String" with a user-friendly 2015 description of the problems. 2017 Other than making sure it conforms to the correct type, the server 2018 MUST NOT attempt to validate from/to/cc/bcc when saved as a draft. 2019 This is to ensure messages can be saved at any point. Validation 2020 occurs when the user tries to send a message. 2022 If a draft cannot be saved due to the user reaching their maximum 2023 mail storage quota, the creation MUST be rejected with a 2024 "maxQuotaReached" error. 2026 5.3.2. Updating messages 2028 Messages are mainly immutable, so to update a draft the client must 2029 create a new message and delete the old one. This ensures that if 2030 the draft is also being edited elsewhere, the two will split into two 2031 different drafts to avoid data loss. 2033 Only the _mailboxIds_ and _keywords_ properties may be modified, and 2034 they are subject to the following constraints: 2036 o *mailboxIds*: The server MUST reject any attempt to add a message 2037 to the outbox that does not have the "$Draft" keyword with an 2038 "invalidProperties" error. 2040 o *keywords*: The server MUST reject any attempt to add or remove 2041 the "$Draft" flag in an update with an "invalidProperties" error. 2042 The server MAY have a maximum number of keywords it supports; if 2043 the change would exceed this, it MUST be rejected with a 2044 "tooManyKeywords" error. 2046 Note, a mailbox id may be a _creation id_ (see "setFoos" for a 2047 description of how this works). 2049 If any of the properties in the update are invalid (immutable and 2050 different to the current server value, wrong type, invalid value for 2051 the property - like a mailbox id for non-existent mailbox), the 2052 server MUST reject the update with an "invalidProperties" error. The 2053 Error object SHOULD contain a property called _properties_ of type 2054 "String[]" that lists *all* the properties that were invalid. The 2055 object MAY also contain a _description_ property of type "String" 2056 with a user-friendly description of the problems. 2058 If the _id_ given does not correspond to a Message in the given 2059 account, reject the update with a "notFound" error. 2061 To *delete a message* to trash, simply change the "mailboxIds" 2062 property so it is now in the mailbox with "role == "trash"", and 2063 remove all other mailbox ids. 2065 5.3.3. Sending messages 2067 To send a message, either create a new message directly into the 2068 mailbox with "role == "outbox"" or move an existing draft into this 2069 mailbox. At this point the server will check that it has everything 2070 it needs for a valid message. In particular, that it has a valid 2071 "From" address (and the user has permission to use this From 2072 address), it has at least one address to send to, and all addresses 2073 in To/Cc/Bcc are valid email addresses. If it cannot send, it will 2074 reject the creation/update with an "invalidProperties" error. The 2075 Error object SHOULD contain a property called _properties_ of type 2076 "String[]" that lists *all* the properties that were invalid. The 2077 object SHOULD also contain a _description_ property of type "String" 2078 with a user-friendly description of the problems to present to the 2079 user. 2081 If the message is accepted, the server SHOULD *asynchronously* 2082 schedule the message to be sent *after* this method call is complete 2083 (note, this MAY occur before the next method in the same API request 2084 or after the whole API request is complete). This means that the 2085 "newState" string in the response represents a state where the 2086 message is still in the outbox. 2088 When the message is sent, the server MUST remove the message from the 2089 *outbox* and add it to the *sent* mailbox, unless the user has 2090 indicated another preference. The version added to the sent mailbox 2091 MAY be different (for example have extra headers added by the 2092 server), and so have a different id to the version that was in the 2093 outbox. If the message has an "In-Reply-To" header, the server 2094 SHOULD add the "$Answered" keyword to all messages with the 2095 coresponding "Message-Id" header at this point. If the message has 2096 an "X-Forwarded-Message-Id" header, the server SHOULD add the 2097 "$Forwarded" keyword to all messages with the coresponding "Message- 2098 Id" header at this point. 2100 The server is responsible for either reporting an error (normally a 2101 "bounce" email), or ensuring delivery of the message to the next hop. 2103 5.3.4. Cancelling a send 2105 A message may be moved out of the *outbox* and back to the *drafts* 2106 mailbox using the standard update message mechanism, if it has not 2107 yet been sent at the time the method is called. This MUST cancel the 2108 queued send. If the message has already been sent then it will have 2109 been deleted from the outbox, so the update will fail with a standard 2110 "notFound" error. 2112 5.3.5. Destroying messages 2114 If the _id_ given does not correspond to a Message in the given 2115 account, the server MUST reject the destruction with a "notFound" 2116 error. 2118 Destroying a message removes it from all mailboxes to which it 2119 belonged. 2121 When emptying the trash, clients SHOULD NOT destroy messages which 2122 are also in a mailbox other than trash. For those messages, they 2123 should just remove the Trash mailbox from the message. 2125 5.3.6. Response 2127 The response to _setMessages_ is called _messagesSet_. It has the 2128 following arguments: 2130 o *accountId*: "String" The id of the account used for the call. 2132 o *oldState*: "String|null" The state string that would have been 2133 returned by _getMessages_ before making the requested changes, or 2134 "null" if the server doesn't know what the previous state string 2135 was. 2137 o *newState*: "String" The state string that will now be returned by 2138 _getMessages_. 2140 o *created*: "String[Message]" A map of the creation id to an object 2141 containing the _id_, _blobId_, _threadId_, and _size_ properties 2142 for each successfully created Message. 2144 o *updated*: "String[Message|null]" The _keys_ in this map are the 2145 ids of all messages that were successfully updated. If the server 2146 made any other changes to the record beyond those explicitly 2147 requested by the client, the _value_ for the corresponding id in 2148 the map is an object containing the updated value of each property 2149 the *server changed*. Otherwise (if no properties changed on the 2150 server other than those explicitly updated by the client), the 2151 value is "null". 2153 o *destroyed*: "String[]" A list of Message ids for Messages that 2154 were successfully destroyed. 2156 o *notCreated*: "String[SetError]" A map of creation id to a 2157 SetError object for each Message that failed to be created. The 2158 possible errors are defined above. 2160 o *notUpdated*: "String[SetError]" A map of Message id to a SetError 2161 object for each Message that failed to be updated. The possible 2162 errors are defined above. 2164 o *notDestroyed*: "String[SetError]" A map of Message id to a 2165 SetError object for each Message that failed to be destroyed. The 2166 possible errors are defined above. 2168 The following errors may be returned instead of the _messagesSet_ 2169 response: 2171 "accountNotFound": Returned if an _accountId_ was explicitly included 2172 with the request, but it does not correspond to a valid account. 2174 "accountNotSupportedByMethod": Returned if the _accountId_ given 2175 corresponds to a valid account, but the account does not support this 2176 data type. 2178 "accountReadOnly": Returned if the account has "isReadOnly == true". 2180 "invalidArguments": Returned if one of the arguments is of the wrong 2181 type, or otherwise invalid. A _description_ property MAY be present 2182 on the response object to help debug with an explanation of what the 2183 problem was. 2185 "stateMismatch": Returned if an _ifInState_ argument was supplied and 2186 it does not match the current state. 2188 5.4. importMessages 2190 The _importMessages_ method adds [RFC5322] messages to a user's set 2191 of messages. The messages must first be uploaded as a file using the 2192 standard upload mechanism. It takes the following arguments: 2194 o *accountId*: "String|null" The id of the account to use for this 2195 call. If "null", defaults to the primary account. 2197 o *messages*: "String[MessageImport]" A map of creation id (client 2198 specified) to MessageImport objects 2200 An *MessageImport* object has the following properties: 2202 o *blobId*: "String" The id representing the raw [RFC5322] message 2203 (see the file upload section). 2205 o *mailboxIds* "String[]" The ids of the mailbox(es) to assign this 2206 message to. 2208 o *keywords*: "String[Boolean]" 2210 Adding to the outbox will send the message, as described in the 2211 _setMessages_ section. The "$Draft" keyword MUST also be included if 2212 the message is being imported to the outbox. 2214 The response to _importMessages_ is called _messagesImported_. It has 2215 the following arguments: 2217 o *accountId*: "String" The id of the account used for this call. 2219 o *created*: "String[Message]" A map of the creation id to an object 2220 containing the _id_, _blobId_, _threadId_ and _size_ properties 2221 for each successfully imported Message. 2223 o *notCreated*: "String[SetError]" A map of creation id to a 2224 SetError object for each Message that failed to be created. The 2225 possible errors are defined above. 2227 The following errors may be returned instead of the _messageImported_ 2228 response: 2230 "accountNotFound": Returned if an _accountId_ was explicitly included 2231 with the request, but it does not correspond to a valid account. 2233 "accountNotSupportedByMethod": Returned if the _accountId_ given 2234 corresponds to a valid account, but the account does not support this 2235 data type. 2237 "accountReadOnly": Returned if the account has "isReadOnly == true". 2239 "invalidArguments": Returned if one of the arguments is of the wrong 2240 type, or otherwise invalid. A "description" property MAY be present 2241 on the response object to help debug with an explanation of what the 2242 problem was. 2244 "notFound": Returned if the URL given in the "file" argument does not 2245 correspond to an internal file. 2247 "invalidMailboxes": Returned if one of the mailbox ids cannot be 2248 found, or an invalid combination of mailbox ids is specified. 2250 "maxQuotaReached": Returned if the user has reached their mail quota 2251 so the message cannot be imported. 2253 5.5. copyMessages 2255 The only way to move messages *between* two different accounts is to 2256 copy them using the _copyMessages_ method, then once the copy has 2257 succeeded, delete the original. It takes the following arguments: 2259 o *fromAccountId*: "String|null" The id of the account to copy 2260 messages from. If "null", defaults to the primary account. 2262 o *toAccountId*: "String|null" The id of the account to copy 2263 messages to. If "null", defaults to the primary account. 2265 o *messages*: "String[MessageCopy]" A map of _creation id_ to a 2266 MessageCopy object. 2268 A *MessageCopy* object has the following properties: 2270 o *messageId*: "String" The id of the message to be copied in the 2271 "from" account. 2273 o *mailboxIds*: "String[]" The ids of the mailboxes (in the "to" 2274 account) to add the copied message to. 2276 o *keywords*: "String[Boolean]" The _keywords_ property for the 2277 copy. 2279 The "from" account may be the same as the "to" account to copy 2280 messages within an account. 2282 The response to _copyMessages_ is called _messagesCopied_. It has the 2283 following arguments: 2285 o *fromAccountId*: "String" The id of the account messages were 2286 copied from. 2288 o *toAccountId*: "String" The id of the account messages were copied 2289 to. 2291 o *created*: "String[Message]|null" A map of the creation id to an 2292 object containing the _id_, _blobId_, _threadId_ and _size_ 2293 properties for each successfully copied Message. 2295 o *notCreated*: "String[SetError]|null" A map of creation id to a 2296 SetError object for each Message that failed to be copied, "null" 2297 if none. 2299 The *SetError* may be one of the following types: 2301 "notFound": Returned if the messageId given can't be found. 2303 "invalidMailboxes": Returned if one of the mailbox ids cannot be 2304 found, or an invalid combination of mailbox ids is specified. 2306 "maxQuotaReached": Returned if the user has reached their mail quota 2307 so the message cannot be copied. 2309 The following errors may be returned instead of the _messagesCopied_ 2310 response: 2312 "fromAccountNotFound": Returned if a _fromAccountId_ was explicitly 2313 included with the request, but it does not correspond to a valid 2314 account. 2316 "toAccountNotFound": Returned if a _toAccountId_ was explicitly 2317 included with the request, but it does not correspond to a valid 2318 account. 2320 "fromAccountNoMail": Returned if the _fromAccountId_ given 2321 corresponds to a valid account, but does not contain any mail data. 2323 "toAccountNoMail": Returned if the _toAccountId_ given corresponds to 2324 a valid account, but does not contain any mail data. 2326 "accountReadOnly": Returned if the "to" account has "isReadOnly == 2327 true". 2329 "invalidArguments": Returned if one of the arguments is of the wrong 2330 type, or otherwise invalid. A "description" property MAY be present 2331 on the response object to help debug with an explanation of what the 2332 problem was. 2334 6. Identities 2336 A *Identity* object stores information about an email address (or 2337 domain) the user may send from. It has the following properties: 2339 o *id*: "String" The id of the identity. This property is 2340 immutable. 2342 o *name*: "String" The "From" _name_ the client SHOULD use when 2343 creating a new message from this identity. 2345 o *email*: "String" The "From" email address the client MUST use 2346 when creating a new message from this identity. This property is 2347 immutable. The "email" property MAY alternatively be of the form 2348 "*@example.com", in which case the client may use any valid email 2349 address ending in "@example.com". 2351 o *replyTo*: "String" The Reply-To value the client SHOULD set when 2352 creating a new message from this identity. 2354 o *bcc*: "String" The Bcc value the client SHOULD set when creating 2355 a new message from this identity. 2357 o *textSignature*: "String" Signature the client SHOULD insert into 2358 new rich-text messages that will be sending from this identity. 2359 Clients MAY ignore this and/or combine this with a client-specific 2360 signature preference. 2362 o *htmlSignature*: "String" Signature the client SHOULD insert into 2363 new HTML messages that will be sending from this identity. This 2364 text MUST be an HTML snippet to be inserted into the 2365 "" section of the new email. Clients MAY ignore this 2366 and/or combine this with a client-specific signature preference. 2368 o *mayDeleteIdentity*: "Boolean" Is the user allowed to delete this 2369 identity? Servers may wish to set this to false for the user's 2370 username or other default address. 2372 Multiple identities with the same email address MAY exist, to allow 2373 for different settings the user wants to pick between (for example 2374 with different names/signatures). 2376 6.1. getIdentities 2378 Identities can either be fetched explicitly by id, or all of them at 2379 once. To fetch identities, make a call to "getIdentities". It takes 2380 the following arguments: 2382 o *accountId*: "String|null" The Account to fetch the identities 2383 for. If "null", the primary account is used. 2385 o *ids*: "String[]|null" The ids of the identities to fetch. If 2386 "null", all identities in the account are be fetched. 2388 The response to _getIdentities_ is called _identities_. It has the 2389 following arguments: 2391 o *accountId*: "String" The id of the account used for the call. 2393 o *state*: "String" A string encoding the current state on the 2394 server. This string will change if any identities change (that 2395 is, a new identity is created, a change is made to an existing 2396 identity, or an identity is deleted). It can be passed to 2397 _getIdentityUpdates_ to efficiently get the list of changes from 2398 the previous state. 2400 o *list*: "Identity[]" An array of the Identity objects requested. 2401 This will be the *empty array* if the _ids_ argument was the empty 2402 array, or contained only ids for identities that could not be 2403 found. 2405 o *notFound*: "String[]|null" This array contains the ids passed to 2406 the method for identities that do not exist, or "null" if all 2407 requested ids were found. It MUST be "null" if the _ids_ argument 2408 in the call was "null". 2410 The following errors may be returned instead of the _identities_ 2411 response: 2413 "accountNotFound": Returned if an _accountId_ was explicitly included 2414 with the request, but it does not correspond to a valid account. 2416 "accountNotSupportedByMethod": Returned if the _accountId_ given 2417 corresponds to a valid account, but the account does not support this 2418 data type. 2420 "invalidArguments": Returned if one of the arguments is of the wrong 2421 type, or otherwise invalid. A "description" property MAY be present 2422 on the response object to help debug with an explanation of what the 2423 problem was. 2425 6.2. getIdentityUpdates 2427 The _getIdentityUpdates_ call allows a client to efficiently update 2428 the state of its cached identities to match the new state on the 2429 server. It takes the following arguments: 2431 o *accountId*: "String|null" The id of the account to use for this 2432 call. If "null", the primary account will be used. 2434 o *sinceState*: "String" The current state of the client. This is 2435 the string that was returned as the _state_ argument in the 2436 _identities_ response. The server will return the changes made 2437 since this state. 2439 o *maxChanges*: "Number|null" The maximum number of Identity ids to 2440 return in the response. The server MAY choose to clamp this value 2441 to a particular maximum or set a maximum if none is given by the 2442 client. If supplied by the client, the value MUST be a positive 2443 integer greater than 0. If a value outside of this range is 2444 given, the server MUST reject the call with an "invalidArguments" 2445 error. 2447 o *fetchRecords*: "Boolean|null" If "true", immediately after 2448 outputting an _identityUpdates_ response, an implicit call will be 2449 made to _getidentities_ with the _changed_ property of the 2450 response as the _ids_ argument, and the _fetchRecordProperties_ 2451 argument as the _properties_ argument. If "false" or "null", no 2452 implicit call is made. 2454 The response to _getIdentityUpdates_ is called _identityUpdates_. It 2455 has the following arguments: 2457 o *accountId*: "String" The id of the account used for the call. 2459 o *oldState*: "String" This is the _sinceState_ argument echoed 2460 back; the state from which the server is returning changes. 2462 o *newState*: "String" This is the state the client will be in after 2463 applying the set of changes to the old state. 2465 o *hasMoreUpdates*: "Boolean" If "true", the client may call 2466 _getIdentityUpdates_ again with the _newState_ returned to get 2467 further updates. If "false", _newState_ is the current server 2468 state. 2470 o *changed*: "String[]" An array of Identity ids where a property of 2471 the identity has changed between the old state and the new state, 2472 or the identity has been created, and the identity has not been 2473 destroyed. 2475 o *removed*: "String[]" An array of Identity ids for identities 2476 which have been destroyed since the old state. 2478 If a _maxChanges_ is supplied, or set automatically by the server, 2479 the server must try to limit the number of ids across _changed_ and 2480 _removed_ to the number given. If there are more changes than this 2481 between the client's state and the current server state, the update 2482 returned MUST take the client to an intermediate state, from which 2483 the client can continue to call _getIdentityUpdates_ until it is 2484 fully up to date. The server MAY return more ids than the 2485 _maxChanges_ total if this is required for it to be able to produce 2486 an update to an intermediate state, but it SHOULD try to keep it 2487 close to the maximum requested. 2489 If an identity has been modified AND deleted since the oldState, the 2490 server should just return the id in the _removed_ array, but MAY 2491 return it in the _changed_ array as well. If an identity has been 2492 created AND deleted since the oldState, the server SHOULD remove the 2493 identity id from the response entirely, but MAY include it in the 2494 _removed_ array. 2496 The following errors may be returned instead of the "identityUpdates" 2497 response: 2499 "accountNotFound": Returned if an _accountId_ was explicitly included 2500 with the request, but it does not correspond to a valid account. 2502 "accountNotSupportedByMethod": Returned if the _accountId_ given 2503 corresponds to a valid account, but the account does not support this 2504 data type. 2506 "invalidArguments": Returned if the request does not include one of 2507 the required arguments, or one of the arguments is of the wrong type, 2508 or otherwise invalid. A "description" property MAY be present on the 2509 response object to help debug with an explanation of what the problem 2510 was. 2512 "cannotCalculateChanges": Returned if the server cannot calculate the 2513 changes from the state string given by the client. Usually due to 2514 the client's state being too old, or the server being unable to 2515 produce an update to an intermediate state when there are too many 2516 updates. The client MUST invalidate its Identity cache. 2518 6.3. setIdentities 2520 Modifying the state of Identity objects on the server is done via the 2521 _setIdentities_ method. This encompasses creating, updating and 2522 destroying Identity records. 2524 The _setIdentities_ method takes the following arguments: 2526 o *accountId*: "String|null" The id of the account to use for this 2527 call. If "null", the primary account will be used. 2529 o *ifInState*: "String|null" This is a state string as returned by 2530 the _getIdentities_ method. If supplied, the string must match 2531 the current state, otherwise the method MUST be aborted and a 2532 "stateMismatch" error returned. If "null", any changes will be 2533 applied to the current state. 2535 o *create*: "String[Identity]|null" A map of _creation id_ (an 2536 arbitrary string set by the client) to Identity objects 2537 (containing all properties except the id). 2539 o *update*: "String[Identity]|null" A map of id to Identity objects. 2540 The object may omit any property; only properties that have 2541 changed need be included. 2543 o *destroy*: "String[]|null" A list of ids for Identity objects to 2544 permanently delete. 2546 Each create, update or destroy is considered an atomic unit. It is 2547 permissible for the server to commit some of the changes but not 2548 others, however it is not permissible to only commit part of an 2549 update to a single identity. 2551 If a create, update or destroy is rejected, the appropriate error 2552 MUST be added to the notCreated/notUpdated/notDestroyed property of 2553 the response and the server MUST continue to the next create/update/ 2554 destroy. It does not terminate the method. 2556 A *create* MAY be rejected with one of the following errors: 2558 o "maxQuotaReached": Returned if the user has reached a server- 2559 defined limit on the number of identities. 2561 o "emailNotPermitted": Returned if the user tries to create an 2562 identity with an email address the user does not allow them to 2563 send from. 2565 If the identity has "mayDeleteIdentity == false", any attempt to 2566 destroy it MUST be rejected with a "forbidden" error. 2568 If an id given cannot be found, the update or destroy MUST be 2569 rejected with a "notFound" set error. 2571 The response to _setIdentities_ is called _identitiesSet_. It has the 2572 following arguments: 2574 o *accountId*: "String" The id of the account used for the call. 2576 o *oldState*: "String|null" The state string that would have been 2577 returned by _getIdentities_ before making the requested changes, 2578 or "null" if the server doesn't know what the previous state 2579 string was. 2581 o *newState*: "String" The state string that will now be returned by 2582 _getIdentities_. 2584 o *created*: "String[Identity]" A map of the creation id to an 2585 object containing the *id* property for all successfully created 2586 identities. 2588 o *updated*: "String[Identity|null]" The _keys_ in this map are the 2589 ids of all identities that were successfully updated. If the 2590 server made any other changes to the record beyond those 2591 explicitly requested by the client, the _value_ for the 2592 corresponding id in the map is an object containing the updated 2593 value of each property the *server changed*. Otherwise (if no 2594 properties changed on the server other than those explicitly 2595 updated by the client), the value is "null". 2597 o *destroyed*: "String[]" A list of ids for identities that were 2598 successfully destroyed. 2600 o *notCreated*: "String[SetError]" A map of creation id to a 2601 SetError object for each identity that failed to be created. The 2602 possible errors are defined in the description of the method for 2603 specific data types. 2605 o *notUpdated*: "String[SetError]" A map of Identity id to a 2606 SetError object for each identity that failed to be updated. The 2607 possible errors are defined in the description of the method for 2608 specific data types. 2610 o *notDestroyed*: "String[SetError]" A map of Identity id to a 2611 SetError object for each identity that failed to be destroyed. 2612 The possible errors are defined in the description of the method 2613 for specific data types. 2615 A *SetError* object has the following properties: 2617 o *type*: "String" The type of error. 2619 o *description*: "String|null" A description of the error to display 2620 to the user. 2622 The following errors may be returned instead of the _identitiesSet_ 2623 response: 2625 "accountNotFound": Returned if an _accountId_ was explicitly included 2626 with the request, but it does not correspond to a valid account. 2628 "accountNotSupportedByMethod": Returned if the _accountId_ given 2629 corresponds to a valid account, but the account does not support this 2630 data type. 2632 "accountReadOnly": Returned if the account has MailCapabilities with 2633 "isReadOnly == true". 2635 "requestTooLarge": Returned if the total number of objects to create, 2636 update or destroy exceeds the maximum number the server is willing to 2637 process in a single method call. 2639 "invalidArguments": Returned if one of the arguments is of the wrong 2640 type, or otherwise invalid. A _description_ property MAY be present 2641 on the response object to help debug with an explanation of what the 2642 problem was. 2644 "stateMismatch": Returned if an _ifInState_ argument was supplied and 2645 it does not match the current state. 2647 7. SearchSnippets 2649 When doing a search on a "String" property, the client may wish to 2650 show the relevant section of the body that matches the search as a 2651 preview instead of the beginning of the message, and to highlight any 2652 matching terms in both this and the subject of the message. Search 2653 snippets represent this data. 2655 A *SearchSnippet* object has the following properties: 2657 o *messageId*: "String" The message id the snippet applies to. 2659 o *subject*: "String|null" If text from the filter matches the 2660 subject, this is the subject of the message HTML-escaped, with 2661 matching words/phrases wrapped in "" tags. If it 2662 does not match, this is "null". 2664 o *preview*: "String|null" If text from the filter matches the 2665 plain-text or HTML body, this is the relevant section of the body 2666 (converted to plain text if originally HTML), HTML-escaped, with 2667 matching words/phrases wrapped in "" tags, up to 256 2668 characters long. If it does not match, this is "null". 2670 It is server-defined what is a relevant section of the body for 2671 preview. If the server is unable to determine search snippets, it 2672 MUST return "null" for both the _subject_ and _preview_ properties. 2674 Note, unlike most data types, a SearchSnippet DOES NOT have a 2675 property called "id". 2677 7.1. getSearchSnippets 2679 To fetch search snippets, make a call to "getSearchSnippets". It 2680 takes the following arguments: 2682 o *accountId*: "String|null" The id of the account to use for this 2683 call. If "null", defaults to the primary account. 2685 o *messageIds*: "String[]" The list of ids of messages to fetch the 2686 snippets for. 2688 o *filter*: "FilterCondition|FilterOperator|null" The same filter as 2689 passed to getMessageList; see the description of this method for 2690 details. 2692 The response to "getSearchSnippets" is called "searchSnippets". It 2693 has the following arguments: 2695 o *accountId*: "String" The id of the account used for the call. 2697 o *filter*: "FilterCondition|FilterOperator|null" Echoed back from 2698 the call. 2700 o *list*: "SearchSnippet[]" An array of SearchSnippet objects for 2701 the requested message ids. This may not be in the same order as 2702 the ids that were in the request. 2704 o *notFound*: "String[]|null" An array of message ids requested 2705 which could not be found, or "null" if all ids were found. 2707 Since snippets are only based on immutable properties, there is no 2708 state string or update mechanism needed. 2710 The following errors may be returned instead of the _searchSnippets_ 2711 response: 2713 "accountNotFound": Returned if an _accountId_ was explicitly included 2714 with the request, but it does not correspond to a valid account. 2716 "accountNotSupportedByMethod": Returned if the _accountId_ given 2717 corresponds to a valid account, but the account does not support this 2718 data type. 2720 "requestTooLarge": Returned if the number of _messageIds_ requested 2721 by the client exceeds the maximum number the server is willing to 2722 process in a single method call. 2724 "cannotDoFilter": Returned if the server is unable to process the 2725 given _filter_ for any reason. 2727 "invalidArguments": Returned if the request does not include one of 2728 the required arguments, or one of the arguments is of the wrong type, 2729 or otherwise invalid. A "description" property MAY be present on the 2730 response object to help debug with an explanation of what the problem 2731 was. 2733 8. Vacation Response 2735 The *VacationResponse* object represents the state of vacation- 2736 response related settings for an account. It has the following 2737 properties: 2739 o *id*: "String" The id of the object. This property is immutable. 2740 There is only ever one vacation response object, and its id is 2741 ""singleton"". 2743 o *isEnabled* "Boolean" Should a vacation response be sent if a 2744 message arrives between the _fromDate_ and _toDate_? 2746 o *fromDate*: "Date|null" If _isEnabled_ is "true", the date/time 2747 after which messages that arrive should receive the user's 2748 vacation response, in UTC. If "null", the vacation response is 2749 effective immediately. 2751 o *toDate*: "Date|null" If _isEnabled_ is "true", the date/time 2752 after which messages that arrive should no longer receive the 2753 user's vacation response, in UTC. If "null", the vacation 2754 response is effective indefinitely. 2756 o *subject*: "String|null" The subject that will be used by the mail 2757 sent in response to messages when the vacation response is 2758 enabled. If null, an appropriate subject SHOULD be set by the 2759 server. 2761 o *textBody*: "String|null" The plain text part of the message to 2762 send in response to messages when the vacation response is 2763 enabled. If this is "null", when the vacation message is sent a 2764 plain-text body part SHOULD be generated from the _htmlBody_ but 2765 the server MAY choose to send the response as HTML only. 2767 o *htmlBody*: "String|null" The HTML message to send in response to 2768 messages when the vacation response is enabled. If this is 2769 "null", when the vacation message is sent an HTML body part MAY be 2770 generated from the _textBody_, or the server MAY choose to send 2771 the response as plain-text only. 2773 8.1. getVacationResponse 2775 There MUST only be exactly one VacationResponse object in an account. 2776 It MUST have the id ""singleton"". 2778 To fetch the vacation response object, make a call to 2779 "getVacationResponse". It takes the following argument: 2781 o *accountId*: "String|null" The Account to get the vacation 2782 response for. If "null", the primary account is used. 2784 The response to _getVacationResponse_ is called _vacationResponse_. 2785 It has the following arguments: 2787 o *accountId*: "String" The id of the account used for the call. 2789 o *list*: "VacationResponse[]" An array containing the single 2790 VacationResponse object. 2792 The following errors may be returned instead of the 2793 _vacationResponse_ response: 2795 "accountNotFound": Returned if an _accountId_ was explicitly included 2796 with the request, but it does not correspond to a valid account. 2798 "accountNotSupportedByMethod": Returned if the _accountId_ given 2799 corresponds to a valid account, but the account does not support this 2800 data type. 2802 8.2. setVacationResponse 2804 Sets properties on the vacation response object. It takes the 2805 following arguments: 2807 o *accountId*: "String|null" The Account to set the vacation 2808 response for. If "null", the primary account is used. 2810 o *update*: "String[VacationResponse]|null" A map of id 2811 ("singleton") to the VacationResponse object with new values for 2812 the properties you wish to change. The object may omit any 2813 property; only properties that have changed need be included. 2815 If any of the properties in the update are invalid (immutable and 2816 different to the current server value, wrong type), the server MUST 2817 reject the update with a SetError of type "invalidProperties". The 2818 SetError object SHOULD contain a property called _properties_ of type 2819 "String[]" that lists *all* the properties that were invalid. The 2820 object MAY also contain a _description_ property of type "String" 2821 with a user-friendly description of the problems. 2823 The response is called _vacationResponseSet_. It has the following 2824 arguments: 2826 o *updated*: "String[]" 2828 o *updated*: "String[VacationResponse|null]" If successfully 2829 updated, this map will have a sole key of "singleton". The 2830 _value_ in the map is an object containing the updated value of 2831 each property the *server changed* on the record, if any. 2832 Otherwise (if no properties changed on the server other than those 2833 explicitly updated by the client), the value is "null". 2835 o *notUpdated*: "String[SetError]" A map of id ("singleton") to a 2836 SetError object if the update failed. 2838 A *SetError* object has the following properties: 2840 o *type*: "String" The type of error. 2842 o *description*: "String|null" A description of the error to display 2843 to the user. 2845 The following errors may be returned instead of the 2846 _vacationResponseSet_ response: 2848 "accountNotFound": Returned if an _accountId_ was explicitly included 2849 with the request, but it does not correspond to a valid account. 2851 "accountNotSupportedByMethod": Returned if the _accountId_ given 2852 corresponds to a valid account, but the account does not support this 2853 data type. 2855 "invalidArguments": Returned if one of the arguments is of the wrong 2856 type, or otherwise invalid (including using an id other than 2857 ""singleton""). A "description" property MAY be present on the 2858 response object to help debug with an explanation of what the problem 2859 was. 2861 9. References 2863 9.1. Normative References 2865 [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate 2866 Requirement Levels", BCP 14, RFC 2119, 2867 DOI 10.17487/RFC2119, March 1997, 2868 . 2870 [RFC3629] Yergeau, F., "UTF-8, a transformation format of ISO 2871 10646", STD 63, RFC 3629, DOI 10.17487/RFC3629, November 2872 2003, . 2874 [RFC5322] Resnick, P., Ed., "Internet Message Format", RFC 5322, 2875 DOI 10.17487/RFC5322, October 2008, 2876 . 2878 [RFC5788] Melnikov, A. and D. Cridland, "IMAP4 Keyword Registry", 2879 RFC 5788, DOI 10.17487/RFC5788, March 2010, 2880 . 2882 [RFC7159] Bray, T., Ed., "The JavaScript Object Notation (JSON) Data 2883 Interchange Format", RFC 7159, DOI 10.17487/RFC7159, March 2884 2014, . 2886 9.2. URIs 2888 [1] server.html 2890 [2] https://tools.ietf.org/html/rfc4648 2892 [3] http://tools.ietf.org/html/rfc2047 2894 [4] https://www.iana.org/assignments/imap-keywords/imap- 2895 keywords.xhtml 2897 Author's Address 2899 Neil Jenkins 2900 FastMail 2901 Level 1, 91 William St 2902 Melbourne VIC 3000 2903 Australia 2905 Email: neilj@fastmail.com 2906 URI: https://www.fastmail.com