idnits 2.17.1 draft-jenkins-jmapmail-00.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. Miscellaneous warnings: ---------------------------------------------------------------------------- == The copyright year in the IETF Trust and authors Copyright Line does not match the current year -- The exact meaning of the all-uppercase expression 'MAY NOT' is not defined in RFC 2119. If it is intended as a requirements expression, it should be rewritten using one of the combinations defined in RFC 2119; otherwise it should not be all-uppercase. == The expression 'MAY NOT', while looking like RFC 2119 requirements text, is not defined in RFC 2119, and should not be used. Consider using 'MUST NOT' instead (if that is what you mean). Found 'MAY NOT' in this paragraph: * "outbox" - messages the user has finished writing and wishes to send (see the "setMessages" method description for more information). A mailbox with this role MUST be present if the user is allowed to send mail through an account. If not present, the user MAY NOT send mail with that account. == The expression 'MAY NOT', while looking like RFC 2119 requirements text, is not defined in RFC 2119, and should not be used. Consider using 'MUST NOT' instead (if that is what you mean). Found 'MAY NOT' in this paragraph: A mailbox MAY NOT be destroyed if it still has any child mailboxes. Attempting to do so will result in the destruction being rejected with a "mailboxHasChild" error. == 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. -- The document date (October 19, 2016) is 2747 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 2904 -- Looks like a reference, but probably isn't: '2' on line 2906 -- Looks like a reference, but probably isn't: '3' on line 2908 ** Obsolete normative reference: RFC 7159 (Obsoleted by RFC 8259) Summary: 4 errors (**), 0 flaws (~~), 4 warnings (==), 5 comments (--). Run idnits with the --verbose option for more detailed information about the items above. -------------------------------------------------------------------------------- 2 JMAP N. Jenkins 3 Internet-Draft FastMail 4 Intended status: Standards Track October 19, 2016 5 Expires: April 22, 2017 7 JMAP for Mail 8 draft-jenkins-jmapmail-00 10 Abstract 12 This document specifies a data model for synchronising email data 13 with a server using JMAP. 15 Status of This Memo 17 This Internet-Draft is submitted in full conformance with the 18 provisions of BCP 78 and BCP 79. 20 Internet-Drafts are working documents of the Internet Engineering 21 Task Force (IETF). Note that other groups may also distribute 22 working documents as Internet-Drafts. The list of current Internet- 23 Drafts is at http://datatracker.ietf.org/drafts/current/. 25 Internet-Drafts are draft documents valid for a maximum of six months 26 and may be updated, replaced, or obsoleted by other documents at any 27 time. It is inappropriate to use Internet-Drafts as reference 28 material or to cite them other than as "work in progress." 30 This Internet-Draft will expire on April 22, 2017. 32 Copyright Notice 34 Copyright (c) 2016 IETF Trust and the persons identified as the 35 document authors. All rights reserved. 37 This document is subject to BCP 78 and the IETF Trust's Legal 38 Provisions Relating to IETF Documents 39 (http://trustee.ietf.org/license-info) in effect on the date of 40 publication of this document. Please review these documents 41 carefully, as they describe your rights and restrictions with respect 42 to this document. Code Components extracted from this document must 43 include Simplified BSD License text as described in Section 4.e of 44 the Trust Legal Provisions and are provided without warranty as 45 described in the Simplified BSD License. 47 Table of Contents 49 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 3 50 1.1. Notational Conventions . . . . . . . . . . . . . . . . . 3 51 1.2. Terminology . . . . . . . . . . . . . . . . . . . . . . . 4 52 1.3. Addition to the capabilities object . . . . . . . . . . . 4 53 2. Mailboxes . . . . . . . . . . . . . . . . . . . . . . . . . . 4 54 2.1. getMailboxes . . . . . . . . . . . . . . . . . . . . . . 7 55 2.2. getMailboxUpdates . . . . . . . . . . . . . . . . . . . . 8 56 2.3. setMailboxes . . . . . . . . . . . . . . . . . . . . . . 10 57 2.3.1. Ordering of changes . . . . . . . . . . . . . . . . . 11 58 2.3.2. Creating mailboxes . . . . . . . . . . . . . . . . . 11 59 2.3.3. Updating mailboxes . . . . . . . . . . . . . . . . . 12 60 2.3.4. Destroying mailboxes . . . . . . . . . . . . . . . . 13 61 2.3.5. Response . . . . . . . . . . . . . . . . . . . . . . 14 62 3. MessageLists . . . . . . . . . . . . . . . . . . . . . . . . 15 63 3.1. getMessageList . . . . . . . . . . . . . . . . . . . . . 16 64 3.1.1. Filtering . . . . . . . . . . . . . . . . . . . . . . 17 65 3.1.2. Sorting . . . . . . . . . . . . . . . . . . . . . . . 20 66 3.1.3. Thread collapsing . . . . . . . . . . . . . . . . . . 21 67 3.1.4. Windowing . . . . . . . . . . . . . . . . . . . . . . 22 68 3.1.5. Response . . . . . . . . . . . . . . . . . . . . . . 22 69 3.2. getMessageListUpdates . . . . . . . . . . . . . . . . . . 24 70 4. Threads . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 71 4.1. getThreads . . . . . . . . . . . . . . . . . . . . . . . 27 72 4.2. getThreadUpdates . . . . . . . . . . . . . . . . . . . . 29 73 5. Messages . . . . . . . . . . . . . . . . . . . . . . . . . . 31 74 5.1. getMessages . . . . . . . . . . . . . . . . . . . . . . . 35 75 5.2. getMessageUpdates . . . . . . . . . . . . . . . . . . . . 37 76 5.3. setMessages . . . . . . . . . . . . . . . . . . . . . . . 39 77 5.3.1. Saving a draft . . . . . . . . . . . . . . . . . . . 40 78 5.3.2. Updating messages . . . . . . . . . . . . . . . . . . 43 79 5.3.3. Sending messages . . . . . . . . . . . . . . . . . . 44 80 5.3.4. Cancelling a send . . . . . . . . . . . . . . . . . . 44 81 5.3.5. Destroying messages . . . . . . . . . . . . . . . . . 44 82 5.3.6. Response . . . . . . . . . . . . . . . . . . . . . . 45 83 5.4. importMessages . . . . . . . . . . . . . . . . . . . . . 46 84 5.5. copyMessages . . . . . . . . . . . . . . . . . . . . . . 47 85 5.6. reportMessages . . . . . . . . . . . . . . . . . . . . . 49 86 6. Identities . . . . . . . . . . . . . . . . . . . . . . . . . 50 87 6.1. getIdentities . . . . . . . . . . . . . . . . . . . . . . 51 88 6.2. getIdentityUpdates . . . . . . . . . . . . . . . . . . . 52 89 6.3. setIdentities . . . . . . . . . . . . . . . . . . . . . . 54 90 7. SearchSnippets . . . . . . . . . . . . . . . . . . . . . . . 57 91 7.1. getSearchSnippets . . . . . . . . . . . . . . . . . . . . 57 92 8. Vacation Response . . . . . . . . . . . . . . . . . . . . . . 58 93 8.1. getVacationResponse . . . . . . . . . . . . . . . . . . . 59 94 8.2. setVacationResponse . . . . . . . . . . . . . . . . . . . 60 96 9. References . . . . . . . . . . . . . . . . . . . . . . . . . 61 97 9.1. Normative References . . . . . . . . . . . . . . . . . . 61 98 9.2. URIs . . . . . . . . . . . . . . . . . . . . . . . . . . 61 99 Author's Address . . . . . . . . . . . . . . . . . . . . . . . . 62 101 1. Introduction 103 JMAP is a generic protocol for synchronising data, such as mail, 104 calendars or contacts, between a client and a server. It is 105 optimised for mobile and web environments, and aims to provide a 106 consistent interface to different data types. 108 This specification defines a data model for synchronising mail 109 between a client and a server using JMAP. 111 1.1. Notational Conventions 113 The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", 114 "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this 115 document are to be interpreted as described in [RFC2119]. 117 The underlying format used for this specification is JSON. 118 Consequently, the terms "object" and "array" as well as the four 119 primitive types (strings, numbers, booleans, and null) are to be 120 interpreted as described in Section 1 of [RFC7159]. 122 Some examples in this document contain "partial" JSON documents used 123 for illustrative purposes. In these examples, three periods "..." 124 are used to indicate a portion of the document that has been removed 125 for compactness. 127 Types signatures are given for all JSON objects in this document. 128 The following conventions are used: 130 o "Boolean|String" - The value is either a JSON "Boolean" value, or 131 a JSON "String" value. 133 o "Foo" - Any name that is not a native JSON type means an object 134 for which the properties (and their types) are defined elsewhere 135 within this document. 137 o "Foo[]" - An array of objects of type "Foo". 139 o "String[Foo]" - A JSON "Object" being used as a map (associative 140 array), where all the values are of type "Foo". 142 1.2. Terminology 144 The same terminology is used in this document as in the core JMAP 145 specification. 147 1.3. Addition to the capabilities object 149 The capabilities object is returned as part of the standard JMAP 150 authentication response; see the JMAP spec. Servers supporting 151 _this_ specification MUST add a property called "{TODO: URI for this 152 spec}" to the capabilities object. The value of this property is an 153 object which SHOULD contain the following information on server 154 capabilities: 156 o *maxSizeMessageAttachments*: "Number" The maximum total size of 157 attachments, in bytes, allowed for messages. A server MAY still 158 reject messages with a lower attachment size total (for example, 159 if the body includes several megabytes of text, causing the size 160 of the encoded MIME structure to be over some server-defined 161 limit). 163 o *canDelaySend*: "Boolean" Does the server support inserting a 164 message into the outbox to be sent later at a user-specified time? 166 o *messageListSortOptions*: "String[]" A list of all the message 167 properties the server supports for sorting by. This MAY include 168 properties the client does not recognise (for example custom 169 properties specified in a vendor extension). Clients MUST ignore 170 any unknown properties in the list. 172 2. Mailboxes 174 A mailbox represents a named set of emails. This is the primary 175 mechanism for organising messages within an account. It is analogous 176 to a folder in IMAP or a label in other systems. A mailbox may 177 perform a certain role in the system; see below for more details. 179 For compatibility with IMAP, a message MUST belong to one or more 180 mailboxes. The message id does not change if the message changes 181 mailboxes. 183 A *Mailbox* object has the following properties: 185 o *id*: "String" The id of the mailbox. This property is immutable. 187 o *name*: "String" User-visible name for the mailbox, e.g. "Inbox". 188 This may be any UTF-8 string of at least 1 character in length and 189 maximum 256 bytes in size. Servers SHOULD forbid sibling 190 Mailboxes with the same name. 192 o *parentId*: "String|null" The mailbox id for the parent of this 193 mailbox, or "null" if this mailbox is at the top level. Mailboxes 194 form acyclic graphs (forests) directed by the child-to-parent 195 relationship. There MUST NOT be a loop. 197 o *role*: "String|null" Identifies system mailboxes. This property 198 can only be set on create. After the record has been created, 199 this property is immutable. The following values MUST be used for 200 the relevant mailboxes: 202 * "inbox" - the mailbox to which new mail is delivered by 203 default, unless diverted by a rule or spam filter etc. 205 * "archive" - messages the user does not need right now, but does 206 not wish to delete. 208 * "drafts" - messages the user is currently writing and are not 209 yet sent. 211 * "outbox" - messages the user has finished writing and wishes to 212 send (see the "setMessages" method description for more 213 information). A mailbox with this role MUST be present if the 214 user is allowed to send mail through an account. If not 215 present, the user MAY NOT send mail with that account. 217 * "sent" - messages the user has sent. 219 * "trash" - messages the user has deleted. 221 * "spam" - messages considered spam by the server. 223 * "templates" - drafts which should be used as templates (i.e. 224 used as the basis for creating new drafts). 226 No two mailboxes may have the same role. Mailboxes without a 227 known purpose MUST have a role of "null". An account is not 228 required to have mailboxes with any of the above roles. A client 229 MAY create new mailboxes with a role property to help them keep 230 track of a use-case not covered by the above list. To avoid 231 potential conflict with any special behaviour a server might apply 232 to mailboxes with certain roles in the future, any roles not in 233 the above list created by the client must begin with ""x-"". The 234 client MAY attempt to create mailboxes with the standard roles if 235 not already present, but the server MAY reject these. 237 o *sortOrder*: "Number" Defines the sort order of mailboxes when 238 presented in the client's UI, so it is consistent between devices. 239 The number MUST be an integer in the range 0 <= sortOrder < 2^31. 240 A mailbox with a lower order should be displayed before a mailbox 241 with a higher order (that has the same parent) in any mailbox 242 listing in the client's UI. Mailboxes with equal order SHOULD be 243 sorted in alphabetical order by name. The sorting SHOULD take 244 into account locale-specific character order convention. 246 o *mustBeOnlyMailbox*: "Boolean" If "true", messages in this mailbox 247 may not also be in any other mailbox that also has 248 "mustBeOnlyMailbox: true". If "false", messages may be added to 249 this mailbox in addition to any other mailbox (i.e. it's a label). 250 This property is immutable. 252 o *mayReadItems*: "Boolean" If true, may use this mailbox as part of 253 a filter in a _getMessageList_ call. If a submailbox is shared 254 but not the parent mailbox, this may be "false". 256 o *mayAddItems*: "Boolean" The user may add messages to this mailbox 257 (by either creating a new message or moving an existing one). 259 o *mayRemoveItems*: "Boolean" The user may remove messages from this 260 mailbox (by either changing the mailboxes of a message or deleting 261 it). 263 o *mayCreateChild*: "Boolean" The user may create a mailbox with 264 this mailbox as its parent. 266 o *mayRename*: "Boolean" The user may rename the mailbox or make it 267 a child of another mailbox. 269 o *mayDelete*: "Boolean" The user may delete the mailbox itself. 271 o *totalMessages*: "Number" The number of messages in this mailbox. 273 o *unreadMessages*: "Number" The number of messages in this mailbox 274 where the _isUnread_ property of the message is "true" and the 275 _isDraft_ property is "false". 277 o *totalThreads*: "Number" The number of threads where at least one 278 message in the thread is in this mailbox (but see below for 279 special case handling of Trash). 281 o *unreadThreads*: "Number" The number of threads where at least one 282 message in the thread has "isUnread == true" and "isDraft == 283 false" AND at least one message in the thread is in this mailbox 284 (but see below for special case handling of Trash). Note, the 285 unread message does not need to be the one in this mailbox. 287 The Trash mailbox (that is a mailbox with "role == "trash"") MUST be 288 treated specially: 290 o Messages in the Trash are ignored when calculating the 291 "unreadThreads" and "totalThreads" count of other mailboxes. 293 o Messages not in the Trash are ignored when calculating the 294 "unreadThreads" and "totalThreads" count for the Trash mailbox. 296 The result of this is that messages in the Trash are treated as 297 though they are in a separate thread for the purposes of mailbox 298 counts. It is expected that clients will hide messages in the Trash 299 when viewing a thread in another mailbox and vice versa. This allows 300 you to delete a single message to the Trash out of a thread. 302 For example, suppose you have an account where the entire contents is 303 a single conversation with 2 messages: an unread message in the Trash 304 and a read message in the Inbox. The "unreadThreads" count would be 305 "1" for the Trash and "0" for the Inbox. 307 Destroying a mailbox MUST NOT delete any messages still contained 308 within it. It only removes them from the mailbox. Since messages 309 MUST always be in at least one mailbox, if the last mailbox they are 310 in is deleted the messages must be added to the mailbox with "role == 311 "inbox"". If no Inbox exists, the messages must be moved to any 312 other mailbox; this is server dependent. 314 2.1. getMailboxes 316 Mailboxes can either be fetched explicitly by id, or all of them at 317 once. To fetch mailboxes, make a call to "getMailboxes". It takes 318 the following arguments: 320 o *accountId*: "String|null" The Account to fetch the mailboxes for. 321 If "null", the primary account is used. 323 o *ids*: "String[]|null" The ids of the mailboxes to fetch. If 324 "null", all mailboxes in the account are returned. 326 o *properties*: "String[]|null" The properties of each mailbox to 327 fetch. If "null", all properties are returned. The id of the 328 mailbox will *always* be returned, even if not explicitly 329 requested. 331 The response to _getMailboxes_ is called _mailboxes_. It has the 332 following arguments: 334 o *accountId*: "String" The id of the account used for the call. 336 o *state*: "String" A string representing the state on the server 337 for *all* mailboxes. If the state of a mailbox changes, or a new 338 mailbox is created, or a mailbox is destroyed, this string will 339 change. It is used to get delta updates. 341 o *list*: "Mailbox[]" An array of the Mailbox objects requested. 342 This will be the *empty array* if the _ids_ argument was the empty 343 array, or contained only ids for mailboxes that could not be 344 found. 346 o *notFound*: "String[]|null" This array contains the ids passed to 347 the method for mailboxes that do not exist, or "null" if all 348 requested ids were found. It MUST be "null" if the _ids_ argument 349 in the call was "null". 351 The following errors may be returned instead of the _mailboxes_ 352 response: 354 "accountNotFound": Returned if an _accountId_ was explicitly included 355 with the request, but it does not correspond to a valid account. 357 "accountNotSupportedByMethod": Returned if the _accountId_ given 358 corresponds to a valid account, but the account does not support this 359 data type. 361 "requestTooLarge": Returned if the number of _ids_ requested by the 362 client exceeds the maximum number the server is willing to process in 363 a single method call. 365 "invalidArguments": Returned if the request does not include one of 366 the required arguments, or one of the arguments is of the wrong type, 367 or otherwise invalid. A "description" property MAY be present on the 368 response object to help debug with an explanation of what the problem 369 was. 371 2.2. getMailboxUpdates 373 The _getMailboxUpdates_ call allows a client to efficiently update 374 the state of its cached mailboxes to match the new state on the 375 server. It takes the following arguments: 377 o *accountId*: "String|null" The id of the account to use for this 378 call. If "null", the primary account will be used. 380 o *sinceState*: "String" The current state of the client. This is 381 the string that was returned as the _state_ argument in the 382 _mailboxes_ response. The server will return the changes made 383 since this state. 385 o *fetchRecords*: "Boolean|null" If "true", immediately after 386 outputting a _mailboxUpdates_ response, an implicit call will be 387 made to _getMailboxes_ with the _changed_ property of the response 388 as the _ids_ argument, and the _fetchRecordProperties_ argument as 389 the _properties_ argument. If "false" or "null", no implicit call 390 will be made. 392 o *fetchRecordProperties*: "String[]|null" If "null", all Mailbox 393 properties will be fetched unless _onlyCountsChanged_ in the 394 _mailboxUpdates_ response is "true", in which case only the 4 395 counts properties will be returned (_totalMessages_, 396 _unreadMessages_, _totalThreads_ and _unreadThreads_). If not 397 "null", this value will be passed through to the _getMailboxes_ 398 call regardless of the _onlyCountsChanged_ value in the 399 _mailboxUpdates_ response. 401 The response to _getMailboxUpdates_ is called _mailboxUpdates_. It 402 has the following arguments: 404 o *accountId*: "String" The id of the account used for the call. 406 o *oldState*: "String" This is the _sinceState_ argument echoed 407 back; the state from which the server is returning changes. 409 o *newState*: "String" This is the state the client will be in after 410 applying the set of changes to the old state. 412 o *changed*: "String[]" An array of Mailbox ids where a property of 413 the mailbox has changed between the old state and the new state, 414 or the mailbox has been created, and the mailbox has not been 415 destroyed. 417 o *removed*: "String[]" An array of Mailbox ids for mailboxes which 418 have been destroyed since the old state. 420 o *onlyCountsChanged*: "Boolean" Indicates that only the mailbox 421 counts (unread/total messages/threads) have changed since the old 422 state. The client can then use this to optimise its data transfer 423 and only fetch the counts. If the server is unable to tell if 424 only counts have changed, it should just always return "false". 426 If a mailbox has been modified AND deleted since the oldState, the 427 server should just return the id in the _removed_ array, but MAY 428 return it in the _changed_ array as well. If a mailbox has been 429 created AND deleted since the oldState, the server SHOULD remove the 430 mailbox id from the response entirely, but MAY include it in the 431 _removed_ array. 433 The following errors may be returned instead of the "mailboxUpdates" 434 response: 436 "accountNotFound": Returned if an _accountId_ was explicitly included 437 with the request, but it does not correspond to a valid account. 439 "accountNotSupportedByMethod": Returned if the _accountId_ given 440 corresponds to a valid account, but the account does not support this 441 data type. 443 "invalidArguments": Returned if the request does not include one of 444 the required arguments, or one of the arguments is of the wrong type, 445 or otherwise invalid. A "description" property MAY be present on the 446 response object to help debug with an explanation of what the problem 447 was. 449 "cannotCalculateChanges": Returned if the server cannot calculate the 450 changes from the state string given by the client. Usually due to 451 the client's state being too old. The client MUST invalidate its 452 Mailbox cache. 454 2.3. setMailboxes 456 Mailboxes can be created, updated and destroyed using the 457 _setMailboxes_ method. The method takes the following arguments: 459 o *accountId*: "String|null" The id of the account to use for this 460 call. If "null", defaults to the primary account. 462 o *ifInState*: "String|null" This is a state string as returned by 463 the _getMailboxes_ method. If supplied, the string must match the 464 current state, otherwise the method will be aborted and a 465 "stateMismatch" error returned. If "null", any changes will be 466 applied to the current state. 468 o *create*: "String[Mailbox]|null" A map of _creation id_ (an 469 arbitrary string set by the client) to Mailbox objects. If 470 "null", no objects will be created. 472 o *update*: "String[Mailbox]|null" A map of mailbox id to objects 473 containing the properties to update for that Mailbox. If "null", 474 no objects will be updated. 476 o *destroy*: "String[]|null" A list of ids for Mailboxes to 477 permanently delete. If "null", no objects will be deleted. 479 If a create, update or destroy is rejected, the appropriate error 480 MUST be added to the notCreated/notUpdated/notDestroyed property of 481 the response and the server MUST continue to the next create/update/ 482 destroy. It does not terminate the method. 484 2.3.1. Ordering of changes 486 Each create, update or destroy is considered an atomic unit. The 487 server MAY commit some of the changes but not others, however MUST 488 NOT only commit part of an update to a single record (e.g. update the 489 _name_ field but not the _parentId_ field, if both are supplied in 490 the update object). 492 The final state MUST be valid after the setMailboxes is finished, 493 however the server MAY have to transition through invalid 494 intermediate states (not exposed to the client) while processing the 495 individual create/update/destroy requests. For example, a single 496 method call could rename Mailbox A => B, and simultaneously rename 497 Mailbox B => A. The final state is valid, so this is allowed, 498 however if processed sequentially there will be an internal state 499 where temporarily both mailboxes have the same name. 501 A Mailbox may reference another Mailbox object as a parent. When a 502 Mailbox is created or modified, it may reference another Mailbox 503 being created _in the same API request_ by using the creation id 504 prefixed with a "#". The order of the method calls in the request by 505 the client MUST be such that the mailbox being referenced is created 506 in *either the same or an earlier method call*. If within the same 507 method call, the server MUST process the parent create first, as if 508 this fails the create/update that references it will also fail. 510 Creation ids sent by the client SHOULD be unique within the single 511 API request for a particular data type. If a creation id is reused, 512 the server MUST map the creation id to the most recently created item 513 with that id. 515 2.3.2. Creating mailboxes 517 The properties of the Mailbox object submitted for creation MUST 518 conform to the following conditions: 520 o The _id_ property MUST NOT be present. 522 o The _parentId_ property MUST be either "null" or be a valid id for 523 a mailbox for which the "mayCreateChild" property is "true". 525 o The _role_ property MUST be either "null", a valid role as listed 526 in the Mailbox object specification, or prefixed by ""x-"". 528 o The _mustBeOnlyMailbox_ property MUST NOT be present. This is 529 server dependent and will be set by the server. 531 o The _mayXXX_ properties MUST NOT be present. Restrictions may 532 only be set by the server for system mailboxes, or when sharing 533 mailboxes with other users (setting sharing is not defined yet in 534 this spec). 536 o The _totalMessages_, _unreadMessages_, _totalThreads_ and 537 _unreadThreads_ properties MUST NOT be present. 539 If any of the properties are invalid, the server MUST reject the 540 create with an "invalidProperties" error. The Error object SHOULD 541 contain a property called _properties_ of type "String[]" that lists 542 *all* the properties that were invalid. The object MAY also contain 543 a _description_ property of type "String" with a user-friendly 544 description of the problems. 546 There may be a maximum number of mailboxes allowed on the server. If 547 this is reached, any attempt at creation will be rejected with a 548 "maxQuotaReached" error. 550 2.3.3. Updating mailboxes 552 If the _id_ given does not correspond to a Mailbox in the given 553 account, the update MUST be rejected with a "notFound" error. 555 All properties being updated must be of the correct type, not 556 immutable or server-set-only, and the new value must obey all 557 conditions of the property. In particular, note the following 558 conditions: 560 o The _name_ property MUST be a valid UTF-8 string of at least 1 561 character in length and maximum 256 bytes in size. 563 o The _parentId_ property MUST be either "null" or be a valid id for 564 _another_ mailbox that is *not a descendant* of this mailbox, and 565 for which the "mayCreateChild" property is "true". 567 o These properties are immutable or may only be set by the server: 569 * id 571 * role 572 * mustBeOnlyMailbox 574 * mayReadItems 576 * mayAddItems 578 * mayRemoveItems 580 * mayCreateChild 582 * mayRename 584 * mayDelete 586 * totalMessages 588 * unreadMessages 590 * totalThreads 592 * unreadThreads 594 If any of the properties are invalid, the server MUST reject the 595 update with an "invalidProperties" error. The Error object SHOULD 596 contain a property called _properties_ of type "String[]" that lists 597 *all* the properties that were invalid. The object MAY also contain 598 a _description_ property of type "String" with a user-friendly 599 description of the problems. 601 2.3.4. Destroying mailboxes 603 If the _id_ given does not correspond to a Mailbox in the given 604 account, the destruction MUST be rejected with a "notFound" error. 606 If the mailbox has "mayDeleteMailbox == false", the destruction MUST 607 be rejected with a "forbidden" error. 609 A mailbox MAY NOT be destroyed if it still has any child mailboxes. 610 Attempting to do so will result in the destruction being rejected 611 with a "mailboxHasChild" error. 613 Destroying a mailbox MUST NOT delete any messages still contained 614 within it. It only removes them from the mailbox. Since messages 615 MUST always be in at least one mailbox, if the last mailbox they are 616 in is deleted the messages must be added to the mailbox with "role == 617 "inbox"". If no Inbox exists, the messages must be moved to any 618 other mailbox; this is server dependent. 620 There MUST always be *at least one* mailbox. It is expected that the 621 server will enforce this by setting "mayDeleteMailbox == false" on at 622 least the Inbox, if not all system mailboxes. However, if this is 623 not the case, an attempt to destroy the last mailbox MUST still be 624 rejected with a "mailboxRequired" error. 626 2.3.5. Response 628 The response to _setMailboxes_ is called _mailboxesSet_. It has the 629 following arguments: 631 o *accountId*: "String" The id of the account used for the call. 633 o *oldState*: "String|null" The state string that would have been 634 returned by "getMailboxes" before making the requested changes, or 635 "null" if the server doesn't know what the previous state string 636 was. 638 o *newState*: "String" The state string that will now be returned by 639 "getMailboxes". 641 o *created*: "String[Mailbox]" A map of the creation id to an object 642 containing all server-set properties for each successfully created 643 Mailbox: _id_, _mustBeOnlyMailbox_, all _mayXXX_ properties, 644 _totalMessages_, _unreadMessages_, _totalThreads_ and 645 _unreadThreads_. 647 o *updated*: "String[]" A list of ids for Mailboxes that were 648 successfully updated. 650 o *destroyed*: "String[]" A list of ids for Mailboxes that were 651 successfully destroyed. 653 o *notCreated*: "String[SetError]" A map of creation id to a 654 SetError object for each Mailbox that failed to be created. The 655 possible errors are defined above. 657 o *notUpdated*: "String[SetError]" A map of Mailbox id to a SetError 658 object for each Mailbox that failed to be updated. The possible 659 errors are defined above. 661 o *notDestroyed*: "String[SetError]" A map of Mailbox id to a 662 SetError object for each Mailbox that failed to be destroyed. The 663 possible errors are defined above. 665 The following errors may be returned instead of the _mailboxesSet_ 666 response: 668 "accountNotFound": Returned if an _accountId_ was explicitly included 669 with the request, but it does not correspond to a valid account. 671 "accountNotSupportedByMethod": Returned if the _accountId_ given 672 corresponds to a valid account, but the account does not support this 673 data type. 675 "accountReadOnly": Returned if the account has "isReadOnly == true". 677 "requestTooLarge": Returned if the total number of objects to create, 678 update or destroy exceeds the maximum number the server is willing to 679 process in a single method call. 681 "invalidArguments": Returned if one of the arguments is of the wrong 682 type, or otherwise invalid. A _description_ property MAY be present 683 on the response object to help debug with an explanation of what the 684 problem was. 686 "stateMismatch": Returned if an "ifInState" argument was supplied and 687 it does not match the current state. 689 Example request: 691 [ "setMailboxes", { 692 "ifInState": "ms4123", 693 "update": { 694 "f3": { 695 "name": "The new name" 696 } 697 }, 698 "destroy": [ "f5" ] 699 }, "#0" ] 701 3. MessageLists 703 A *MessageList* is a sorted query on the set of messages in a user's 704 account. Since it can be very long, the client must specify what 705 section of the list to return. The client can optionally also fetch 706 the threads and/or messages for this part of the list. 708 The same message may appear in multiple messages lists. For example, 709 it may belong to multiple mailboxes, and of course it can appear in 710 searches. Since messages have an immutable id, a client can easily 711 tell if it already has a message cached and only fetch the ones it 712 needs. 714 When the state changes on the server, a delta update can be requested 715 to efficiently update the client's cache of this list to the new 716 state. If the server doesn't support this, the client still only 717 needs to fetch the message list again, not the messages themselves. 719 3.1. getMessageList 721 To fetch a message list, make a call to _getMessageList_. It takes 722 the following arguments: 724 o *accountId*: "String|null" The id of the account to use for this 725 call. If "null", the primary account will be used. 727 o *filter*: "FilterCondition|FilterOperator|null" Determines the set 728 of messages returned in the results. See the "Filtering" section 729 below for allowed values and semantics. 731 o *sort*: "String[]|null" A list of Message property names to sort 732 by. See the "Sorting" section below for allowed values and 733 semantics. 735 o *collapseThreads*: "Boolean|null" If true, each thread will only 736 be returned once in the resulting list, at the position of the 737 first message in the list (given the filter and sort order) 738 belonging to the thread. If "false" or "null", threads may be 739 returned multiple times. 741 o *position*: "Number|null" The 0-based index of the first result in 742 the list to return. If a negative value is given, the call MUST 743 be rejected with an "invalidArguments" error. If "null", 0 is 744 used. 746 o *anchor*: "String|null" A Message id. The index of this message 747 id will be used in combination with the "anchorOffset" argument to 748 determine the index of the first result to return (see the 749 "Windowing" section below for more details). 751 o *anchorOffset*: "Number|null" The index of the anchor message 752 relative to the index of the first result to return. This MAY be 753 negative. For example, "-1" means the first message after the 754 anchor message should be the first result in the results returned 755 (see the "Windowing" section below for more details). 757 o *limit*: "Number|null" The maximum number of results to return. 758 If "null", no limit is presumed. The server MAY choose to enforce 759 a maximum "limit" argument. In this case, if a greater value is 760 given, the limit should be clamped to the maximum; since the total 761 number of results in the list is returned, the client should not 762 be relying on how many results are returned to determine if it has 763 reached the end of the list. If a negative value is given, the 764 call MUST be rejected with an "invalidArguments" error. 766 o *fetchThreads*: "Boolean|null" If "true", after outputting a 767 _messageList_ response, an implicit call will be made to 768 _getThreads_ with the _threadIds_ array in the response as the 769 _ids_ argument, and the _fetchMessages_ and 770 _fetchMessageProperties_ arguments passed straight through from 771 the call to _getMessageList_. If "false" or "null", no implicit 772 call will be made. 774 o *fetchMessages*: "Boolean|null" If "true" and "fetchThreads == 775 false", then after outputting a _messageList_ response, an 776 implicit call will be made to _getMessages_ with the "messageIds" 777 array in the response as the _ids_ argument, and the 778 _fetchMessageProperties_ argument as the _properties_ argument. 779 If "false" or "null", no implicit call will be made. 781 o *fetchMessageProperties*: "String[]|null" The list of properties 782 to fetch on any fetched messages. See _getMessages_ for a full 783 description. 785 o *fetchSearchSnippets*: "Boolean|null" If "true", then after 786 outputting a _messageList_ and making any other implicit calls, an 787 implicit call will be made to _getSearchSnippets_. The 788 _messageIds_ array from the response will be used as the 789 _messageIds_ argument, and the _filter_ argument will be passed 790 straight through. If "false" or "null", no implicit call will be 791 made. 793 3.1.1. Filtering 795 A *FilterOperator* object has the following properties: 797 o *operator*: "String" This MUST be one of the following strings: 798 "AND"/"OR"/"NOT": 800 * *AND*: all of the conditions must match for the filter to 801 match. 803 * *OR*: at least one of the conditions must match for the filter 804 to match. 806 * *NOT*: none of the conditions must match for the filter to 807 match. 809 o *conditions*: "(FilterCondition|FilterOperator)[]" The conditions 810 to evaluate against each message. 812 A *FilterCondition* object has the following properties: 814 o *inMailboxes*: "String[]|null" A list of mailbox ids. A message 815 must be in ALL of these mailboxes to match the condition. 817 o *notInMailboxes*: "String[]|null" A list of mailbox ids. A 818 message must NOT be in ANY of these mailboxes to match the 819 condition. 821 o *before*: "Date|null" The date of the message (as returned on the 822 Message object) must be before this date to match the condition. 824 o *after*: "Date|null" The date of the message (as returned on the 825 Message object) must be on or after this date to match the 826 condition. 828 o *minSize*: "Number|null" The size of the message in bytes (as 829 returned on the Message object) must be equal to or greater than 830 this number to match the condition. 832 o *maxSize*: "Number|null" The size of the message in bytes (as 833 returned on the Message object) must be less than this number to 834 match the condition. 836 o *threadIsFlagged*: "Boolean|null" If "true", the condition is 837 matched if the "isFlagged" property of _any_ message in the same 838 thread as the message being examined is "true". If "false", the 839 "isFlagged" property of _every_ message in the same thread as the 840 message being examined must be "false" to match the condition. 842 o *threadIsUnread*: "Boolean|null" If "true", the condition is 843 matched if the "isUnread" property of _any_ message in the same 844 thread as the message being examined is "true". If "false", the 845 "isUnread" property of _every_ message in the same thread as the 846 message being examined must be "false" to match the condition. 848 o *isFlagged*: "Boolean|null" The "isFlagged" property of the 849 message must be identical to the value given to match the 850 condition. 852 o *isUnread*: "Boolean|null" The "isUnread" property of the message 853 must be identical to the value given to match the condition. 855 o *isAnswered*: "Boolean|null" The "isAnswered" property of the 856 message must be identical to the value given to match the 857 condition. 859 o *isDraft*: "Boolean|null" The "isDraft" property of the message 860 must be identical to the value given to match the condition. 862 o *hasAttachment*: "Boolean|null" The "hasAttachment" property of 863 the message must be identical to the value given to match the 864 condition. 866 o *text*: "String|null" Looks for the text in the _from_, _to_, 867 _cc_, _bcc_, _subject_, _textBody_ or _htmlBody_ properties of the 868 message. 870 o *from*: "String|null" Looks for the text in the _from_ property of 871 the message. 873 o *to*: "String|null" Looks for the text in the _to_ property of the 874 message. 876 o *cc*: "String|null" Looks for the text in the _cc_ property of the 877 message. 879 o *bcc*: "String|null" Looks for the text in the _bcc_ property of 880 the message. 882 o *subject*: "String|null" Looks for the text in the _subject_ 883 property of the message. 885 o *body*: "String|null" Looks for the text in the _textBody_ or 886 _htmlBody_ property of the message. 888 o *header*: "String[]|null" The array MUST contain either one or two 889 elements. The first element is the name of the header to match 890 against. The second (optional) element is the text to look for in 891 the header. If not supplied, the message matches simply if it 892 _has_ a header of the given name. 894 If zero properties are specified on the FilterCondition, the 895 condition MUST always evaluate to "true". If multiple properties are 896 specified, ALL must apply for the condition to be "true" (it is 897 equivalent to splitting the object into one-property conditions and 898 making them all the child of an AND filter operator). 900 The exact semantics for matching "String" fields is *deliberately not 901 defined* to allow for flexibility in indexing implementation, subject 902 to the following: 904 o Text SHOULD be matched in a case-insensitive manner. 906 o Text contained in either (but matched) single or double quotes 907 SHOULD be treated as a *phrase search*, that is a match is 908 required for that exact sequence of words, excluding the 909 surrounding quotation marks. Use "\"", "\'" and "\\" to match a 910 literal """, "'" and "\" respectively in a phrase. 912 o Outside of a phrase, white-space SHOULD be treated as dividing 913 separate tokens that may be searched for separately in the 914 message, but MUST all be present for the message to match the 915 filter. 917 o Tokens MAY be matched on a whole-word basis using stemming (so for 918 example a text search for "bus" would match "buses" but not 919 "business"). 921 o When searching inside the _htmlBody_ property, HTML tags and 922 attributes SHOULD be ignored. 924 3.1.2. Sorting 926 The "sort" argument lists the properties to compare between two 927 messages to determine which comes first in the sort. If two messages 928 have an identical value for the first property, the next property 929 will be considered and so on. If all properties are the same (this 930 includes the case where an empty array or "null" is given as the 931 argument), the sort order is server-dependent, but MUST be stable 932 between calls to "getMessageList". 934 Following the property name there MUST be a space and then either the 935 string "asc" or "desc" to specify ascending or descending sort for 936 that property. 938 The following properties MUST be supported for sorting: 940 o *id* - The id as returned in the Message object. 942 o *date* - The date as returned in the Message object. 944 The following properties SHOULD be supported for sorting: 946 o *size* - The size as returned in the Message object. 948 o *from* - This is taken to be either the "name" part of the Emailer 949 object, or if none then the "email" part of the Emailer object 950 (see the definition of the from property in the Message object). 951 If still none, consider the value to be the empty string. 953 o *to* - This is taken to be either the "name" part of the *first* 954 Emailer object, or if none then the "email" part of the *first* 955 Emailer object (see the definition of the to property in the 956 Message object). If still none, consider the value to be the 957 empty string. 959 o *subject* - This is taken to be the subject of the Message with 960 any ignoring any leading "Fwd:"s or "Re:"s (case-insensitive 961 match). 963 o *threadIsFlagged* - This value MUST be considered "true" for the 964 message if *any* of the messages in the same thread (regardless of 965 mailbox) have "isFlagged: true". 967 o *threadIsUnread* - This value MUST be considered "true" for the 968 message if *any* of the messages in the same thread (regardless of 969 mailbox) have "isUnread: true". 971 o *isFlagged* - The "isFlagged" state of the message (only). 973 o *isUnread* - The "isUnread" state of the message (only). 975 The server MAY support sorting based on other properties as well. A 976 client can discover which properties are supported by inspecting the 977 server's _capabilities_ object (see section 1). 979 The method of comparison depends on the type of the property: 981 o "String": Comparison function is server-dependent. It SHOULD be 982 case-insensitive and SHOULD take into account locale-specific 983 conventions if known for the user. However, the server MAY choose 984 to just sort based on unicode code point, after best-effort 985 translation to lower-case. 987 o "Date": If sorting in ascending order, the earlier date MUST come 988 first. 990 o "Boolean": If sorting in ascending order, a "false" value MUST 991 come before a "true" value. 993 3.1.3. Thread collapsing 995 When "collapseThreads == true", then after filtering and sorting the 996 message list, the list is further winnowed by removing any messages 997 for a thread id that has already been seen (when passing through the 998 list sequentially). A thread will therefore only appear *once* in 999 the "threadIds" list of the result, at the position of the first 1000 message in the list that belongs to the thread. 1002 3.1.4. Windowing 1004 If a _position_ offset is supplied, then this is the 0-based index of 1005 the first result to return in the list of messages after filtering, 1006 sorting and collapsing threads. If the index is greater than or 1007 equal to the total number of messages in the list, then there are no 1008 results to return, but this DOES NOT generate an error. If 1009 _position_ is "null" (or, equivalently, omitted) this MUST be 1010 interpreted as "position: 0". 1012 Alternatively, a message id, called the *anchor* may be given. In 1013 this case, after filtering, sorting and collapsing threads, the 1014 anchor is searched for in the message list. If found, the *anchor 1015 offset* is then subtracted from this index. If the resulting index 1016 is now negative, it is clamped to 0. This index is now used exactly 1017 as though it were supplied as the "position" argument. If the anchor 1018 is not found, the call is rejected with an "anchorNotFound" error. 1020 If an _anchor_ is specified, any position argument supplied by the 1021 client MUST be ignored. If _anchorOffset_ is "null", it defaults to 1022 "0". If no _anchor_ is supplied, any anchor offset argument MUST be 1023 ignored. 1025 3.1.5. Response 1027 The response to a call to _getMessageList_ is called _messageList_. 1028 It has the following arguments: 1030 o *accountId*: "String" The id of the account used for the call. 1032 o *filter*: "FilterCondition|FilterOperator|null" The filter of the 1033 message list. Echoed back from the call. 1035 o *sort*: "String[]|null" A list of Message property names used to 1036 sort by. Echoed back from the call. 1038 o *collapseThreads*: "Boolean|null" Echoed back from the call. 1040 o *state*: "String" A string encoding the current state on the 1041 server. This string will change if the results of the message 1042 list MAY have changed (for example, there has been a change to the 1043 state of the set of Messages; it does not guarantee that anything 1044 in the list has changed). It may be passed to 1045 _getMessageListUpdates_ to efficiently get the set of changes from 1046 the previous state. Should a client receive back a response with 1047 a different state string to a previous call, it MUST either throw 1048 away the currently cached list and fetch it again (note, this does 1049 not require fetching the messages again, just the list of ids) or, 1050 if the server supports it, call _getMessageListUpdates_ to get the 1051 delta difference. 1053 o *canCalculateUpdates*: "Boolean" This is "true" if the server 1054 supports calling "getMessageListUpdates" with these 1055 "filter"/"sort"/"collapseThreads" parameters. Note, this does not 1056 guarantee that the getMessageListUpdates call will succeed, as it 1057 may only be possible for a limited time afterwards due to server 1058 internal implementation details. 1060 o *position*: "Number" The 0-based index of the first result in the 1061 "threadIds" array within the complete list. 1063 o *total*: "Number" The total number of messages in the message list 1064 (given the _filter_ and _collapseThreads_ arguments). 1066 o *threadIds*: "String[]" The list of Thread ids for each message in 1067 the list after filtering, sorting and collapsing threads, starting 1068 at the index given by the _position_ argument of this response, 1069 and continuing until it hits the end of the list or reaches the 1070 "limit" number of ids. 1072 o *messageIds*: "String[]" The list of Message ids for each message 1073 in the list after filtering, sorting and collapsing threads, 1074 starting at the index given by the _position_ argument of this 1075 response, and continuing until it hits the end of the list or 1076 reaches the "limit" number of ids. 1078 The following errors may be returned instead of the "messageList" 1079 response: 1081 "accountNotFound": Returned if an _accountId_ was explicitly included 1082 with the request, but it does not correspond to a valid account. 1084 "accountNotSupportedByMethod": Returned if the _accountId_ given 1085 corresponds to a valid account, but the account does not support this 1086 data type. 1088 "unsupportedSort": Returned if the _sort_ includes a property the 1089 server does not support sorting on. 1091 "cannotDoFilter": Returned if the server is unable to process the 1092 given _filter_ for any reason. 1094 "invalidArguments": Returned if the request does not include one of 1095 the required arguments, or one of the arguments is of the wrong type, 1096 or otherwise invalid. A "description" property MAY be present on the 1097 response object to help debug with an explanation of what the problem 1098 was. 1100 "anchorNotFound": Returned if an anchor argument was supplied, but it 1101 cannot be found in the message list. 1103 3.2. getMessageListUpdates 1105 The "getMessageListUpdates" call allows a client to efficiently 1106 update the state of any cached message list to match the new state on 1107 the server. It takes the following arguments: 1109 o *accountId*: "String|null" The id of the account to use for this 1110 call. If "null", the primary account will be used. 1112 o *filter*: "FilterCondition|FilterOperator|null" The filter 1113 argument that was used with _getMessageList_. 1115 o *sort*: "String[]|null" The sort argument that was used with 1116 _getMessageList_. 1118 o *collapseThreads*: "Boolean|null" The _collapseThreads_ argument 1119 that was used with _getMessageList_. 1121 o *sinceState*: "String" The current state of the client. This is 1122 the string that was returned as the _state_ argument in the 1123 _messageList_ response. The server will return the changes made 1124 since this state. 1126 o *uptoMessageId*: "String|null" The message id of the last message 1127 in the list that the client knows about. In the common case of 1128 the client only having the first X ids cached, this allows the 1129 server to ignore changes further down the list the client doesn't 1130 care about. 1132 o *maxChanges*: "Number|null" The maximum number of changes to 1133 return in the response. See below for a more detailed 1134 description. 1136 The response to _getMessageListUpdates_ is called 1137 _messageListUpdates_ It has the following arguments: 1139 o *accountId*: "String" The id of the account used for the call. 1141 o *filter*: "FilterCondition|FilterOperator|null" The filter of the 1142 message list. Echoed back from the call. 1144 o *sort*: "String[]|null" A list of Message property names used to 1145 sort by. Echoed back from the call. 1147 o *collapseThreads*: "Boolean|null" Echoed back from the call. 1149 o *oldState*: "String" This is the "sinceState" argument echoed 1150 back; the state from which the server is returning changes. 1152 o *newState*: "String" This is the state the client will be in after 1153 applying the set of changes to the old state. 1155 o *uptoMessageId*: "String|null" Echoed back from the call. 1157 o *total*: "Number" The total number of messages in the message list 1158 (given the filter and collapseThreads arguments). 1160 o *removed*: "RemovedItem[]" The _messageId_ and _threadId_ for 1161 every message that was in the list in the old state and is not in 1162 the list in the new state. If the server cannot calculate this 1163 exactly, the server MAY return extra messages in addition that MAY 1164 have been in the old list but are not in the new list. If an 1165 _uptoMessageId_ was given AND this id was found in the list, only 1166 messages positioned before this message that were removed need be 1167 returned. In addition, if the sort includes the property 1168 _isUnread_ or _isFlagged_, the server MUST include all messages in 1169 the current list for which this property MAY have changed. If 1170 "collapseThreads == true", then the server MUST include all 1171 messages in the current list for which this property MAY have 1172 changed *on any of the messages in the thread*. 1174 o *added*: "AddedItem[]" The messageId and threadId and index in the 1175 list (in the new state) for every message that has been added to 1176 the list since the old state AND every message in the current list 1177 that was included in the _removed_ array (due to a filter or sort 1178 based upon a mutable property). The array MUST be sorted in order 1179 of index, lowest index first. If an _uptoMessageId_ was given AND 1180 this id was found in the list, only messages positioned before 1181 this message that have been added need be returned. 1183 A *RemovedItem* object has the following properties: 1185 o *messageId*: "String" 1187 o *threadId*: "String" 1189 An *AddedItem* object has the following properties: 1191 o *messageId*: "String" 1192 o *threadId*: "String" 1194 o *index*: "Number" 1196 The result of this should be that if the client has a cached sparse 1197 array of message ids in the list in the old state: 1199 messageIds = [ "id1", "id2", null, null, "id3", "id4", null, null, null ] 1201 then if it *splices out* all messages in the removed array: 1203 removed = [{ messageId: "id2", ... }]; 1204 messageIds => [ "id1", null, null, "id3", "id4", null, null, null ] 1206 and *splices in* (in order) all of the messages in the added array: 1208 added = [{ messageId: "id5", index: 0, ... }]; 1209 messageIds => [ "id5", "id1", null, null, "id3", "id4", null, null, null ] 1211 then the message list will now be in the new state. 1213 The following errors may be returned instead of the 1214 "messageListUpdates" response: 1216 "accountNotFound": Returned if an _accountId_ was explicitly included 1217 with the request, but it does not correspond to a valid account. 1219 "accountNotSupportedByMethod": Returned if the _accountId_ given 1220 corresponds to a valid account, but the account does not support this 1221 data type. 1223 "invalidArguments": Returned if the request does not include one of 1224 the required arguments, or one of the arguments is of the wrong type, 1225 or otherwise invalid. A _description_ property MAY be present on the 1226 response object to help debug with an explanation of what the problem 1227 was. 1229 "tooManyChanges": Returned if there are more changes the the client's 1230 _maxChanges_ argument. Each item in the removed or added array is 1231 considered as one change. The client may retry with a higher max 1232 changes or invalidate its cache of the message list. 1234 "cannotCalculateChanges": Returned if the server cannot calculate the 1235 changes from the state string given by the client. Usually due to 1236 the client's state being too old. The client MUST invalidate its 1237 cache of the message list. 1239 4. Threads 1241 Replies are grouped together with the original message to form a 1242 thread. In JMAP, a thread is simply a flat list of messages, ordered 1243 by date. Every message MUST belong to a thread, even if it is the 1244 only message in the thread. 1246 The JMAP spec does not require the server to use any particular 1247 algorithm for determining whether two messages belong to the same 1248 thread, however there is a recommended algorithm in the 1249 implementation guide [1]. 1251 If messages are delivered out of order for some reason, a user may 1252 receive two messages in the same thread but without headers that 1253 associate them with each other. The arrival of a third message in 1254 the thread may provide the missing references to join them all 1255 together into a single thread. Since the "threadId" of a message is 1256 immutable, if the server wishes to merge the threads, it MUST handle 1257 this by deleting and reinserting (with a new message id) the messages 1258 that change threadId. 1260 A *Thread* object has the following properties: 1262 o *id*: "String" The id of the thread. This property is immutable. 1264 o *messageIds*: "String[]" The ids of the messages in the thread, 1265 sorted such that: 1267 * Any message with "isDraft == true" and an _inReplyToMessageId_ 1268 property that corresponds to another message in the thread 1269 comes immediately after that message in the sort order. 1271 * Other than that, everything is sorted in date order (the same 1272 as the _date_ property on the Message object), oldest first. 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 calculat 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 the body, such as base64 [2], or RFC 1467 2047 [3] encoding of non-ASCII characters, MUST be fully decoded into 1468 standard 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 *inReplyToMessageId*: "String|null" The id of the Message this 1486 message is a reply to. This is primarily for drafts, but the 1487 server MAY support this for received messages as well by looking 1488 up the [RFC5322] Message-Id referenced in the "In-Reply-To" header 1489 and searching for this message in the user's mail. 1491 o *isUnread*: "Boolean" (Mutable) Has the message not yet been read? 1492 This corresponds to the *opposite* of the "\Seen" system flag in 1493 IMAP. 1495 o *isFlagged*: "Boolean" (Mutable) Is the message flagged? This 1496 corresponds to the "\Flagged" system flag in IMAP. 1498 o *isAnswered*: "Boolean" (Mutable) Has the message been replied to? 1499 This corresponds to the "\Answered" system flag in IMAP. 1501 o *isDraft*: "Boolean" (Mutable by the server only) Is the message a 1502 draft? This corresponds to the "\Draft" system flag in IMAP. 1504 o *hasAttachment*: "Boolean" Does the message have any attachments? 1506 o *headers*: "String[String]" A map of lower-cased header name to 1507 (decoded) header value for all headers in the message. For 1508 headers that occur multiple times (e.g. "Received"), the values 1509 are concatenated with a single new line ("\n") character in 1510 between each one. 1512 o *sender*: "Emailer|null" An Emailer object (see below) containing 1513 the name/email from the parsed "Sender" header of the email. If 1514 the email doesn't have a "Sender" header, this is "null". 1516 o *from*: "Emailer[]|null" An array of name/email objects (see 1517 below) representing the parsed "From" header of the email, in the 1518 same order as they appear in the header. If the email doesn't 1519 have a "From" header, this is "null". If the header exists but 1520 does not have any content, the response is an array of zero 1521 length. 1523 o *to*: "Emailer[]|null" An array of name/email objects (see below) 1524 representing the parsed "To" header of the email, in the same 1525 order as they appear in the header. If the email doesn't have a 1526 "To" header, this is "null". If the header exists but does not 1527 have any content, the response is an array of zero length. 1529 o *cc*: "Emailer[]|null" An array of name/email objects (see below) 1530 representing the parsed "Cc" header of the email, in the same 1531 order as they appear in the header. If the email doesn't have a 1532 "Cc" header, this is "null". If the header exists but does not 1533 have any content, the response is an array of zero length. 1535 o *bcc*: "Emailer[]|null" An array of name/email objects (see below) 1536 representing the parsed "Bcc" header of the email. If the email 1537 doesn't have a "Bcc" header (which will be true for most emails 1538 outside of the Sent mailbox), this is "null". If the header 1539 exists but does not have any content, the response is an array of 1540 zero length. 1542 o *replyTo*: "Emailer[]|null" An array of name/email objects (see 1543 below) representing the parsed "Reply-To" header of the email, in 1544 the same order as they appear in the header. If the email doesn't 1545 have a "Reply-To" header, this is "null". If the header exists 1546 but does not have any content, the response is an array of zero 1547 length. 1549 o *subject*: "String" The subject of the message. 1551 o *date*: "Date" The date the message was sent (or saved, if the 1552 message is a draft). 1554 o *size*: "Number" The size in bytes of the whole message as counted 1555 by the server towards the user's quota. 1557 o *preview*: "String" Up to 256 characters of the beginning of a 1558 plain text version of the message body. This is intended to be 1559 shown as a preview line on a mailbox listing, and the server may 1560 choose to skip quoted sections or salutations to return a more 1561 useful preview. 1563 o *textBody*: "String" The plain text body part for the message. If 1564 there is only an HTML version of the body, a plain text version 1565 MUST be generated from this; the exact method of conversion in 1566 this case is not defined and is server-specific. 1568 o *htmlBody*: "String|null" The HTML body part for the message if 1569 present. 1571 o *attachments*: "Attachment[]|null" An array of attachment objects 1572 (see below) detailing all the attachments to the message. 1574 o *attachedMessages*: "String[Message]|null" An object mapping 1575 attachment id (as found in the "attachments" property) to a 1576 *Message* object with the following properties, for each [RFC5322] 1577 message attached to this one: 1579 * headers 1581 * from 1583 * to 1585 * cc 1587 * bcc 1589 * replyTo 1591 * subject 1593 * date 1595 * textBody 1597 * htmlBody 1599 * attachments 1601 * attachedMessages 1603 An *Emailer* object has the following properties: 1605 o *name*: "String" The name of the sender/recipient. If a name 1606 cannot be extracted for an email, this property SHOULD be the 1607 empty string. 1609 o *email*: "String" The email address of the sender/recipient. This 1610 MUST be of the form ""@"" If a "host" or even 1611 "mailbox" cannot be extracted for an email, the empty string 1612 SHOULD be used for this part (so the result MUST always still 1613 contain an ""@"" character). 1615 Group information and comments from the RFC 5322 header MUST be 1616 discarded when converting into an Emailer object. 1618 Example array of Emailer objects: 1620 [ 1621 {name:"Joe Bloggs", email:"joeb@example.com"}, 1622 {name:"", email:"john@example.com"}, 1623 {name:"John Smith", email: "john@"} 1624 ] 1626 An *Attachment* object has the following properties: 1628 o *blobId*: "String" The id of the binary data. 1630 o *type*: "String" The content-type of the attachment. 1632 o *name*: "String|null" The full file name, e.g. 1633 "myworddocument.doc", if available. 1635 o *size*: "Number" The size, in bytes, of the attachment when fully 1636 decoded (i.e. the number of bytes in the file the user would 1637 download). 1639 o *cid*: "String|null" The id used within the message body to 1640 reference this attachment. This is only unique when paired with 1641 the message id, and has no meaning without reference to that. 1643 o *isInline*: "Boolean" True if the attachment is referenced by a 1644 "cid:" link from within the HTML body of the message. 1646 o *width*: "Number|null" The width (in px) of the image, if the 1647 attachment is an image. 1649 o *height*: "Number|null" The height (in px) of the image, if the 1650 attachment is an image. 1652 5.1. getMessages 1654 Messages can only be fetched explicitly by id. To fetch messages, 1655 make a call to "getMessages". It takes the following arguments: 1657 o *accountId*: "String|null" The id of the account to use for this 1658 call. If not given, defaults to the primary account. 1660 o *ids*: "String[]" An array of ids for the messages to fetch. 1662 o *properties*: "String[]|null" A list of properties to fetch for 1663 each message. If "null", all properties will be fetched. 1665 The "id" property is always returned, regardless of whether it is in 1666 the list of requested properties. The possible values for 1667 "properties" can be found above in the description of the Message 1668 object. In addition to this, the client may request the following 1669 special values: 1671 o *body*: If ""body"" is included in the list of requested 1672 properties, it will be interpreted by the server as a request for 1673 ""htmlBody"" if the message has an HTML part, or ""textBody"" 1674 otherwise. 1676 o *headers.property*: Instead of requesting all the headers (by 1677 requesting the ""headers"" property, the client may specify the 1678 particular headers it wants using the "headers.property-name" 1679 syntax, e.g. ""headers.x-spam-score", "headers.x-spam-hits""). 1680 The server will return a _headers_ property but with just the 1681 requested headers in the object rather than all headers. If 1682 ""headers"" is requested, the server MUST ignore the individual 1683 header requests and just return all headers. If a requested 1684 header is not present in the message, it MUST not be present in 1685 the _headers_ object. Header names are case-insensitive. 1687 The response to _getMessages_ is called _messages_. It has the 1688 following arguments: 1690 o *accountId*: "String" The id of the account used for the call. 1692 o *state*: "String" A string encoding the current state on the 1693 server. This string will change if any messages change (that is, 1694 a new message arrives, a change is made to one of the mutable 1695 properties, or a message is deleted). It can be passed to 1696 _getMessageUpdates_ to efficiently get the list of changes from 1697 the previous state. 1699 o *list*: "Message[]" An array of Message objects for the requested 1700 message ids. This may not be in the same order as the ids were in 1701 the request. 1703 o *notFound*: "String[]|null" An array of message ids requested 1704 which could not be found, or "null" if all ids were found. 1706 The following errors may be returned instead of the _messages_ 1707 response: 1709 "accountNotFound": Returned if an _accountId_ was explicitly included 1710 with the request, but it does not correspond to a valid account. 1712 "accountNotSupportedByMethod": Returned if the _accountId_ given 1713 corresponds to a valid account, but the account does not support this 1714 data type. 1716 "requestTooLarge": Returned if the number of _ids_ requested by the 1717 client exceeds the maximum number the server is willing to process in 1718 a single method call. 1720 "invalidArguments": Returned if the request does not include one of 1721 the required arguments, or one of the arguments is of the wrong type, 1722 or otherwise invalid. A _description_ property MAY be present on the 1723 response object to help debug with an explanation of what the problem 1724 was. 1726 Example request: 1728 ["getMessages", { 1729 "ids": [ "f123u456", "f123u457" ], 1730 "properties": [ "threadId", "mailboxIds", "from", "subject", "date" ] 1731 }, "#1"] 1733 and response: 1735 ["messages", { 1736 "state": "41234123231", 1737 "list": [ 1738 { 1739 messageId: "f123u457", 1740 threadId: "ef1314a", 1741 mailboxIds: [ "f123" ], 1742 from: [{name: "Joe Bloggs", email: "joe@bloggs.com"}], 1743 subject: "Dinner on Thursday?", 1744 date: "2013-10-13T14:12:00Z" 1745 } 1746 ], 1747 notFound: [ "f123u456" ] 1748 }, "#1"] 1750 5.2. getMessageUpdates 1752 If a call to _getMessages_ returns with a different _state_ string in 1753 the response to a previous call, the state of the messages has 1754 changed on the server. For example, a new message may have been 1755 delivered, or an existing message may have changed mailboxes. 1757 The _getMessageUpdates_ call allows a client to efficiently update 1758 the state of any cached messages to match the new state on the 1759 server. It takes the following arguments: 1761 o *accountId*: "String|null" The id of the account to use for this 1762 call. If not given, defaults to the primary account. 1764 o *sinceState*: "String" The current state of the client. This is 1765 the string that was returned as the _state_ argument in the 1766 _messages_ response. The server will return the changes made 1767 since this state. 1769 o *maxChanges*: "Number|null" The maximum number of changed messages 1770 to return in the response. The server MAY choose to clamp this 1771 value to a particular maximum or set a maximum if none is given by 1772 the client. If supplied by the client, the value MUST be a 1773 positive integer greater than 0. If a value outside of this range 1774 is given, the server MUST reject the call with an 1775 "invalidArguments" error. 1777 o *fetchRecords*: "Boolean|null" If true, immediately after 1778 outputting a _messageUpdates_ response, an implicit call will be 1779 made to _getMessages_ with a list of all message ids in the 1780 _changed_ argument of the response as the _ids_ argument, and the 1781 _fetchRecordProperties_ argument as the _properties_ argument. 1783 o *fetchRecordProperties*: "String[]|null" The list of properties to 1784 fetch on any fetched messages. See _getMessages_ for a full 1785 description. 1787 The response to _getMessageUpdates_ is called _messageUpdates_. It 1788 has the following arguments: 1790 o *accountId*: "String" The id of the account used for the call. 1792 o *oldState*: "String" This is the _sinceState_ argument echoed 1793 back; the state from which the server is returning changes. 1795 o *newState*: "String" This is the state the client will be in after 1796 applying the set of changes to the old state. 1798 o *hasMoreUpdates*: "Boolean" If "true", the client may call 1799 _getMessageUpdates_ again with the _newState_ returned to get 1800 further updates. If "false", _newState_ is the current server 1801 state. 1803 o *changed*: "String[]" An array of message ids for messages that 1804 have either been created or had their state change, and are not 1805 currently deleted. 1807 o *removed*: "String[]" An array of message ids for messages that 1808 have been deleted since the oldState. 1810 If a _maxChanges_ is supplied, or set automatically by the server, 1811 the server MUST ensure the number of ids returned across _changed_ 1812 and _removed_ does not exceed this limit. If there are more changes 1813 than this between the client's state and the current server state, 1814 the update returned SHOULD generate an update to take the client to 1815 an intermediate state, from which the client can continue to call 1816 _getMessageUpdates_ until it is fully up to date. If it is unable to 1817 calculat an intermediate state, it MUST return a 1818 "cannotCalculateChanges" error response instead. 1820 If a message has been modified AND deleted since the oldState, the 1821 server SHOULD just return the id in the _removed_ response, but MAY 1822 return it in the changed response as well. If a message has been 1823 created AND deleted since the oldState, the server SHOULD remove the 1824 message id from the response entirely, but MAY include it in the 1825 _removed_ response, and (if in the _removed_ response) MAY included 1826 it in the _changed_ response as well. 1828 The following errors may be returned instead of the _messageUpdates_ 1829 response: 1831 "accountNotFound": Returned if an _accountId_ was explicitly included 1832 with the request, but it does not correspond to a valid account. 1834 "accountNotSupportedByMethod": Returned if the _accountId_ given 1835 corresponds to a valid account, but the account does not support this 1836 data type. 1838 "invalidArguments": Returned if the request does not include one of 1839 the required arguments, or one of the arguments is of the wrong type, 1840 or otherwise invalid. A _description_ property MAY be present on the 1841 response object to help debug with an explanation of what the problem 1842 was. 1844 "cannotCalculateChanges": Returned if the server cannot calculate the 1845 changes from the state string given by the client. Usually due to 1846 the client's state being too old, or the server being unable to 1847 produce an update to an intermediate state when there are too many 1848 updates. The client MUST invalidate its Message cache. 1850 5.3. setMessages 1852 The _setMessages_ method encompasses: 1854 o Creating a draft message 1856 o Sending a message 1858 o Changing the flags of a message (unread/flagged status) 1859 o Adding/removing a message to/from mailboxes (moving a message) 1861 o Deleting messages 1863 It takes the following arguments: 1865 o *accountId*: "String|null" The id of the account to use for this 1866 call. If not given, defaults to the primary account. 1868 o *ifInState*: "String|null" This is a state string as returned by 1869 the _getMessages_ method. If supplied, the string must match the 1870 current state, otherwise the method will be aborted and a 1871 "stateMismatch" error returned. If "null", any changes will be 1872 applied to the current state. 1874 o *create*: "String[Message]|null" A map of _creation id_ (an 1875 arbitrary string set by the client) to Message objects (see below 1876 for a detailed description). 1878 o *update*: "String[Message]|null" A map of message id to objects 1879 containing the properties to update for that Message. 1881 o *destroy*: "String[]|null" A list of ids for Message objects to 1882 permanently delete. 1884 Each create, update or destroy is considered an atomic unit. It is 1885 permissible for the server to commit some of the changes but not 1886 others, however it is not permissible to only commit part of an 1887 update to a single record (e.g. update the _isFlagged_ field but not 1888 the _mailboxIds_ field, if both are supplied in the update object for 1889 a message). 1891 If a create, update or destroy is rejected, the appropriate error 1892 MUST be added to the notCreated/notUpdated/notDestroyed property of 1893 the response and the server MUST continue to the next create/update/ 1894 destroy. It does not terminate the method. 1896 If an id given cannot be found, the update or destroy MUST be 1897 rejected with a "notFound" set error. 1899 5.3.1. Saving a draft 1901 Creating messages via the _setMessages_ method is only for creating 1902 draft messages and sending them. For delivering/importing a complete 1903 [RFC5322] message, use the "importMessages" method. 1905 The properties of the Message object submitted for creation MUST 1906 conform to the following conditions: 1908 o *id*: This property MUST NOT be included. It is set by the server 1909 upon creation. 1911 o *blobId*: This property MUST NOT be included. It is set by the 1912 server upon creation. 1914 o *threadId*: This property MUST NOT be included. It is set by the 1915 server upon creation. 1917 o *mailboxIds*: This property MUST be included. The value MUST 1918 include the id of either the mailbox with "role == "drafts"" (to 1919 save a draft) or the mailbox with "role == "outbox"" (to send the 1920 message). If this mailbox does not have "mustBeOnlyMailbox == 1921 true", others may be included too. 1923 o *inReplyToMessageId*: Optional. If included, the server will look 1924 up this message and if found set appropriate "References" and "In- 1925 Reply-To" headers. These will override any such headers supplied 1926 in the _headers_ property. If not found, the creation MUST be 1927 rejected with an "inReplyToNotFound" error. 1929 o *isUnread*: Optional, defaults to "false". If included this MUST 1930 be "false". 1932 o *isFlagged*: Optional, defaults to "false". 1934 o *isAnswered*: Optional, defaults to "false". If included this 1935 MUST be "false". 1937 o *isDraft*: Optional, defaults to "true". If included this MUST be 1938 "true". 1940 o *hasAttachment*: This property MUST NOT be included. It is set by 1941 the server upon creation based on the attachments property. 1943 o *headers*: Optional. The keys MUST only contain the characters 1944 a-z (lower-case only), 0-9 and hyphens. 1946 o *from*: Optional. Overrides a "From" in the _headers_. 1948 o *to*: Optional. Overrides a "To" in the _headers_. 1950 o *cc*: Optional. Overrides a "Cc" in the _headers_. 1952 o *bcc*: Optional. Overrides a "Bcc" in the _headers_. 1954 o *replyTo*: Optional. Overrides a "Reply-To" in the _headers_. 1956 o *subject*: Optional. Defaults to the empty string (""""). 1958 o *date*: Optional. If included, the server SHOULD wait until this 1959 time to send the message (once moved to the outbox mailbox). 1960 Until it is sent, the send may be cancelled by moving the message 1961 back out of the outbox mailbox. If the date is in the past, the 1962 message must be sent immediately. A client may find out if the 1963 server supports delayed sending by querying the server's 1964 _capabilities_ object (see section 1). 1966 o *size*: This MUST NOT be included. It is set by the server upon 1967 creation. 1969 o *preview*: This MUST NOT be included. It is set by the server 1970 upon creation. 1972 o *textBody*: Optional. If not supplied and an htmlBody is, the 1973 server SHOULD generate a text version for the message from the 1974 HTML body. 1976 o *htmlBody*: Optional. 1978 o *attachments*: Optional. An array of Attachment objects detailing 1979 all the attachments to the message. To add an attachment, the 1980 file must first be uploaded using the standard upload mechanism; 1981 this will give the client a blobId that may be used to identify 1982 the file. The "cid" property may be assigned by the client, and 1983 is solely used for matching up with "cid:" links inside the 1984 "htmlBody". The server MAY change the cids upon sending. 1986 If any of the files specified in _attachments_ cannot be found, the 1987 creation MUST be rejected with an "invalidProperties" error. An 1988 extra property SHOULD be included in the error object called 1989 "attachmentsNotFound", of type "String[]", which SHOULD be an array 1990 of the _blobId_ of every attachment that could not be found on the 1991 server. - *attachedMessages*: This MUST NOT be included. 1993 All optional properties default to "null" unless otherwise stated. 1994 Where included, properties MUST conform to the type given in the 1995 Message object definition. 1997 If any of the properties are invalid, the server MUST reject the 1998 create with an "invalidProperties" error. The Error object SHOULD 1999 contain a property called _properties_ of type "String[]" that lists 2000 *all* the properties that were invalid. The object MAY also contain 2001 a _description_ property of type "String" with a user-friendly 2002 description of the problems. 2004 Other than making sure it conforms to the correct type, the server 2005 MUST NOT attempt to validate from/to/cc/bcc when saved as a draft. 2006 This is to ensure messages can be saved at any point. Validation 2007 occurs when the user tries to send a message. 2009 If a draft cannot be saved due to the user reaching their maximum 2010 mail storage quota, the creation MUST be rejected with a 2011 "maxQuotaReached" error. 2013 5.3.2. Updating messages 2015 Messages are mainly immutable, so to update a draft the client must 2016 create a new message and delete the old one. This ensures that if 2017 the draft is also being edited elsewhere, the two will split into two 2018 different drafts to avoid data loss. 2020 Only the following properties may be modified: 2022 o *mailboxIds*: The server MUST reject any attempt to add a message 2023 with "isDraft == false" to the outbox. The server MAY reject 2024 attempts to add a draft message to a mailbox that does not have a 2025 role of "drafts", "outbox" or "templates". 2027 o *isFlagged* 2029 o *isUnread* 2031 o *isAnswered* 2033 Note, a mailbox id may be a _creation id_ (see "setFoos" for a 2034 description of how this works). 2036 If any of the properties in the update are invalid (immutable and 2037 different to the current server value, wrong type, invalid value for 2038 the property - like a mailbox id for non-existent mailbox), the 2039 server MUST reject the update with an "invalidProperties" error. The 2040 Error object SHOULD contain a property called _properties_ of type 2041 "String[]" that lists *all* the properties that were invalid. The 2042 object MAY also contain a _description_ property of type "String" 2043 with a user-friendly description of the problems. 2045 If the _id_ given does not correspond to a Message in the given 2046 account, reject the update with a "notFound" error. 2048 To *delete a message* to trash, simply change the "mailboxIds" 2049 property so it is now in the mailbox with "role == "trash"". If the 2050 mailbox has the property "mustBeOnlyMailbox == true", it must be 2051 removed from all other mailboxes. Otherwise, leave it in those 2052 mailboxes so that it will be restored to its previous state if 2053 undeleted. 2055 5.3.3. Sending messages 2057 To send a message, either create a new message directly into the 2058 mailbox with "role == "outbox"" or move an existing draft into this 2059 mailbox. At this point the server will check that it has everything 2060 it needs for a valid message. In particular, that it has a valid 2061 "From" address (and the user has permission to use this From 2062 address), it has at least one address to send to, and all addresses 2063 in To/Cc/Bcc are valid email addresses. If it cannot send, it will 2064 reject the creation/update with an "invalidProperties" error. The 2065 Error object SHOULD contain a property called _properties_ of type 2066 "String[]" that lists *all* the properties that were invalid. The 2067 object SHOULD also contain a _description_ property of type "String" 2068 with a user-friendly description of the problems to present to the 2069 user. 2071 If the message is accepted, the server SHOULD *asynchronously* 2072 schedule the message to be sent *after* this method call is complete 2073 (note, this MAY occur before the next method in the same API request 2074 or after the whole API request is complete). This means that the 2075 "newState" string in the response represents a state where the 2076 message is still in the outbox. 2078 When the message is sent, the server MUST delete the message from the 2079 *outbox* and SHOULD create a *new* copy of the sent message (with a 2080 new id) in the *sent* mailbox, unless the user has indicated another 2081 preference. If "inReplyToMessageId" was set, the server SHOULD mark 2082 this message as "isAnswered: true" at this point, if found. The 2083 server is responsible for either reporting an error (normally a 2084 "bounce" email), or ensuring delivery of the message to the next hop. 2086 5.3.4. Cancelling a send 2088 A message may be moved out of the *outbox* and back to the *drafts* 2089 mailbox using the standard update message mechanism, if it has not 2090 yet been sent at the time the method is called. This MUST cancel the 2091 queued send. If the message has already been sent then it will have 2092 been deleted from the outbox, so the update will fail with a standard 2093 "notFound" error. 2095 5.3.5. Destroying messages 2097 If the _id_ given does not correspond to a Message in the given 2098 account, the server MUST reject the destruction with a "notFound" 2099 error. 2101 Destroying a message removes it from all mailboxes to which it 2102 belonged. 2104 5.3.6. Response 2106 The response to _setMessages_ is called _messagesSet_. It has the 2107 following arguments: 2109 o *accountId*: "String" The id of the account used for the call. 2111 o *oldState*: "String|null" The state string that would have been 2112 returned by _getMessages_ before making the requested changes, or 2113 "null" if the server doesn't know what the previous state string 2114 was. 2116 o *newState*: "String" The state string that will now be returned by 2117 _getMessages_. 2119 o *created*: "String[Message]" A map of the creation id to an object 2120 containing the _id_, _blobId_, _threadId_, and _size_ properties 2121 for each successfully created Message. 2123 o *updated*: "String[]" A list of Message ids for Messages that were 2124 successfully updated. 2126 o *destroyed*: "String[]" A list of Message ids for Messages that 2127 were successfully destroyed. 2129 o *notCreated*: "String[SetError]" A map of creation id to a 2130 SetError object for each Message that failed to be created. The 2131 possible errors are defined above. 2133 o *notUpdated*: "String[SetError]" A map of Message id to a SetError 2134 object for each Message that failed to be updated. The possible 2135 errors are defined above. 2137 o *notDestroyed*: "String[SetError]" A map of Message id to a 2138 SetError object for each Message that failed to be destroyed. The 2139 possible errors are defined above. 2141 The following errors may be returned instead of the _messagesSet_ 2142 response: 2144 "accountNotFound": Returned if an _accountId_ was explicitly included 2145 with the request, but it does not correspond to a valid account. 2147 "accountNotSupportedByMethod": Returned if the _accountId_ given 2148 corresponds to a valid account, but the account does not support this 2149 data type. 2151 "accountReadOnly": Returned if the account has "isReadOnly == true". 2153 "invalidArguments": Returned if one of the arguments is of the wrong 2154 type, or otherwise invalid. A _description_ property MAY be present 2155 on the response object to help debug with an explanation of what the 2156 problem was. 2158 "stateMismatch": Returned if an _ifInState_ argument was supplied and 2159 it does not match the current state. 2161 5.4. importMessages 2163 The _importMessages_ method adds [RFC5322] messages to a user's set 2164 of messages. The messages must first be uploaded as a file using the 2165 standard upload mechanism. It takes the following arguments: 2167 o *accountId*: "String|null" The id of the account to use for this 2168 call. If "null", defaults to the primary account. 2170 o *messages*: "String[MessageImport]" A map of creation id (client 2171 specified) to MessageImport objects 2173 An *MessageImport* object has the following properties: 2175 o *blobId*: "String" The id representing the raw [RFC5322] message 2176 (see the file upload section). 2178 o *mailboxIds* "String[]" The ids of the mailbox(es) to assign this 2179 message to. 2181 o *isUnread*: "Boolean" 2183 o *isFlagged*: "Boolean" 2185 o *isAnswered*: "Boolean" 2187 o *isDraft*: "Boolean" 2189 If "isDraft == true", the mailboxes MUST include the drafts or outbox 2190 mailbox. Adding to the outbox will send the message, as described in 2191 the _setMessages_ section (it will NOT automatically mark any other 2192 message as _isAnswered_). 2194 The response to _importMessages_ is called _messagesImported_. It has 2195 the following arguments: 2197 o *accountId*: "String" The id of the account used for this call. 2199 o *created*: "String[Message]" A map of the creation id to an object 2200 containing the _id_, _blobId_, _threadId_ and _size_ properties 2201 for each successfully imported Message. 2203 o *notCreated*: "String[SetError]" A map of creation id to a 2204 SetError object for each Message that failed to be created. The 2205 possible errors are defined above. 2207 The following errors may be returned instead of the _messageImported_ 2208 response: 2210 "accountNotFound": Returned if an _accountId_ was explicitly included 2211 with the request, but it does not correspond to a valid account. 2213 "accountNotSupportedByMethod": Returned if the _accountId_ given 2214 corresponds to a valid account, but the account does not support this 2215 data type. 2217 "accountReadOnly": Returned if the account has "isReadOnly == true". 2219 "invalidArguments": Returned if one of the arguments is of the wrong 2220 type, or otherwise invalid. A "description" property MAY be present 2221 on the response object to help debug with an explanation of what the 2222 problem was. 2224 "notFound": Returned if the URL given in the "file" argument does not 2225 correspond to an internal file. 2227 "invalidMailboxes": Returned if one of the mailbox ids cannot be 2228 found, or an invalid combination of mailbox ids is specified. 2230 "maxQuotaReached": Returned if the user has reached their mail quota 2231 so the message cannot be imported. 2233 5.5. copyMessages 2235 The only way to move messages *between* two different accounts is to 2236 copy them using the _copyMessages_ method, then once the copy has 2237 succeeded, delete the original. It takes the following arguments: 2239 o *fromAccountId*: "String|null" The id of the account to copy 2240 messages from. If "null", defaults to the primary account. 2242 o *toAccountId*: "String|null" The id of the account to copy 2243 messages to. If "null", defaults to the primary account. 2245 o *messages*: "String[MessageCopy]" A map of _creation id_ to a 2246 MessageCopy object. 2248 A *MessageCopy* object has the following properties: 2250 o *messageId*: "String" The id of the message to be copied in the 2251 "from" account. 2253 o *mailboxIds*: "String[]" The ids of the mailboxes (in the "to" 2254 account) to add the copied message to. 2256 o *isUnread*: "Boolean" The _isUnread_ property for the copy. 2258 o *isFlagged*: "Boolean" The _isFlagged_ property for the copy. 2260 o *isAnswered*: "Boolean" The _isAnswered_ property for the copy. 2262 o *isDraft*: "Boolean" The _isDraft_ property for the copy. 2264 The "from" account may be the same as the "to" account to copy 2265 messages within an account. 2267 The response to _copyMessages_ is called _messagesCopied_. It has the 2268 following arguments: 2270 o *fromAccountId*: "String" The id of the account messages were 2271 copied from. 2273 o *toAccountId*: "String" The id of the account messages were copied 2274 to. 2276 o *created*: "String[Message]|null" A map of the creation id to an 2277 object containing the _id_, _blobId_, _threadId_ and _size_ 2278 properties for each successfully copied Message. 2280 o *notCreated*: "String[SetError]|null" A map of creation id to a 2281 SetError object for each Message that failed to be copied, "null" 2282 if none. 2284 The *SetError* may be one of the following types: 2286 "notFound": Returned if the messageId given can't be found. 2288 "invalidMailboxes": Returned if one of the mailbox ids cannot be 2289 found, or an invalid combination of mailbox ids is specified. 2291 "maxQuotaReached": Returned if the user has reached their mail quota 2292 so the message cannot be copied. 2294 The following errors may be returned instead of the _messagesCopied_ 2295 response: 2297 "fromAccountNotFound": Returned if a _fromAccountId_ was explicitly 2298 included with the request, but it does not correspond to a valid 2299 account. 2301 "toAccountNotFound": Returned if a _toAccountId_ was explicitly 2302 included with the request, but it does not correspond to a valid 2303 account. 2305 "fromAccountNoMail": Returned if the _fromAccountId_ given 2306 corresponds to a valid account, but does not contain any mail data. 2308 "toAccountNoMail": Returned if the _toAccountId_ given corresponds to 2309 a valid account, but does not contain any mail data. 2311 "accountReadOnly": Returned if the "to" account has "isReadOnly == 2312 true". 2314 "invalidArguments": Returned if one of the arguments is of the wrong 2315 type, or otherwise invalid. A "description" property MAY be present 2316 on the response object to help debug with an explanation of what the 2317 problem was. 2319 5.6. reportMessages 2321 Messages can be reported as spam or non-spam to help train the user's 2322 spam filter. This MUST NOT affect the state of the Message objects 2323 (it DOES NOT move a message into or out of the Spam mailbox). 2325 To report messages, make a call to _reportMessages_. It takes the 2326 following arguments: 2328 o *accountId*: "String|null" The id of the account to use for this 2329 call. If not given, defaults to the primary account. 2331 o *messageIds*: "String[]" The list of ids of messages to report. 2333 o *asSpam*: "Boolean" If "true", learn these messages as spam. If 2334 "false", learn as non-spam. 2336 The response to _reportMessages_ is called _messagesReported_. It has 2337 the following arguments: 2339 o *accountId*: "String" The id of the account used for this call. 2341 o *asSpam*: "Boolean" Echoed back from the call 2343 o *reported*: "String[]" The ids of each message successfully 2344 reported. 2346 o *notFound*: "String[]|null" An array of message ids requested 2347 which could not be found, or "null" if all ids were found. 2349 The following errors may be returned instead of the 2350 _messagesReported_ response: 2352 "accountNotFound": Returned if an _accountId_ was explicitly included 2353 with the request, but it does not correspond to a valid account. 2355 "accountNotSupportedByMethod": Returned if the _accountId_ given 2356 corresponds to a valid account, but the account does not support this 2357 data type. 2359 "accountReadOnly": Returned if the account has "isReadOnly == true". 2361 "requestTooLarge": Returned if the total number of objects to create, 2362 update or destroy exceeds the maximum number the server is willing to 2363 process in a single method call. 2365 "invalidArguments": Returned if one of the arguments is of the wrong 2366 type, or otherwise invalid. A "description" property MAY be present 2367 on the response object to help debug with an explanation of what the 2368 problem was. 2370 6. Identities 2372 A *Identity* object stores information about an email address (or 2373 domain) the user may send from. It has the following properties: 2375 o *id*: "String" The id of the identity. This property is 2376 immutable. 2378 o *name*: "String" The "From" _name_ the client SHOULD use when 2379 creating a new message from this identity. 2381 o *email*: "String" The "From" email address the client MUST use 2382 when creating a new message from this identity. This property is 2383 immutable. The "email" property MAY alternatively be of the form 2384 "*@example.com", in which case the client may use any valid email 2385 address ending in "@example.com". 2387 o *replyTo*: "String" The Reply-To value the client SHOULD set when 2388 creating a new message from this identity. 2390 o *bcc*: "String" The Bcc value the client SHOULD set when creating 2391 a new message from this identity. 2393 o *textSignature*: "String" Signature the client SHOULD insert into 2394 new rich-text messages that will be sending from this identity. 2395 Clients MAY ignore this and/or combine this with a client-specific 2396 signature preference. 2398 o *htmlSignature*: "String" Signature the client SHOULD insert into 2399 new HTML messages that will be sending from this identity. This 2400 text MUST be an HTML snippet to be inserted into the 2401 "" section of the new email. Clients MAY ignore this 2402 and/or combine this with a client-specific signature preference. 2404 o *mayDeleteIdentity*: "Boolean" Is the user allowed to delete this 2405 identity? Servers may wish to set this to false for the user's 2406 username or other default address. 2408 Multiple identities with the same email address MAY exist, to allow 2409 for different settings the user wants to pick between (for example 2410 with different names/signatures). 2412 6.1. getIdentities 2414 Identities can either be fetched explicitly by id, or all of them at 2415 once. To fetch identities, make a call to "getIdentities". It takes 2416 the following arguments: 2418 o *accountId*: "String|null" The Account to fetch the identities 2419 for. If "null", the primary account is used. 2421 o *ids*: "String[]|null" The ids of the identities to fetch. If 2422 "null", all identities in the account are be fetched. 2424 The response to _getIdentities_ is called _identities_. It has the 2425 following arguments: 2427 o *accountId*: "String" The id of the account used for the call. 2429 o *state*: "String" A string encoding the current state on the 2430 server. This string will change if any identities change (that 2431 is, a new identity is created, a change is made to an existing 2432 identity, or an identity is deleted). It can be passed to 2433 _getIdentityUpdates_ to efficiently get the list of changes from 2434 the previous state. 2436 o *list*: "Identity[]" An array of the Identity objects requested. 2437 This will be the *empty array* if the _ids_ argument was the empty 2438 array, or contained only ids for identities that could not be 2439 found. 2441 o *notFound*: "String[]|null" This array contains the ids passed to 2442 the method for identities that do not exist, or "null" if all 2443 requested ids were found. It MUST be "null" if the _ids_ argument 2444 in the call was "null". 2446 The following errors may be returned instead of the _identities_ 2447 response: 2449 "accountNotFound": Returned if an _accountId_ was explicitly included 2450 with the request, but it does not correspond to a valid account. 2452 "accountNotSupportedByMethod": Returned if the _accountId_ given 2453 corresponds to a valid account, but the account does not support this 2454 data type. 2456 "invalidArguments": Returned if one of the arguments is of the wrong 2457 type, or otherwise invalid. A "description" property MAY be present 2458 on the response object to help debug with an explanation of what the 2459 problem was. 2461 6.2. getIdentityUpdates 2463 The _getIdentityUpdates_ call allows a client to efficiently update 2464 the state of its cached identities to match the new state on the 2465 server. It takes the following arguments: 2467 o *accountId*: "String|null" The id of the account to use for this 2468 call. If "null", the primary account will be used. 2470 o *sinceState*: "String" The current state of the client. This is 2471 the string that was returned as the _state_ argument in the 2472 _identities_ response. The server will return the changes made 2473 since this state. 2475 o *maxChanges*: "Number|null" The maximum number of Identity ids to 2476 return in the response. The server MAY choose to clamp this value 2477 to a particular maximum or set a maximum if none is given by the 2478 client. If supplied by the client, the value MUST be a positive 2479 integer greater than 0. If a value outside of this range is 2480 given, the server MUST reject the call with an "invalidArguments" 2481 error. 2483 o *fetchRecords*: "Boolean|null" If "true", immediately after 2484 outputting an _identityUpdates_ response, an implicit call will be 2485 made to _getidentities_ with the _changed_ property of the 2486 response as the _ids_ argument, and the _fetchRecordProperties_ 2487 argument as the _properties_ argument. If "false" or "null", no 2488 implicit call is made. 2490 The response to _getIdentityUpdates_ is called _identityUpdates_. It 2491 has the following arguments: 2493 o *accountId*: "String" The id of the account used for the call. 2495 o *oldState*: "String" This is the _sinceState_ argument echoed 2496 back; the state from which the server is returning changes. 2498 o *newState*: "String" This is the state the client will be in after 2499 applying the set of changes to the old state. 2501 o *hasMoreUpdates*: "Boolean" If "true", the client may call 2502 _getIdentityUpdates_ again with the _newState_ returned to get 2503 further updates. If "false", _newState_ is the current server 2504 state. 2506 o *changed*: "String[]" An array of Identity ids where a property of 2507 the identity has changed between the old state and the new state, 2508 or the identity has been created, and the identity has not been 2509 destroyed. 2511 o *removed*: "String[]" An array of Identity ids for identities 2512 which have been destroyed since the old state. 2514 If a _maxChanges_ is supplied, or set automatically by the server, 2515 the server must try to limit the number of ids across _changed_ and 2516 _removed_ to the number given. If there are more changes than this 2517 between the client's state and the current server state, the update 2518 returned MUST take the client to an intermediate state, from which 2519 the client can continue to call _getIdentityUpdates_ until it is 2520 fully up to date. The server MAY return more ids than the 2521 _maxChanges_ total if this is required for it to be able to produce 2522 an update to an intermediate state, but it SHOULD try to keep it 2523 close to the maximum requested. 2525 If an identity has been modified AND deleted since the oldState, the 2526 server should just return the id in the _removed_ array, but MAY 2527 return it in the _changed_ array as well. If an identity has been 2528 created AND deleted since the oldState, the server SHOULD remove the 2529 identity id from the response entirely, but MAY include it in the 2530 _removed_ array. 2532 The following errors may be returned instead of the "identityUpdates" 2533 response: 2535 "accountNotFound": Returned if an _accountId_ was explicitly included 2536 with the request, but it does not correspond to a valid account. 2538 "accountNotSupportedByMethod": Returned if the _accountId_ given 2539 corresponds to a valid account, but the account does not support this 2540 data type. 2542 "invalidArguments": Returned if the request does not include one of 2543 the required arguments, or one of the arguments is of the wrong type, 2544 or otherwise invalid. A "description" property MAY be present on the 2545 response object to help debug with an explanation of what the problem 2546 was. 2548 "cannotCalculateChanges": Returned if the server cannot calculate the 2549 changes from the state string given by the client. Usually due to 2550 the client's state being too old, or the server being unable to 2551 produce an update to an intermediate state when there are too many 2552 updates. The client MUST invalidate its Identity cache. 2554 6.3. setIdentities 2556 Modifying the state of Identity objects on the server is done via the 2557 _setIdentities_ method. This encompasses creating, updating and 2558 destroying Identity records. 2560 The _setIdentities_ method takes the following arguments: 2562 o *accountId*: "String|null" The id of the account to use for this 2563 call. If "null", the primary account will be used. 2565 o *ifInState*: "String|null" This is a state string as returned by 2566 the _getIdentities_ method. If supplied, the string must match 2567 the current state, otherwise the method MUST be aborted and a 2568 "stateMismatch" error returned. If "null", any changes will be 2569 applied to the current state. 2571 o *create*: "String[Identity]|null" A map of _creation id_ (an 2572 arbitrary string set by the client) to Identity objects 2573 (containing all properties except the id). 2575 o *update*: "String[Identity]|null" A map of id to Identity objects. 2576 The object may omit any property; only properties that have 2577 changed need be included. 2579 o *destroy*: "String[]|null" A list of ids for Identity objects to 2580 permanently delete. 2582 Each create, update or destroy is considered an atomic unit. It is 2583 permissible for the server to commit some of the changes but not 2584 others, however it is not permissible to only commit part of an 2585 update to a single identity. 2587 If a create, update or destroy is rejected, the appropriate error 2588 MUST be added to the notCreated/notUpdated/notDestroyed property of 2589 the response and the server MUST continue to the next create/update/ 2590 destroy. It does not terminate the method. 2592 A *create* MAY be rejected with one of the following errors: 2594 o "maxQuotaReached": Returned if the user has reached a server- 2595 defined limit on the number of identities. 2597 o "emailNotPermitted": Returned if the user tries to create an 2598 identity with an email address the user does not allow them to 2599 send from. 2601 If the identity has "mayDeleteIdentity == false", any attempt to 2602 destroy it MUST be rejected with a "forbidden" error. 2604 If an id given cannot be found, the update or destroy MUST be 2605 rejected with a "notFound" set error. 2607 The response to _setIdentities_ is called _identitiesSet_. It has the 2608 following arguments: 2610 o *accountId*: "String" The id of the account used for the call. 2612 o *oldState*: "String|null" The state string that would have been 2613 returned by _getIdentities_ before making the requested changes, 2614 or "null" if the server doesn't know what the previous state 2615 string was. 2617 o *newState*: "String" The state string that will now be returned by 2618 _getIdentities_. 2620 o *created*: "String[Identity]" A map of the creation id to an 2621 object containing the *id* property for all successfully created 2622 identities. 2624 o *updated*: "String[]" A list of ids for identities that were 2625 successfully updated. 2627 o *destroyed*: "String[]" A list of ids for identities that were 2628 successfully destroyed. 2630 o *notCreated*: "String[SetError]" A map of creation id to a 2631 SetError object for each identity that failed to be created. The 2632 possible errors are defined in the description of the method for 2633 specific data types. 2635 o *notUpdated*: "String[SetError]" A map of Identity id to a 2636 SetError object for each identity that failed to be updated. The 2637 possible errors are defined in the description of the method for 2638 specific data types. 2640 o *notDestroyed*: "String[SetError]" A map of Identity id to a 2641 SetError object for each identity that failed to be destroyed. 2642 The possible errors are defined in the description of the method 2643 for specific data types. 2645 A *SetError* object has the following properties: 2647 o *type*: "String" The type of error. 2649 o *description*: "String|null" A description of the error to display 2650 to the user. 2652 The following errors may be returned instead of the _identitiesSet_ 2653 response: 2655 "accountNotFound": Returned if an _accountId_ was explicitly included 2656 with the request, but it does not correspond to a valid account. 2658 "accountNotSupportedByMethod": Returned if the _accountId_ given 2659 corresponds to a valid account, but the account does not support this 2660 data type. 2662 "accountReadOnly": Returned if the account has MailCapabilities with 2663 "isReadOnly == true". 2665 "requestTooLarge": Returned if the total number of objects to create, 2666 update or destroy exceeds the maximum number the server is willing to 2667 process in a single method call. 2669 "invalidArguments": Returned if one of the arguments is of the wrong 2670 type, or otherwise invalid. A _description_ property MAY be present 2671 on the response object to help debug with an explanation of what the 2672 problem was. 2674 "stateMismatch": Returned if an _ifInState_ argument was supplied and 2675 it does not match the current state. 2677 7. SearchSnippets 2679 When doing a search on a "String" property, the client may wish to 2680 show the relevant section of the body that matches the search as a 2681 preview instead of the beginning of the message, and to highlight any 2682 matching terms in both this and the subject of the message. Search 2683 snippets represent this data. 2685 A *SearchSnippet* object has the following properties: 2687 o *messageId*: "String" The message id the snippet applies to. 2689 o *subject*: "String|null" If text from the filter matches the 2690 subject, this is the subject of the message HTML-escaped, with 2691 matching words/phrases wrapped in "" tags. If it 2692 does not match, this is "null". 2694 o *preview*: "String|null" If text from the filter matches the 2695 plain-text or HTML body, this is the relevant section of the body 2696 (converted to plain text if originally HTML), HTML-escaped, with 2697 matching words/phrases wrapped in "" tags, up to 256 2698 characters long. If it does not match, this is "null". 2700 It is server-defined what is a relevant section of the body for 2701 preview. If the server is unable to determine search snippets, it 2702 MUST return "null" for both the _subject_ and _preview_ properties. 2704 Note, unlike most data types, a SearchSnippet DOES NOT have a 2705 property called "id". 2707 7.1. getSearchSnippets 2709 To fetch search snippets, make a call to "getSearchSnippets". It 2710 takes the following arguments: 2712 o *accountId*: "String|null" The id of the account to use for this 2713 call. If "null", defaults to the primary account. 2715 o *messageIds*: "String[]" The list of ids of messages to fetch the 2716 snippets for. 2718 o *filter*: "FilterCondition|FilterOperator|null" The same filter as 2719 passed to getMessageList; see the description of this method for 2720 details. 2722 The response to "getSearchSnippets" is called "searchSnippets". It 2723 has the following arguments: 2725 o *accountId*: "String" The id of the account used for the call. 2727 o *filter*: "FilterCondition|FilterOperator|null" Echoed back from 2728 the call. 2730 o *list*: "SearchSnippet[]" An array of SearchSnippets objects for 2731 the requested message ids. This may not be in the same order as 2732 the ids that were in the request. 2734 o *notFound*: "String[]|null" An array of message ids requested 2735 which could not be found, or "null" if all ids were found. 2737 Since snippets are only based on immutable properties, there is no 2738 state string or update mechanism needed. 2740 The following errors may be returned instead of the _searchSnippets_ 2741 response: 2743 "accountNotFound": Returned if an _accountId_ was explicitly included 2744 with the request, but it does not correspond to a valid account. 2746 "accountNotSupportedByMethod": Returned if the _accountId_ given 2747 corresponds to a valid account, but the account does not support this 2748 data type. 2750 "requestTooLarge": Returned if the number of _messageIds_ requested 2751 by the client exceeds the maximum number the server is willing to 2752 process in a single method call. 2754 "cannotDoFilter": Returned if the server is unable to process the 2755 given _filter_ for any reason. 2757 "invalidArguments": Returned if the request does not include one of 2758 the required arguments, or one of the arguments is of the wrong type, 2759 or otherwise invalid. A "description" property MAY be present on the 2760 response object to help debug with an explanation of what the problem 2761 was. 2763 8. Vacation Response 2765 The *VacationResponse* object represents the state of vacation- 2766 response related settings for an account. It has the following 2767 properties: 2769 o *id*: "String" The id of the object. This property is immutable. 2770 There is only ever one vacation response object, and its id is 2771 ""singleton"". 2773 o *isEnabled* "Boolean" Should a vacation response be sent if a 2774 message arrives between the _fromDate_ and _toDate_? 2776 o *fromDate*: "Date|null" If _isEnabled_ is "true", the date/time 2777 after which messages that arrive should receive the user's 2778 vacation response, in UTC. If "null", the vacation response is 2779 effective immediately. 2781 o *toDate*: "Date|null" If _isEnabled_ is "true", the date/time 2782 after which messages that arrive should no longer receive the 2783 user's vacation response, in UTC. If "null", the vacation 2784 response is effective indefinitely. 2786 o *subject*: "String|null" The subject that will be used by the mail 2787 sent in response to messages when the vacation response is 2788 enabled. If null, an appropriate subject SHOULD be set by the 2789 server. 2791 o *textBody*: "String|null" The plain text part of the message to 2792 send in response to messages when the vacation response is 2793 enabled. If this is "null", when the vacation message is sent a 2794 plain-text body part SHOULD be generated from the _htmlBody_ but 2795 the server MAY choose to send the response as HTML only. 2797 o *htmlBody*: "String|null" The HTML message to send in response to 2798 messages when the vacation response is enabled. If this is 2799 "null", when the vacation message is sent an HTML body part MAY be 2800 generated from the _textBody_, or the server MAY choose to send 2801 the response as plain-text only. 2803 8.1. getVacationResponse 2805 There MUST only be exactly one VacationResponse object in an account. 2806 It MUST have the id ""singleton"". 2808 To fetch the vacation response object, make a call to 2809 "getVacationResponse". It takes the following argument: 2811 o *accountId*: "String|null" The Account to get the vacation 2812 response for. If "null", the primary account is used. 2814 The response to _getVacationResponse_ is called _vacationResponse_. 2815 It has the following arguments: 2817 o *accountId*: "String" The id of the account used for the call. 2819 o *list*: "VacationResponse[]" An array containing the single 2820 VacationResponse object. 2822 The following errors may be returned instead of the 2823 _vacationResponse_ response: 2825 "accountNotFound": Returned if an _accountId_ was explicitly included 2826 with the request, but it does not correspond to a valid account. 2828 "accountNotSupportedByMethod": Returned if the _accountId_ given 2829 corresponds to a valid account, but the account does not support this 2830 data type. 2832 8.2. setVacationResponse 2834 Sets properties on the vacation response object. It takes the 2835 following arguments: 2837 o *accountId*: "String|null" The Account to set the vacation 2838 response for. If "null", the primary account is used. 2840 o *update*: "String[VacationResponse]|null" A map of id 2841 ("singleton") to the VacationResponse object with new values for 2842 the properties you wish to change. The object may omit any 2843 property; only properties that have changed need be included. 2845 If any of the properties in the update are invalid (immutable and 2846 different to the current server value, wrong type), the server MUST 2847 reject the update with a SetError of type "invalidProperties". The 2848 SetError object SHOULD contain a property called _properties_ of type 2849 "String[]" that lists *all* the properties that were invalid. The 2850 object MAY also contain a _description_ property of type "String" 2851 with a user-friendly description of the problems. 2853 The response is called _vacationResponseSet_. It has the following 2854 arguments: 2856 o *updated*: "String[]" Contains the single id ("singleton") if the 2857 vacation response was successfully updated. 2859 o *notUpdated*: "String[SetError]" A map of id ("singleton") to a 2860 SetError object if the update failed. 2862 A *SetError* object has the following properties: 2864 o *type*: "String" The type of error. 2866 o *description*: "String|null" A description of the error to display 2867 to the user. 2869 The following errors may be returned instead of the 2870 _vacationResponseSet_ response: 2872 "accountNotFound": Returned if an _accountId_ was explicitly included 2873 with the request, but it does not correspond to a valid account. 2875 "accountNotSupportedByMethod": Returned if the _accountId_ given 2876 corresponds to a valid account, but the account does not support this 2877 data type. 2879 "invalidArguments": Returned if one of the arguments is of the wrong 2880 type, or otherwise invalid (including using an id other than 2881 ""singleton""). A "description" property MAY be present on the 2882 response object to help debug with an explanation of what the problem 2883 was. 2885 9. References 2887 9.1. Normative References 2889 [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate 2890 Requirement Levels", BCP 14, RFC 2119, 2891 DOI 10.17487/RFC2119, March 1997, 2892 . 2894 [RFC5322] Resnick, P., Ed., "Internet Message Format", RFC 5322, 2895 DOI 10.17487/RFC5322, October 2008, 2896 . 2898 [RFC7159] Bray, T., Ed., "The JavaScript Object Notation (JSON) Data 2899 Interchange Format", RFC 7159, DOI 10.17487/RFC7159, March 2900 2014, . 2902 9.2. URIs 2904 [1] server.html 2906 [2] https://tools.ietf.org/html/rfc4648 2908 [3] http://tools.ietf.org/html/rfc2047 2910 Author's Address 2912 Neil Jenkins 2913 FastMail 2914 Level 1, 91 William St 2915 Melbourne VIC 3000 2916 Australia 2918 Email: neilj@fastmail.com 2919 URI: https://www.fastmail.com