5. Search Snippets
When doing a search on a "String" property, the client may wish to show the relevant section of the body that matches the search as a preview and to highlight any matching terms in both this and the subject of the Email. Search snippets represent this data. A *SearchSnippet* object has the following properties: o emailId: "Id" The Email id the snippet applies to.
o subject: "String|null" If text from the filter matches the subject, this is the subject of the Email with the following transformations: 1. Any instance of the following three characters MUST be replaced by an appropriate HTML entity: & (ampersand), < (less-than sign), and > (greater-than sign) [HTML]. Other characters MAY also be replaced with an HTML entity form. 2. The matching words/phrases from the filter are wrapped in HTML "<mark></mark>" tags. If the subject does not match text from the filter, this property is null. o preview: "String|null" If text from the filter matches the plaintext or HTML body, this is the relevant section of the body (converted to plaintext if originally HTML), with the same transformations as the "subject" property. It MUST NOT be bigger than 255 octets in size. If the body does not contain a match for the text from the filter, this property is null. What is a relevant section of the body for preview is server defined. If the server is unable to determine search snippets, it MUST return null for both the "subject" and "preview" properties. Note that unlike most data types, a SearchSnippet DOES NOT have a property called "id". The following JMAP method is supported.5.1. SearchSnippet/get
To fetch search snippets, make a call to "SearchSnippet/get". It takes the following arguments: o accountId: "Id" The id of the account to use. o filter: "FilterOperator|FilterCondition|null" The same filter as passed to "Email/query"; see the description of this method in Section 4.4 for details.
o emailIds: "Id[]" The ids of the Emails to fetch snippets for. The response has the following arguments: o accountId: "Id" The id of the account used for the call. o list: "SearchSnippet[]" An array of SearchSnippet objects for the requested Email ids. This may not be in the same order as the ids that were in the request. o notFound: "Id[]|null" An array of Email ids requested that could not be found, or null if all ids were found. As the search snippets are derived from the message content and the algorithm for doing so could change over time, fetching the same snippets a second time MAY return a different result. However, the previous value is not considered incorrect, so there is no state string or update mechanism needed. The following additional errors may be returned instead of the "SearchSnippet/get" response: "requestTooLarge": The number of "emailIds" requested by the client exceeds the maximum number the server is willing to process in a single method call. "unsupportedFilter": The server is unable to process the given "filter" for any reason.
5.2. Example
Here, we did an "Email/query" to search for any Email in the account containing the word "foo"; now, we are fetching the search snippets for some of the ids that were returned in the results: [[ "SearchSnippet/get", { "accountId": "ue150411c", "filter": { "text": "foo" }, "emailIds": [ "M44200ec123de277c0c1ce69c", "M7bcbcb0b58d7729686e83d99", "M28d12783a0969584b6deaac0", ... ] }, "0" ]] Example response: [[ "SearchSnippet/get", { "accountId": "ue150411c", "list": [{ "emailId": "M44200ec123de277c0c1ce69c", "subject": null, "preview": null }, { "emailId": "M7bcbcb0b58d7729686e83d99", "subject": "The <mark>Foo</mark>sball competition", "preview": "...year the <mark>foo</mark>sball competition will be held in the Stadium de ..." }, { "emailId": "M28d12783a0969584b6deaac0", "subject": null, "preview": "...the <mark>Foo</mark>/bar method results often returns <1 widget rather than the complete..." }, ... ], "notFound": null }, "0" ]]
6. Identities
An *Identity* object stores information about an email address or domain the user may send from. It has the following properties: o id: "Id" (immutable; server-set) The id of the Identity. o name: "String" (default: "") The "From" name the client SHOULD use when creating a new Email from this Identity. o email: "String" (immutable) The "From" email address the client MUST use when creating a new Email from this Identity. If the "mailbox" part of the address (the section before the "@") is the single character "*" (e.g., "*@example.com"), the client may use any valid address ending in that domain (e.g., "foo@example.com"). o replyTo: "EmailAddress[]|null" (default: null) The Reply-To value the client SHOULD set when creating a new Email from this Identity. o bcc: "EmailAddress[]|null" (default: null) The Bcc value the client SHOULD set when creating a new Email from this Identity. o textSignature: "String" (default: "") A signature the client SHOULD insert into new plaintext messages that will be sent from this Identity. Clients MAY ignore this and/or combine this with a client-specific signature preference. o htmlSignature: "String" (default: "") A signature the client SHOULD insert into new HTML messages that will be sent from this Identity. This text MUST be an HTML snippet to be inserted into the "<body></body>" section of the HTML. Clients MAY ignore this and/or combine this with a client- specific signature preference.
o mayDelete: "Boolean" (server-set) Is the user allowed to delete this Identity? Servers may wish to set this to false for the user's username or other default address. Attempts to destroy an Identity with "mayDelete: false" will be rejected with a standard "forbidden" SetError. See the "Addresses" header form description in the Email object (Section 4.1.2.3) for the definition of EmailAddress. Multiple identities with the same email address MAY exist, to allow for different settings the user wants to pick between (for example, with different names/signatures). The following JMAP methods are supported.6.1. Identity/get
This is a standard "/get" method as described in [RFC8620], Section 5.1. The "ids" argument may be null to fetch all at once.6.2. Identity/changes
This is a standard "/changes" method as described in [RFC8620], Section 5.2.6.3. Identity/set
This is a standard "/set" method as described in [RFC8620], Section 5.3. The following extra SetError types are defined: For "create": o "forbiddenFrom": The user is not allowed to send from the address given as the "email" property of the Identity.6.4. Example
Request: [ "Identity/get", { "accountId": "acme" }, "0" ]
with response: [ "Identity/get", { "accountId": "acme", "state": "99401312ae-11-333", "list": [ { "id": "XD-3301-222-11_22AAz", "name": "Joe Bloggs", "email": "joe@example.com", "replyTo": null, "bcc": [{ "name": null, "email": "joe+archive@example.com" }], "textSignature": "-- \nJoe Bloggs\nMaster of Email", "htmlSignature": "<div><b>Joe Bloggs</b></div> <div>Master of Email</div>", "mayDelete": false }, { "id": "XD-9911312-11_22AAz", "name": "Joe B", "email": "*@example.com", "replyTo": null, "bcc": null, "textSignature": "", "htmlSignature": "", "mayDelete": true } ], "notFound": [] }, "0" ]7. Email Submission
An *EmailSubmission* object represents the submission of an Email for delivery to one or more recipients. It has the following properties: o id: "Id" (immutable; server-set) The id of the EmailSubmission. o identityId: "Id" (immutable) The id of the Identity to associate with this submission.
o emailId: "Id" (immutable) The id of the Email to send. The Email being sent does not have to be a draft, for example, when "redirecting" an existing Email to a different address. o threadId: "Id" (immutable; server-set) The Thread id of the Email to send. This is set by the server to the "threadId" property of the Email referenced by the "emailId". o envelope: "Envelope|null" (immutable) Information for use when sending via SMTP. An *Envelope* object has the following properties: * mailFrom: "Address" The email address to use as the return address in the SMTP submission, plus any parameters to pass with the MAIL FROM address. The JMAP server MAY allow the address to be the empty string. When a JMAP server performs an SMTP message submission, it MAY use the same id string for the ENVID parameter [RFC3461] and the EmailSubmission object id. Servers that do this MAY replace a client-provided value for ENVID with a server- provided value. * rcptTo: "Address[]" The email addresses to send the message to, and any RCPT TO parameters to pass with the recipient. An *Address* object has the following properties: * email: "String" The email address being represented by the object. This is a "Mailbox" as used in the Reverse-path or Forward-path of the MAIL FROM or RCPT TO command in [RFC5321]. * parameters: "Object|null" Any parameters to send with the email address (either mail- parameter or rcpt-parameter as appropriate, as specified in [RFC5321]). If supplied, each key in the object is a parameter name, and the value is either the parameter value (type
"String") or null if the parameter does not take a value. For both name and value, any xtext or unitext encodings are removed (see [RFC3461] and [RFC6533]) and JSON string encoding is applied. If the "envelope" property is null or omitted on creation, the server MUST generate this from the referenced Email as follows: * "mailFrom": The email address in the Sender header field, if present; otherwise, it's the email address in the From header field, if present. In either case, no parameters are added. If multiple addresses are present in one of these header fields, or there is more than one Sender/From header field, the server SHOULD reject the EmailSubmission as invalid; otherwise, it MUST take the first address in the last Sender/From header field. If the address found from this is not allowed by the Identity associated with this submission, the "email" property from the Identity MUST be used instead. * "rcptTo": The deduplicated set of email addresses from the To, Cc, and Bcc header fields, if present, with no parameters for any of them. o sendAt: "UTCDate" (immutable; server-set) The date the submission was/will be released for delivery. If the client successfully used FUTURERELEASE [RFC4865] with the submission, this MUST be the time when the server will release the message; otherwise, it MUST be the time the EmailSubmission was created. o undoStatus: "String" This represents whether the submission may be canceled. This is server set on create and MUST be one of the following values: * "pending": It may be possible to cancel this submission. * "final": The message has been relayed to at least one recipient in a manner that cannot be recalled. It is no longer possible to cancel this submission. * "canceled": The submission was canceled and will not be delivered to any recipient.
On systems that do not support unsending, the value of this property will always be "final". On systems that do support canceling submission, it will start as "pending" and MAY transition to "final" when the server knows it definitely cannot recall the message, but it MAY just remain "pending". If in pending state, a client can attempt to cancel the submission by setting this property to "canceled"; if the update succeeds, the submission was successfully canceled, and the message has not been delivered to any of the original recipients. o deliveryStatus: "String[DeliveryStatus]|null" (server-set) This represents the delivery status for each of the submission's recipients, if known. This property MAY not be supported by all servers, in which case it will remain null. Servers that support it SHOULD update the EmailSubmission object each time the status of any of the recipients changes, even if some recipients are still being retried. This value is a map from the email address of each recipient to a DeliveryStatus object. A *DeliveryStatus* object has the following properties: * smtpReply: "String" The SMTP reply string returned for this recipient when the server last tried to relay the message, or in a later Delivery Status Notification (DSN, as defined in [RFC3464]) response for the message. This SHOULD be the response to the RCPT TO stage, unless this was accepted and the message as a whole was rejected at the end of the DATA stage, in which case the DATA stage reply SHOULD be used instead. Multi-line SMTP responses should be concatenated to a single string as follows: + The hyphen following the SMTP code on all but the last line is replaced with a space. + Any prefix in common with the first line is stripped from lines after the first. + CRLF is replaced by a space.
For example: 550-5.7.1 Our system has detected that this message is 550 5.7.1 likely spam. would become: 550 5.7.1 Our system has detected that this message is likely spam. For messages relayed via an alternative to SMTP, the server MAY generate a synthetic string representing the status instead. If it does this, the string MUST be of the following form: + A 3-digit SMTP reply code, as defined in [RFC5321], Section 4.2.3. + Then a single space character. + Then an SMTP Enhanced Mail System Status Code as defined in [RFC3463], with a registry defined in [RFC5248]. + Then a single space character. + Then an implementation-specific information string with a human-readable explanation of the response. * delivered: "String" Represents whether the message has been successfully delivered to the recipient. This MUST be one of the following values: + "queued": The message is in a local mail queue and the status will change once it exits the local mail queues. The "smtpReply" property may still change. + "yes": The message was successfully delivered to the mail store of the recipient. The "smtpReply" property is final. + "no": Delivery to the recipient permanently failed. The "smtpReply" property is final. + "unknown": The final delivery status is unknown, (e.g., it was relayed to an external machine and no further information is available). The "smtpReply" property may still change if a DSN arrives.
Note that successful relaying to an external SMTP server SHOULD NOT be taken as an indication that the message has successfully reached the final mail store. In this case though, the server may receive a DSN response, if requested. If a DSN is received for the recipient with Action equal to "delivered", as per [RFC3464], Section 2.3.3, then the "delivered" property SHOULD be set to "yes"; if the Action equals "failed", the property SHOULD be set to "no". Receipt of any other DSN SHOULD NOT affect this property. The server MAY also set this property based on other feedback channels. * displayed: "String" Represents whether the message has been displayed to the recipient. This MUST be one of the following values: + "unknown": The display status is unknown. This is the initial value. + "yes": The recipient's system claims the message content has been displayed to the recipient. Note that there is no guarantee that the recipient has noticed, read, or understood the content. If a Message Disposition Notification (MDN) is received for this recipient with Disposition-Type (as per [RFC8098], Section 3.2.6.2) equal to "displayed", this property SHOULD be set to "yes". The server MAY also set this property based on other feedback channels. o dsnBlobIds: "Id[]" (server-set) A list of blob ids for DSNs [RFC3464] received for this submission, in order of receipt, oldest first. The blob is the whole MIME message (with a top-level content-type of "multipart/ report"), as received. o mdnBlobIds: "Id[]" (server-set) A list of blob ids for MDNs [RFC8098] received for this submission, in order of receipt, oldest first. The blob is the whole MIME message (with a top-level content-type of "multipart/ report"), as received.
JMAP servers MAY choose not to expose DSN and MDN responses as Email objects if they correlate to an EmailSubmission object. It SHOULD only do this if it exposes them in the "dsnBlobIds" and "mdnblobIds" fields instead, and it expects the user to be using clients capable of fetching and displaying delivery status via the EmailSubmission object. For efficiency, a server MAY destroy EmailSubmission objects at any time after the message is successfully sent or after it has finished retrying to send the message. For very basic SMTP proxies, this MAY be immediately after creation, as it has no way to assign a real id and return the information again if fetched later. The following JMAP methods are supported.7.1. EmailSubmission/get
This is a standard "/get" method as described in [RFC8620], Section 5.1.7.2. EmailSubmission/changes
This is a standard "/changes" method as described in [RFC8620], Section 5.2.7.3. EmailSubmission/query
This is a standard "/query" method as described in [RFC8620], Section 5.5. A *FilterCondition* object has the following properties, any of which may be omitted: o identityIds: "Id[]" The EmailSubmission "identityId" property must be in this list to match the condition. o emailIds: "Id[]" The EmailSubmission "emailId" property must be in this list to match the condition. o threadIds: "Id[]" The EmailSubmission "threadId" property must be in this list to match the condition.
o undoStatus: "String" The EmailSubmission "undoStatus" property must be identical to the value given to match the condition. o before: "UTCDate" The "sendAt" property of the EmailSubmission object must be before this date-time to match the condition. o after: "UTCDate" The "sendAt" property of the EmailSubmission object must be the same as or after this date-time to match the condition. An EmailSubmission object matches the FilterCondition if and only if all of the given conditions match. If zero properties are specified, it is automatically true for all objects. The following EmailSubmission properties MUST be supported for sorting: o "emailId" o "threadId" o "sentAt"7.4. EmailSubmission/queryChanges
This is a standard "/queryChanges" method as described in [RFC8620], Section 5.6.7.5. EmailSubmission/set
This is a standard "/set" method as described in [RFC8620], Section 5.3 with the following two additional request arguments: o onSuccessUpdateEmail: "Id[PatchObject]|null" A map of EmailSubmission id to an object containing properties to update on the Email object referenced by the EmailSubmission if the create/update/destroy succeeds. (For references to EmailSubmissions created in the same "/set" invocation, this is equivalent to a creation-reference, so the id will be the creation id prefixed with a "#".)
o onSuccessDestroyEmail: "Id[]|null" A list of EmailSubmission ids for which the Email with the corresponding "emailId" should be destroyed if the create/update/ destroy succeeds. (For references to EmailSubmission creations, this is equivalent to a creation-reference, so the id will be the creation id prefixed with a "#".) After all create/update/destroy items in the "EmailSubmission/set" invocation have been processed, a single implicit "Email/set" call MUST be made to perform any changes requested in these two arguments. The response to this MUST be returned after the "EmailSubmission/set" response. An Email is sent by creating an EmailSubmission object. When processing each create, the server must check that the message is valid, and the user has sufficient authorisation to send it. If the creation succeeds, the message will be sent to the recipients given in the envelope "rcptTo" parameter. The server MUST remove any Bcc header field present on the message during delivery. The server MAY add or remove other header fields from the submitted message or make further alterations in accordance with the server's policy during delivery. If the referenced Email is destroyed at any point after the EmailSubmission object is created, this MUST NOT change the behaviour of the submission (i.e., it does not cancel a future send). The "emailId" and "threadId" properties of the EmailSubmission object remain, but trying to fetch them (with a standard "Email/get" call) will return a "notFound" error if the corresponding objects have been destroyed. Similarly, destroying an EmailSubmission object MUST NOT affect the deliveries it represents. It purely removes the record of the submission. The server MAY automatically destroy EmailSubmission objects after some time or in response to other triggers, and MAY forbid the client from manually destroying EmailSubmission objects. If the message to be sent is larger than the server supports sending, a standard "tooLarge" SetError MUST be returned. A "maxSize" "UnsignedInt" property MUST be present on the SetError specifying the maximum size of a message that may be sent, in octets. If the Email or Identity id given cannot be found, the submission creation is rejected with a standard "invalidProperties" SetError.
The following extra SetError types are defined: For "create": o "invalidEmail" - The Email to be sent is invalid in some way. The SetError SHOULD contain a property called "properties" of type "String[]" that lists *all* the properties of the Email that were invalid. o "tooManyRecipients" - The envelope (supplied or generated) has more recipients than the server allows. A "maxRecipients" "UnsignedInt" property MUST also be present on the SetError specifying the maximum number of allowed recipients. o "noRecipients" - The envelope (supplied or generated) does not have any rcptTo email addresses. o "invalidRecipients" - The "rcptTo" property of the envelope (supplied or generated) contains at least one rcptTo value, which is not a valid email address for sending to. An "invalidRecipients" "String[]" property MUST also be present on the SetError, which is a list of the invalid addresses. o "forbiddenMailFrom" - The server does not permit the user to send a message with the envelope From address [RFC5321]. o "forbiddenFrom" - The server does not permit the user to send a message with the From header field [RFC5322] of the message to be sent. o "forbiddenToSend" - The user does not have permission to send at all right now for some reason. A "description" "String" property MAY be present on the SetError object to display to the user why they are not permitted. For "update": o "cannotUnsend" - The client attempted to update the "undoStatus" of a valid EmailSubmission object from "pending" to "canceled", but the message cannot be unsent.
7.5.1. Example
The following example presumes a draft of the Email to be sent has already been saved, and its Email id is "M7f6ed5bcfd7e2604d1753f6c". This call then sends the Email immediately, and if successful, removes the "$draft" flag and moves it from the drafts folder (which has Mailbox id "7cb4e8ee-df87-4757-b9c4-2ea1ca41b38e") to the sent folder (which we presume has Mailbox id "73dbcb4b-bffc-48bd-8c2a- a2e91ca672f6"). [[ "EmailSubmission/set", { "accountId": "ue411d190", "create": { "k1490": { "identityId": "I64588216", "emailId": "M7f6ed5bcfd7e2604d1753f6c", "envelope": { "mailFrom": { "email": "john@example.com", "parameters": null }, "rcptTo": [{ "email": "jane@example.com", "parameters": null }, ... ] } } }, "onSuccessUpdateEmail": { "#k1490": { "mailboxIds/7cb4e8ee-df87-4757-b9c4-2ea1ca41b38e": null, "mailboxIds/73dbcb4b-bffc-48bd-8c2a-a2e91ca672f6": true, "keywords/$draft": null } } }, "0" ]]
A successful response might look like this. Note that there are two responses due to the implicit "Email/set" call, but both have the same method call id as they are due to the same call in the request: [[ "EmailSubmission/set", { "accountId": "ue411d190", "oldState": "012421s6-8nrq-4ps4-n0p4-9330r951ns21", "newState": "355421f6-8aed-4cf4-a0c4-7377e951af36", "created": { "k1490": { "id": "ES-3bab7f9a-623e-4acf-99a5-2e67facb02a0" } } }, "0" ], [ "Email/set", { "accountId": "ue411d190", "oldState": "778193", "newState": "778197", "updated": { "M7f6ed5bcfd7e2604d1753f6c": null } }, "0" ]] Suppose instead an admin has removed sending rights for the user, so the submission is rejected with a "forbiddenToSend" error. The description argument of the error is intended for display to the user, so it should be localised appropriately. Let's suppose the request was sent with an Accept-Language header like this: Accept-Language: de;q=0.9,en;q=0.8
The server should attempt to choose the best localisation from those it has available based on the Accept-Language header, as described in [RFC8620], Section 3.8. If the server has English, French, and German translations, it would choose German as the preferred language and return a response like this: [[ "EmailSubmission/set", { "accountId": "ue411d190", "oldState": "012421s6-8nrq-4ps4-n0p4-9330r951ns21", "newState": "012421s6-8nrq-4ps4-n0p4-9330r951ns21", "notCreated": { "k1490": { "type": "forbiddenToSend", "description": "Verzeihung, wegen verdaechtiger Aktivitaeten Ihres Benutzerkontos haben wir den Versand von Nachrichten gesperrt. Bitte wenden Sie sich fuer Hilfe an unser Support Team." } } }, "0" ]]8. Vacation Response
A vacation response sends an automatic reply when a message is delivered to the mail store, informing the original sender that their message may not be read for some time. Automated message sending can produce undesirable behaviour. To avoid this, implementors MUST follow the recommendations set forth in [RFC3834]. The *VacationResponse* object represents the state of vacation- response-related settings for an account. It has the following properties: o id: "Id" (immutable; server-set) The id of the object. There is only ever one VacationResponse object, and its id is "singleton". o isEnabled: "Boolean" Should a vacation response be sent if a message arrives between the "fromDate" and "toDate"?
o fromDate: "UTCDate|null" If "isEnabled" is true, messages that arrive on or after this date-time (but before the "toDate" if defined) should receive the user's vacation response. If null, the vacation response is effective immediately. o toDate: "UTCDate|null" If "isEnabled" is true, messages that arrive before this date-time (but on or after the "fromDate" if defined) should receive the user's vacation response. If null, the vacation response is effective indefinitely. o subject: "String|null" The subject that will be used by the message sent in response to messages when the vacation response is enabled. If null, an appropriate subject SHOULD be set by the server. o textBody: "String|null" The plaintext body to send in response to messages when the vacation response is enabled. If this is null, the server SHOULD generate a plaintext body part from the "htmlBody" when sending vacation responses but MAY choose to send the response as HTML only. If both "textBody" and "htmlBody" are null, an appropriate default body SHOULD be generated for responses by the server. o htmlBody: "String|null" The HTML body to send in response to messages when the vacation response is enabled. If this is null, the server MAY choose to generate an HTML body part from the "textBody" when sending vacation responses or MAY choose to send the response as plaintext only. The following JMAP methods are supported.8.1. VacationResponse/get
This is a standard "/get" method as described in [RFC8620], Section 5.1. There MUST only be exactly one VacationResponse object in an account. It MUST have the id "singleton".
8.2. VacationResponse/set
This is a standard "/set" method as described in [RFC8620], Section 5.3.