From nobody Wed Feb 7 22:11:32 2018
Return-Path:
X-Original-To: jmap@ietfa.amsl.com
Delivered-To: jmap@ietfa.amsl.com
Received: from localhost (localhost [127.0.0.1]) by ietfa.amsl.com (Postfix) with ESMTP id BDB6312773A for ; Wed, 7 Feb 2018 22:11:30 -0800 (PST)
X-Virus-Scanned: amavisd-new at amsl.com
X-Spam-Flag: NO
X-Spam-Score: -2.719
X-Spam-Level:
X-Spam-Status: No, score=-2.719 tagged_above=-999 required=5 tests=[BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, HTML_MESSAGE=0.001, RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, SPF_PASS=-0.001, URIBL_BLOCKED=0.001] autolearn=ham autolearn_force=no
Authentication-Results: ietfa.amsl.com (amavisd-new); dkim=pass (2048-bit key) header.d=fastmailteam.com header.b=t5WJ0TzZ; dkim=pass (2048-bit key) header.d=messagingengine.com header.b=ddwk5bGe
Received: from mail.ietf.org ([4.31.198.44]) by localhost (ietfa.amsl.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id qQ-euRirMLko for ; Wed, 7 Feb 2018 22:11:26 -0800 (PST)
Received: from out2-smtp.messagingengine.com (out2-smtp.messagingengine.com [66.111.4.26]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by ietfa.amsl.com (Postfix) with ESMTPS id 67AC21243F6 for ; Wed, 7 Feb 2018 22:11:26 -0800 (PST)
Received: from betaweb1.internal (betaweb1.nyi.internal [10.202.2.10]) by mailout.nyi.internal (Postfix) with ESMTP id B44D920E45 for ; Thu, 8 Feb 2018 01:11:25 -0500 (EST)
Received: from betaweb1 ([::ffff:10.202.2.10]) by betaweb1.internal (MEProxy); Thu, 08 Feb 2018 01:11:25 -0500
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= fastmailteam.com; h=content-transfer-encoding:content-type:date :from:message-id:mime-version:subject:to:x-me-sender:x-me-sender :x-sasl-enc; s=fm1; bh=ErqdJKOVpLZMH4i0lQ3TlI0ZwmKqHnR9SB1GH9us4 ks=; b=t5WJ0TzZPRgg9cMaZ+xQO1faoq9ie36rzMKD1f+SLHWUKZFansmPgu5oS zFUcV3d5Je+olugiGvWSvF2vH5593TMeRZhNoVgYR+8dPMZ9PVeM5QrZmNmgb6QX 6rwT/MaS+BxxMEEkg7rgSTBcjPYzMyXpebCwbhRZv05XDHlEqYBjbPrVBjwth9HM 5a0Xr6Gj701linSqy1okl4iq8fNDVjGLUNucKSUg1d/1BUort0FkMyX9vVCRXnqf TLkXwIglsTVNs9Qt+zPmzOzvyqcvWibr3WU5KgvqF2TNbJ4H407P3bqQ1uM24XNy Pw/CdW0djft7DmsLXLnoM0aZmIShg==
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=content-transfer-encoding:content-type :date:from:message-id:mime-version:subject:to:x-me-sender :x-me-sender:x-sasl-enc; s=fm1; bh=ErqdJKOVpLZMH4i0lQ3TlI0ZwmKqH nR9SB1GH9us4ks=; b=ddwk5bGeCQNWlf/Iuu8RUXXdukSNvIXJm2xRjuewECeeW CFC6lYFC7QBzU094LZPVgTrORbxDApl+pmpzDsFUJvMdPz1C55b5pTi3QFLkY22f D9fFrjgEGJiUHRVwSwndSnDtkCHMVDeclK1XmBZdpYj5gu0sIs/lLbfWLydb4A/x Tj5o28m1DpLIbj9JLDwuq/qnZFQPKA6Y6EGM3f5b8Nn5p6BlqBATwVSTxQMf3veS X8wdFPa9XorU3NXvRN4P8odxfQ8aWprbyVRTZUTvZUM5qiTZ5bBHe2ay0j2pvH7X v4cKGZpijNOuPSwNSr3Jue60l2q77GUQ0wre4ldlg==
X-ME-Sender:
Received: by mailuser.nyi.internal (Postfix, from userid 99) id 51EDEE22A4; Thu, 8 Feb 2018 01:11:25 -0500 (EST)
Message-Id: <1518070284.168650.1263633200.05C7397A@webmail.messagingengine.com>
From: Neil Jenkins
To: IETF JMAP Mailing List
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Type: multipart/alternative; boundary="_----------=_15180702851686500"
X-Mailer: MessagingEngine.com Webmail Interface - ajax-2ce04827
Date: Thu, 08 Feb 2018 17:11:24 +1100
Archived-At:
Subject: [Jmap] New JSON message representation
X-BeenThere: jmap@ietf.org
X-Mailman-Version: 2.1.22
Precedence: list
List-Id: JSON Message Access Protocol
List-Unsubscribe: ,
List-Archive:
List-Post:
List-Help:
List-Subscribe: ,
X-List-Received-Date: Thu, 08 Feb 2018 06:11:31 -0000
This is a multi-part message in MIME format.
--_----------=_15180702851686500
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset="utf-8"
With an eye to closing off all remaining issues before the next IETF
meeting in March, I have been looking at the issues raised with the JSON
representation of an RFC5322 message. This email presents a new proposal
that I think resolves the issues presented. In particular, I aim to
address the following goals:
* Allow access to the full MIME structure without requiring the client
to parse the full message itself.
* Allow access to full header field information if required.
* Keep a simpler representation available for the common case.
* Allow the client to only load the data required.Comments, suggestions an=
d other feedback requested. Cheers!
------
Emails
The *Email* object is a representation of an [@!RFC5322] message, which
allows clients to avoid the complexities of MIME parsing, transport
encoding and character encoding.Properties of the Email object
Broadly, a message consists of two parts: a list of header fields, then
a body. The body is normally a MIME-encoded set of documents in a tree
structure. The JMAP Email object provides a way to access the full
structure, or to use simplified properties and avoid some complexity if
this is sufficient for the client application.Due to the number of properti=
es involved, the set of *Email* properties
is specified over the following three sub-sections.Metadata
These properties represent metadata about the [@!RFC5322] message, and
are not derived from parsing the message itself.
* *id*: String (immutable; server-set) The id of the Email object.
Note, this is the JMAP object id, NOT the [@!RFC5322] Message-Id
header field value.
* *blobId*: String (immutable; server-set) The id representing the raw
bytes of the [@!RFC5322] message. This may be used to download the
raw original message, or to attach it directly to another Email etc.
* *threadId*: String (immutable; server-set) The id of the Thread to
which this Email belongs.
* *mailboxIds*: String[Boolean] The set of mailbox ids this email
belongs to. An email MUST belong to one or more mailboxes at all
times (until it is deleted). The set is represented as an object,
with each key being a *Mailbox id*. The value for each key in the
object MUST be true.
* *keywords*: String[Boolean] (default: {}) A set of keywords that
apply to the email. The set is represented as an object, with the
keys being the *keywords*. The value for each key in the object
MUST be true.
Keywords are shared with IMAP. The six system keywords from IMAP are
treated specially. The following four keywords have their first
character changed from \ in IMAP to $ in JMAP and have particular
semantic meaning:
* $Draft: The email is a draft the user is composing.
* $Seen: The email has been read.
* $Flagged: The email has been flagged for urgent/special attention.
* $Answered: The email has been replied to. The IMAP \Recent keyword
is not exposed via JMAP. The IMAP \Deleted keyword is also not
present: IMAP uses a delete+expunge model, which JMAP does not. Any
message with the \Deleted keyword MUST NOT be visible via JMAP.
Users may add arbitrary keywords to an email. For compatibility with
IMAP, a keyword is a (case-sensitive) string of 1=E2=80=93255 characters in=
the
ASCII subset %x21=E2=80=93%x7e (excludes control chars and space), and MUST=
NOT
include any of these characters: ( ) { ] % * " \
The IANA Keyword Registry[1] as established in [@!RFC5788] assigns
semantic meaning to some other keywords in common use. New keywords may
be established here in the future. In particular, note:
* $Forwarded: The email has been forwarded.
* $Phishing: The email is highly likely to be phishing. Clients
SHOULD warn users to take care when viewing this email and disable
links and attachments.
* $Junk: The email is definitely spam. Clients SHOULD set this
flag when users report spam to help train automated spam-
detection systems.
* $NotJunk: The email is definitely not spam. Clients SHOULD set this
flag when users indicate an email is legitimate, to help train
automated spam-detection systems.
* *size*: Number (immutable; server-set) The size in bytes of the whole
email as counted by the server towards the user's quota.
* *receivedAt*: UTCDate (immutable; default: time of creation on
server) The date the email was received by the message store. This is
the *internal date* in IMAP.Header fields
These properties are derived from the [@!RFC5322] message header fields.
Header fields may be fetched in a variety of forms:
* *Decoded* The header field value with:
1. White space unfolded (as defined in [@!RFC5322] section 2.2.3)
2. The terminating CRLF at the end of the value removed
3. Any SP characters at the beginning of the value removed
4. Any [@!RFC2047] encoded sections decoded
5. Any [@!RFC6532] UTF-8 values decoded If any decodings fail, the
parser SHOULD insert a unicode replacement character (U+FFFD) and
attempt to continue as much as possible.
* *Raw Base64* The raw bytes of the header field value from the first
byte following the header field name terminating colon, up to but
excluding the header field terminating CRLF, encoded as Base64
([@!RFC4648]). (Note, this is required as the value may not be valid
UTF-8 if 8-bit values are present.)
* *Addresses* The header is parsed as an address-list value, as
specified in [@!RFC5322] section 3.4, into the EmailAddress[] type.
The *EmailAddress* object has the following properties:
* *name*: String|null The *display name* of the [@!RFC5322] *mailbox*
or *group*, or null if none.
* *email*: String|null The *addr-spec* of the [@!RFC5322] *mailbox*,
or null if a *group*. Parsing SHOULD be best-effort in the face of
invalid structure to accommodate invalid messages and semi-complete
drafts. EmailAddress objects MAY have an *email* property that does
not conform to the *addr-spec* form (for example, may not contain
an @ symbol).
* *Date* The header is parsed as a date-time value, as specified in
[@!RFC5322] section 3.3, into the Date type.The following *Email* proper=
ties are specified for complete access to
the header data of the message. Where {header-field-name} is specified
within a property name, this means any series of one or more printable
US-ASCII characters (i.e. characters that have values between 33 and
126, inclusive), except colon:
* *headers*: EmailHeader[] (immutable) This is a list of all
[@!RFC5322] header fields, in the same order they appear in the
message. The values are in *Decoded* form.
* *headers:asRaw*: EmailHeader[] (immutable) This is a list of all
[@!RFC5322] header fields, in the same order they appear in the
message. The values are in *Raw Base64* form.
* *header:{header-field-name}*: String|null (immutable) The value of
the *last* header field in the message with the given header field
name (matched case-insensitively), or null if none. The value is in
*Decoded* form.
* *header:{header-field-name}:asRaw*: String|null (immutable) The value
of the *last* header field in the message with the given header field
name (matched case-insensitively), or null if none. The value is in
*Raw Base64* form.
* *header:{header-field-name}:asAddresses*: EmailAddress[]|null
(immutable) The value of the *last* header field in the message with
the given header field name (matched case-insensitively), or null if
none. The value is in *Addresses* form.
* *header:{header-field-name}:asDate*: Date|null (immutable) The value
of the *last* header field in the message with the given header field
name (matched case-insensitively), or null if none. The value is in
*Date* form.An *EmailHeader* object has the following properties:
* *name*: String The header *field name* as defined in RFC5322, with
the same capitalization that it has in the message.
* *value*: String The header *field value* as defined in RFC5322, in
either *Decoded* or *Raw Base64* form as determined by the property
being fetched.The following convenience properties are also specified fo=
r the
*Email* object:
* *sender*: EmailAddress[]|null (immutable) The value is identical to
the value of *header:Sender:asAddresses*.
* *from*: EmailAddress[]|null (immutable) The value is identical to the
value of *header:From:asAddresses*.
* *to*: EmailAddress[]|null (immutable) The value is identical to the
value of *header:To:asAddresses*.
* *cc*: EmailAddress[]|null (immutable) The value is identical to the
value of *header:Cc:asAddresses*.
* *bcc*: EmailAddress[]|null (immutable) The value is identical to the
value of *header:Bcc:asAddresses*.
* *replyTo*: EmailAddress[]|null (immutable) The value is identical to
the value of *header:Reply-To:asAddresses*.
* *subject*: String|null (immutable) The value is identical to the
value of *header:Subject*.
* *sentAt*: Date (immutable; default: time of creation on server) The
value is identical to the value of *header:Date:asDate*.Body parts
These properties are derived from the [@!RFC5322] message body and its
[@RFC2045] MIME entities.A *EmailBodyPart* object has the following propert=
ies:
* *partId*: String Identifies this part uniquely within the Email. This
is scoped to the *emailId* and has no meaning outside of the JMAP
Email object representation.
* *blobId*: String The id references the raw bytes of the contents of
the part after decoding any *Content-Transfer* encoding (as defined
in [@!RFC2045]). Note, two parts may be transfer-encoded differently
but have same the same blob id if their decoded bytes are identical
and the server is using a secure hash of the data for the blob id.
* *size*: Number The size, in bytes, of the raw data after content-
transfer decoding (as refrenced by the *blobId*, i.e. the number of
bytes in the file the user would download).
* *headers*: EmailHeader[] (immutable) This is a list of all header
fields in the part, in the order they appear. The values are in
*Decoded* form.
* *headers:asRaw*: EmailHeader[] (immutable) This is a list of all
header fields in the part, in the order they appear. The values are
in *Raw Base64* form.
* *name*: String|null This is the [@!RFC2231] decoded *filename*
parameter of the *Content-Disposition* header field, or (for
compatibility with existing systems) if not present then the
[@!RFC2047] decoded *name* property of the *Content-Type* header
field. For compatibility with the widest array of existing systems,
both forms should be set if creating a message.
* *type*: String The value of the *Content-Type* header field of the
part, excluding any parameters.
* *charset*: String|null The value of the charset parameter of the *Conten=
t-
Type* header field, if present.
* *disposition*: String|null The value of the *Content-Disposition*
header field of the part, excluding any parameters, if present.
* *cid*: String|null The value of the *Content-Id* header field of the
part, if present. This may be used to reference the content from
within an html body part using the cid: protocol.
* *language*: String[]|null The list of language tags, as defined in
[@!RFC3282], in the *Content-Language* header field of the part,
if present.
* *location*: String|null The URI, as defined in [@!RFC2557], in the
*Content-Location* header field of the part, if present.
* *width*: Number|null The width (in px) of the image, if the type is
an image and the server is able to determine this information for
the image. This MAY not be supported for all or any image types on
some servers.
* *height*: Number|null The height (in px) of the image, if the type
is an image and the server is able to determine this information for
the image. This MAY not be supported for all or any image types on
some servers.
* *subParts*: EmailBodyPart[] (optional) If type is multipart/*, this
contains the body parts of each child.The following *Email* properties a=
re specified for access to the body
data of the message:
* *bodyStructure*: EmailBodyPart[] (immutable) This is the full MIME
structure of the message body, including sub parts but not recursing
into message/rfc822 parts.
* *bodyValues*: String[BodyValue] (immutable) This is a map of *partId*
to an *EmailBodyValue* object. Which parts are included and whether
the value is truncated is determined by various arguments to
*Email/get* and *Email/parse*.
An *EmailBodyValue* object has the following properties:
* *value*: String The value of the body part after decoding *Content-
Transport* encoding and decoding the *Content-Type* charset.
* *isTruncated* Boolean This is true if the *value* has been
truncated.
* *textBody*: EmailBodyPart[] (immutable) A list of text/plain,
text/html and image/* parts to display (sequentially) as the message
body, with a preference for text/plain when alternative versions are
available.
* *htmlBody*: EmailBodyPart[] (immutable) A list of text/plain,
text/html and image/* parts to display (sequentially) as the message
body, with a preference for text/html when alternative versions are
available.
* *attachedEmails*: EmailBodyPart[] (immutable) A list of all parts of
type message/rfc822. Note, this *does not* recurse, so the parts
within these are not included. The attached message may be fetched
using the Email/parse method and the blobId.
* *attachedFiles*: EmailBodyPart[] (immutable) A list of all parts in
*bodyStructure*, traversing depth-first, not of type multipart/*, and
not included in any of the *textBody*, *htmlBody* or *attachedEmails*
properties. Note, an HTML body part may reference image parts in
attachedFiles using cid: links to reference the *Content-Id* or by
referencing the *Content-Location*.
* *hasAttachment*: Boolean (immutable; server-set) This is true if
there are one or more parts in the message that a client UI should
offer as downloadable. A server SHOULD set hasAttachment if either:
* The *attachedEmails* list contains at least one item.
* The *attachedFiles* list contains at least one item that does not
have Content-Disposition: attachment. The server MAY ignore parts
in this list that are processed automatically in some way, or are
referenced as embedded images in one of the text/html parts of the
message. The server MAY set hasAttachment based on implementation-
defined or site configurable heuristics.
* *preview*: String (immutable; server-set) Up to 256 characters of the
beginning of a plain text version of the message body. This is
intended to be shown as a preview line on a mailbox listing, and the
server may choose to skip quoted sections or salutations to return a
more useful preview.MIME structures are arbitrary nested trees of docume=
nts, but the
majority of email clients present a model of an email body (normally
plain text or HTML), with a set of attachments. Interpreting the MIME
structure to form this flat model represents considerable difficulty and
causes inconsistency between clients. Therefore in addition to the
*bodyStructure* property, which gives the full tree, the Email object
contains 4 alternate properties with flat lists of body parts:
* *textBody*/*htmlBody*: These provide a list of parts that should be
rendered as the "body" of the message. This is a list rather than a
single part as messages may have headers and/or footers
appended/prepended as separate parts as they are transmitted, and
some clients send text and images intended to be displayed inline in
the body as multiple parts rather than a single HTML part with
referenced images.
Because MIME allows for multiple representations of the same data (using
multipart/alternative), there is a textBody property (which prefers a
plain text representation) and an htmlBody property (which prefers an
HTML representation) to accommodate the two most common client
requirements. The same part may appear in both lists where there is no
alternative between the two.
* *attachedEmails*/*attachedFiles*: These provide a list of parts that
should be presented as "attachments" to the message. Emails are
presented in a separate list so their contents may be easily fetched
via a back-reference with the Email/parse method in the same request,
if the client wishes to. Some images in attachedFiles may be solely
there for embedding within an HTML body part; clients may wish to not
present these as attachments in the user interface if they are
displaying the HTML with the embedded images directly.The *bodyValues* p=
roperty allows for clients to fetch the value of text
parts directly without having to do a second request for the blob, and
have the server handle decoding the charset into unicode. This data is
in a separate property rather than on the EmailBodyPart object to avoid
duplication of large amounts of data, as the same part may be included
twice if the client fetches more than one of bodyStructure, textBody
and htmlBody.The exact algorithm for decomposing bodyStructure into textBod=
y,
htmlBody, attachedEmails and attachedFiles part lists is not mandated,
as this is a quality-of-service implementation issue and likely to
require workarounds for malformed content discovered over time.However, we =
will define a suggested algorithm for the RFC to help
implementors. TODO.Email/get
Standard */get* method, with the following additional arguments:
* *bodyProperties*: String[] (optional) A list of properties to fetch
for each EmailBodyPart returned. If omitted, this defaults to:
[ "partId", "blobId", "size", "name", "type", "charset", "disposition",
cid", "language", "location", "width", "height" ]
* *fetchTextBodyValues*: Boolean (default: false) If true, the
*bodyValues* property includes any text/* part in the textBody
property.
* *fetchHTMLBodyValues*: Boolean (default: false) If true, the
*bodyValues* property includes any text/* part in the htmlBody
property.
* *fetchAllBodyValues*: Boolean (default: false) If true, the
*bodyValues* property includes any text/* part in the
bodyStructure property.
* *maxBodyValueBytes*: Number (optional) If supplied by the client, the
value MUST be a positive integer greater than 0. If a value outside
of this range is given, the server MUST reject the call with an
invalidArguments error. When given, the *value* property of any
EmailBodyValue object returned in *bodyValues* MUST be truncated if
necessary so it does not exceed this number of bytes in size. The
server MUST ensure the truncation results in valid UTF-8 and does not
occur mid-codepoint. If the part is of type text/html, the server
SHOULD NOT truncate inside an HTML tag.If the standard *properties* argu=
ment is omitted or null, the following
default MUST be used instead of "all" properties:
[ "id", "blobId", "threadId", "mailboxIds", "keywords", "size",
"receivedAt", "sender", "from", "to", "cc", "bcc", "replyTo", "subject",
"sentAt", "hasAttachment", "preview", "bodyValues", "textBody",
"htmlBody", "attachedFiles", "attachedEmails" ]The following properties are=
expected to be fast to fetch in a quality
implementation:
* id
* blobId
* threadId
* mailboxIds
* keywords
* size
* receivedAt
* sender
* from
* to
* cc
* bcc
* replyTo
* subject
* sentAt
* hasAttachment
* previewClients SHOULD take care when fetching any other properties, as t=
here
may be significantly longer latency in fetching and returning the data.Exam=
ple
Request:
["Email/get", { "ids": [ "f123u456", "f123u457" ], "properties": [
"threadId", "mailboxIds", "from", "subject", "receivedAt", "htmlBody",
"bodyValues" ], "bodyProperties": [ "partId", "blobId", "size", "type"
], "fetchHTMLBodyValues": true, "maxBodyValueBytes": 256 }, "#1"]and respon=
se:
["Email/get", { "accountId": "abc", "state": "41234123231", "list": [ {
"id": "f123u457", "threadId": "ef1314a", "mailboxIds": { "f123": true },
"from": [{name: "Joe Bloggs", email: "joe@bloggs.com"}], "subject":
"Dinner on Thursday?", "receivedAt": "2013-10-13T14:12:00Z", "htmlBody":
[{ "partId": "1", "blobId": "841623871", "size": 283331, "type":
"text/html" }, { "partId": "2", "blobId": "319437193", "size": 10343,
"type": "text/plain" }], "bodyValues": { "1": { "isTruncated": true,
"value": "Hello ..." }, "2": { "isTruncated": false,
"value": "-- \nSent by your friendly mailing list ..." } } } ],
notFound: [ "f123u456" ] }, "#1"]
Links:
1. https://www.iana.org/assignments/imap-keywords/imap-keywords.xhtml
--_----------=_15180702851686500
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset="utf-8"
With an eye to closing off all remaining issues before the next =
IETF meeting in March, I have been looking at the issues raised with the JS=
ON representation of an RFC5322 message. This email presents a new proposal=
that I think resolves the issues presented. In particular, I aim to addres=
s the following goals:
- Allow access to the full MIME structure without requiring the clien=
t to parse the full message itself.
- Allow access to full header=
field information if required.
- Keep a simpler representation a=
vailable for the common case.
- Allow the client to only load the=
data required.
Comments, suggestions and other feedback =
requested. Cheers!
------
Emails
The Email object is a representa=
tion of an [@!RFC5322] message, which allows clients to avoid the complexit=
ies of MIME parsing, transport encoding and character encoding.
Properties of the Email object
Broadly, a message consists of two parts: a list of header fields, then a =
body. The body is normally a MIME-encoded set of documents in a tree struct=
ure. The JMAP Email object provides a way to access the full structure, or =
to use simplified properties and avoid some complexity if this is sufficien=
t for the client application.
Due to the number of properties inv=
olved, the set of Email properties is specified over the following t=
hree sub-sections.
These pro=
perties represent metadata about the [@!RFC5322] message, and are not deriv=
ed from parsing the message itself.
id: Stri=
ng
(immutable; server-set)
The id of the Email object. Note, this is the JMAP object id, NOT the [@!RF=
C5322] Message-Id header field value.
blobId: String (immutable; server-set)
The id representing the raw bytes of the [@!RFC5322] message. This may be u=
sed to download the raw original message, or to attach it directly to anoth=
er Email etc.
threadId: String
(immu=
table; server-set)
The id of the Thread to which this Email belongs.
mai=
lboxIds: String[Boolean]
The set of mailbox ids this email=
belongs to. An email MUST belong to one or more mailboxes at all times (un=
til it is deleted). The set is represented as an object, with each key bein=
g a Mailbox id. The value for each key in the object MUST be t=
rue
.
keywords: String[Boolean]
(default: {}
)
A set of keywords that apply to the email. The set is represented as an obj=
ect, with the keys being the keywords. The value for each key in the=
object MUST be true
.
Keywords are shared with IMAP.=
The six system keywords from IMAP are treated specially. The following fou=
r keywords have their first character changed from \
in IMAP t=
o $
in JMAP and have particular semantic meaning:
<=
li>$Draft
: The email is a draft the user is composing.
$Seen
: The email has been read.
$Flagge=
d
: The email has been flagged for urgent/special attention.
=
$Answered
: The email has been replied to.
=
The IMAP \Recent
keyword is not exposed via JMAP. The IMAP \Deleted keyword is also not present: IMAP uses a delete+expunge =
model, which JMAP does not. Any message with the \Deleted
keyw=
ord MUST NOT be visible via JMAP.
Users may add arbitrary keyword=
s to an email. For compatibility with IMAP, a keyword is a (case-sensitive)=
string of 1=E2=80=93255 characters in the ASCII subset %x21=E2=80=93%x7e (=
excludes control chars and space), and MUST NOT include any of these charac=
ters: ( ) { ] % * " \
The IANA Keyword Registry<=
/a> as established in [@!RFC5788] assigns semantic meaning to some other ke=
ywords in common use. New keywords may be established here in the future. I=
n particular, note:
$Forwarded
: The email has b=
een forwarded.
$Phishing
: The email is highly like=
ly to be phishing. Clients SHOULD warn users to take care when viewing this=
email and disable links and attachments.
$Junk
: T=
he email is definitely spam. Clients SHOULD set this flag when users report=
spam to help train automated spam-detection systems.
$No=
tJunk
: The email is definitely not spam. Clients SHOULD set this fla=
g when users indicate an email is legitimate, to help train automated spam-=
detection systems.
size: Number
(immutable; server-set)
The size in bytes of the whole email as counted by the server towards the u=
ser's quota.
receivedAt: UTCDate
(im=
mutable; default: time of creation on server)
The date the email was received by the message store. This is the intern=
al date in IMAP.
These properties are derived from the [@!RFC5322] message heade=
r fields. Header fields may be fetched in a variety of forms:
Decoded The header field value with:
- White space=
unfolded (as defined in [@!RFC5322] section 2.2.3)
- The termina=
ting CRLF at the end of the value removed
- Any SP characters at =
the beginning of the value removed
- Any [@!RFC2047] encoded sect=
ions decoded
- Any [@!RFC6532] UTF-8 values decoded
=
If any decodings fail, the parser SHOULD insert a unicode replacement
character (U+FFFD) and attempt to continue as much as possible.
Raw Base64 The raw bytes of the header field value from the =
first byte following the header field name terminating colon, up to but exc=
luding the header field terminating CRLF, encoded as Base64 ([@!RFC4648]). =
(Note, this is required as the value may not be valid UTF-8 if 8-bit values=
are present.)
Addresses The header is parsed as =
an address-list
value, as specified in [@!RFC5322] section 3.4=
, into the EmailAddress[]
type. The EmailAddress object=
has the following properties:
- name:
String|nul=
l
The display name of the [@!RFC5322] mailbox or gr=
oup, or null
if none.
- email:
Stri=
ng|null
The addr-spec of the [@!RFC5322] mailbox, or <=
code>null if a group.
Parsing SHOULD be best-=
effort in the face of invalid structure to accommodate
invalid messages and semi-complete drafts. EmailAddress objects MAY have an=
email property that does not conform to the addr-spec form (=
for example, may not contain an @ symbol).
Date T=
he header is parsed as a date-time
value, as specified in [@!R=
FC5322] section 3.3, into the Date
type.
T=
he following Email properties are specified for complete access to t=
he header data of the message. Where {header-field-name}
is sp=
ecified within a property name, this means any series of one or more printa=
ble US-ASCII characters (i.e. characters that have values between 33 and 12=
6, inclusive), except colon:
- headers:
EmailHead=
er[]
(immutable)
This is a list of all [@!RFC5322] header fields, in the same order they app=
ear in the message. The values are in Decoded form.
- h=
eaders:asRaw:
EmailHeader[]
(immutable)
This is a list of all [@!RFC5322] header fields, in the same order they app=
ear in the message. The values are in Raw Base64 form.
- <=
b>header:{header-field-name}:
String|null
(immutable)
The value of the last header field in the message with the given hea=
der field name (matched case-insensitively), or null
if none. =
The value is in Decoded form.
- header:{header-field-na=
me}:asRaw:
String|null
(immutable)
The value of the last header field in the message with the given hea=
der field name (matched case-insensitively), or null
if none. =
The value is in Raw Base64 form.
- header:{header-field=
-name}:asAddresses:
EmailAddress[]|null
(immutable)
The value of the last header field in the message with the given hea=
der field name (matched case-insensitively), or null
if none. =
The value is in Addresses form.
- header:{header-field-=
name}:asDate:
Date|null
(immutable)
The value of the last header field in the message with the given hea=
der field name (matched case-insensitively), or null
if none. =
The value is in Date form.
An EmailHeader obj=
ect has the following properties:
- name:
String<=
/code> The header field name as defined in RFC5322, with the same ca=
pitalization that it has in the message.
- value:
St=
ring
The header field value as defined in RFC5322, in either =
Decoded or Raw Base64 form as determined by the property bein=
g fetched.
The following convenience properties are also sp=
ecified for the Email object:
- sender:
Em=
ailAddress[]|null
(immutable)
The value is identical to the value of header:Sender:asAddresses.
- from:
EmailAddress[]|null
(immutable)
The value is identical to the value of header:From:asAddresses.
<=
/li> - to:
EmailAddress[]|null
(immutable)
The value is identical to the value of header:To:asAddresses.
- cc:
EmailAddress[]|null
(immutable)
The value is identical to the value of header:Cc:asAddresses.
- bcc:
EmailAddress[]|null
(immutable)
The value is identical to the value of header:Bcc:asAddresses.
=
li> - replyTo:
EmailAddress[]|null
(immutable)
The value is identical to the value of header:Reply-To:asAddresses.<=
br> - subject:
String|null
(immutable)
The value is identical to the value of header:Subject.
- <=
b>sentAt:
Date
(immutable; default: time of creation on se=
rver)
The value is identical to the value of header:Date:asDate.
<=
/ul>Body parts
These properties are derived=
from the [@!RFC5322] message body and its [@RFC2045] MIME entities.
A EmailBodyPart object has the following properties:
=
- partId:
String
Identifies this part uniquely within=
the Email. This is scoped to the emailId and has no meaning outside=
of the JMAP Email object representation.
- blobId:
=
String
The id references the raw bytes of the contents of the part a=
fter decoding any Content-Transfer encoding (as defined in [@!RFC204=
5]). Note, two parts may be transfer-encoded differently but have same the =
same blob id if their decoded bytes are identical and the server is using a=
secure hash of the data for the blob id.
- size:
Nu=
mber
The size, in bytes, of the raw data after content-transfer deco=
ding (as refrenced by the blobId, i.e. the number of bytes in the fi=
le the user would download).
- headers:
EmailHeader[=
]
(immutable)
This is a list of all header fields in the part, in the order they appear. =
The values are in Decoded form.
- headers:asRaw: EmailHeader[] (immutable)
This is a list of all header fields in the part, in the order they appear. =
The values are in Raw Base64 form.
- name:
St=
ring|null
This is the [@!RFC2231] decoded filename parameter =
of the Content-Disposition header field, or (for compatibility with =
existing systems) if not present then the [@!RFC2047] decoded name p=
roperty of the Content-Type header field. For compatibility with the=
widest array of existing systems, both forms should be set if creating a m=
essage.
- type:
String
The value of the Co=
ntent-Type header field of the part, excluding any parameters.
=
- charset:
String|null
The value of the charset param=
eter of the Content-Type header field, if present.
- di=
sposition:
String|null
The value of the Content-Disposi=
tion header field of the part, excluding any parameters, if present.
- cid:
String|null
The value of the Content-=
Id header field of the part, if present. This may be used to reference =
the content from within an html body part using the cid:
proto=
col.
- language:
String[]|null
The list of la=
nguage tags, as defined in [@!RFC3282], in the Content-Language head=
er field of the part, if present.
- location:
String=
|null
The URI, as defined in [@!RFC2557], in the Content-Location=
header field of the part, if present.
- width:
=
Number|null
The width (in px) of the image, if the type is an image =
and the server is able to determine this information for the image. This MA=
Y not be supported for all or any image types on some servers.
- =
height:
Number|null
The height (in px) of the image, if=
the type is an image and the server is able to determine this information =
for the image. This MAY not be supported for all or any image types on some=
servers.
- subParts:
EmailBodyPart[]
(option=
al)
If type is multipart/*
, this contains the body parts of each c=
hild.
The following Email properties are specified f=
or access to the body data of the message:
bodyStructu=
re: EmailBodyPart[]
(immutable)
This is the full MIME structure of the message body, including sub parts bu=
t not recursing into message/rfc822
parts.
=
bodyValues: String[BodyValue]
(immutable)
This is a map of partId to an EmailBodyValue object. Which pa=
rts are included and whether the value is truncated is determined by variou=
s arguments to Email/get and Email/parse.
An Ema=
ilBodyValue object has the following properties:
- valu=
e:
String
The value of the body part after decoding Con=
tent-Transport encoding and
decoding the Content-Type charset.
- isTruncated Boolean This is
true
if the value has been t=
runcated.
textBody: EmailBodyPart[]=
code> (immutable)
A list of text/plain
, text/html
and image/*=
parts to display (sequentially) as the message body, with a prefere=
nce for text/plain
when alternative versions are available.
htmlBody: EmailBodyPart[]
(immutable)
A list of text/plain
, text/html
and image/*=
parts to display (sequentially) as the message body, with a prefere=
nce for text/html
when alternative versions are available.
=
attachedEmails: EmailBodyPart[]
(immuta=
ble)
A list of all parts of type message/rfc822
. Note, this does=
not recurse, so the parts within these are not included. The attached =
message may be fetched using the Email/parse method and the blobId.
=
attachedFiles: EmailBodyPart[]
(immutable)
A list of all parts in bodyStructure, traversing depth-first, not of=
type multipart/*
, and not included in any of the textBody<=
/i>, htmlBody or attachedEmails properties. Note, an HTML bod=
y part may reference image parts in attachedFiles using cid:
l=
inks to reference the Content-Id or by referencing the Content-Lo=
cation.
hasAttachment: Boolean
(=
immutable; server-set)
This is true
if there are one or more parts in the message tha=
t a client UI should offer as downloadable. A server SHOULD set hasAttachme=
nt if either:
- The attachedEmails list contains at lea=
st one item.
- The attachedFiles list contains at least on=
e item that does not have
Content-Disposition: attachment
. The=
server MAY ignore parts in this list that are processed automatically in s=
ome way, or are referenced as embedded images in one of the text/html=
parts of the message.
The server MAY set hasAttachm=
ent based on implementation-defined or site configurable heuristics.
preview: String
(immutable; server-set)
Up to 256 characters of the beginning of a plain text version of the messag=
e body. This is intended to be shown as a preview line on a mailbox listing=
, and the server may choose to skip quoted sections or salutations to retur=
n a more useful preview.
MIME structures are arbitrary =
nested trees of documents, but the majority of email clients present a mode=
l of an email body (normally plain text or HTML), with a set of attachments=
. Interpreting the MIME structure to form this flat model represents consid=
erable difficulty and causes inconsistency between clients. Therefore in ad=
dition to the bodyStructure property, which gives the full tree, the=
Email object contains 4 alternate properties with flat lists of body parts=
:
textBody/htmlBody: These provide a list o=
f parts that should be
rendered as the "body" of the message. This is a list rather than a single =
part as messages may have headers and/or footers appended/prepended as sepa=
rate parts as they are transmitted, and some clients send text and images i=
ntended to be displayed inline in the body as multiple parts rather than a =
single HTML part with referenced images.
Because MIME allows for =
multiple representations of the same data (using multipart/alternativ=
e
), there is a textBody property (which prefers a plain text represe=
ntation) and an htmlBody property (which prefers an HTML representation) to=
accommodate the two most common client requirements. The same part may app=
ear in both lists where there is no alternative between the two.
attachedEmails/attachedFiles: These provide a list o=
f parts that should
be presented as "attachments" to the message. Emails are presented in a sep=
arate list so their contents may be easily fetched via a back-reference wit=
h the Email/parse
method in the same request, if the client wi=
shes to. Some images in attachedFiles may be solely there for embedding wit=
hin an HTML body part; clients may wish to not present these as attachments=
in the user interface if they are displaying the HTML with the embedded im=
ages directly.
The bodyValues property allows fo=
r clients to fetch the value of text parts directly without having to do a =
second request for the blob, and have the server handle decoding the charse=
t into unicode. This data is in a separate property rather than on the Emai=
lBodyPart object to avoid duplication of large amounts of data, as the same=
part may be included twice if the client fetches more than one of bodyStru=
cture, textBody and htmlBody.
The exact algorithm for decomposing=
bodyStructure into textBody, htmlBody, attachedEmails and attachedFiles pa=
rt lists is not mandated, as this is a quality-of-service implementation is=
sue and likely to require workarounds for malformed content discovered over=
time.
However, we will define a suggested algorithm for the RFC =
to help implementors. TODO.
Email/get
Standard /get method, with the following additional arguments:
<=
/p>
bodyProperties: String[]
(optional)
A list of properties to fetch for each EmailBodyPart returned. If omitted, =
this defaults to:
[ "partId", "blobId", "size", "name", "type", "=
charset", "disposition", cid", "language", "location", "width", "height" ]<=
br>
fetchTextBodyValues: Boolean
(defaul=
t: false
)
If true
, the bodyValues property includes any tex=
t/*
part in the textBody
property.
<=
b>fetchHTMLBodyValues: Boolean
(default: false
)
If true
, the bodyValues property includes any tex=
t/*
part in the htmlBody
property.
<=
b>fetchAllBodyValues: Boolean
(default: false
)
If true
, the bodyValues property includes any tex=
t/*
part in the bodyStructure
property.
maxBodyValueBytes: Number
(optional)
If supplied by the client, the value MUST be a positive integer greater tha=
n 0. If a value outside of this range is given, the server MUST reject the =
call with an invalidArguments
error. When given, the value<=
/i> property of any EmailBodyValue object returned in bodyValues MUS=
T be truncated if necessary so it does not exceed this number of bytes in s=
ize. The server MUST ensure the truncation results in valid UTF-8 and does =
not occur mid-codepoint. If the part is of type text/html
, the=
server SHOULD NOT truncate inside an HTML tag.
If the =
standard properties argument is omitted or null
, the fo=
llowing default MUST be used instead of "all" properties:
[ "id", "blobId", "threadId", "mailboxIds", "keywords", "size", "receivedA=
t", "sender", "from", "to", "cc", "bcc", "replyTo", "subject", "sentAt", "h=
asAttachment", "preview", "bodyValues", "textBody", "htmlBody", "attachedFi=
les", "attachedEmails" ]
The following properties are expected to be fast to fet=
ch in a quality implementation:
- id
- blobId
- threadId
- mailboxIds
- keywords
- size=
- receivedAt
- sender
- from
- to<=
br>
- cc
- bcc
- replyTo
- subject
<=
/li> - sentAt
- hasAttachment
- preview
<=
p>Clients SHOULD take care when fetching any other properties, as there may=
be significantly longer latency in fetching and returning the data.
Example
Request:
["Email/g=
et", {
"ids": [ "f123u456", "f123u457" ],
"properties": [ "threadId", "mailboxIds", "from", "subject", "receivedAt"=
, "htmlBody", "bodyValues" ],
"bodyProperties": [ "partId", "blobId", "size", "type" ],
"fetchHTMLBodyValues": true,
"maxBodyValueBytes": 256
}, "#1"]
and response:
["Email/get", {
"accountId": "abc",
"state": "41234123231",
"list": [
{
"id": "f123u457",
"threadId": "ef1314a",
"mailboxIds": { "f123": true },
"from": [{name: "Joe Bloggs", email: "joe@bloggs.com"}],
"subject": "Dinner on Thursday?",
"receivedAt": "2013-10-13T14:12:00Z",
"htmlBody": [{
"partId": "1",
"blobId": "841623871",
"size": 283331,
"type": "text/html"
}, {
"partId": "2",
"blobId": "319437193",
"size": 10343,
"type": "text/plain"
}],
"bodyValues": {
"1": {
"isTruncated": true,
"value": "<html><body><p>Hello ..."
},
"2": {
"isTruncated": false,
"value": "-- \nSent by your friendly mailing list ..."
}
}
}
],
notFound: [ "f123u456" ]
}, "#1"]
--_----------=_15180702851686500--
From nobody Fri Feb 9 03:41:58 2018
Return-Path:
X-Original-To: jmap@ietfa.amsl.com
Delivered-To: jmap@ietfa.amsl.com
Received: from localhost (localhost [127.0.0.1]) by ietfa.amsl.com (Postfix) with ESMTP id 5D876126E01 for ; Fri, 9 Feb 2018 03:41:56 -0800 (PST)
X-Virus-Scanned: amavisd-new at amsl.com
X-Spam-Flag: NO
X-Spam-Score: -2.01
X-Spam-Level:
X-Spam-Status: No, score=-2.01 tagged_above=-999 required=5 tests=[BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, HTML_MESSAGE=0.001, SPF_PASS=-0.001, T_RP_MATCHES_RCVD=-0.01] autolearn=ham autolearn_force=no
Authentication-Results: ietfa.amsl.com (amavisd-new); dkim=pass (1024-bit key) header.d=isode.com
Received: from mail.ietf.org ([4.31.198.44]) by localhost (ietfa.amsl.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id ewXu7LhQe5wW for ; Fri, 9 Feb 2018 03:41:54 -0800 (PST)
Received: from waldorf.isode.com (waldorf.isode.com [62.232.206.188]) by ietfa.amsl.com (Postfix) with ESMTP id B2689126BF0 for ; Fri, 9 Feb 2018 03:41:54 -0800 (PST)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; t=1518176513; d=isode.com; s=june2016; i=@isode.com; bh=utNpzEjFq+qNmJXPFmUPNyCvKD+ipYMsrmX62GujoYs=; h=From:Sender:Reply-To:Subject:Date:Message-ID:To:Cc:MIME-Version: In-Reply-To:References:Content-Type:Content-Transfer-Encoding: Content-ID:Content-Description; b=UYBQzih+7SHwqlpnP2Q37JlRaN16PmMYHKg0LymeA66hGIGNef7OhL0DhcOXG253vF5KA5 fc5tNsgtOjn9iiiXarkr5v1ZZyZk7gIWBlzXf8q7gdsXxX5vwKQa+jjz00jCO1xqhqcJVi LP/gXDG3kQXQtN/f6jUxo0K+hX+GZGU=;
Received: from [172.20.1.215] (dhcp-215.isode.net [172.20.1.215]) by waldorf.isode.com (submission channel) via TCP with ESMTPSA id ; Fri, 9 Feb 2018 11:41:53 +0000
From: Alexey Melnikov
To: Neil Jenkins , IETF JMAP Mailing List
References: <1518070284.168650.1263633200.05C7397A@webmail.messagingengine.com>
Message-ID: <0bb7d2f4-bcba-86ea-12f7-43a59a2f951e@isode.com>
Date: Fri, 9 Feb 2018 11:41:27 +0000
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:52.0) Gecko/20100101 Thunderbird/52.5.2
In-Reply-To: <1518070284.168650.1263633200.05C7397A@webmail.messagingengine.com>
MIME-Version: 1.0
Content-Type: multipart/alternative; boundary="------------DEF1A268E23D1481DA1CD017"
Content-Language: en-GB
Archived-At:
Subject: Re: [Jmap] New JSON message representation
X-BeenThere: jmap@ietf.org
X-Mailman-Version: 2.1.22
Precedence: list
List-Id: JSON Message Access Protocol
List-Unsubscribe: ,
List-Archive:
List-Post:
List-Help:
List-Subscribe: ,
X-List-Received-Date: Fri, 09 Feb 2018 11:41:56 -0000
--------------DEF1A268E23D1481DA1CD017
Content-Type: text/plain; charset=utf-8; format=flowed
Content-transfer-encoding: quoted-printable
Hi Neal,
I haven't digested your whole email yet, but a very quick comment about=20
keywords:
On 08/02/2018 06:11, Neil Jenkins wrote:
> *
>
> *keywords*: |String[Boolean]| (default: |{}|) A set of keywords
> that apply to the email. The set is represented as an object, with
> the keys being the /keywords/. The value for each key in the
> object MUST be |true|.
>
> Keywords are shared with IMAP. The six system keywords from IMAP
> are treated specially. The following four keywords have their
> first character changed from |\| in IMAP to |$| in JMAP and have
> particular semantic meaning:
>
> o |$Draft|: The email is a draft the user is composing.
> o |$Seen|: The email has been read.
> o |$Flagged|: The email has been flagged for urgent/special
> attention.
> o |$Answered|: The email has been replied to.
>
> The IMAP |\Recent| keyword is not exposed via JMAP. The IMAP
> |\Deleted| keyword is also not present: IMAP uses a delete+expunge
> model, which JMAP does not. Any message with the |\Deleted|
> keyword MUST NOT be visible via JMAP.
>
> Users may add arbitrary keywords to an email. For compatibility
> with IMAP, a keyword is a (case-sensitive)
>
IMAP keywords are case insensitive. So $MDNSent and $mdnsent are the same.
>
> *
>
> string of 1=E2=80=93255 characters in the ASCII subset %x21=E2=80=93%x=
7e (excludes
> control chars and space), and MUST NOT include any of these
> characters: |( ) { ] % * " \|
>
|Probably not including } and [ as well. But I need to double check.
Best Regards,
Alexey
|
--------------DEF1A268E23D1481DA1CD017
Content-Type: text/html; charset=utf-8
Content-transfer-encoding: quoted-printable
Hi Neal,
I haven't digested your whole email yet, but a very quick comment
about keywords:
On 08/02/2018 06:11, Neil Jenkins wrote:
-
keywords: String[Boolean]
(default: {=
}
)
A set of keywords that apply to the email. The set is
represented as an object, with the keys being the keywords.
The value for each key in the object MUST be true
.<=
br>
Keywords are shared with IMAP. The six system keywords from
IMAP are treated specially. The following four keywords have
their first character changed from \
in IMAP
to $
in JMAP and have particular semantic
meaning:
$Draft
: The email is a draft the user is
composing.
$Seen
: The email has been read.
$Flagged
: The email has been flagged for
urgent/special attention.
$Answered
: The email has been replied to.
The IMAP \Recent
keyword is not exposed via
JMAP. The IMAP \Deleted
keyword is also not
present: IMAP uses a delete+expunge model, which JMAP does
not. Any message with the \Deleted
keyword
MUST NOT be visible via JMAP.
Users may add arbitrary keywords to an email. For
compatibility with IMAP, a keyword is a (case-sensitive)
IMAP keywords are case insensitive. So $MDNSent and $mdnsent are the
same.
Probably not including } and [ as well. But I need to double
check.
Best Regards,
Alexey
--------------DEF1A268E23D1481DA1CD017--
From nobody Fri Feb 9 09:48:08 2018
Return-Path:
X-Original-To: jmap@ietfa.amsl.com
Delivered-To: jmap@ietfa.amsl.com
Received: from localhost (localhost [127.0.0.1]) by ietfa.amsl.com (Postfix) with ESMTP id 879B412D7E7 for ; Fri, 9 Feb 2018 09:48:07 -0800 (PST)
X-Virus-Scanned: amavisd-new at amsl.com
X-Spam-Flag: NO
X-Spam-Score: -1.7
X-Spam-Level:
X-Spam-Status: No, score=-1.7 tagged_above=-999 required=5 tests=[BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, FREEMAIL_FORGED_FROMDOMAIN=0.199, FREEMAIL_FROM=0.001, HEADER_FROM_DIFFERENT_DOMAINS=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_PASS=-0.001] autolearn=no autolearn_force=no
Authentication-Results: ietfa.amsl.com (amavisd-new); dkim=pass (2048-bit key) header.d=gmail.com
Received: from mail.ietf.org ([4.31.198.44]) by localhost (ietfa.amsl.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id bsYPLajZCD8i for ; Fri, 9 Feb 2018 09:48:06 -0800 (PST)
Received: from mail-qt0-x232.google.com (mail-qt0-x232.google.com [IPv6:2607:f8b0:400d:c0d::232]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by ietfa.amsl.com (Postfix) with ESMTPS id 2561A1201F8 for ; Fri, 9 Feb 2018 09:48:06 -0800 (PST)
Received: by mail-qt0-x232.google.com with SMTP id g14so11552317qti.2 for ; Fri, 09 Feb 2018 09:48:06 -0800 (PST)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:sender:in-reply-to:references:from:date:message-id :subject:to:cc:content-transfer-encoding; bh=N4huwTjWHxfh8bgbBfRsm1kaV0JlYjD86/lHp7QAzXI=; b=bHFdAWj26bFpGUpe9XYs8jzU2PuK01b8cr2vEv/uQId+aDLMeryK+IOsO5UMKVdXpy CFEk6WELTrc3Q/IKMbNfqhAtI3SzRft3nFC5fwDGFPkzZ/eSlKmRIAzQM9iLkZMlZlcV a9YGtmWVg/JMSip2vGgnb6H9JObpYEyzcbDy6TqcdLrcOS7Cit/TidVDbHij2K22gVtk FVlXL72QLIzZNPNIH320GgLKbGajBx58MawEf1Fr5OjRj4JnVFip08oQygCVgSeBI/3S aEZX9d488l7FAxvFSoAjH+PMuDUdWQU1hjaBMk4CPkAR03xzDCZpDeNt4GJw04iRdaNE qY0g==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:sender:in-reply-to:references:from :date:message-id:subject:to:cc:content-transfer-encoding; bh=N4huwTjWHxfh8bgbBfRsm1kaV0JlYjD86/lHp7QAzXI=; b=rnnaxHpt/GR4/BJnYVheG2iCwVg2aLh0Gd9C89BUKgZkXR6tErcNMBnysmepqi8CtH ddW44zGDLvUpOo9y/USwahZsZ/RGYG5dNZbGBOwBgqvG0FQFLsB3uczXZXeX0uzzHlpz zfTrET7UahuvmEZ9X3qfBwoRtnMVIed5G6O3rsh3dGs0TnhNR5c0KWCv1zuGDY/RylJi g5/fwFlsG8xX0am22RxJ+WTAWcVToJap1ancFSVQiww6hHe4fDpkoS+Ipm5TKGwOHnKF 4lcIe0i/20zhk2tKPA0hCVoAq3mNGdXS19wx5nh8wTF/YUEFJvskvhTn0XoA6mjF2IpB Bsyw==
X-Gm-Message-State: APf1xPDgQIL1ivHYMJctA8RKV9wN13cKaNQSwq0rw9qNZRbB41KnWI4+ sc8+8MTbM8P2uSPwU4FnoCraybDEXDRXBJ81uvA=
X-Google-Smtp-Source: AH8x227etsSidePRjKWB6S9wI5lZ27NAiefH3YITYskNFK4GHb6f0XqNk3K6Xyu/kNclKVLUyb3WO5/fjR5AGsgFDrY=
X-Received: by 10.200.56.162 with SMTP id f31mr864773qtc.9.1518198485316; Fri, 09 Feb 2018 09:48:05 -0800 (PST)
MIME-Version: 1.0
Sender: barryleiba.mailing.lists@gmail.com
Received: by 10.200.35.199 with HTTP; Fri, 9 Feb 2018 09:48:04 -0800 (PST)
In-Reply-To: <0bb7d2f4-bcba-86ea-12f7-43a59a2f951e@isode.com>
References: <1518070284.168650.1263633200.05C7397A@webmail.messagingengine.com> <0bb7d2f4-bcba-86ea-12f7-43a59a2f951e@isode.com>
From: Barry Leiba
Date: Fri, 9 Feb 2018 12:48:04 -0500
X-Google-Sender-Auth: b_8EvIa0dRz32ASjQdd3OSjpdZ0
Message-ID:
To: Alexey Melnikov
Cc: Neil Jenkins , IETF JMAP Mailing List
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
Archived-At:
Subject: Re: [Jmap] New JSON message representation
X-BeenThere: jmap@ietf.org
X-Mailman-Version: 2.1.22
Precedence: list
List-Id: JSON Message Access Protocol
List-Unsubscribe: ,
List-Archive:
List-Post:
List-Help:
List-Subscribe: ,
X-List-Received-Date: Fri, 09 Feb 2018 17:48:07 -0000
>> string of 1=E2=80=93255 characters in the ASCII subset %x21=E2=80=93%x7e=
(excludes control
>> chars and space), and MUST NOT include any of these characters:
>> ( ) { ] % * " \
>
> Probably not including } and [ as well. But I need to double check.
According to the IMAP grammar, that's the complete list: } and [ are
not forbidden in IMAP.
b
From nobody Fri Feb 9 11:08:34 2018
Return-Path:
X-Original-To: jmap@ietfa.amsl.com
Delivered-To: jmap@ietfa.amsl.com
Received: from localhost (localhost [127.0.0.1]) by ietfa.amsl.com (Postfix) with ESMTP id D36BF12D7EC for ; Fri, 9 Feb 2018 11:08:32 -0800 (PST)
X-Virus-Scanned: amavisd-new at amsl.com
X-Spam-Flag: NO
X-Spam-Score: -2.031
X-Spam-Level:
X-Spam-Status: No, score=-2.031 tagged_above=-999 required=5 tests=[BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, RCVD_IN_MSPIKE_H4=-0.01, RCVD_IN_MSPIKE_WL=-0.01, SPF_PASS=-0.001, T_RP_MATCHES_RCVD=-0.01] autolearn=ham autolearn_force=no
Authentication-Results: ietfa.amsl.com (amavisd-new); dkim=pass (2048-bit key) header.d=oracle.com
Received: from mail.ietf.org ([4.31.198.44]) by localhost (ietfa.amsl.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 4V9F4rKPQmT9 for ; Fri, 9 Feb 2018 11:08:30 -0800 (PST)
Received: from aserp2120.oracle.com (aserp2120.oracle.com [141.146.126.78]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ietfa.amsl.com (Postfix) with ESMTPS id B4EFD12D7E9 for ; Fri, 9 Feb 2018 11:08:30 -0800 (PST)
Received: from pps.filterd (aserp2120.oracle.com [127.0.0.1]) by aserp2120.oracle.com (8.16.0.22/8.16.0.22) with SMTP id w19J7JdJ110376; Fri, 9 Feb 2018 19:08:26 GMT
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oracle.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-type; s=corp-2017-10-26; bh=vPeTqmSBzsL7kT2cgxb/Le8mVGaGXnm4KPh0VJCi0zg=; b=a6scWEw28LL3Z2/FKGr8npHpOo25fEGBzIXHkV5NB31E6StwdZkjQp3sKAHAdk5w8E48 9tQvWuS1FqiC2i3db9V2sTmtrY2FoYUYp0e0fwHKMhPxdB4c4WDKxm9Ww8T5fr5ULx+o OdEF2goLwqilF1D6fA6mw0qIUsSYjKgyTL2PPxTxCEKBReXnPzRqy8Sk2wTBMneAZkM6 KeHgcEni07DL9crYG0m+quevTCY2yGnEv26ATEPNX64a3oiuMIlm3WroP4/SuXpVwb6P zYeiwFhWGhlp+Cd9lj1yqGBl0sqnWR40/JvYyyIZ/p2BiYkQyGytUaLQ120E/UFPIaZK 2Q==
Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by aserp2120.oracle.com with ESMTP id 2g1gyy05en-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 09 Feb 2018 19:08:26 +0000
Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by aserv0021.oracle.com (8.14.4/8.14.4) with ESMTP id w19J8Pt2007153 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Fri, 9 Feb 2018 19:08:25 GMT
Received: from abhmp0005.oracle.com (abhmp0005.oracle.com [141.146.116.11]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id w19J8Ots006869; Fri, 9 Feb 2018 19:08:24 GMT
Received: from [10.145.239.148] (/10.145.239.148) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Fri, 09 Feb 2018 11:08:24 -0800
From: "Chris Newman"
To: "Neil Jenkins"
Cc: "IETF JMAP Mailing List"
Date: Fri, 09 Feb 2018 11:08:22 -0800
X-Mailer: MailMate (1.10r5443)
Message-ID: <500E0B79-200E-4DFA-939A-C3419559743E@oracle.com>
In-Reply-To: <1518070284.168650.1263633200.05C7397A@webmail.messagingengine.com>
References: <1518070284.168650.1263633200.05C7397A@webmail.messagingengine.com>
MIME-Version: 1.0
Content-Type: text/plain; format=flowed
X-Proofpoint-Virus-Version: vendor=nai engine=5900 definitions=8800 signatures=668666
X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 suspectscore=0 malwarescore=0 phishscore=0 bulkscore=0 spamscore=0 mlxscore=0 mlxlogscore=999 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1711220000 definitions=main-1802090242
Archived-At:
Subject: Re: [Jmap] New JSON message representation
X-BeenThere: jmap@ietf.org
X-Mailman-Version: 2.1.22
Precedence: list
List-Id: JSON Message Access Protocol
List-Unsubscribe: ,
List-Archive:
List-Post:
List-Help:
List-Subscribe: ,
X-List-Received-Date: Fri, 09 Feb 2018 19:08:33 -0000
Overall I'm supportive of this approach. Detailed comments:
I concur with Alexey's comment about keywords being case-insensitive.
On 7 Feb 2018, at 22:11, Neil Jenkins wrote:
> * *size*: Number (immutable; server-set) The size in bytes of the
> whole
> email as counted by the server towards the user's quota.
The problem with a quota-based size measurement is "0" is a reasonable
answer for single-copy message stores that allow multiple Email objects
that refer to the same message (particularly if a reference to the
message in a trash folder is not the only reference). Also, some number
substantially less than what the user might want to see in a UI is
possible in a single-attachment-copy mail store where each attachment is
charged only once against the user's quota.
One option is to define *size* as the RFC822 size of the message (same
definition as IMAP RFC 3501). Another option is that *size* is a number
that would be appropriate to display to a user representing the size of
the message content and attachments. This allows use of RFC 5322 size,
RFC 6532 size or a binary MIME variation of either.
> * *receivedAt*: UTCDate (immutable; default: time of creation on
> server) The date the email was received by the message store. This
> is
> the *internal date* in IMAP.Header fields
I note the IMAP APPEND command allows this to be client-specified. This
is very useful in practice when migrating mail between mail stores. The
date the user really wants is when the mail first entered a mailstore
owned by the user (or operated on behalf of the user). The date when the
mail first entered this particular mailstore is less useful to the end
user.
> These properties are derived from the [@!RFC5322] message header
> fields.
It's also fine to allow [@!RFC6532] message header fields, I believe.
> Header fields may be fetched in a variety of forms:
>
>
> * *Decoded* The header field value with:
>
>
> 1. White space unfolded (as defined in [@!RFC5322] section 2.2.3)
> 2. The terminating CRLF at the end of the value removed
> 3. Any SP characters at the beginning of the value removed
> 4. Any [@!RFC2047] encoded sections decoded
This is a security design error. I suggest:
Any syntactically correct [@!RFC2047] encoded sections with a known
character set are decoded and re-encoded as a UTF-8 string with proper
quoting and escaping for the active RFC 5322 syntactic context
appropriate for the specific header field. Any [@!RFC2047] encoded NUL
octets or control characters are dropped from the decoded value. Any
text that looks like [@!RFC2047] syntax but violates [@!RFC2047]
placement or whitespace rules MUST NOT be decoded. Any [@!RFC2047]
content in an unrecognized header MUST NOT be decoded. Same rules apply
to [@!RFC2231] decoding.
The alternative is to not do 2047/2231 decoding for *decoded* form, or
only do it for unstructured headers like Subject & Content-Description.
> 5. Any [@!RFC6532] UTF-8 values decoded If any decodings fail, the
> parser SHOULD insert a unicode replacement character (U+FFFD)
> and
> attempt to continue as much as possible.
We might also want to add 6. require the server to convert denormalized
Unicode to NFC. This is easy enough for a server to do and makes it
easier for clients to comply with RFC 5198.
> * *Raw Base64* The raw bytes of the header field value from the first
> byte following the header field name terminating colon, up to but
> excluding the header field terminating CRLF, encoded as Base64
> ([@!RFC4648]). (Note, this is required as the value may not be
> valid
> UTF-8 if 8-bit values are present.)
Are non-UTF-8 headers so prevalent that it merits corruption of JMAP?
There has never been a standard allowing non-UTF-8 content with the
high-bit set in email headers. I think it's fine to drop (or use Unicode
replacement character) for any octet or octet run with the high bit set
that violates UTF-8 syntax. Avoiding the unnecessary base64 step will
simplify clients. NUL octets should also be dropped, although most mail
stores will drop them on ingress since they became illegal in generated
email on April 2001.
> * *Addresses* The header is parsed as an address-list value, as
> specified in [@!RFC5322] section 3.4, into the EmailAddress[] type.
> The *EmailAddress* object has the following properties:
>
>
> * *name*: String|null The *display name* of the [@!RFC5322]
> *mailbox*
> or *group*, or null if none.
It's important for 2047 decoding (as described previously) to be applied
to this when possible.
> * *email*: String|null The *addr-spec* of the [@!RFC5322]
> *mailbox*,
> or null if a *group*. Parsing SHOULD be best-effort in the face
> of
> invalid structure to accommodate invalid messages and
> semi-complete
> drafts. EmailAddress objects MAY have an *email* property that
> does
> not conform to the *addr-spec* form (for example, may not contain
> an @ symbol).
Should this allow non-punycode IDN? Should this allow RFC 6532?
> * *name*: String|null This is the [@!RFC2231] decoded *filename*
> parameter of the *Content-Disposition* header field, or (for
> compatibility with existing systems) if not present then the
> [@!RFC2047] decoded *name* property of the *Content-Type* header
> field. For compatibility with the widest array of existing systems,
> both forms should be set if creating a message.
I think this is the wrong place to include rules for generating email. I
note that setting a "name" parameter on a MIME content type which
doesn't explicitly register a "name" parameter is a violation of the
MIME model. Advice to violate the model may be fine as an implementation
suggestion, but I wouldn't make it a standards-level recommendation.
> * *type*: String The value of the *Content-Type* header field of the
> part, excluding any parameters.
Should this have CFWS removed? I think it should.
> * *bodyStructure*: EmailBodyPart[] (immutable) This is the full MIME
> structure of the message body, including sub parts but not
> recursing
> into message/rfc822 parts.
make that "message/rfc822 or message/global parts."
> * *value*: String The value of the body part after decoding
> *Content-
> Transport* encoding and decoding the *Content-Type* charset.
I think you mean *Content-Transfer-Encoding*, and decoding it is fine.
Decoding the charset unconditionally in this way violates the MIME model
as the charset parameter has no strictly defined meaning outside the
top-level text media-type.
I think there are three design options here:
1. CTE only
2. CTE, plus charset decoding of text/ and other recognized media types
the server knows have a registered and defined meaning for charset.
3. allow the server to be helpful and briefly describe what it did.
If you choose option 3, I'd add a third "decodingKind" field to
EmailBodyValue that explains the value. It could be:
*decodingKind*
This is an enumerated type indicating what decoding the server applied
to the content. I suggest the following options:
*text*: The server decoded any content-transfer-encoding, recognized the
declared media type as a textual type (regardless of whether it's a
"text/" or "application/" media type), correctly interpreted the charset
according to that media type's documented rules and converted it to
UTF-8. No NUL code points were found in the content.
*UTF8*: The server decoded any content-transfer-encoding and determined
that the content follows UTF-8 syntax and contains no NUL octets. This
is never used on standards-compliant body parts with a top-level text
type. However, if a body part with a top-level text type contains
non-ASCII UTF-8 content and has no charset parameter (a violation of RFC
2046), this may be used.
*base64*: The server decoded any content-transfer-encoding but the
resulting content contains a NUL octet or does not meet UTF-8 syntax
rules, the value will be base64-encoded without additional modification.
*heuristic*: The server applied some heuristic to convert the content
charset to UTF-8 text (and no NUL code points were found). For example,
the server looked at the magic number in an application/octet-stream and
identified the content as a structured textual type with a known charset
that could be converted to UTF-8. This may also be used, for example, if
the charset media type parameter does not match a charset attribute in
HTML/XML but the content matches the latter parameter.
> * *attachedEmails*: EmailBodyPart[] (immutable) A list of all parts
> of
> type message/rfc822. Note, this *does not* recurse, so the parts
or type message/global.
> * The *attachedFiles* list contains at least one item that does not
> have Content-Disposition: attachment. The server MAY ignore parts
I think you mean "Content-Disposition: inline".
- Chris
From nobody Sun Feb 11 20:08:34 2018
Return-Path:
X-Original-To: jmap@ietfa.amsl.com
Delivered-To: jmap@ietfa.amsl.com
Received: from localhost (localhost [127.0.0.1]) by ietfa.amsl.com (Postfix) with ESMTP id 7C444124207 for ; Sun, 11 Feb 2018 20:08:32 -0800 (PST)
X-Virus-Scanned: amavisd-new at amsl.com
X-Spam-Flag: NO
X-Spam-Score: -2.72
X-Spam-Level:
X-Spam-Status: No, score=-2.72 tagged_above=-999 required=5 tests=[BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, HTML_MESSAGE=0.001, RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, SPF_PASS=-0.001] autolearn=ham autolearn_force=no
Authentication-Results: ietfa.amsl.com (amavisd-new); dkim=pass (2048-bit key) header.d=fastmailteam.com header.b=M2CTwsxn; dkim=pass (2048-bit key) header.d=messagingengine.com header.b=C9JiiHS6
Received: from mail.ietf.org ([4.31.198.44]) by localhost (ietfa.amsl.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id nXTKadeGZ4gE for ; Sun, 11 Feb 2018 20:08:28 -0800 (PST)
Received: from out2-smtp.messagingengine.com (out2-smtp.messagingengine.com [66.111.4.26]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by ietfa.amsl.com (Postfix) with ESMTPS id 55E851205F0 for ; Sun, 11 Feb 2018 20:08:28 -0800 (PST)
Received: from compute6.internal (compute6.nyi.internal [10.202.2.46]) by mailout.nyi.internal (Postfix) with ESMTP id 8F70520D3A for ; Sun, 11 Feb 2018 23:08:27 -0500 (EST)
Received: from web5 ([10.202.2.215]) by compute6.internal (MEProxy); Sun, 11 Feb 2018 23:08:27 -0500
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= fastmailteam.com; h=content-transfer-encoding:content-type:date :from:in-reply-to:message-id:mime-version:references:subject:to :x-me-sender:x-me-sender:x-sasl-enc; s=fm1; bh=JMwQBJVO8lHpW2i6H PNhDAGikyL5V9u55JVPF5JcVlw=; b=M2CTwsxnaxDHBYCc4EFbRmUan0ay3BUu8 K2murlilnCXNbafaKiPJxr+Z0cFB+cjt9VG/MUX6h2K7qd8jZKPTOllAbePhdEMN l4Ne093Iqju3p2OM8fMG76dnxQs7wDursXjJi4PyNCSrkliNVzRH3E0tzPTVEiBc DJv3i/ye09Q3yfxIbtHjtZ8sEtOaiMz9J7MGdAxhnRHf4mAdnupX6pzHP9tQc7N8 6RHmXYQ4pbRZEpNrgEOJShMURVYdiKuI1zeK5krlclSGKsI3sFuDNiT2tXxc31pf Rp17lR0GfIv4n6ASyOGoEVOozaE/XADx0scJEsi2yrfejvA++SezA==
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=content-transfer-encoding:content-type :date:from:in-reply-to:message-id:mime-version:references :subject:to:x-me-sender:x-me-sender:x-sasl-enc; s=fm2; bh=JMwQBJ VO8lHpW2i6HPNhDAGikyL5V9u55JVPF5JcVlw=; b=C9JiiHS6xVYQRfolXf5kRa YMZovte/Noo2mihO3/SEavQSlKB9Piyxu7D+iuYAoSRmBsB2rsMLCEN37rn3w8D0 EQQZmLFmJqc8Yucd5eI+MR5JBut1z8J8BX7zts3/yK5ZKxW/0aDRRl8ye/mfsQpA O2HyPsi6zwjfvFYgoMC62JKUn3gpDLhh63Z5muzcFwrMlU/eQdWugEXP8tYJ3s/o 0zCJi1IBvwJ8gqdRM14G8l1kxp2nYzFvVUwg4erT+rxsehDt0Sk84wdkO3vx6l2o I6x9V22p/8Nri5mRmacpozxAApq33Ng7/UxoxEbzc3XrpO64JMwjexSGj+IZWCmA ==
X-ME-Sender:
Received: by mailuser.nyi.internal (Postfix, from userid 99) id 253029E0D3; Sun, 11 Feb 2018 23:08:27 -0500 (EST)
Message-Id: <1518408506.1699741.1267466096.17DCF605@webmail.messagingengine.com>
From: Bron Gondwana
To: jmap@ietf.org
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Type: multipart/alternative; boundary="_----------=_151840850716997411"
X-Mailer: MessagingEngine.com Webmail Interface - ajax-fde26eb3
References: <1518070284.168650.1263633200.05C7397A@webmail.messagingengine.com>
In-Reply-To: <1518070284.168650.1263633200.05C7397A@webmail.messagingengine.com>
Date: Mon, 12 Feb 2018 15:08:26 +1100
Archived-At:
Subject: Re: [Jmap] New JSON message representation
X-BeenThere: jmap@ietf.org
X-Mailman-Version: 2.1.22
Precedence: list
List-Id: JSON Message Access Protocol
List-Unsubscribe: ,
List-Archive:
List-Post:
List-Help:
List-Subscribe: ,
X-List-Received-Date: Mon, 12 Feb 2018 04:08:32 -0000
This is a multi-part message in MIME format.
--_----------=_151840850716997411
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset="utf-8"
On Thu, 8 Feb 2018, at 17:11, Neil Jenkins wrote:
> With an eye to closing off all remaining issues before the next IETF
> meeting in March, I have been looking at the issues raised with the
> JSON representation of an RFC5322 message. This email presents a new
> proposal that I think resolves the issues presented. In particular, I
> aim to address the following goals:
> * Allow access to the full MIME structure without requiring the
> client to parse the full message itself.
> * Allow access to full header field information if required.
> * Keep a simpler representation available for the common case.
> * Allow the client to only load the data required.> Comments, suggestion=
s and other feedback requested. Cheers!
Sorry, saw this on my phone for the first read-through, so I didn't
reply. I see Chris already caught some of this, but I'll do my read-
through again and reply as well.
> ------
> Emails
> The *Email* object is a representation of an [@!RFC5322] message,
> which allows clients to avoid the complexities of MIME parsing,
> transport encoding and character encoding.> Properties of the Email object
> Broadly, a message consists of two parts: a list of header fields,
> then a body. The body is normally a MIME-encoded set of documents in a
> tree structure. The JMAP Email object provides a way to access the
> full structure, or to use simplified properties and avoid some
> complexity if this is sufficient for the client application.> Due to the =
number of properties involved, the set of *Email*
> properties is specified over the following three sub-sections.> Metadata
> These properties represent metadata about the [@!RFC5322] message, and
> are not derived from parsing the message itself.
> * *id*: String (immutable; server-set) The id of the Email object.
> Note, this is the JMAP object id, NOT the [@!RFC5322] Message-Id
> header field value.
> * *blobId*: String (immutable; server-set) The id representing the
> raw bytes of the [@!RFC5322] message. This may be used to download
> the raw original message, or to attach it directly to another
> Email etc.
> * *threadId*: String (immutable; server-set) The id of the Thread to
> which this Email belongs.
> * *mailboxIds*: String[Boolean] The set of mailbox ids this email
> belongs to. An email MUST belong to one or more mailboxes at all
> times (until it is deleted). The set is represented as an object,
> with each key being a *Mailbox id*. The value for each key in the
> object MUST be true.
> * *keywords*: String[Boolean] (default: {}) A set of keywords that
> apply to the email. The set is represented as an object, with the
> keys being the *keywords*. The value for each key in the object
> MUST be true.
> Keywords are shared with IMAP. The six system keywords from IMAP are
> treated specially. The following four keywords have their first
> character changed from \ in IMAP to $ in JMAP and have particular
> semantic meaning:
> * $Draft: The email is a draft the user is composing.
> * $Seen: The email has been read.
> * $Flagged: The email has been flagged for urgent/special
> attention.
> * $Answered: The email has been replied to. The IMAP \Recent
> keyword is not exposed via JMAP. The IMAP \Deleted keyword is
> also not present: IMAP uses a delete+expunge model, which JMAP
> does not. Any message with the \Deleted keyword MUST NOT be
> visible via JMAP.
> Users may add arbitrary keywords to an email. For compatibility with
> IMAP, a keyword is a (case-sensitive) string of 1=E2=80=93255 characters =
in
> the ASCII subset %x21=E2=80=93%x7e (excludes control chars and space), and
> MUST NOT include any of these characters: ( ) { ] % * " \
> The IANA Keyword Registry[1] as established in [@!RFC5788] assigns
> semantic meaning to some other keywords in common use. New keywords
> may be established here in the future. In particular, note:
> * $Forwarded: The email has been forwarded.
> * $Phishing: The email is highly likely to be phishing. Clients
> SHOULD warn users to take care when viewing this email and
> disable links and attachments.
> * $Junk: The email is definitely spam. Clients SHOULD set this flag
> when users report spam to help train automated spam-detection
> systems.
> * $NotJunk: The email is definitely not spam. Clients SHOULD set
> this flag when users indicate an email is legitimate, to help
> train automated spam-detection systems.
did we want to talk about $HasAttachment and friend as well?
> * *size*: Number (immutable; server-set) The size in bytes of the
> whole email as counted by the server towards the user's quota.
I noticed this inconsistency as well - matching blobId size is by far
the most useful thing to do here.
> * *receivedAt*: UTCDate (immutable; default: time of creation on
> server) The date the email was received by the message store. This
> is the *internal date* in IMAP.> Header fields
> These properties are derived from the [@!RFC5322] message header
> fields. Header fields may be fetched in a variety of forms:
> * *Decoded* The header field value with:
> 1. White space unfolded (as defined in [@!RFC5322] section 2.2.3)
> 2. The terminating CRLF at the end of the value removed
> 3. Any SP characters at the beginning of the value removed
> 4. Any [@!RFC2047] encoded sections decoded
> 5. Any [@!RFC6532] UTF-8 values decoded If any decodings fail, the
> parser SHOULD insert a unicode replacement character (U+FFFD)
> and attempt to continue as much as possible.
> * *Raw Base64* The raw bytes of the header field value from the first
> byte following the header field name terminating colon, up to but
> excluding the header field terminating CRLF, encoded as Base64
> ([@!RFC4648]). (Note, this is required as the value may not be
> valid UTF-8 if 8-bit values are present.)
> * *Addresses* The header is parsed as an address-list value, as
> specified in [@!RFC5322] section 3.4, into the EmailAddress[] type.
> The *EmailAddress* object has the following properties:
> * *name*: String|null The *display name* of the [@!RFC5322]
> *mailbox* or *group*, or null if none.
> * *email*: String|null The *addr-spec* of the [@!RFC5322]
> *mailbox*, or null if a *group*.
I don't know enough about the group syntax, but I thought it was
nestable in a way that makes it hard to flatten. Maybe just a null
group is enough, but the example in RFC5322 shows a group with 3
addresses in it:
Appendix A.1.3[2]. Group Addresses ---- From: Pete
To: A Group:Ed Jones ,joe@where.test,John
; Cc: Undisclosed recipients:; Date: Thu, 13 Feb 1969
23:32:54 -0330 Message-ID: Testing. ----
In this message, the "To:" field has a single group recipient named "A
Group", which contains 3 addresses, and a "Cc:" field with an empty
group recipient named Undisclosed recipients.And I have a horrible sinking =
feeling that the group could contain
nested groups in the full RFC5322 syntax, meaning you could have an
arbitrarily deep tree of addresses.
> * Parsing SHOULD be best-effort in the face of invalid structure to
> accommodate invalid messages and semi-complete drafts. EmailAddress
> objects MAY have an *email* property that does not conform to the
> *addr-spec* form (for example, may not contain an @ symbol).
> * *Date* The header is parsed as a date-time value, as specified in
> [@!RFC5322] section 3.3, into the Date type.> The following *Email* pr=
operties are specified for complete access to
> the header data of the message. Where {header-field-name} is specified
> within a property name, this means any series of one or more printable
> US-ASCII characters (i.e. characters that have values between 33 and
> 126, inclusive), except colon:
> * *headers*: EmailHeader[] (immutable) This is a list of all
> [@!RFC5322] header fields, in the same order they appear in the
> message. The values are in *Decoded* form.
> * *headers:asRaw*: EmailHeader[] (immutable) This is a list of all
> [@!RFC5322] header fields, in the same order they appear in the
> message. The values are in *Raw Base64* form.
> * *header:{header-field-name}*: String|null (immutable) The value of
> the *last* header field in the message with the given header field
> name (matched case-insensitively), or null if none. The value is in
> *Decoded* form.
This does seem to mean that it's impossible to ask for all instances of
a particular named header. You either get the whole lot, or you get
just the last of a particular named one. I don't know that it's likely
to be a big problem, but I do note the limitation.
> * *header:{header-field-name}:asRaw*: String|null (immutable) The
> value of the *last* header field in the message with the given
> header field name (matched case-insensitively), or null if none.
> The value is in *Raw Base64* form.
> * *header:{header-field-name}:asAddresses*: EmailAddress[]|null
> (immutable) The value of the *last* header field in the message
> with the given header field name (matched case-insensitively), or
> null if none. The value is in *Addresses* form.
> * *header:{header-field-name}:asDate*: Date|null (immutable) The
> value of the *last* header field in the message with the given
> header field name (matched case-insensitively), or null if none.
> The value is in *Date* form.> An *EmailHeader* object has the followin=
g properties:
> * *name*: String The header *field name* as defined in RFC5322, with
> the same capitalization that it has in the message.
> * *value*: String The header *field value* as defined in RFC5322, in
> either *Decoded* or *Raw Base64* form as determined by the property
> being fetched.> The following convenience properties are also specifie=
d for the
> *Email* object:
> * *sender*: EmailAddress[]|null (immutable) The value is identical to
> the value of *header:Sender:asAddresses*.
> * *from*: EmailAddress[]|null (immutable) The value is identical to
> the value of *header:From:asAddresses*.
> * *to*: EmailAddress[]|null (immutable) The value is identical to the
> value of *header:To:asAddresses*.
> * *cc*: EmailAddress[]|null (immutable) The value is identical to the
> value of *header:Cc:asAddresses*.
> * *bcc*: EmailAddress[]|null (immutable) The value is identical to
> the value of *header:Bcc:asAddresses*.
> * *replyTo*: EmailAddress[]|null (immutable) The value is identical
> to the value of *header:Reply-To:asAddresses*.
> * *subject*: String|null (immutable) The value is identical to the
> value of *header:Subject*.
> * *sentAt*: Date (immutable; default: time of creation on server) The
> value is identical to the value of *header:Date:asDate*.> Body parts
> These properties are derived from the [@!RFC5322] message body and its
> [@RFC2045] MIME entities.> A *EmailBodyPart* object has the following pro=
perties:
> * *partId*: String Identifies this part uniquely within the Email.
> This is scoped to the *emailId* and has no meaning outside of the
> JMAP Email object representation.
> * *blobId*: String The id references the raw bytes of the contents of
> the part after decoding any *Content-Transfer* encoding (as defined
> in [@!RFC2045]). Note, two parts may be transfer-encoded
> differently but have same the same blob id if their decoded bytes
> are identical and the server is using a secure hash of the data for
> the blob id.
> * *size*: Number The size, in bytes, of the raw data after content-
> transfer decoding (as refrenced by the *blobId*, i.e. the number of
> bytes in the file the user would download).
> * *headers*: EmailHeader[] (immutable) This is a list of all header
> fields in the part, in the order they appear. The values are in
> *Decoded* form.
> * *headers:asRaw*: EmailHeader[] (immutable) This is a list of all
> header fields in the part, in the order they appear. The values are
> in *Raw Base64* form.
> * *name*: String|null This is the [@!RFC2231] decoded *filename*
> parameter of the *Content-Disposition* header field, or (for
> compatibility with existing systems) if not present then the
> [@!RFC2047] decoded *name* property of the *Content-Type* header
> field. For compatibility with the widest array of existing systems,
> both forms should be set if creating a message.
> * *type*: String The value of the *Content-Type* header field of the
> part, excluding any parameters.
> * *charset*: String|null The value of the charset parameter of the
> *Content-Type* header field, if present.
> * *disposition*: String|null The value of the *Content-Disposition*
> header field of the part, excluding any parameters, if present.
> * *cid*: String|null The value of the *Content-Id* header field of
> the part, if present. This may be used to reference the content
> from within an html body part using the cid: protocol.
> * *language*: String[]|null The list of language tags, as defined in
> [@!RFC3282], in the *Content-Language* header field of the part, if
> present.
> * *location*: String|null The URI, as defined in [@!RFC2557], in the
> *Content-Location* header field of the part, if present.
> * *width*: Number|null The width (in px) of the image, if the type is
> an image and the server is able to determine this information for
> the image. This MAY not be supported for all or any image types on
> some servers.
> * *height*: Number|null The height (in px) of the image, if the type
> is an image and the server is able to determine this information
> for the image. This MAY not be supported for all or any image types
> on some servers.
> * *subParts*: EmailBodyPart[] (optional) If type is multipart/*, this
> contains the body parts of each child.> The following *Email* properti=
es are specified for access to the body
> data of the message:
> * *bodyStructure*: EmailBodyPart[] (immutable) This is the full MIME
> structure of the message body, including sub parts but not
> recursing into message/rfc822 parts.
> * *bodyValues*: String[BodyValue] (immutable) This is a map of
> *partId* to an *EmailBodyValue* object. Which parts are included
> and whether the value is truncated is determined by various
> arguments to *Email/get* and *Email/parse*.
> An *EmailBodyValue* object has the following properties:
> * *value*: String The value of the body part after decoding *Content-
> Transport* encoding and decoding the *Content-Type* charset.
> * *isTruncated* Boolean This is true if the *value* has been
> truncated.
> * *textBody*: EmailBodyPart[] (immutable) A list of text/plain,
> text/html and image/* parts to display (sequentially) as the
> message body, with a preference for text/plain when alternative
> versions are available.
> * *htmlBody*: EmailBodyPart[] (immutable) A list of text/plain,
> text/html and image/* parts to display (sequentially) as the
> message body, with a preference for text/html when alternative
> versions are available.
There was some discussion about how to handle RFC 8255
multipart/multilingual or other things here - whether we add something
along the lines of "the server will choose which representation to
include based on the original language plus what it knows about the
user's preferred language" - plus of course the full information is
available in the bodyStructure if the client wants to be smart about it.
This is also a good place for a JMAP extension which could give a more
powerful query language for choosing specific parts in multipart.
> * *attachedEmails*: EmailBodyPart[] (immutable) A list of all parts
> of type message/rfc822. Note, this *does not* recurse, so the parts
> within these are not included. The attached message may be fetched
> using the Email/parse method and the blobId.
Might be worth having an example of this - it's going to be one of the
tricky bits for people to understand.
> * *attachedFiles*: EmailBodyPart[] (immutable) A list of all parts in
> *bodyStructure*, traversing depth-first, not of type multipart/*,
> and not included in any of the *textBody*, *htmlBody* or
> *attachedEmails* properties. Note, an HTML body part may reference
> image parts in attachedFiles using cid: links to reference the *Conten=
t-
> Id* or by referencing the *Content-Location*.
This could do with being a little clearer that "even if referenced by an
HTML body part, attached files will be included in this list" - or
something like that.
> * *hasAttachment*: Boolean (immutable; server-set) This is true if
> there are one or more parts in the message that a client UI should
> offer as downloadable. A server SHOULD set hasAttachment if either:
> * The *attachedEmails* list contains at least one item.
> * The *attachedFiles* list contains at least one item that does not
> have Content-Disposition: attachment. The server MAY ignore parts
> in this list that are processed automatically in some way, or are
> referenced as embedded images in one of the text/html parts of
> the message.
It's already been noted that the logic is reversed here, should be "does
have" or maybe even "does not have Content-Disposition: inline" instead.
> * The server MAY set hasAttachment based on implementation-defined or
> site configurable heuristics.
> * *preview*: String (immutable; server-set) Up to 256 characters of
> the beginning of a plain text version of the message body. This is
> intended to be shown as a preview line on a mailbox listing, and
> the server may choose to skip quoted sections or salutations to
> return a more useful preview.
I wouldn't even say "of the beginning" - it's up to 256 characters
that provide a good summary of the content of the message. I would
say something like: This is intended to be shown as a preview line on
a mailbox listing, and not all characters may be shown. The server
may choose which part of the message to include in the preview, for
example skipping quoted sections and salutations can result in a more
useful preview.
> MIME structures are arbitrary nested trees of documents, but the
> majority of email clients present a model of an email body (normally
> plain text or HTML), with a set of attachments. Interpreting the MIME
> structure to form this flat model represents considerable difficulty
> and causes inconsistency between clients. Therefore in addition to the
> *bodyStructure* property, which gives the full tree, the Email object
> contains 4 alternate properties with flat lists of body parts:
> * *textBody*/*htmlBody*: These provide a list of parts that should be
> rendered as the "body" of the message. This is a list rather than a
> single part as messages may have headers and/or footers
> appended/prepended as separate parts as they are transmitted, and
> some clients send text and images intended to be displayed inline
> in the body as multiple parts rather than a single HTML part with
> referenced images.
> Because MIME allows for multiple representations of the same data
> (using multipart/alternative), there is a textBody property (which
> prefers a plain text representation) and an htmlBody property (which
> prefers an HTML representation) to accommodate the two most common
> client requirements. The same part may appear in both lists where
> there is no alternative between the two.
> * *attachedEmails*/*attachedFiles*: These provide a list of parts
> that should be presented as "attachments" to the message. Emails
> are presented in a separate list so their contents may be easily
> fetched via a back-reference with the Email/parse method in the
> same request, if the client wishes to. Some images in attachedFiles
> may be solely there for embedding within an HTML body part; clients
> may wish to not present these as attachments in the user interface
> if they are displaying the HTML with the embedded images directly.> Th=
e *bodyValues* property allows for clients to fetch the value of
> text parts directly without having to do a second request for the
> blob, and have the server handle decoding the charset into unicode.
> This data is in a separate property rather than on the EmailBodyPart
> object to avoid duplication of large amounts of data, as the same part
> may be included twice if the client fetches more than one of
> bodyStructure, textBody and htmlBody.> The exact algorithm for decomposin=
g bodyStructure into textBody,
> htmlBody, attachedEmails and attachedFiles part lists is not mandated,
> as this is a quality-of-service implementation issue and likely to
> require workarounds for malformed content discovered over time.> However,=
we will define a suggested algorithm for the RFC to help
> implementors. TODO.> Email/get
> Standard */get* method, with the following additional arguments:
> * *bodyProperties*: String[] (optional) A list of properties to fetch
> for each EmailBodyPart returned. If omitted, this defaults to:
> [ "partId", "blobId", "size", "name", "type", "charset",
> "disposition", cid", "language", "location", "width", "height" ]
> * *fetchTextBodyValues*: Boolean (default: false) If true, the
> *bodyValues* property includes any text/* part in the textBody
> property.
> * *fetchHTMLBodyValues*: Boolean (default: false) If true, the
> *bodyValues* property includes any text/* part in the htmlBody
> property.
> * *fetchAllBodyValues*: Boolean (default: false) If true, the
> *bodyValues* property includes any text/* part in the bodyStructure
> property.
> * *maxBodyValueBytes*: Number (optional) If supplied by the client,
> the value MUST be a positive integer greater than 0. If a value
> outside of this range is given, the server MUST reject the call
> with an invalidArguments error. When given, the *value* property of
> any EmailBodyValue object returned in *bodyValues* MUST be
> truncated if necessary so it does not exceed this number of bytes
> in size. The server MUST ensure the truncation results in valid UTF-
> 8 and does not occur mid-codepoint. If the part is of type
> text/html, the server SHOULD NOT truncate inside an HTML tag.> If the =
standard *properties* argument is omitted or null, the
> following default MUST be used instead of "all" properties:
> [ "id", "blobId", "threadId", "mailboxIds", "keywords", "size",
> "receivedAt", "sender", "from", "to", "cc", "bcc", "replyTo",
> "subject", "sentAt", "hasAttachment", "preview", "bodyValues",
> "textBody", "htmlBody", "attachedFiles", "attachedEmails" ]
>> The following properties are expected to be fast to fetch in a quality
> implementation:
> * id
> * blobId
> * threadId
> * mailboxIds
> * keywords
> * size
> * receivedAt
> * sender
> * from
> * to
> * cc
> * bcc
> * replyTo
> * subject
> * sentAt
> * hasAttachment
> * preview> Clients SHOULD take care when fetching any other properties, =
as
> there may be significantly longer latency in fetching and returning
> the data.> Example
> Request:
> ["Email/get", { "ids": [ "f123u456", "f123u457" ], "properties": [
> "threadId", "mailboxIds", "from", "subject", "receivedAt", "htmlBody",
> "bodyValues" ], "bodyProperties": [ "partId", "blobId", "size", "type"
> ], "fetchHTMLBodyValues": true, "maxBodyValueBytes": 256 }, "#1"]
>> and response:
> ["Email/get", { "accountId": "abc", "state": "41234123231", "list": [
> { "id": "f123u457", "threadId": "ef1314a", "mailboxIds": { "f123":
> true }, "from": [{name: "Joe Bloggs", email: "joe@bloggs.com"}],
> "subject": "Dinner on Thursday?", "receivedAt": "2013-10-
> 13T14:12:00Z", "htmlBody": [{ "partId": "1", "blobId": "841623871",
> "size": 283331, "type": "text/html" }, { "partId": "2", "blobId":
> "319437193", "size": 10343, "type": "text/plain" }], "bodyValues": {
> "1": { "isTruncated": true, "value": "Hello ..." },
> "2": { "isTruncated": false, "value": "-- \nSent by your friendly
> mailing list ..." } } } ], notFound: [ "f123u456" ] }, "#1"]
>>=20
> _________________________________________________
> Jmap mailing list
> Jmap@ietf.org
> https://www.ietf.org/mailman/listinfo/jmap
--
Bron Gondwana, CEO, FastMail Pty Ltd
brong@fastmailteam.com
Links:
1. https://www.iana.org/assignments/imap-keywords/imap-keywords.xhtml
2. https://tools.ietf.org/html/rfc5322#appendix-A.1.3
--_----------=_151840850716997411
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset="utf-8"
On Thu, 8 Feb 2018, at 17:11, Neil =
Jenkins wrote:
With an eye to closing off all remaining iss=
ues before the next IETF meeting in March, I have been looking at the issue=
s raised with the JSON representation of an RFC5322 message. This email pre=
sents a new proposal that I think resolves the issues presented. In particu=
lar, I aim to address the following goals:
- Allow access to the full MIME structure without requiring the clien=
t to parse the full message itself.
- Allow access to full header=
field information if required.
- Keep a simpler representation a=
vailable for the common case.
- Allow the client to only load the=
data required.
Comments, suggestions and other feedback =
requested. Cheers!
Sorry, saw this on my phone for the first=
read-through, so I didn't reply. I see Chris already caught some of =
this, but I'll do my read-through again and reply as well.
------
Emails
The Email object is a representation of an [@!=
RFC5322] message, which allows clients to avoid the complexities of MIME pa=
rsing, transport encoding and character encoding.
Properties of =
the Email object
Broadly, a message consists of two parts: a lis=
t of header fields, then a body. The body is normally a MIME-encoded set of=
documents in a tree structure. The JMAP Email object provides a way to acc=
ess the full structure, or to use simplified properties and avoid some comp=
lexity if this is sufficient for the client application.
Due to t=
he number of properties involved, the set of Email properties is spe=
cified over the following three sub-sections.
Metadata
<=
p>These properties represent metadata about the [@!RFC5322] message, and ar=
e not derived from parsing the message itself.
id:=
String
(immutable; server-set)
The id of the Email object. Note, this is the JMAP object id, NOT the [@!RF=
C5322] Message-Id header field value.
blobId: String (immutable; server-set)
The id representing the raw bytes of the [@!RFC5322] message. This may be u=
sed to download the raw original message, or to attach it directly to anoth=
er Email etc.
threadId: String
(immu=
table; server-set)
The id of the Thread to which this Email belongs.
mai=
lboxIds: String[Boolean]
The set of mailbox ids this email=
belongs to. An email MUST belong to one or more mailboxes at all times (un=
til it is deleted). The set is represented as an object, with each key bein=
g a Mailbox id. The value for each key in the object MUST be t=
rue
.
keywords: String[Boolean]
(default: {}
)
A set of keywords that apply to the email. The set is represented as an obj=
ect, with the keys being the keywords. The value for each key in the=
object MUST be true
.
Keywords are shared with IMAP.=
The six system keywords from IMAP are treated specially. The following fou=
r keywords have their first character changed from \
in IMAP t=
o $
in JMAP and have particular semantic meaning:
<=
li>$Draft
: The email is a draft the user is composing.
$Seen
: The email has been read.
$Flagge=
d
: The email has been flagged for urgent/special attention.
=
$Answered
: The email has been replied to.
=
The IMAP \Recent
keyword is not exposed via JMAP. The IMAP \Deleted keyword is also not present: IMAP uses a delete+expunge =
model, which JMAP does not. Any message with the \Deleted
keyw=
ord MUST NOT be visible via JMAP.
Users may add arbitrary keyword=
s to an email. For compatibility with IMAP, a keyword is a (case-sensitive)=
string of 1=E2=80=93255 characters in the ASCII subset %x21=E2=80=93%x7e (=
excludes control chars and space), and MUST NOT include any of these charac=
ters: ( ) { ] % * " \
The IANA Keyword Registry<=
/a> as established in [@!RFC5788] assigns semantic meaning to some other ke=
ywords in common use. New keywords may be established here in the future. I=
n particular, note:
$Forwarded
: The email has b=
een forwarded.
$Phishing
: The email is highly like=
ly to be phishing. Clients SHOULD warn users to take care when viewing this=
email and disable links and attachments.
$Junk
: T=
he email is definitely spam. Clients SHOULD set this flag when users report=
spam to help train automated spam-detection systems.
$No=
tJunk
: The email is definitely not spam. Clients SHOULD set this fla=
g when users indicate an email is legitimate, to help train automated spam-=
detection systems.
did we want to talk about $HasAttachment =
and friend as well?
I noticed this inconsistency as well - ma=
tching blobId size is by far the most useful thing to do here.
Header fields
These pr=
operties are derived from the [@!RFC5322] message header fields. Header fie=
lds may be fetched in a variety of forms:
Decoded =
The header field value with:
- White space unfolded (as define=
d in [@!RFC5322] section 2.2.3)
- The terminating CRLF at the end=
of the value removed
- Any SP characters at the beginning of the=
value removed
- Any [@!RFC2047] encoded sections decoded
- Any [@!RFC6532] UTF-8 values decoded
If any decodings =
fail, the parser SHOULD insert a unicode replacement
character (U+FFFD) and attempt to continue as much as possible.
Raw Base64 The raw bytes of the header field value from the =
first byte following the header field name terminating colon, up to but exc=
luding the header field terminating CRLF, encoded as Base64 ([@!RFC4648]). =
(Note, this is required as the value may not be valid UTF-8 if 8-bit values=
are present.)
Addresses The header is parsed as =
an address-list
value, as specified in [@!RFC5322] section 3.4=
, into the EmailAddress[]
type. The EmailAddress object=
has the following properties:
- name:
String|nul=
l
The display name of the [@!RFC5322] mailbox or gr=
oup, or null
if none.
- email:
Stri=
ng|null
The addr-spec of the [@!RFC5322] mailbox, or <=
code>null if a group.
I don't know enough about the group synta=
x, but I thought it was nestable in a way that makes it hard to flatten.&nb=
sp; Maybe just a null group is enough, but the example in RFC5322 shows a g=
roup with 3 addresses in it:
Appendix A.1.3. Group Addresses
----
From: Pete <pete@silly.example<=
/a>>
To: A Group:Ed Jones <c@a.test>,joe@where.test,John <jdoe@one.test>;
Cc: Undisclosed recipients:;
Date: Thu, 13 Feb 1969 23:32:54 -0330
Message-ID: <testabcd.=
1234@silly.example>
Testing.
----
In this message, the "To:" field has a single group recipient named
"A Group", which contains 3 addresses, and a "Cc:" field with an
empty group recipient named Undisclosed recipients.
And I have a horrible sinking fe=
eling that the group could contain nested groups in the full RFC5322 syntax=
, meaning you could have an arbitrarily deep tree of addresses.
Parsing=
SHOULD be best-effort in the face of invalid structure to accommodate
invalid messages and semi-complete drafts. EmailAddress objects MAY have an=
email property that does not conform to the addr-spec form (=
for example, may not contain an @ symbol).
Date The header is parsed as a date-time
va=
lue, as specified in [@!RFC5322] section 3.3, into the Date
ty=
pe.
The following Email properties are specified=
for complete access to the header data of the message. Where {header=
-field-name}
is specified within a property name, this means any ser=
ies of one or more printable US-ASCII characters (i.e. characters that have=
values between 33 and 126, inclusive), except colon:
- hea=
ders:
EmailHeader[]
(immutable)
This is a list of all [@!RFC5322] header fields, in the same order they app=
ear in the message. The values are in Decoded form.
- h=
eaders:asRaw:
EmailHeader[]
(immutable)
This is a list of all [@!RFC5322] header fields, in the same order they app=
ear in the message. The values are in Raw Base64 form.
- <=
b>header:{header-field-name}:
String|null
(immutable)
The value of the last header field in the message with the given hea=
der field name (matched case-insensitively), or null
if none. =
The value is in Decoded form.
This does seem to mean that it's impossib=
le to ask for all instances of a particular named header. You either =
get the whole lot, or you get just the last of a particular named one. =
; I don't know that it's likely to be a big problem, but I do note the limi=
tation.
- header:{header-field-name}:asRaw: =
String|null
(immutable)
The value of the last header field in the message with the given hea=
der field name (matched case-insensitively), or null
if none. =
The value is in Raw Base64 form.
- header:{header-field=
-name}:asAddresses:
EmailAddress[]|null
(immutable)
The value of the last header field in the message with the given hea=
der field name (matched case-insensitively), or null
if none. =
The value is in Addresses form.
- header:{header-field-=
name}:asDate:
Date|null
(immutable)
The value of the last header field in the message with the given hea=
der field name (matched case-insensitively), or null
if none. =
The value is in Date form.
An EmailHeader obj=
ect has the following properties:
- name:
String<=
/code> The header field name as defined in RFC5322, with the same ca=
pitalization that it has in the message.
- value:
St=
ring
The header field value as defined in RFC5322, in either =
Decoded or Raw Base64 form as determined by the property bein=
g fetched.
The following convenience properties are also sp=
ecified for the Email object:
- sender:
Em=
ailAddress[]|null
(immutable)
The value is identical to the value of header:Sender:asAddresses.
- from:
EmailAddress[]|null
(immutable)
The value is identical to the value of header:From:asAddresses.
<=
/li> - to:
EmailAddress[]|null
(immutable)
The value is identical to the value of header:To:asAddresses.
- cc:
EmailAddress[]|null
(immutable)
The value is identical to the value of header:Cc:asAddresses.
- bcc:
EmailAddress[]|null
(immutable)
The value is identical to the value of header:Bcc:asAddresses.
=
li> - replyTo:
EmailAddress[]|null
(immutable)
The value is identical to the value of header:Reply-To:asAddresses.<=
br> - subject:
String|null
(immutable)
The value is identical to the value of header:Subject.
- <=
b>sentAt:
Date
(immutable; default: time of creation on se=
rver)
The value is identical to the value of header:Date:asDate.
<=
/ul>Body parts
These properties are derived from the [@!RFC5=
322] message body and its [@RFC2045] MIME entities.
A EmailBod=
yPart object has the following properties:
- partId=
:
String
Identifies this part uniquely within the Email. This =
is scoped to the emailId and has no meaning outside of the JMAP Emai=
l object representation.
- blobId:
String
The=
id references the raw bytes of the contents of the part after decoding any=
Content-Transfer encoding (as defined in [@!RFC2045]). Note, two pa=
rts may be transfer-encoded differently but have same the same blob id if t=
heir decoded bytes are identical and the server is using a secure hash of t=
he data for the blob id.
- size:
Number
The s=
ize, in bytes, of the raw data after content-transfer decoding (as refrence=
d by the blobId, i.e. the number of bytes in the file the user would=
download).
- headers:
EmailHeader[]
(immutab=
le)
This is a list of all header fields in the part, in the order they appear. =
The values are in Decoded form.
- headers:asRaw: EmailHeader[] (immutable)
This is a list of all header fields in the part, in the order they appear. =
The values are in Raw Base64 form.
- name:
St=
ring|null
This is the [@!RFC2231] decoded filename parameter =
of the Content-Disposition header field, or (for compatibility with =
existing systems) if not present then the [@!RFC2047] decoded name p=
roperty of the Content-Type header field. For compatibility with the=
widest array of existing systems, both forms should be set if creating a m=
essage.
- type:
String
The value of the Co=
ntent-Type header field of the part, excluding any parameters.
=
- charset:
String|null
The value of the charset param=
eter of the Content-Type header field, if present.
- di=
sposition:
String|null
The value of the Content-Disposi=
tion header field of the part, excluding any parameters, if present.
- cid:
String|null
The value of the Content-=
Id header field of the part, if present. This may be used to reference =
the content from within an html body part using the cid:
proto=
col.
- language:
String[]|null
The list of la=
nguage tags, as defined in [@!RFC3282], in the Content-Language head=
er field of the part, if present.
- location:
String=
|null
The URI, as defined in [@!RFC2557], in the Content-Location=
header field of the part, if present.
- width:
=
Number|null
The width (in px) of the image, if the type is an image =
and the server is able to determine this information for the image. This MA=
Y not be supported for all or any image types on some servers.
- =
height:
Number|null
The height (in px) of the image, if=
the type is an image and the server is able to determine this information =
for the image. This MAY not be supported for all or any image types on some=
servers.
- subParts:
EmailBodyPart[]
(option=
al)
If type is multipart/*
, this contains the body parts of each c=
hild.
The following Email properties are specified f=
or access to the body data of the message:
bodyStructu=
re: EmailBodyPart[]
(immutable)
This is the full MIME structure of the message body, including sub parts bu=
t not recursing into message/rfc822
parts.
=
bodyValues: String[BodyValue]
(immutable)
This is a map of partId to an EmailBodyValue object. Which pa=
rts are included and whether the value is truncated is determined by variou=
s arguments to Email/get and Email/parse.
An Ema=
ilBodyValue object has the following properties:
- valu=
e:
String
The value of the body part after decoding Con=
tent-Transport encoding and
decoding the Content-Type charset.
- isTruncated Boolean This is
true
if the value has been t=
runcated.
textBody: EmailBodyPart[]=
code> (immutable)
A list of text/plain
, text/html
and image/*=
parts to display (sequentially) as the message body, with a prefere=
nce for text/plain
when alternative versions are available.
htmlBody: EmailBodyPart[]
(immutable)
A list of text/plain
, text/html
and image/*=
parts to display (sequentially) as the message body, with a prefere=
nce for text/html
when alternative versions are available.
=
There was some discussion about how to ha=
ndle RFC 8255 multipart/multilingual or other things here - whether we add =
something along the lines of "the server will choose which representation t=
o include based on the original language plus what it knows about the user'=
s preferred language" - plus of course the full information is available in=
the bodyStructure if the client wants to be smart about it. This is =
also a good place for a JMAP extension which could give a more powerful que=
ry language for choosing specific parts in multipart.
attachedEmails: EmailBody=
Part[]
(immutable)
A list of all parts of type message/rfc822
. Note, this does=
not recurse, so the parts within these are not included. The attached =
message may be fetched using the Email/parse method and the blobId.
=
Might be worth having an example of this =
- it's going to be one of the tricky bits for people to understand.
attachedFiles: EmailBodyP=
art[]
(immutable)
A list of all parts in bodyStructure, traversing depth-first, not of=
type multipart/*
, and not included in any of the textBody<=
/i>, htmlBody or attachedEmails properties. Note, an HTML bod=
y part may reference image parts in attachedFiles using cid:
l=
inks to reference the Content-Id or by referencing the Content-Lo=
cation.
This could do with being a little clearer=
that "even if referenced by an HTML body part, attached files will be incl=
uded in this list" - or something like that.
It's already been noted that the logic is=
reversed here, should be "does have" or maybe even "does not have Content-=
Disposition: inline" instead.
The server MAY set hasAttachment based=
on implementation-defined or site configurable heuristics.
preview: String
(immutable; server-set)
Up to 256 characters of the beginning of a plain text version of the messag=
e body. This is intended to be shown as a preview line on a mailbox listing=
, and the server may choose to skip quoted sections or salutations to retur=
n a more useful preview.
I wouldn't even say "of the beginning" - =
it's up to 256 characters that provide a good summary of the content of the=
message. I would say something like: This is intended to be shown as=
a preview line on a mailbox listing, and not all characters may be shown.&=
nbsp; The server may choose which part of the message to include in the pre=
view, for example skipping quoted sections and salutations can result in a =
more useful preview.
MIME structures are arbitrary nested trees of =
documents, but the majority of email clients present a model of an email bo=
dy (normally plain text or HTML), with a set of attachments. Interpreting t=
he MIME structure to form this flat model represents considerable difficult=
y and causes inconsistency between clients. Therefore in addition to the bodyStructure property, which gives the full tree, the Email object co=
ntains 4 alternate properties with flat lists of body parts:
textBody/htmlBody: These provide a list of parts that sho=
uld be
rendered as the "body" of the message. This is a list rather than a single =
part as messages may have headers and/or footers appended/prepended as sepa=
rate parts as they are transmitted, and some clients send text and images i=
ntended to be displayed inline in the body as multiple parts rather than a =
single HTML part with referenced images.
Because MIME allows for =
multiple representations of the same data (using multipart/alternativ=
e
), there is a textBody property (which prefers a plain text represe=
ntation) and an htmlBody property (which prefers an HTML representation) to=
accommodate the two most common client requirements. The same part may app=
ear in both lists where there is no alternative between the two.
attachedEmails/attachedFiles: These provide a list o=
f parts that should
be presented as "attachments" to the message. Emails are presented in a sep=
arate list so their contents may be easily fetched via a back-reference wit=
h the Email/parse
method in the same request, if the client wi=
shes to. Some images in attachedFiles may be solely there for embedding wit=
hin an HTML body part; clients may wish to not present these as attachments=
in the user interface if they are displaying the HTML with the embedded im=
ages directly.
The bodyValues property allows fo=
r clients to fetch the value of text parts directly without having to do a =
second request for the blob, and have the server handle decoding the charse=
t into unicode. This data is in a separate property rather than on the Emai=
lBodyPart object to avoid duplication of large amounts of data, as the same=
part may be included twice if the client fetches more than one of bodyStru=
cture, textBody and htmlBody.
The exact algorithm for decomposing=
bodyStructure into textBody, htmlBody, attachedEmails and attachedFiles pa=
rt lists is not mandated, as this is a quality-of-service implementation is=
sue and likely to require workarounds for malformed content discovered over=
time.
However, we will define a suggested algorithm for the RFC =
to help implementors. TODO.
Email/get
Standard /ge=
t method, with the following additional arguments:
bodyProperties: String[]
(optional)
A list of properties to fetch for each EmailBodyPart returned. If omitted, =
this defaults to:
[ "partId", "blobId", "size", "name", "type", "=
charset", "disposition", cid", "language", "location", "width", "height" ]<=
br>
fetchTextBodyValues: Boolean
(defaul=
t: false
)
If true
, the bodyValues property includes any tex=
t/*
part in the textBody
property.
<=
b>fetchHTMLBodyValues: Boolean
(default: false
)
If true
, the bodyValues property includes any tex=
t/*
part in the htmlBody
property.
<=
b>fetchAllBodyValues: Boolean
(default: false
)
If true
, the bodyValues property includes any tex=
t/*
part in the bodyStructure
property.
maxBodyValueBytes: Number
(optional)
If supplied by the client, the value MUST be a positive integer greater tha=
n 0. If a value outside of this range is given, the server MUST reject the =
call with an invalidArguments
error. When given, the value<=
/i> property of any EmailBodyValue object returned in bodyValues MUS=
T be truncated if necessary so it does not exceed this number of bytes in s=
ize. The server MUST ensure the truncation results in valid UTF-8 and does =
not occur mid-codepoint. If the part is of type text/html
, the=
server SHOULD NOT truncate inside an HTML tag.
If the =
standard properties argument is omitted or null
, the fo=
llowing default MUST be used instead of "all" properties:
[ "id", "blobId", "threadId", "mailboxIds", "keywords", "size", "receivedA=
t", "sender", "from", "to", "cc", "bcc", "replyTo", "subject", "sentAt", "h=
asAttachment", "preview", "bodyValues", "textBody", "htmlBody", "attachedFi=
les", "attachedEmails" ]
The following properties are expected to be fast to fet=
ch in a quality implementation:
- id
- blobId
- threadId
- mailboxIds
- keywords
- size=
- receivedAt
- sender
- from
- to<=
br>
- cc
- bcc
- replyTo
- subject
<=
/li> - sentAt
- hasAttachment
- preview
<=
p>Clients SHOULD take care when fetching any other properties, as there may=
be significantly longer latency in fetching and returning the data.
Example
Request:
["Email/get", {
"ids": [ "f123u456", "f123u457" ],
"properties": [ "threadId", "mailboxIds", "from", "subject", "receivedAt"=
, "htmlBody", "bodyValues" ],
"bodyProperties": [ "partId", "blobId", "size", "type" ],
"fetchHTMLBodyValues": true,
"maxBodyValueBytes": 256
}, "#1"]
and response:
["Email/get", {
"accountId": "abc",
"state": "41234123231",
"list": [
{
"id": "f123u457",
"threadId": "ef1314a",
"mailboxIds": { "f123": true },
"from": [{name: "Joe Bloggs", email: "joe@bloggs.com"}],
"subject": "Dinner on Thursday?",
"receivedAt": "2013-10-13T14:12:00Z",
"htmlBody": [{
"partId": "1",
"blobId": "841623871",
"size": 283331,
"type": "text/html"
}, {
"partId": "2",
"blobId": "319437193",
"size": 10343,
"type": "text/plain"
}],
"bodyValues": {
"1": {
"isTruncated": true,
"value": "<html><body><p>Hello ..."
},
"2": {
"isTruncated": false,
"value": "-- \nSent by your friendly mailing list ..."
}
}
}
],
notFound: [ "f123u456" ]
}, "#1"]
_______________________________________________
Jmap mailing list
--
Bron Gondwana, CEO, FastMail Pty Ltd
brong@fastmailteam.com
--_----------=_151840850716997411--
From nobody Sun Feb 11 23:06:00 2018
Return-Path:
X-Original-To: jmap@ietfa.amsl.com
Delivered-To: jmap@ietfa.amsl.com
Received: from localhost (localhost [127.0.0.1]) by ietfa.amsl.com (Postfix) with ESMTP id 29652126CF6 for ; Sun, 11 Feb 2018 23:05:59 -0800 (PST)
X-Virus-Scanned: amavisd-new at amsl.com
X-Spam-Flag: NO
X-Spam-Score: -2.72
X-Spam-Level:
X-Spam-Status: No, score=-2.72 tagged_above=-999 required=5 tests=[BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, HTML_MESSAGE=0.001, RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, SPF_PASS=-0.001] autolearn=ham autolearn_force=no
Authentication-Results: ietfa.amsl.com (amavisd-new); dkim=pass (2048-bit key) header.d=fastmailteam.com header.b=V17zqsQ9; dkim=pass (2048-bit key) header.d=messagingengine.com header.b=hAaDV9le
Received: from mail.ietf.org ([4.31.198.44]) by localhost (ietfa.amsl.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id iRmOcDRInO3t for ; Sun, 11 Feb 2018 23:05:55 -0800 (PST)
Received: from out2-smtp.messagingengine.com (out2-smtp.messagingengine.com [66.111.4.26]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by ietfa.amsl.com (Postfix) with ESMTPS id C4036124BE8 for ; Sun, 11 Feb 2018 23:05:55 -0800 (PST)
Received: from betaweb1.internal (betaweb1.nyi.internal [10.202.2.10]) by mailout.nyi.internal (Postfix) with ESMTP id 1869320A47; Mon, 12 Feb 2018 02:05:55 -0500 (EST)
Received: from betaweb1 ([::ffff:10.202.2.10]) by betaweb1.internal (MEProxy); Mon, 12 Feb 2018 02:05:55 -0500
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= fastmailteam.com; h=cc:content-transfer-encoding:content-type :date:from:in-reply-to:message-id:mime-version:references :subject:to:x-me-sender:x-me-sender:x-sasl-enc; s=fm1; bh=J8cID/ taIvWd5JxJJS/2uLpHDqtfuLEK5EkSfwdUI6U=; b=V17zqsQ9hGO54+tseEkocU kMPQysFoQHe5NilVdRgqY/lSDfhToiIoS4cgPqW1RdEKCjizM8BDg57LSuyScoF5 ix75ttZhfjFLie9UCi8/IZRngouJ0qCuvfunOZuE7mE751hGsVobz5wmtZ6U+tHx XQvoaPWe9Bh5zk7vvKdqqpkXOAFd7C+bQyJX2VWc4g6UoLqAfDXdubQ+3skFCsAr rqYHJsgO8CCA9bQV7C6JXi9YUhzvCRXaYAjKKJz+P6GSFAJS7RvE6eVl0ZqpIAD5 Dx9rf0jLygVCfg5IAAurblEV16kxDbTg+CiOp83uIXQmCFmtvSH5PUJDaLxMU7dA ==
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:content-type :date:from:in-reply-to:message-id:mime-version:references :subject:to:x-me-sender:x-me-sender:x-sasl-enc; s=fm2; bh=J8cID/ taIvWd5JxJJS/2uLpHDqtfuLEK5EkSfwdUI6U=; b=hAaDV9le7mfYbHSHtOdCVy LxWuCflvttGGNf5A5qS+/zJU8VhMjBWgW4ZKsts60KG90i2kTBrb4UGwZP7erITI 8SqSVYCQTlJ29HNnKoZ8zaopjJ+dRLh2XgrWY9Rk3aHlA3IfpN1KIYrVpPw/bkdO xpaiK6DQlZEE5fmv+3PspBCAMuVvCamsRr54tRugskaOZ8vGIP9x+XYkufhJ15eQ 92x3eR5fhfncGJa7f/gAZuYI3lJOLb35ae8hFTWE46iah6Vwk0XU0P8S1roX5v/V igm4nvvn8Rkw/BQZdJINJj21CX5XLdNJP/ZRtMf3VLyJMIz/OupJCgpK5ia/qfqg ==
X-ME-Sender:
Received: by mailuser.nyi.internal (Postfix, from userid 99) id B27A3E21FA; Mon, 12 Feb 2018 02:05:54 -0500 (EST)
Message-Id: <1518419154.999872.1267587168.461E9F6F@webmail.messagingengine.com>
From: Neil Jenkins
To: Chris Newman
Cc: IETF JMAP Mailing List
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Type: multipart/alternative; boundary="_----------=_15184191549998720"
X-Mailer: MessagingEngine.com Webmail Interface - ajax-2ce04827
Date: Mon, 12 Feb 2018 18:05:54 +1100
References: <1518070284.168650.1263633200.05C7397A@webmail.messagingengine.com> <500E0B79-200E-4DFA-939A-C3419559743E@oracle.com>
In-Reply-To: <500E0B79-200E-4DFA-939A-C3419559743E@oracle.com>
Archived-At:
Subject: Re: [Jmap] New JSON message representation
X-BeenThere: jmap@ietf.org
X-Mailman-Version: 2.1.22
Precedence: list
List-Id: JSON Message Access Protocol
List-Unsubscribe: ,
List-Archive:
List-Post:
List-Help:
List-Subscribe: ,
X-List-Received-Date: Mon, 12 Feb 2018 07:05:59 -0000
This is a multi-part message in MIME format.
--_----------=_15184191549998720
Content-Transfer-Encoding: 7bit
Content-Type: text/plain; charset="utf-8"
Thanks for the great feedback!
> I concur with Alexey's comment about keywords being case-insensitive.
I've changed it so they are case-insensitive but the server MUST
return them lower-cased (as JSON is case-sensitive and it's a pain to
have to iterate through keys in an object rather than be able to do a
direct lookup).
> On 7 Feb 2018, at 22:11, Neil Jenkins wrote:
>> * **size**: Number (immutable; server-set) The size in bytes of the
>> whole
>> email as counted by the server towards the user's quota.
>
> The problem with a quota-based size measurement is "0" is a reasonable> answer for single-copy message stores that allow multiple Email
> objects> that refer to the same message (particularly if a reference to the
> message in a trash folder is not the only reference).
Yep, this is also inconsistent with everywhere else there are
blobId/size properties on an object. I've changed it so it's the size
of the file you get if you download the blob (i.e. the size of the
RFC5322 message), which is then consistent with the rest of the spec
and with IMAP.
>> * **receivedAt**: UTCDate
> I note the IMAP APPEND command allows this to be client-specified.
This is also already client-specifiable in JMAP (see the Email/import
method, which is the equivalent of APPEND). It's just the *default*
that's the time the message is inserted in the mail store if no other
date is supplied.
>> These properties are derived from the [@!RFC5322] message header
>> fields.
> It's also fine to allow [@!RFC6532] message header fields, I believe.
Yep, I'll note this in the spec.
>> * **Decoded** The header field value with:
>> 1. White space unfolded (as defined in [@!RFC5322] section 2.2.3)
>> 2. The terminating CRLF at the end of the value removed
>> 3. Any SP characters at the beginning of the value removed
>> 4. Any [@!RFC2047] encoded sections decoded
>
> This is a security design error. I suggest:
>
> Any syntactically correct [@!RFC2047] encoded sections with a known
> character set are decoded and re-encoded as a UTF-8 string with proper> quoting and escaping for the active RFC 5322 syntactic context
> appropriate for the specific header field. Any [@!RFC2047] encoded NUL> octets or control characters are dropped from the decoded value. Any
> text that looks like [@!RFC2047] syntax but violates [@!RFC2047]
> placement or whitespace rules MUST NOT be decoded. Any [@!RFC2047]
> content in an unrecognized header MUST NOT be decoded. Same
> rules apply> to [@!RFC2231] decoding.
Yes, looking at this again we have come to the conclusion that allowing
clients to request arbitrary headers be parsed in arbitrary forms is
allowing them to shoot themselves in the foot too much, and going to
lead to security and/or interoperability errors.
My new suggestion:
* Raw form doesn't base64 (as you say, any standards-compliant email
should be valid ASCII or UTF-8), and becomes the default, and the
only form in which you can request any header.
* A number of parsed forms are defined. These may only be fetched/set
for appropriate header fields from RFC5322 or fields not defined in
this spec (which allows for more future proofing, if someone defines
a new header field that contains a date for example).I'll send another email with the full revised spec shortly.
> We might also want to add 6. require the server to convert
> denormalized> Unicode to NFC. This is easy enough for a server to do and makes it
> easier for clients to comply with RFC 5198.
Seems reasonable.
>> * **Addresses** The header is parsed as an address-list value, as
>> specified in [@!RFC5322] section 3.4, into the EmailAddress[] type.>> The **EmailAddress** object has the following properties:
>>
>>
>> * **name**: String|null The *display name* of the [@!RFC5322]
>> **mailbox**
>> or **group**, or null if none.
>
> It's important for 2047 decoding (as described previously) to
> be applied> to this when possible.
Yes, this was meant to be the case, looks like I missed specifying that.
>> EmailAddress objects MAY have an **email** property that
>> does not conform to the **addr-spec** form (for example, may not
>> contain an @ symbol).> Should this allow non-punycode IDN?
I think the value there should be automatically converted to or from
punycode, but other than that I don't think we should be rejecting
anything, just doing best-effort parsing into a form that's easier for
the client to handle. The client can convert or analyse for phishing
issues with the domain.
> Should this allow RFC 6532?
Yes, I've now noted this.
>> * **name**: String|null This is the [@!RFC2231] decoded **filename**>> parameter of the **Content-Disposition** header field, or (for
>> compatibility with existing systems) if not present then the
>> [@!RFC2047] decoded **name** property of the **Content-Type**
>> header>> field. For compatibility with the widest array of existing systems,>> both forms should be set if creating a message.
>
> I think this is the wrong place to include rules for generating
> email. I> note that setting a "name" parameter on a MIME content type which
> doesn't explicitly register a "name" parameter is a violation of the
> MIME model. Advice to violate the model may be fine as an
> implementation> suggestion, but I wouldn't make it a standards-level recommendation.
OK. I'll remove the last sentence and add a note to the server
implementation guide[1].
>> * **type**: String The value of the **Content-Type** header field
>> of the>> part, excluding any parameters.
> Should this have CFWS removed? I think it should.
Yes.
>> * **bodyStructure**: EmailBodyPart[] (immutable) This is the
>> full MIME>> structure of the message body, including sub parts but not
>> recursing
>> into message/rfc822 parts.
> make that "message/rfc822 or message/global parts."
Yep.
>> * **value**: String The value of the body part after decoding
>> *Content-
>> Transport* encoding and decoding the **Content-Type** charset.
>
> I think you mean **Content-Transfer-Encoding**, and decoding it
> is fine.> Decoding the charset unconditionally in this way violates the
> MIME model> as the charset parameter has no strictly defined meaning outside the
> top-level text media-type.
>
> I think there are three design options here:
> 1. CTE only
> 2. CTE, plus charset decoding of text/ and other recognized media
> types> the server knows have a registered and defined meaning for charset.
The bodyValues property is *only* used to return text/* parts.
(Anything else, the client has to download the blob, which does CTE
decoding only).
> 3. allow the server to be helpful and briefly describe what it did.
>
> If you choose option 3, I'd add a third "decodingKind" field to
> EmailBodyValue that explains the value.
I feel this is overkill. The main purpose of this property is to let
clients fetch the message text/html body without having to deal with
charset decoding. I think what we want here are:
1. A best-effort decoded value.
2. A flag to tell the client if the charset was unknown, or invalid data
was found for the charset. The client can then choose what to do
(download the blob and try to decode it itself, or more likely show a
warning to the user that the message may display incorrectly, or even
just not show the message at all and say it could not be
understood).
With that in mind, here's a new suggestion:
An *EmailBodyValue* object has the following properties:
* *value*: String The value of the body part after decoding *Content-Transport-
Encoding* and decoding the *Content-Type* charset, if known to the
server. The server MAY use heuristics to determine the charset to use
for decoding if the charset is unknown, or if no charset is given, or
if it believes the charset given is incorrect. Decoding is best-
effort and SHOULD insert the unicode replacement character (U+FFFD)
and continue when a malformed section is encountered.
* *isEncodingProblem*: Boolean This is true if malformed sections were
found while decoding the charset, or the charset was unknown.
* *isTruncated*: Boolean This is true if the *value* has been
truncated.
>> * **attachedEmails**: EmailBodyPart[] (immutable) A list of all parts>> of type message/rfc822. Note, this *does not* recurse, so the parts> or type message/global.
Yes
>> * The **attachedFiles** list contains at least one item that does
>> not>> have Content-Disposition: attachment. The server MAY ignore parts> I think you mean "Content-Disposition: inline".
Oops, yes.
Neil.
Links:
1. http://jmap.io/server.html
--_----------=_15184191549998720
Content-Transfer-Encoding: 7bit
Content-Type: text/html; charset="utf-8"
Thanks for the great feedback!
I concur with Alexey's comment about keywords being case-insensitive.
I've changed it so they are case-insensitive but the server MUST return them lower-cased (as JSON is case-sensitive and it's a pain to have to iterate through keys in an object rather than be able to do a direct lookup).
On 7 Feb 2018, at 22:11, Neil Jenkins wrote:
* *size*: Number (immutable; server-set) The size in bytes of the
whole
email as counted by the server towards the user's quota.
The problem with a quota-based size measurement is "0" is a reasonable
answer for single-copy message stores that allow multiple Email objects
that refer to the same message (particularly if a reference to the
message in a trash folder is not the only reference).
Yep, this is also inconsistent with everywhere else there are blobId/size properties on an object. I've changed it so it's the size of the file you get if you download the blob (i.e. the size of the RFC5322 message), which is then consistent with the rest of the spec and with IMAP.
* *receivedAt*: UTCDate
I note the IMAP APPEND command allows this to be client-specified.
This is also already client-specifiable in JMAP (see the Email/import method, which is the equivalent of APPEND). It's just the default that's the time the message is inserted in the mail store if no other date is supplied.
These properties are derived from the [@!RFC5322] message header
fields.
It's also fine to allow [@!RFC6532] message header fields, I believe.
Yep, I'll note this in the spec.
* *Decoded* The header field value with:
1. White space unfolded (as defined in [@!RFC5322] section 2.2.3)
2. The terminating CRLF at the end of the value removed
3. Any SP characters at the beginning of the value removed
4. Any [@!RFC2047] encoded sections decoded
This is a security design error. I suggest:
Any syntactically correct [@!RFC2047] encoded sections with a known
character set are decoded and re-encoded as a UTF-8 string with proper
quoting and escaping for the active RFC 5322 syntactic context
appropriate for the specific header field. Any [@!RFC2047] encoded NUL
octets or control characters are dropped from the decoded value. Any
text that looks like [@!RFC2047] syntax but violates [@!RFC2047]
placement or whitespace rules MUST NOT be decoded. Any [@!RFC2047]
content in an unrecognized header MUST NOT be decoded. Same rules apply
to [@!RFC2231] decoding.
Yes, looking at this again we have come to the conclusion that allowing clients to request arbitrary headers be parsed in arbitrary forms is allowing them to shoot themselves in the foot too much, and going to lead to security and/or interoperability errors.
My new suggestion:
- Raw form doesn't base64 (as you say, any standards-compliant email should be valid ASCII or UTF-8), and becomes the default, and the only form in which you can request any header.
- A number of parsed forms are defined. These may only be fetched/set for appropriate header fields from RFC5322 or fields not defined in this spec (which allows for more future proofing, if someone defines a new header field that contains a date for example).
I'll send another email with the full revised spec shortly.
We might also want to add 6. require the server to convert denormalized
Unicode to NFC. This is easy enough for a server to do and makes it
easier for clients to comply with RFC 5198.
Seems reasonable.
* *Addresses* The header is parsed as an address-list value, as
specified in [@!RFC5322] section 3.4, into the EmailAddress[] type.
The *EmailAddress* object has the following properties:
* *name*: String|null The *display name* of the [@!RFC5322]
*mailbox*
or *group*, or null if none.
It's important for 2047 decoding (as described previously) to be applied
to this when possible.
Yes, this was meant to be the case, looks like I missed specifying that.
EmailAddress objects MAY have an *email* property that
does not conform to the *addr-spec* form (for example, may not contain an @ symbol).
Should this allow non-punycode IDN?
I think the value there should be automatically converted to or from punycode, but other than that I don't think we should be rejecting anything, just doing best-effort parsing into a form that's easier for the client to handle. The client can convert or analyse for phishing issues with the domain.
Should this allow RFC 6532?
Yes, I've now noted this.
* *name*: String|null This is the [@!RFC2231] decoded *filename*
parameter of the *Content-Disposition* header field, or (for
compatibility with existing systems) if not present then the
[@!RFC2047] decoded *name* property of the *Content-Type* header
field. For compatibility with the widest array of existing systems,
both forms should be set if creating a message.
I think this is the wrong place to include rules for generating email. I
note that setting a "name" parameter on a MIME content type which
doesn't explicitly register a "name" parameter is a violation of the
MIME model. Advice to violate the model may be fine as an implementation
suggestion, but I wouldn't make it a standards-level recommendation.
* *type*: String The value of the *Content-Type* header field of the
part, excluding any parameters.
Should this have CFWS removed? I think it should.
Yes.
* *bodyStructure*: EmailBodyPart[] (immutable) This is the full MIME
structure of the message body, including sub parts but not
recursing
into message/rfc822 parts.
make that "message/rfc822 or message/global parts."
Yep.
* *value*: String The value of the body part after decoding
*Content-
Transport* encoding and decoding the *Content-Type* charset.
I think you mean *Content-Transfer-Encoding*, and decoding it is fine.
Decoding the charset unconditionally in this way violates the MIME model
as the charset parameter has no strictly defined meaning outside the
top-level text media-type.
I think there are three design options here:
1. CTE only
2. CTE, plus charset decoding of text/ and other recognized media types
the server knows have a registered and defined meaning for charset.
The bodyValues property is only used to return text/* parts. (Anything else, the client has to download the blob, which does CTE decoding only).
3. allow the server to be helpful and briefly describe what it did.
If you choose option 3, I'd add a third "decodingKind" field to
EmailBodyValue that explains the value.
I feel this is overkill. The main purpose of this property is to let clients fetch the message text/html body without having to deal with charset decoding. I think what we want here are:
1. A best-effort decoded value.
2. A flag to tell the client if the charset was unknown, or invalid data was found for the charset. The client can then choose what to do (download the blob and try to decode it itself, or more likely show a warning to the user that the message may display incorrectly, or even just not show the message at all and say it could not be understood).
With that in mind, here's a new suggestion:
An EmailBodyValue object has the following properties:
- value: String
The value of the body part after decoding Content-Transport-Encoding and decoding the Content-Type charset, if known to the server. The server MAY use heuristics to determine the charset to use for decoding if the charset is unknown, or if no charset is given, or if it believes the charset given is incorrect. Decoding is best-effort and SHOULD insert the unicode replacement character (U+FFFD) and continue when a malformed section is encountered.
- isEncodingProblem: Boolean
This is true if malformed sections were found while decoding the charset, or the charset was unknown.
- isTruncated: Boolean
This is true if the *value* has been truncated.
* *attachedEmails*: EmailBodyPart[] (immutable) A list of all parts
of type message/rfc822. Note, this *does not* recurse, so the parts
or type message/global.
Yes
* The *attachedFiles* list contains at least one item that does not
have Content-Disposition: attachment. The server MAY ignore parts
I think you mean "Content-Disposition: inline".
Oops, yes.
Neil.
--_----------=_15184191549998720--
From nobody Sun Feb 11 23:15:13 2018
Return-Path:
X-Original-To: jmap@ietfa.amsl.com
Delivered-To: jmap@ietfa.amsl.com
Received: from localhost (localhost [127.0.0.1]) by ietfa.amsl.com (Postfix) with ESMTP id BFA62126CD8 for ; Sun, 11 Feb 2018 23:15:10 -0800 (PST)
X-Virus-Scanned: amavisd-new at amsl.com
X-Spam-Flag: NO
X-Spam-Score: -2.72
X-Spam-Level:
X-Spam-Status: No, score=-2.72 tagged_above=-999 required=5 tests=[BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, HTML_MESSAGE=0.001, RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, SPF_PASS=-0.001] autolearn=ham autolearn_force=no
Authentication-Results: ietfa.amsl.com (amavisd-new); dkim=pass (2048-bit key) header.d=fastmailteam.com header.b=UqQ1qTDF; dkim=pass (2048-bit key) header.d=messagingengine.com header.b=PJTpl5uC
Received: from mail.ietf.org ([4.31.198.44]) by localhost (ietfa.amsl.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id hB-YvD6XE5El for ; Sun, 11 Feb 2018 23:15:09 -0800 (PST)
Received: from out2-smtp.messagingengine.com (out2-smtp.messagingengine.com [66.111.4.26]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by ietfa.amsl.com (Postfix) with ESMTPS id 2176A124BE8 for ; Sun, 11 Feb 2018 23:15:09 -0800 (PST)
Received: from betaweb1.internal (betaweb1.nyi.internal [10.202.2.10]) by mailout.nyi.internal (Postfix) with ESMTP id 8A3602090A for ; Mon, 12 Feb 2018 02:15:08 -0500 (EST)
Received: from betaweb1 ([::ffff:10.202.2.10]) by betaweb1.internal (MEProxy); Mon, 12 Feb 2018 02:15:08 -0500
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= fastmailteam.com; h=content-transfer-encoding:content-type:date :from:in-reply-to:message-id:mime-version:references:subject:to :x-me-sender:x-me-sender:x-sasl-enc; s=fm1; bh=MTVAlGiyTBVxYkEbZ 8NVHcUvKMGgbW1bTg9nXo9KfnY=; b=UqQ1qTDFfQ/5P8iRlNxzYA/sFA0q9TUnv Xt0Q+1+oKsV/5+/YUe6DCvwogzUP49Ovyyo71rc2+ISrV474izS1GcVGFGfhU99e +L/DVYmHQKHvOX5T7oHk0q0ciQoivuOiHxOEb2UbFcZM1twGPnTxQ3Tqg0PeMHAb cHuFZeX9QxrSbFPyFApAONB88FR3DuEtBjVgfiP7dXjmueGFidpZXnpLPAteYVok HFFh9+cA0goB/aPDfa08gRIEEkD8rGU8GcgaqqdZIckuxp7BTWEgd+XYK1G1bSbo 4/Z6a+MGME7gbxzdq0+ETuBplIt6gmxyXzgMAzkcA0AcDxGZIxBJw==
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=content-transfer-encoding:content-type :date:from:in-reply-to:message-id:mime-version:references :subject:to:x-me-sender:x-me-sender:x-sasl-enc; s=fm2; bh=MTVAlG iyTBVxYkEbZ8NVHcUvKMGgbW1bTg9nXo9KfnY=; b=PJTpl5uCe5bFJ51EJQuE6l nlTnezMAQOijbxQUSXz7K3yiCHXuRVYyB/267UMEepo/bV8g0THBQZK8bjuGaDhZ 0KD7CXx9tXkONAwVlCNFy1KmBrgmQbSHREGmCRh+PIJuBO3//gdmQfb+qWaa7gCd p/W4RXb97BcvQDqbj25C3vSyS3YlvyctdofGgFlwxN/RfylomlF3YzzB7/+2CYbO XqP6BAjk1WjshETvvxRpyMHri18rwJPl8JxhCBUpbj6TsJz1dN4RdyYHZ6oNFCI6 /at+0o6ck4dQ10dbgS+BALOw2nx2AH3WAJvYrC5bM/WkAFrehVdrdMu/yAV+PXOQ ==
X-ME-Sender:
Received: by mailuser.nyi.internal (Postfix, from userid 99) id 47C02E2479; Mon, 12 Feb 2018 02:15:08 -0500 (EST)
Message-Id: <1518419708.1006757.1267595536.799BEEC0@webmail.messagingengine.com>
From: Neil Jenkins
To: IETF JMAP Mailing List
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Type: multipart/alternative; boundary="_----------=_151841970810067573"
X-Mailer: MessagingEngine.com Webmail Interface - ajax-2ce04827
In-Reply-To: <1518408506.1699741.1267466096.17DCF605@webmail.messagingengine.com>
References: <1518070284.168650.1263633200.05C7397A@webmail.messagingengine.com> <1518408506.1699741.1267466096.17DCF605@webmail.messagingengine.com>
Date: Mon, 12 Feb 2018 18:15:08 +1100
Archived-At:
Subject: Re: [Jmap] New JSON message representation
X-BeenThere: jmap@ietf.org
X-Mailman-Version: 2.1.22
Precedence: list
List-Id: JSON Message Access Protocol
List-Unsubscribe: ,
List-Archive:
List-Post:
List-Help:
List-Subscribe: ,
X-List-Received-Date: Mon, 12 Feb 2018 07:15:11 -0000
This is a multi-part message in MIME format.
--_----------=_151841970810067573
Content-Transfer-Encoding: 7bit
Content-Type: text/plain; charset="utf-8"
On Mon, 12 Feb 2018, at 3:08 PM, Bron Gondwana wrote:
> did we want to talk about $HasAttachment and friend as well?
I believe it is worthwhile having a hasAttachment property in JMAP
despite the existence of this keyword, because the keyword is not
guaranteed to be set when appropriate, so the client cannot rely on it,
and it's an important feature for building a good client.
> I don't know enough about the group syntax, but I thought it was
> nestable in a way that makes it hard to flatten.
No, if you look at the syntax[1], you can't nest groups.
> This does seem to mean that it's impossible to ask for all instances
> of a particular named header. You either get the whole lot, or you
> get just the last of a particular named one. I don't know that it's
> likely to be a big problem, but I do note the limitation.
I think this is still a reasonable balance between power and complexity.
>> * *attachedEmails*: EmailBodyPart[] (immutable) A list of all parts
>> of type message/rfc822. Note, this *does not* recurse, so the
>> parts within these are not included. The attached message may be
>> fetched using the Email/parse method and the blobId.>
> Might be worth having an example of this - it's going to be one of the
> tricky bits for people to understand.
Yeh, we need a lot more examples in general.
>> * *attachedFiles*: EmailBodyPart[] (immutable) A list of all parts
>> in *bodyStructure*, traversing depth-first, not of type
>> multipart/*, and not included in any of the *textBody*, *htmlBody*
>> or *attachedEmails* properties. Note, an HTML body part may
>> reference image parts in attachedFiles using cid: links to
>> reference the *Content-Id* or by referencing the *Content-
>> Location*.>
> This could do with being a little clearer that "even if referenced by
> an HTML body part, attached files will be included in this list" - or
> something like that.
I'm not sure I think that's clearer than the current description.
>> * *preview*: String (immutable; server-set) Up to 256 characters of
>> the beginning of a plain text version of the message body. This is
>> intended to be shown as a preview line on a mailbox listing, and
>> the server may choose to skip quoted sections or salutations to
>> return a more useful preview.>
> I wouldn't even say "of the beginning" - it's up to 256 characters
> that provide a good summary of the content of the message. I would
> say something like: This is intended to be shown as a preview line on
> a mailbox listing, and not all characters may be shown. The server
> may choose which part of the message to include in the preview, for
> example skipping quoted sections and salutations can result in a more
> useful preview.
Yep, good point, I've updated this.
Neil.
Links:
1. https://tools.ietf.org/html/rfc5322#section-3.4
--_----------=_151841970810067573
Content-Transfer-Encoding: 7bit
Content-Type: text/html; charset="utf-8"
On Mon, 12 Feb 2018, at 3:08 PM, Bron Gondwana wrote:
did we want to talk about $HasAttachment and friend as well?
I believe it is worthwhile having a hasAttachment property in JMAP despite the existence of this keyword, because the keyword is not guaranteed to be set when appropriate, so the client cannot rely on it, and it's an important feature for building a good client.
I don't know enough about the group syntax, but I thought it was nestable in a way that makes it hard to flatten.
No, if you look at
the syntax, you can't nest groups.
This does seem to mean that it's impossible to ask for all instances of a particular named header. You either get the whole lot, or you get just the last of a particular named one. I don't know that it's likely to be a big problem, but I do note the limitation.
I think this is still a reasonable balance between power and complexity.
attachedEmails: EmailBodyPart[]
(immutable)
A list of all parts of type message/rfc822
. Note, this does not recurse, so the parts within these are not included. The attached message may be fetched using the Email/parse method and the blobId.
Might be worth having an example of this - it's going to be one of the tricky bits for people to understand.
Yeh, we need a lot more examples in general.
attachedFiles: EmailBodyPart[]
(immutable)
A list of all parts in bodyStructure, traversing depth-first, not of type multipart/*
, and not included in any of the textBody, htmlBody or attachedEmails properties. Note, an HTML body part may reference image parts in attachedFiles using cid:
links to reference the Content-Id or by referencing the Content-Location.
This could do with being a little clearer that "even if referenced by an HTML body part, attached files will be included in this list" - or something like that.
I'm not sure I think that's clearer than the current description.
I wouldn't even say "of the beginning" - it's up to 256 characters that provide a good summary of the content of the message. I would say something like: This is intended to be shown as a preview line on a mailbox listing, and not all characters may be shown. The server may choose which part of the message to include in the preview, for example skipping quoted sections and salutations can result in a more useful preview.
Yep, good point, I've updated this.
Neil.
--_----------=_151841970810067573--
From nobody Sun Feb 11 23:26:54 2018
Return-Path:
X-Original-To: jmap@ietfa.amsl.com
Delivered-To: jmap@ietfa.amsl.com
Received: from localhost (localhost [127.0.0.1]) by ietfa.amsl.com (Postfix) with ESMTP id ED6FC124BE8 for ; Sun, 11 Feb 2018 23:26:52 -0800 (PST)
X-Virus-Scanned: amavisd-new at amsl.com
X-Spam-Flag: NO
X-Spam-Score: -2.72
X-Spam-Level:
X-Spam-Status: No, score=-2.72 tagged_above=-999 required=5 tests=[BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, HTML_MESSAGE=0.001, RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, SPF_PASS=-0.001] autolearn=ham autolearn_force=no
Authentication-Results: ietfa.amsl.com (amavisd-new); dkim=pass (2048-bit key) header.d=fastmailteam.com header.b=EGPXo5VY; dkim=pass (2048-bit key) header.d=messagingengine.com header.b=XdbzQcDz
Received: from mail.ietf.org ([4.31.198.44]) by localhost (ietfa.amsl.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id TEhvktHBG3eU for ; Sun, 11 Feb 2018 23:26:48 -0800 (PST)
Received: from out2-smtp.messagingengine.com (out2-smtp.messagingengine.com [66.111.4.26]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by ietfa.amsl.com (Postfix) with ESMTPS id 9A9F81201F8 for ; Sun, 11 Feb 2018 23:26:48 -0800 (PST)
Received: from betaweb1.internal (betaweb1.nyi.internal [10.202.2.10]) by mailout.nyi.internal (Postfix) with ESMTP id 0C3D820BF9 for ; Mon, 12 Feb 2018 02:26:48 -0500 (EST)
Received: from betaweb1 ([::ffff:10.202.2.10]) by betaweb1.internal (MEProxy); Mon, 12 Feb 2018 02:26:48 -0500
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= fastmailteam.com; h=content-transfer-encoding:content-type:date :from:in-reply-to:message-id:mime-version:references:subject:to :x-me-sender:x-me-sender:x-sasl-enc; s=fm1; bh=gLqhxdHH1Eaich3wE ZE8kiDGxyXSqL/H6o8g0h8BOHE=; b=EGPXo5VYEbbTkI1J1c8RAiUA+/c+tk4PT WYC3JZ6CW4JgccwdlR81cdI9FFGlQd+V3Wv1RLDQBWcz8g/XEoHYjlykLEcNm3+V jtZrT/l5pcZQJX8C1um3kNPSh4O9kZdMQB+S2wAW7D+t/NffxvP4KEzwOMfIxhT4 N9qVaJo7SSYu3GELipMkzsxVut4B4TmqGQEeXkBd+ztnN9lSEhfr9P6rroYCjLND yX393s1UH8PRNnwNoIBXj36VGsQ3pY+hL75RnPD5PY/EqGw37BGAw1rwZtmwHFwb B/BoxhlIhIMHpOK1VCMDcwngFH3tRJIslYRzUWFxvzSERDxM5ueZg==
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=content-transfer-encoding:content-type :date:from:in-reply-to:message-id:mime-version:references :subject:to:x-me-sender:x-me-sender:x-sasl-enc; s=fm2; bh=gLqhxd HH1Eaich3wEZE8kiDGxyXSqL/H6o8g0h8BOHE=; b=XdbzQcDz2w7uejdn5d4frn FXy2JokKgl+X1+b3X2KZThFwbfv9Dl/mE5B7omx+HmIb3CT5CTJaPkN/RSGGJCp0 tQ86RVzv8OHNN76yFihRbvJ4ee1Bw//oPEXzWH9jl3ULz+jensKxkxvLz1CH4qQ6 oYmgc5ELm4rdFLheqEHfKDt9IHU5J8oY0lBaDkEKEwHgHF2yaj7WFl67uT0K6eHB uHOhfJUTmIEeu0JSFi/dLCLimc2SXGefHhw1wgKrSeQ/lN8LY6AOOJjaOndcMW1A N+9HLDK9RNWgSThoc1edG62IJpAra1EYxmNm3lSBzAAPxOpLiIXEIz+r7wCaZeBw ==
X-ME-Sender:
Received: by mailuser.nyi.internal (Postfix, from userid 99) id 9B989E2479; Mon, 12 Feb 2018 02:26:47 -0500 (EST)
Message-Id: <1518420407.1012131.1267607120.3E7422B3@webmail.messagingengine.com>
From: Neil Jenkins
To: IETF JMAP Mailing List
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Type: multipart/alternative; boundary="_----------=_151842040710121310"
X-Mailer: MessagingEngine.com Webmail Interface - ajax-2ce04827
In-Reply-To: <1518419708.1006757.1267595536.799BEEC0@webmail.messagingengine.com>
References: <1518070284.168650.1263633200.05C7397A@webmail.messagingengine.com> <1518408506.1699741.1267466096.17DCF605@webmail.messagingengine.com> <1518419708.1006757.1267595536.799BEEC0@webmail.messagingengine.com>
Date: Mon, 12 Feb 2018 18:26:47 +1100
Archived-At:
Subject: Re: [Jmap] New JSON message representation
X-BeenThere: jmap@ietf.org
X-Mailman-Version: 2.1.22
Precedence: list
List-Id: JSON Message Access Protocol
List-Unsubscribe: ,
List-Archive:
List-Post:
List-Help:
List-Subscribe: ,
X-List-Received-Date: Mon, 12 Feb 2018 07:26:53 -0000
This is a multi-part message in MIME format.
--_----------=_151842040710121310
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset="utf-8"
Revised text below for further review/comment. (You can also look at the
emailformat branch commits on GitHub[1] for diffs).
Cheers,
Neil.
-------
The *Email* object is a representation of an [@!RFC5322] message, which
allows clients to avoid the complexities of MIME parsing, transport
encoding and character encoding.Properties of the Email object
Broadly, a message consists of two parts: a list of header fields, then
a body. The body is normally a MIME-encoded set of documents in a tree
structure. The JMAP Email object provides a way to access the full
structure, or to use simplified properties and avoid some complexity if
this is sufficient for the client application.Due to the number of properti=
es involved, the set of *Email* properties
is specified over the following three sub-sections.Metadata
These properties represent metadata about the [@!RFC5322] message, and
are not derived from parsing the message itself.
* *id*: String (immutable; server-set) The id of the Email object.
Note, this is the JMAP object id, NOT the [@!RFC5322] Message-ID
header field value.
* *blobId*: String (immutable; server-set) The id representing the raw
octets of the [@!RFC5322] message. This may be used to download the
raw original message, or to attach it directly to another Email etc.
* *threadId*: String (immutable; server-set) The id of the Thread to
which this Email belongs.
* *mailboxIds*: String[Boolean] The set of mailbox ids this email
belongs to. An email MUST belong to one or more mailboxes at all
times (until it is deleted). The set is represented as an object,
with each key being a *Mailbox id*. The value for each key in the
object MUST be true.
* *keywords*: String[Boolean] (default: {}) A set of keywords that
apply to the email. The set is represented as an object, with the
keys being the *keywords*. The value for each key in the object
MUST be true.
Keywords are shared with IMAP. The six system keywords from IMAP are
treated specially. The following four keywords have their first
character changed from \ in IMAP to $ in JMAP and have particular
semantic meaning:
* $draft: The email is a draft the user is composing.
* $seen: The email has been read.
* $flagged: The email has been flagged for urgent/special attention.
* $answered: The email has been replied to. The IMAP \Recent keyword
is not exposed via JMAP. The IMAP \Deleted keyword is also not
present: IMAP uses a delete+expunge model, which JMAP does not. Any
message with the \Deleted keyword MUST NOT be visible via JMAP.
Users may add arbitrary keywords to an email. For compatibility with
IMAP, a keyword is a case-insensitive string of 1=E2=80=93255 characters in=
the
ASCII subset %x21=E2=80=93%x7e (excludes control chars and space), and MUST=
NOT
include any of these characters: ( ) { ] % * " \
Because JSON is case-sensitive, servers MUST return keywords in
lower-case.
The IANA Keyword Registry[2] as established in [@!RFC5788] assigns
semantic meaning to some other keywords in common use. New keywords may
be established here in the future. In particular, note:
* $forwarded: The email has been forwarded.
* $phishing: The email is highly likely to be phishing. Clients
SHOULD warn users to take care when viewing this email and disable
links and attachments.
* $junk: The email is definitely spam. Clients SHOULD set this
flag when users report spam to help train automated spam-
detection systems.
* $notjunk: The email is definitely not spam. Clients SHOULD set this
flag when users indicate an email is legitimate, to help train
automated spam-detection systems.
* *size*: Number (immutable; server-set) The size, in octets, of the
raw data for the RFC5322 message (as referenced by the *blobId*, i.e.
the number of octets in the file the user would download).
* *receivedAt*: UTCDate (immutable; default: time of creation on
server) The date the email was received by the message store. This is
the *internal date* in IMAP.Header fields
These properties are derived from the [@!RFC5322] and [@!RFC6532]
message header fields. All header fields may be fetched in a raw
form. Some headers may also be fetched in a parsed form. The
structured form that may be fetched depends on the header. The
following forms are defined:
* *Raw* The raw octets of the header field value from the first octet
following the header field name terminating colon, up to but
excluding the header field terminating CRLF. Any standards-
compliant message MUST be either ASCII (RFC5322) or UTF-8
(RFC6532), however other encodings exist in the wild. A server MAY
use heuristics to determine a charset and decode the octets, or MAY
replace any octet or octet run with the high bit set that violates
UTF-8 syntax with the unicode replacement character (U+FFFD). Any
NUL octet MUST be dropped.
* *Text* The header field value with:
1. White space unfolded (as defined in [@!RFC5322] section 2.2.3)
2. The terminating CRLF at the end of the value removed
3. Any SP characters at the beginning of the value removed
4. Any syntactically correct [@!RFC2047] encoded sections with a
known character set are decoded. Any [@!RFC2047] encoded NUL
octets or control characters are dropped from the decoded value.
Any text that looks like [@!RFC2047] syntax but violates
[@!RFC2047] placement or whitespace rules MUST NOT be decoded.
5. Any [@!RFC6532] UTF-8 values decoded.
6. The resulting unicode is converted to NFC form. If any decodings
fail, the parser SHOULD insert a unicode replacement character
(U+FFFD) and attempt to continue as much as possible.
To prevent obviously nonsense behaviour, which can lead to
interoperability issues, this form may only be fetched or set for the
following header fields:
* Subject
* Comment
* Any header not defined in [@!RFC5322] or [@!RFC2369]
* *Addresses* The header is parsed as an address-list value, as
specified in [@!RFC5322] section 3.4, into the EmailAddress[] type.
The *EmailAddress* object has the following properties:
* *name*: String|null The *display name* of the [@!RFC5322] *mailbox*
or *group*, or null if none.
* *email*: String|null The *addr-spec* of the [@!RFC5322] *mailbox*,
or null if a *group*. Any syntactically correct [@!RFC2047]
encoded sections with a known encoding MUST be decoded, following
the same rules as for the *Text* form. Any [@!RFC6532] UTF-8
values MUST be decoded.
Parsing SHOULD be best-effort in the face of invalid structure to
accommodate invalid messages and semi-complete drafts. EmailAddress
objects MAY have an *email* property that does not conform to the *addr-
spec* form (for example, may not contain an @ symbol).
To prevent obviously nonsense behaviour, which can lead to
interoperability issues, this form may only be fetched or set for the
following header fields:
* From
* Sender
* Reply-To
* To
* Cc
* Bcc
* Resent-From
* Resent-Sender
* Resent-Reply-To
* Resent-To
* Resent-Cc
* Resent-Bcc
* Any header not defined in [@!RFC5322] or [@!RFC2369]
* *MessageIds* The header is parsed as a list of msg-id values, as
specified in [@!RFC5322] section 3.6.5, into the String[] type.
To prevent obviously nonsense behaviour, which can lead to
interoperability issues, this form may only be fetched or set for the
following header fields:
* Message-ID
* In-Reply-To
* References
* Resent-Message-ID
* Any header not defined in [@!RFC5322] or [@!RFC2369]
* *Date* The header is parsed as a date-time value, as specified in
[@!RFC5322] section 3.3, into the Date type.
To prevent obviously nonsense behaviour, which can lead to
interoperability issues, this form may only be fetched or set for the
following header fields:
* Date
* Resent-Date
* Any header not defined in [@!RFC5322] or [@!RFC2369]
* *URL* The header is parsed as a URL, as described in [@!RFC2369].
This does not include the surrounding angle brackets or any comments
in the header with the URL.
To prevent obviously nonsense behaviour, which can lead to
interoperability issues, this form may only be fetched or set for the
following header fields:
* List-Help
* List-Unsubscribe
* List-Subscribe
* List-Post
* List-Owner
* List-Archive
* Any header not defined in [@!RFC5322] or [@!RFC2369]The following low-=
level *Email* properties are specified for complete
access to the header data of the message. Where {header-field-name} is
specified within a property name, this means any series of one or more
printable ASCII characters (i.e. characters that have values between 33
and 126, inclusive), except colon. Where {header-form} is specified
within a property name, this means one of the parsed-form name
specified above.
* *headers*: EmailHeader[] (immutable) This is a list of all
[@!RFC5322] header fields, in the same order they appear in the
message. An *EmailHeader* object has the following properties:
* *name*: String The header *field name* as defined in RFC5322, with
the same capitalization that it has in the message.
* *value*: String The header *field value* as defined in RFC5322, in
*Raw* form.
* *header:{header-field-name}*: String|null (immutable) The value of
the *last* header field in the message with the given header field
name (matched case-insensitively), or null if none. The value is in
*Raw* form.
* *header:{header-field-name}:as{header-form}*: String|null (immutable)
The value of the *last* header field in the message with the given
header field name (matched case-insensitively), or null if none,
decoded according to the parsing algorithm given.The following convenien=
ce properties are also specified for the
*Email* object:
* *messageId*: MsgIds[] (immutable) The value is identical to the value
of *header:Message-ID:asMessageIds*.
* *inReplyTo*: MsgIds[] (immutable) The value is identical to the value
of *header:In-Reply-To:asMessageIds*.
* *references*: MsgIds[] (immutable) The value is identical to the
value of *header:References:asMessageIds*.
* *sender*: EmailAddress[]|null (immutable) The value is identical to
the value of *header:Sender:asAddresses*.
* *from*: EmailAddress[]|null (immutable) The value is identical to the
value of *header:From:asAddresses*.
* *to*: EmailAddress[]|null (immutable) The value is identical to the
value of *header:To:asAddresses*.
* *cc*: EmailAddress[]|null (immutable) The value is identical to the
value of *header:Cc:asAddresses*.
* *bcc*: EmailAddress[]|null (immutable) The value is identical to the
value of *header:Bcc:asAddresses*.
* *replyTo*: EmailAddress[]|null (immutable) The value is identical to
the value of *header:Reply-To:asAddresses*.
* *subject*: String|null (immutable) The value is identical to the
value of *header:Subject:asText*.
* *sentAt*: Date (immutable; default on creation: current time on
server) The value is identical to the value of *header:Date:asDate*.Body=
parts
These properties are derived from the [@!RFC5322] message body and its
[@RFC2045] MIME entities.A *EmailBodyPart* object has the following propert=
ies:
* *partId*: String Identifies this part uniquely within the Email. This
is scoped to the *emailId* and has no meaning outside of the JMAP
Email object representation.
* *blobId*: String The id references the raw octets of the contents of
the part after decoding any *Content-Transfer* encoding (as defined
in [@!RFC2045]). Note, two parts may be transfer-encoded differently
but have same the same blob id if their decoded octets are identical
and the server is using a secure hash of the data for the blob id.
* *size*: Number The size, in octets, of the raw data after content-
transfer decoding (as referenced by the *blobId*, i.e. the number of
octets in the file the user would download).
* *headers*: EmailHeader[] (immutable) This is a list of all header
fields in the part, in the order they appear. The values are in
*Raw* form.
* *name*: String|null This is the [@!RFC2231] decoded *filename*
parameter of the *Content-Disposition* header field, or (for
compatibility with existing systems) if not present then the
[@!RFC2047] decoded *name* parameter of the *Content-Type*
header field.
* *type*: String The value of the *Content-Type* header field of the
part, if present, otherwise null. CFWS is removed and any parameters
are stripped.
* *charset*: String|null The value of the charset parameter of the *Conten=
t-
Type* header field, if present.
* *disposition*: String|null The value of the *Content-Disposition*
header field of the part, if present, otherwise null. CFWS is removed
and any parameters are stripped.
* *cid*: String|null The value of the *Content-Id* header field of the
part, if present, otherwise null. CFWS is removed. This may be used
to reference the content from within an html body part using the
cid: protocol.
* *language*: String[]|null The list of language tags, as defined in
[@!RFC3282], in the *Content-Language* header field of the part,
if present.
* *location*: String|null The URI, as defined in [@!RFC2557], in the
*Content-Location* header field of the part, if present.
* *width*: Number|null The width (in px) of the image, if the type is
an image and the server is able to determine this information for
the image. This MAY not be supported for all or any image types on
some servers.
* *height*: Number|null The height (in px) of the image, if the type
is an image and the server is able to determine this information for
the image. This MAY not be supported for all or any image types on
some servers.
* *subParts*: EmailBodyPart[] (optional) If type is multipart/*, this
contains the body parts of each child.The following *Email* properties a=
re specified for access to the body
data of the message:
* *bodyStructure*: EmailBodyPart[] (immutable) This is the full MIME
structure of the message body, including sub parts but not recursing
into message/rfc822 or message/global parts.
* *bodyValues*: String[BodyValue] (immutable) This is a map of *partId*
to an *EmailBodyValue* object for none, some or all text/* parts.
Which parts are included and whether the value is truncated is
determined by various arguments to *Email/get* and *Email/parse*.
An *EmailBodyValue* object has the following properties:
* *value*: String The value of the body part after decoding *Content-Tra=
nsport-
Encoding* and decoding the *Content-Type* charset, if known to the
server. The server MAY use heuristics to determine the charset to
use for decoding if the charset is unknown, or if no charset is
given, or if it believes the charset given is incorrect. Decoding
is best-effort and SHOULD insert the unicode replacement character
(U+FFFD) and continue when a malformed section is encountered.
* *isEncodingProblem*: Boolean This is true if malformed sections
were found while decoding the charset, or the charset was unknown.
* *isTruncated*: Boolean This is true if the *value* has been
truncated.
* *textBody*: EmailBodyPart[] (immutable) A list of text/plain,
text/html and image/* parts to display (sequentially) as the message
body, with a preference for text/plain when alternative versions are
available.
* *htmlBody*: EmailBodyPart[] (immutable) A list of text/plain,
text/html and image/* parts to display (sequentially) as the message
body, with a preference for text/html when alternative versions are
available.
* *attachedEmails*: EmailBodyPart[] (immutable) A list of all parts of
type message/rfc822 or message/global. Note, this *does not* recurse,
so the parts within these are not included. The attached message may
be fetched using the Email/parse method and the blobId.
* *attachedFiles*: EmailBodyPart[] (immutable) A list of all parts in
*bodyStructure*, traversing depth-first, not of type multipart/*, and
not included in any of the *textBody*, *htmlBody* or *attachedEmails*
properties. Note, an HTML body part may reference image parts in
attachedFiles using cid: links to reference the *Content-Id* or by
referencing the *Content-Location*.
* *hasAttachment*: Boolean (immutable; server-set) This is true if
there are one or more parts in the message that a client UI should
offer as downloadable. A server SHOULD set hasAttachment if either:
* The *attachedEmails* list contains at least one item.
* The *attachedFiles* list contains at least one item that does not
have Content-Disposition: inline. The server MAY ignore parts in
this list that are processed automatically in some way, or are
referenced as embedded images in one of the text/html parts of the
message. The server MAY set hasAttachment based on implementation-
defined or site configurable heuristics.
* *preview*: String (immutable; server-set) Up to 256 characters of
plain text, summarising the message body. This is intended to be
shown as a preview line on a mailbox listing, and may be
truncated when shown. The server may choose which part of the
message to include in the preview, for example skipping quoted
sections and salutations and collapsing white-space can result in
a more useful preview.MIME structures are arbitrary nested trees of docu=
ments, but the
majority of email clients present a model of an email body (normally
plain text or HTML), with a set of attachments. Interpreting the MIME
structure to form this flat model represents considerable difficulty and
causes inconsistency between clients. Therefore in addition to the
*bodyStructure* property, which gives the full tree, the Email object
contains 4 alternate properties with flat lists of body parts:
* *textBody*/*htmlBody*: These provide a list of parts that should be
rendered as the "body" of the message. This is a list rather than a
single part as messages may have headers and/or footers
appended/prepended as separate parts as they are transmitted, and
some clients send text and images intended to be displayed inline in
the body as multiple parts rather than a single HTML part with
referenced images.
Because MIME allows for multiple representations of the same data (using
multipart/alternative), there is a textBody property (which prefers a
plain text representation) and an htmlBody property (which prefers an
HTML representation) to accommodate the two most common client
requirements. The same part may appear in both lists where there is no
alternative between the two.
* *attachedEmails*/*attachedFiles*: These provide a list of parts that
should be presented as "attachments" to the message. Emails are
presented in a separate list so their contents may be easily fetched
via a back-reference with the Email/parse method in the same request,
if the client wishes to. Some images in attachedFiles may be solely
there for embedding within an HTML body part; clients may wish to not
present these as attachments in the user interface if they are
displaying the HTML with the embedded images directly.The *bodyValues* p=
roperty allows for clients to fetch the value of text
parts directly without having to do a second request for the blob, and
have the server handle decoding the charset into unicode. This data is
in a separate property rather than on the EmailBodyPart object to avoid
duplication of large amounts of data, as the same part may be included
twice if the client fetches more than one of bodyStructure, textBody
and htmlBody.The exact algorithm for decomposing bodyStructure into textBod=
y,
htmlBody, attachedEmails and attachedFiles part lists is not mandated,
as this is a quality-of-service implementation issue and likely to
require workarounds for malformed content discovered over time.However, we =
will define a suggested algorithm for the RFC to help
implementors. TODO.Email/get
Standard */get* method, with the following additional arguments:
* *bodyProperties*: String[] (optional) A list of properties to fetch
for each EmailBodyPart returned. If omitted, this defaults to:
[ "partId", "blobId", "size", "name", "type", "charset", "disposition",
cid", "language", "location", "width", "height" ]
* *fetchTextBodyValues*: Boolean (default: false) If true, the
*bodyValues* property includes any text/* part in the textBody
property.
* *fetchHTMLBodyValues*: Boolean (default: false) If true, the
*bodyValues* property includes any text/* part in the htmlBody
property.
* *fetchAllBodyValues*: Boolean (default: false) If true, the
*bodyValues* property includes any text/* part in the
bodyStructure property.
* *maxBodyValueBytes*: Number (optional) If supplied by the client, the
value MUST be a positive integer greater than 0. If a value outside
of this range is given, the server MUST reject the call with an
invalidArguments error. When given, the *value* property of any
EmailBodyValue object returned in *bodyValues* MUST be truncated if
necessary so it does not exceed this number of octets in size. The
server MUST ensure the truncation results in valid UTF-8 and does not
occur mid-codepoint. If the part is of type text/html, the server
SHOULD NOT truncate inside an HTML tag.If the standard *properties* argu=
ment is omitted or null, the following
default MUST be used instead of "all" properties:
[ "id", "blobId", "threadId", "mailboxIds", "keywords", "size",
"receivedAt", "messageId", "inReplyTo", "references", "sender", "from",
"to", "cc", "bcc", "replyTo", "subject", "sentAt", "hasAttachment",
"preview", "bodyValues", "textBody", "htmlBody", "attachedFiles",
"attachedEmails" ]The following properties are expected to be fast to fetch=
in a quality
implementation:
* id
* blobId
* threadId
* mailboxIds
* keywords
* size
* receivedAt
* messageId
* inReplyTo
* sender
* from
* to
* cc
* bcc
* replyTo
* subject
* sentAt
* hasAttachment
* previewClients SHOULD take care when fetching any other properties, as t=
here
may be significantly longer latency in fetching and returning the data.As s=
pecified above, parsed forms of headers may only be used on
appropriate header fields. Attempting to fetch a form that is forbidden
(e.g. header:From:asDate) MUST result in the method call being rejected
with an invalidArguments error.Where a specific header is requested as a pr=
operty, the capitalization
of the property name in the response MUST be identical to that used in
the request.Example
Request:
["Email/get", { "ids": [ "f123u456", "f123u457" ], "properties": [
"threadId", "mailboxIds", "from", "subject", "receivedAt", "header:List-
POST:asURL" "htmlBody", "bodyValues" ], "bodyProperties": [ "partId",
"blobId", "size", "type" ], "fetchHTMLBodyValues": true,
"maxBodyValueBytes": 256 }, "#1"]and response:
["Email/get", { "accountId": "abc", "state": "41234123231", "list":
[ { "id": "f123u457", "threadId": "ef1314a", "mailboxIds": { "f123":
true }, "from": [{name: "Joe Bloggs", email: "joe@bloggs.com"}],
"subject": "Dinner on Thursday?", "receivedAt": "2013-10-
13T14:12:00Z", "header:List-POST:asURL":
"mailto:partytime@lists.example.com", "htmlBody": [{ "partId": "1",
"blobId": "841623871", "size": 283331, "type": "text/html" }, {
"partId": "2", "blobId": "319437193", "size": 10343, "type":
"text/plain" }], "bodyValues": { "1": { "isEncodingProblem": false,
"isTruncated": true, "value": "Hello ..." }, "2": {
"isEncodingProblem": false, "isTruncated": false, "value": "--
\nSent by your friendly mailing list ..." } } } ], notFound: [
"f123u456" ] }, "#1"]
Links:
1. https://github.com/jmapio/jmap/commits/emailformat
2. https://www.iana.org/assignments/imap-keywords/imap-keywords.xhtml
--_----------=_151842040710121310
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset="utf-8"
Cheers,
Neil.
-------
The Email object is a representation of an [@!RFC5322] message, w=
hich allows clients to avoid the complexities of MIME parsing, transport en=
coding and character encoding.
Properties of the Email object
Broadly, a message consists of t=
wo parts: a list of header fields, then a body. The body is normally a MIME=
-encoded set of documents in a tree structure. The JMAP Email object provid=
es a way to access the full structure, or to use simplified properties and =
avoid some complexity if this is sufficient for the client application.
=
Due to the number of properties involved, the set of Email pr=
operties is specified over the following three sub-sections.
These properties represent metadata about=
the [@!RFC5322] message, and are not derived from parsing the message itse=
lf.
id: String
(immutable; server-set)
The id of the Email object. Note, this is the JMAP object id, NOT the [@!RF=
C5322] Message-ID header field value.
blobId: String (immutable; server-set)
The id representing the raw octets of the [@!RFC5322] message. This may be =
used to download the raw original message, or to attach it directly to anot=
her Email etc.
threadId: String
(imm=
utable; server-set)
The id of the Thread to which this Email belongs.
mai=
lboxIds: String[Boolean]
The set of mailbox ids this email=
belongs to. An email MUST belong to one or more mailboxes at all times (un=
til it is deleted). The set is represented as an object, with each key bein=
g a Mailbox id. The value for each key in the object MUST be t=
rue
.
keywords: String[Boolean]
(default: {}
)
A set of keywords that apply to the email. The set is represented as an obj=
ect, with the keys being the keywords. The value for each key in the=
object MUST be true
.
Keywords are shared with IMAP.=
The six system keywords from IMAP are treated specially. The following fou=
r keywords have their first character changed from \
in IMAP t=
o $
in JMAP and have particular semantic meaning:
<=
li>$draft
: The email is a draft the user is composing.
$seen
: The email has been read.
$flagge=
d
: The email has been flagged for urgent/special attention.
=
$answered
: The email has been replied to.
=
The IMAP \Recent
keyword is not exposed via JMAP. The IMAP \Deleted keyword is also not present: IMAP uses a delete+expunge =
model, which JMAP does not. Any message with the \Deleted
keyw=
ord MUST NOT be visible via JMAP.
Users may add arbitrary keyword=
s to an email. For compatibility with IMAP, a keyword is a case-insensitive=
string of 1=E2=80=93255 characters in the ASCII subset %x21=E2=80=93%x7e (=
excludes control chars and space), and MUST NOT include any of these charac=
ters: ( ) { ] % * " \
Because JSON is case-sensitive=
, servers MUST return keywords in lower-case.
The IANA Keywor=
d Registry as established in [@!RFC5788] assigns semantic meaning to so=
me other keywords in common use. New keywords may be established here in th=
e future. In particular, note:
$forwarded
: The =
email has been forwarded.
$phishing
: The email is =
highly likely to be phishing. Clients SHOULD warn users to take care when v=
iewing this email and disable links and attachments.
$jun=
k
: The email is definitely spam. Clients SHOULD set this flag when u=
sers report spam to help train automated spam-detection systems.
$notjunk
: The email is definitely not spam. Clients SHOULD s=
et this flag when users indicate an email is legitimate, to help train auto=
mated spam-detection systems.
size: N=
umber
(immutable; server-set)
The size, in octets, of the raw data for the RFC5322 message (as referenced=
by the blobId, i.e. the number of octets in the file the user would=
download).
receivedAt: UTCDate
(imm=
utable; default: time of creation on server)
The date the email was received by the message store. This is the intern=
al date in IMAP.
These properties are derived from the [@!RFC5322] and [@!RFC653=
2] message header fields. All header fields may be fetched in a raw form. S=
ome headers may also be fetched in a parsed form. The structured form that =
may be fetched depends on the header. The following forms are defined:
<=
/p>
Raw The raw octets of the header field value from the =
first octet following the header field name terminating colon, up to but ex=
cluding the header field terminating CRLF. Any standards-compliant message =
MUST be either ASCII (RFC5322) or UTF-8 (RFC6532), however other encodings =
exist in the wild. A server MAY use heuristics to determine a charset and d=
ecode the octets, or MAY replace any octet or octet run with the high bit s=
et that violates UTF-8 syntax with the unicode replacement character (U+FFF=
D). Any NUL octet MUST be dropped.
Text The heade=
r field value with:
- White space unfolded (as defined in [@!R=
FC5322] section 2.2.3)
- The terminating CRLF at the end of the v=
alue removed
- Any SP characters at the beginning of the value re=
moved
- Any syntactically correct [@!RFC2047] encoded sections wi=
th a known
character set are decoded. Any [@!RFC2047] encoded NUL octets or control ch=
aracters are dropped from the decoded value. Any text that looks like [@!RF=
C2047] syntax but violates [@!RFC2047] placement or whitespace rules MUST N=
OT be decoded.
- Any [@!RFC6532] UTF-8 values decoded.
The resulting unicode is converted to NFC form.
If any de=
codings fail, the parser SHOULD insert a unicode replacement
character (U+FFFD) and attempt to continue as much as possible.
T=
o prevent obviously nonsense behaviour, which can lead to interoperability =
issues, this form may only be fetched or set for the following header field=
s:
- Subject
- Comment
- Any header not de=
fined in [@!RFC5322] or [@!RFC2369]
Addresses=
b> The header is parsed as an address-list
value, as specified=
in [@!RFC5322] section 3.4, into the EmailAddress[]
type. The=
EmailAddress object has the following properties:
- name:
String|null
The display name of the [@!RFC53=
22] mailbox or group, or null
if none.
<=
li>email: String|null
The addr-spec of the [@!RF=
C5322] mailbox, or null
if a group.
Any syntactically correct [@!RFC2047] encoded sections with a known enc=
oding MUST be decoded, following the same rules as for the Text form=
. Any [@!RFC6532] UTF-8 values MUST be decoded.
Parsing SHOULD be=
best-effort in the face of invalid structure to accommodate
invalid messages and semi-complete drafts. EmailAddress objects MAY have an=
email property that does not conform to the addr-spec form (=
for example, may not contain an @ symbol).
To prevent obviously n=
onsense behaviour, which can lead to interoperability issues, this form may=
only be fetched or set for the following header fields:
- Fro=
m
- Sender
- Reply-To
- To
- Cc
=
- Bcc
- Resent-From
- Resent-Sender
- =
Resent-Reply-To
- Resent-To
- Resent-Cc
- Res=
ent-Bcc
- Any header not defined in [@!RFC5322] or [@!RFC2369]
MessageIds The header is parsed as a list of =
msg-id
values, as specified in [@!RFC5322] section 3.6.5, into=
the String[]
type.
To prevent obviously nonsense be=
haviour, which can lead to interoperability issues, this form may only be f=
etched or set for the following header fields:
- Message-ID
- In-Reply-To
- References
- Resent-Message-ID<=
br>
- Any header not defined in [@!RFC5322] or [@!RFC2369]
=
ul>
Date The header is parsed as a date-time
=
value, as specified in [@!RFC5322] section 3.3, into the Date
=
type.
To prevent obviously nonsense behaviour, which can lead to=
interoperability issues, this form may only be fetched or set for the foll=
owing header fields:
- Date
- Resent-Date
Any header not defined in [@!RFC5322] or [@!RFC2369]
URL The header is parsed as a URL, as described in [@!RFC2369].=
This does not include the surrounding angle brackets or any comments in th=
e header with the URL.
To prevent obviously nonsense behaviour, w=
hich can lead to interoperability issues, this form may only be fetched or =
set for the following header fields:
- List-Help
- L=
ist-Unsubscribe
- List-Subscribe
- List-Post
List-Owner
- List-Archive
- Any header not defined in=
[@!RFC5322] or [@!RFC2369]
The following low-lev=
el Email properties are specified for complete access to the header =
data of the message. Where {header-field-name}
is specified wi=
thin a property name, this means any series of one or more printable ASCII =
characters (i.e. characters that have values between 33 and 126, inclusive)=
, except colon. Where {header-form}
is specified within a prop=
erty name, this means one of the parsed-form name specified above.
<=
ul>headers: EmailHeader[]
(immutable)
This is a list of all [@!RFC5322] header fields, in the same order they app=
ear in the message. An EmailHeader object has the following properti=
es:
- name:
String
The header field nam=
e as defined in RFC5322, with the same capitalization that it has in th=
e message.
- value:
String
The header fiel=
d value as defined in RFC5322, in Raw form.
header:{header-field-name}: String|null
(immutable)
The value of the last header field in the message with the given hea=
der field name (matched case-insensitively), or null
if none. =
The value is in Raw form.
header:{header-field=
-name}:as{header-form}: String|null
(immutable)
The value of the last header field in the message with the given hea=
der field name (matched case-insensitively), or null
if none, =
decoded according to the parsing algorithm given.
The f=
ollowing convenience properties are also specified for the Email obj=
ect:
- messageId:
MsgIds[]
(immutable)
The value is identical to the value of header:Message-ID:asMessageIds.
- inReplyTo:
MsgIds[]
(immutable)
The value is identical to the value of header:In-Reply-To:asMessageIds=
i>.
- references:
MsgIds[]
(immutable)
The value is identical to the value of header:References:asMessageIds.
- sender:
EmailAddress[]|null
(immutable)
The value is identical to the value of header:Sender:asAddresses.
- from:
EmailAddress[]|null
(immutable)
The value is identical to the value of header:From:asAddresses.
<=
/li> - to:
EmailAddress[]|null
(immutable)
The value is identical to the value of header:To:asAddresses.
cc: EmailAddress[]|null
(immutable)
The value is identical to the value of header:Cc:asAddresses.
bcc: EmailAddress[]|null
(immutable)
The value is identical to the value of header:Bcc:asAddresses.
=
li>replyTo: EmailAddress[]|null
(immutable)
The value is identical to the value of header:Reply-To:asAddresses.<=
br>subject: String|null
(immutable)
The value is identical to the value of header:Subject:asText.
sentAt: Date
(immutable; default on creation: cur=
rent time on server)
The value is identical to the value of header:Date:asDate.
<=
/ul>Body parts
These properties are derived=
from the [@!RFC5322] message body and its [@RFC2045] MIME entities.
A EmailBodyPart object has the following properties:
=
- partId:
String
Identifies this part uniquely within=
the Email. This is scoped to the emailId and has no meaning outside=
of the JMAP Email object representation.
- blobId:
=
String
The id references the raw octets of the contents of the part =
after decoding any Content-Transfer encoding (as defined in [@!RFC20=
45]). Note, two parts may be transfer-encoded differently but have same the=
same blob id if their decoded octets are identical and the server is using=
a secure hash of the data for the blob id.
- size:
=
Number
The size, in octets, of the raw data after content-transfer d=
ecoding (as referenced by the blobId, i.e. the number of octets in t=
he file the user would download).
- headers:
EmailHe=
ader[]
(immutable)
This is a list of all header fields in the part, in the order they appear. =
The values are in Raw form.
- name:
String|nu=
ll
This is the [@!RFC2231] decoded filename parameter of the =
Content-Disposition header field, or (for compatibility with existin=
g systems) if not present then the [@!RFC2047] decoded name paramete=
r of the Content-Type header field.
- type:
S=
tring
The value of the Content-Type header field of the part,=
if present, otherwise null
. CFWS is removed and any parameter=
s are stripped.
- charset:
String|null
The va=
lue of the charset parameter of the Content-Type header field, if pr=
esent.
- disposition:
String|null
The value o=
f the Content-Disposition header field of the part, if present, othe=
rwise null
. CFWS is removed and any parameters are stripped. - cid:
String|null
The value of the Content=
-Id header field of the part, if present, otherwise null
. =
CFWS is removed. This may be used to reference the content from within an h=
tml body part using the cid:
protocol.
- language=
:
String[]|null
The list of language tags, as defined in [=
@!RFC3282], in the Content-Language header field of the part, if pre=
sent.
- location:
String|null
The URI, as def=
ined in [@!RFC2557], in the Content-Location header field of the par=
t, if present.
- width:
Number|null
The width=
(in px) of the image, if the type is an image and the server is able to de=
termine this information for the image. This MAY not be supported for all o=
r any image types on some servers.
- height:
Number|=
null
The height (in px) of the image, if the type is an image and th=
e server is able to determine this information for the image. This MAY not =
be supported for all or any image types on some servers.
- sub=
Parts:
EmailBodyPart[]
(optional)
If type is multipart/*
, this contains the body parts of each c=
hild.
The following Email properties are specified f=
or access to the body data of the message:
bodyStructu=
re: EmailBodyPart[]
(immutable)
This is the full MIME structure of the message body, including sub parts bu=
t not recursing into message/rfc822
or message/global parts.
bodyValues: String[BodyValue]=
code> (immutable)
This is a map of partId to an EmailBodyValue object for none,=
some or all text/*
parts. Which parts are included and whethe=
r the value is truncated is determined by various arguments to Email/get=
and Email/parse.
An EmailBodyValue object has =
the following properties:
- value:
String
=
The value of the body part after decoding Content-Transport-Encoding=
and
decoding the Content-Type charset, if known to the server. The serve=
r MAY use heuristics to determine the charset to use for decoding if the ch=
arset is unknown, or if no charset is given, or if it believes the charset =
given is incorrect. Decoding is best-effort and SHOULD insert the unicode r=
eplacement character (U+FFFD) and continue when a malformed section is enco=
untered.
- isEncodingProblem:
Boolean
This is=
true
if malformed sections were found while decoding the char=
set, or the charset was unknown.
- isTruncated:
Bool=
ean
This is true
if the value has been truncated=
.
textBody: EmailBodyPart[]
(i=
mmutable)
A list of text/plain
, text/html
and image/*=
parts to display (sequentially) as the message body, with a prefere=
nce for text/plain
when alternative versions are available.
htmlBody: EmailBodyPart[]
(immutable)
A list of text/plain
, text/html
and image/*=
parts to display (sequentially) as the message body, with a prefere=
nce for text/html
when alternative versions are available.
=
attachedEmails: EmailBodyPart[]
(immuta=
ble)
A list of all parts of type message/rfc822
or message/gl=
obal
. Note, this does not recurse, so the parts within these =
are not included. The attached message may be fetched using the Email/parse=
method and the blobId.
attachedFiles: Emai=
lBodyPart[]
(immutable)
A list of all parts in bodyStructure, traversing depth-first, not of=
type multipart/*
, and not included in any of the textBody<=
/i>, htmlBody or attachedEmails properties. Note, an HTML bod=
y part may reference image parts in attachedFiles using cid:
l=
inks to reference the Content-Id or by referencing the Content-Lo=
cation.
hasAttachment: Boolean
(=
immutable; server-set)
This is true
if there are one or more parts in the message tha=
t a client UI should offer as downloadable. A server SHOULD set hasAttachme=
nt if either:
- The attachedEmails list contains at lea=
st one item.
- The attachedFiles list contains at least on=
e item that does not have
Content-Disposition: inline
. The ser=
ver MAY ignore parts in this list that are processed automatically in some =
way, or are referenced as embedded images in one of the text/html parts of the message.
The server MAY set hasAttachment =
based on implementation-defined or site configurable heuristics.
preview: String
(immutable; server-set)
Up to 256 characters of plain text, summarising the message body. This is i=
ntended to be shown as a preview line on a mailbox listing, and may be trun=
cated when shown. The server may choose which part of the message to includ=
e in the preview, for example skipping quoted sections and salutations and =
collapsing white-space can result in a more useful preview.
MIME structures are arbitrary nested trees of documents, but the major=
ity of email clients present a model of an email body (normally plain text =
or HTML), with a set of attachments. Interpreting the MIME structure to for=
m this flat model represents considerable difficulty and causes inconsisten=
cy between clients. Therefore in addition to the bodyStructure prope=
rty, which gives the full tree, the Email object contains 4 alternate prope=
rties with flat lists of body parts:
textBody/h=
tmlBody: These provide a list of parts that should be
rendered as the "body" of the message. This is a list rather than a single =
part as messages may have headers and/or footers appended/prepended as sepa=
rate parts as they are transmitted, and some clients send text and images i=
ntended to be displayed inline in the body as multiple parts rather than a =
single HTML part with referenced images.
Because MIME allows for =
multiple representations of the same data (using multipart/alternativ=
e
), there is a textBody property (which prefers a plain text represe=
ntation) and an htmlBody property (which prefers an HTML representation) to=
accommodate the two most common client requirements. The same part may app=
ear in both lists where there is no alternative between the two.
attachedEmails/attachedFiles: These provide a list o=
f parts that should
be presented as "attachments" to the message. Emails are presented in a sep=
arate list so their contents may be easily fetched via a back-reference wit=
h the Email/parse
method in the same request, if the client wi=
shes to. Some images in attachedFiles may be solely there for embedding wit=
hin an HTML body part; clients may wish to not present these as attachments=
in the user interface if they are displaying the HTML with the embedded im=
ages directly.
The bodyValues property allows fo=
r clients to fetch the value of text parts directly without having to do a =
second request for the blob, and have the server handle decoding the charse=
t into unicode. This data is in a separate property rather than on the Emai=
lBodyPart object to avoid duplication of large amounts of data, as the same=
part may be included twice if the client fetches more than one of bodyStru=
cture, textBody and htmlBody.
The exact algorithm for decomposing=
bodyStructure into textBody, htmlBody, attachedEmails and attachedFiles pa=
rt lists is not mandated, as this is a quality-of-service implementation is=
sue and likely to require workarounds for malformed content discovered over=
time.
However, we will define a suggested algorithm for the RFC =
to help implementors. TODO.
Email/get
Standard /get method, with the following additional arguments:
<=
/p>
bodyProperties: String[]
(optional)
A list of properties to fetch for each EmailBodyPart returned. If omitted, =
this defaults to:
[ "partId", "blobId", "size", "name", "type", "=
charset", "disposition", cid", "language", "location", "width", "height" ]<=
br>
fetchTextBodyValues: Boolean
(defaul=
t: false
)
If true
, the bodyValues property includes any tex=
t/*
part in the textBody
property.
<=
b>fetchHTMLBodyValues: Boolean
(default: false
)
If true
, the bodyValues property includes any tex=
t/*
part in the htmlBody
property.
<=
b>fetchAllBodyValues: Boolean
(default: false
)
If true
, the bodyValues property includes any tex=
t/*
part in the bodyStructure
property.
maxBodyValueBytes: Number
(optional)
If supplied by the client, the value MUST be a positive integer greater tha=
n 0. If a value outside of this range is given, the server MUST reject the =
call with an invalidArguments
error. When given, the value<=
/i> property of any EmailBodyValue object returned in bodyValues MUS=
T be truncated if necessary so it does not exceed this number of octets in =
size. The server MUST ensure the truncation results in valid UTF-8 and does=
not occur mid-codepoint. If the part is of type text/html
, th=
e server SHOULD NOT truncate inside an HTML tag.
If the=
standard properties argument is omitted or null
, the f=
ollowing default MUST be used instead of "all" properties:
[ "id", "blobId", "threadId", "mailboxIds", "keywords", "size", "received=
At", "messageId", "inReplyTo", "references", "sender", "from", "to", "cc", =
"bcc", "replyTo", "subject", "sentAt", "hasAttachment", "preview", "bodyVal=
ues", "textBody", "htmlBody", "attachedFiles", "attachedEmails" ]
The following properties are expected to be fast to fet=
ch in a quality implementation:
- id
- blobId
- threadId
- mailboxIds
- keywords
- size=
- receivedAt
- messageId
- inReplyTo
- sender
- from
- to
- cc
- bcc<=
br>
- replyTo
- subject
- sentAt
- hasA=
ttachment
- preview
Clients SHOULD take care when=
fetching any other properties, as there may be significantly longer latenc=
y in fetching and returning the data.
As specified above, parsed =
forms of headers may only be used on appropriate header fields. Attempting =
to fetch a form that is forbidden (e.g. header:From:asDate
) MU=
ST result in the method call being rejected with an invalidArguments<=
/code> error.
Where a specific header is requested as a property,=
the capitalization of the property name in the response MUST be identical =
to that used in the request.
Example
R=
equest:
["Email/get", {
"ids": [ "f123u456", "f123u457" ],
"properties": [ "threadId", "mailboxIds", "from", "subject", "receivedAt"=
, "header:List-POST:asURL" "htmlBody", "bodyValues" ],
"bodyProperties": [ "partId", "blobId", "size", "type" ],
"fetchHTMLBodyValues": true,
"maxBodyValueBytes": 256
}, "#1"]
and response:
["Email/get", {
"accountId": "abc",
"state": "41234123231",
"list": [
{
"id": "f123u457",
"threadId": "ef1314a",
"mailboxIds": { "f123": true },
"from": [{name: "Joe Bloggs", email: "joe@bloggs.com"}],
"subject": "Dinner on Thursday?",
"receivedAt": "2013-10-13T14:12:00Z",
"header:List-POST:asURL": "mailto:partytime@lists.example.com",
"htmlBody": [{
"partId": "1",
"blobId": "841623871",
"size": 283331,
"type": "text/html"
}, {
"partId": "2",
"blobId": "319437193",
"size": 10343,
"type": "text/plain"
}],
"bodyValues": {
"1": {
"isEncodingProblem": false,
"isTruncated": true,
"value": "<html><body><p>Hello ..."
},
"2": {
"isEncodingProblem": false,
"isTruncated": false,
"value": "-- \nSent by your friendly mailing list ..."
}
}
}
],
notFound: [ "f123u456" ]
}, "#1"]
--_----------=_151842040710121310--
From nobody Mon Feb 12 11:58:03 2018
Return-Path:
X-Original-To: jmap@ietfa.amsl.com
Delivered-To: jmap@ietfa.amsl.com
Received: from localhost (localhost [127.0.0.1]) by ietfa.amsl.com (Postfix) with ESMTP id 21F9912D94D for ; Mon, 12 Feb 2018 11:57:58 -0800 (PST)
X-Virus-Scanned: amavisd-new at amsl.com
X-Spam-Flag: NO
X-Spam-Score: -2.031
X-Spam-Level:
X-Spam-Status: No, score=-2.031 tagged_above=-999 required=5 tests=[BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, RCVD_IN_MSPIKE_H4=-0.01, RCVD_IN_MSPIKE_WL=-0.01, SPF_PASS=-0.001, T_RP_MATCHES_RCVD=-0.01] autolearn=ham autolearn_force=no
Authentication-Results: ietfa.amsl.com (amavisd-new); dkim=pass (2048-bit key) header.d=oracle.com
Received: from mail.ietf.org ([4.31.198.44]) by localhost (ietfa.amsl.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id Em6u8LbiXqE3 for ; Mon, 12 Feb 2018 11:57:54 -0800 (PST)
Received: from aserp2130.oracle.com (aserp2130.oracle.com [141.146.126.79]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ietfa.amsl.com (Postfix) with ESMTPS id 9F5C412D94C for ; Mon, 12 Feb 2018 11:57:49 -0800 (PST)
Received: from pps.filterd (aserp2130.oracle.com [127.0.0.1]) by aserp2130.oracle.com (8.16.0.22/8.16.0.22) with SMTP id w1CJvig4060386; Mon, 12 Feb 2018 19:57:44 GMT
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oracle.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-type; s=corp-2017-10-26; bh=XmQLkcWhYc7z+xbfoxh5I6+d/nGcfmbEupNi9EvJ2GQ=; b=Z9BpoDaPnM2OejrxPtZBmMQ44upKTvYbNZR8v04ZIjyt7P9qfmBP15GNTEceeBKCRFVs aNrhFih6+5kcB7vEurYQz97Rjuslgb8oO9xNSY8w5W2hUL4TQpTMRDAKawSaUZku/t5t Ej5HxGhqERMhvYOXY0Qfmcx1ajxEHn0ZMY32/Wgm2peDCQCY6GYCm7XGJRpvDtioDETj CMyUYqH8zyzu0RVD6wHkedUrwJdLUEX5FHKTlJCWyDHw+EjqeMOTnCThXM1pZzX+QhgB ASRq9qV8jIy5E8nHUAyqfP0s9ybP8Z4h3zWmaXzTrQk4zWM7+3zQ5D7S3ainT9RTezzf 0g==
Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by aserp2130.oracle.com with ESMTP id 2g3h7f03sv-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Mon, 12 Feb 2018 19:57:44 +0000
Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by aserv0022.oracle.com (8.14.4/8.14.4) with ESMTP id w1CJvUxC019225 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Mon, 12 Feb 2018 19:57:30 GMT
Received: from abhmp0016.oracle.com (abhmp0016.oracle.com [141.146.116.22]) by userv0121.oracle.com (8.14.4/8.13.8) with ESMTP id w1CJvTja006672; Mon, 12 Feb 2018 19:57:30 GMT
Received: from [10.145.239.150] (/10.145.239.150) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Mon, 12 Feb 2018 11:57:29 -0800
From: "Chris Newman"
To: "Neil Jenkins"
Cc: "IETF JMAP Mailing List"
Date: Mon, 12 Feb 2018 11:57:25 -0800
X-Mailer: MailMate (1.10r5443)
Message-ID: <60D63DE9-FC7F-430B-9C0E-42639F83C0F8@oracle.com>
In-Reply-To: <1518420407.1012131.1267607120.3E7422B3@webmail.messagingengine.com>
References: <1518070284.168650.1263633200.05C7397A@webmail.messagingengine.com> <1518408506.1699741.1267466096.17DCF605@webmail.messagingengine.com> <1518419708.1006757.1267595536.799BEEC0@webmail.messagingengine.com> <1518420407.1012131.1267607120.3E7422B3@webmail.messagingengine.com>
MIME-Version: 1.0
Content-Type: text/plain; format=flowed
X-Proofpoint-Virus-Version: vendor=nai engine=5900 definitions=8803 signatures=668668
X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 suspectscore=0 malwarescore=0 phishscore=0 bulkscore=0 spamscore=0 mlxscore=0 mlxlogscore=999 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1711220000 definitions=main-1802120254
Archived-At:
Subject: Re: [Jmap] New JSON message representation
X-BeenThere: jmap@ietf.org
X-Mailman-Version: 2.1.22
Precedence: list
List-Id: JSON Message Access Protocol
List-Unsubscribe: ,
List-Archive:
List-Post:
List-Help:
List-Subscribe: ,
X-List-Received-Date: Mon, 12 Feb 2018 19:57:58 -0000
On 11 Feb 2018, at 23:26, Neil Jenkins wrote:
> An *EmailBodyValue* object has the following properties:
>
>
> * *value*: String The value of the body part after decoding
> *Content-Transport-
> Encoding* and decoding the *Content-Type* charset, if known to
> the
> server. The server MAY use heuristics to determine the charset to
> use for decoding if the charset is unknown, or if no charset is
> given, or if it believes the charset given is incorrect. Decoding
> is best-effort and SHOULD insert the unicode replacement
> character
> (U+FFFD) and continue when a malformed section is encountered.
I'm fine with this approach, but this does have security considerations.
I suggest adding to this section:
"See the security considerations section for issues related to heuristic
determination of content-type and charset."
and here's suggested text for the security considerations:
---
Service providers typically perform security filtering on incoming email
and it's important the detection of content-type and charset for the
security filter aligns with the heuristics performed by JMAP servers.
Servers that apply heuristics to determine the content-type or charset
for *EmailBodyValue* SHOULD document the heuristics and provide a
mechanism to turn them off in the event they are misaligned with the
security filter used at a particular site. Automatic conversion of
charsets that allow hidden channels for ASCII text, such as UTF-7, have
been problematic for security filters in the past so server
implementations can mitigate this risk by having such conversions
off-by-default and/or separately configurable.
---
- Chris
From nobody Mon Feb 12 15:19:32 2018
Return-Path:
X-Original-To: jmap@ietfa.amsl.com
Delivered-To: jmap@ietfa.amsl.com
Received: from localhost (localhost [127.0.0.1]) by ietfa.amsl.com (Postfix) with ESMTP id 0EC0D126C25 for ; Mon, 12 Feb 2018 15:19:31 -0800 (PST)
X-Virus-Scanned: amavisd-new at amsl.com
X-Spam-Flag: NO
X-Spam-Score: -2.72
X-Spam-Level:
X-Spam-Status: No, score=-2.72 tagged_above=-999 required=5 tests=[BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, HTML_MESSAGE=0.001, RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, SPF_PASS=-0.001] autolearn=ham autolearn_force=no
Authentication-Results: ietfa.amsl.com (amavisd-new); dkim=pass (2048-bit key) header.d=fastmailteam.com header.b=ZBQn+tNJ; dkim=pass (2048-bit key) header.d=messagingengine.com header.b=k650VNdY
Received: from mail.ietf.org ([4.31.198.44]) by localhost (ietfa.amsl.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 6B4EBoil5g8L for ; Mon, 12 Feb 2018 15:19:29 -0800 (PST)
Received: from out1-smtp.messagingengine.com (out1-smtp.messagingengine.com [66.111.4.25]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by ietfa.amsl.com (Postfix) with ESMTPS id 3C232120726 for ; Mon, 12 Feb 2018 15:19:29 -0800 (PST)
Received: from betaweb1.internal (betaweb1.nyi.internal [10.202.2.10]) by mailout.nyi.internal (Postfix) with ESMTP id 21D4720CD2; Mon, 12 Feb 2018 18:19:28 -0500 (EST)
Received: from betaweb1 ([::ffff:10.202.2.10]) by betaweb1.internal (MEProxy); Mon, 12 Feb 2018 18:19:28 -0500
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= fastmailteam.com; h=cc:content-transfer-encoding:content-type :date:from:in-reply-to:message-id:mime-version:references :subject:to:x-me-sender:x-me-sender:x-sasl-enc; s=fm1; bh=vqxhmC +rNAqdeak37XK5AcTtDBuNNFubikp0BG4uVs0=; b=ZBQn+tNJy8PSlY+HJwihK9 y4fyIufgmkfWiL3NNmjo8xLNHCIIyg4cXkUR3X16Dqor0NqoPCe+I4lEXvFeu54z 8Iu8xouw7GGB+pMeCPmNjuvGDWKmTKCBPefhek8wEIme+AmRmV0F5RO2HWE/L8Dh S8g1VDjQcFumPA0oKKvXAz6uvxAu3GEyErr9H7cU6xLt3toMI1emRyCsFTKbnUgD keHHiF6+Uh163hKuGyx//Jz3VDf25Y4pa40o7P26TPjY/h6qh/cW860HxMD1IQHN FupoehtYz/e4+Dc5gLJsDLU1pITWq+F4oEOw6P8nrV017LVBs6A8qfA8bOq0bUAA ==
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:content-type :date:from:in-reply-to:message-id:mime-version:references :subject:to:x-me-sender:x-me-sender:x-sasl-enc; s=fm2; bh=vqxhmC +rNAqdeak37XK5AcTtDBuNNFubikp0BG4uVs0=; b=k650VNdY9iII+1WpCp+YEW +wbBB974jlLLRjhjxyibFPLIGKh5UFLpeapa6ssM3BKIjUhdVkKPega6u0J0n8NR PUwIl5EimHVG0INRv5ubWUaALXLrCuUyDLwRAqfTm0PZA1RB/RWF6FsL77zVwxzf O7xfsqT1X3wQ8uhX2zS2o32e2PkA/3ggXx2vcx1rJHigOjL/oTDjei/I0Y22KnmN zlGHibUUQOzbkeHnwxRT5q1v/Q4XNVprXtng7YGTKnw2mRisJ54ieKb0CvHC8OO7 bYVCmJjUY7aDChks0imCkv5P9xVIopXrzCK/oF/ODxEJV25L3DvUttshRUuDMXMw ==
X-ME-Sender:
Received: by mailuser.nyi.internal (Postfix, from userid 99) id CF4F4E2479; Mon, 12 Feb 2018 18:19:27 -0500 (EST)
Message-Id: <1518477567.1847888.1268631136.2D834D85@webmail.messagingengine.com>
From: Neil Jenkins
To: Chris Newman
Cc: IETF JMAP Mailing List
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Type: multipart/alternative; boundary="_----------=_151847756718478880"
X-Mailer: MessagingEngine.com Webmail Interface - ajax-2ce04827
In-Reply-To: <60D63DE9-FC7F-430B-9C0E-42639F83C0F8@oracle.com>
References: <1518070284.168650.1263633200.05C7397A@webmail.messagingengine.com> <1518408506.1699741.1267466096.17DCF605@webmail.messagingengine.com> <1518419708.1006757.1267595536.799BEEC0@webmail.messagingengine.com> <1518420407.1012131.1267607120.3E7422B3@webmail.messagingengine.com> <60D63DE9-FC7F-430B-9C0E-42639F83C0F8@oracle.com>
Date: Tue, 13 Feb 2018 10:19:27 +1100
Archived-At:
Subject: Re: [Jmap] New JSON message representation
X-BeenThere: jmap@ietf.org
X-Mailman-Version: 2.1.22
Precedence: list
List-Id: JSON Message Access Protocol
List-Unsubscribe: ,
List-Archive:
List-Post:
List-Help:
List-Subscribe: ,
X-List-Received-Date: Mon, 12 Feb 2018 23:19:31 -0000
This is a multi-part message in MIME format.
--_----------=_151847756718478880
Content-Transfer-Encoding: 7bit
Content-Type: text/plain; charset="utf-8"
On Tue, 13 Feb 2018, at 6:57 AM, Chris Newman wrote:
> I'm fine with this approach, but this does have security
> considerations.
Agreed. I've already added a security consideration in relation to the
truncation of the value, I'll add in your text regarding heuristic
determination of content-type and charset.
I've created a pull request[1] with the changes. Further comments
welcome either there or on the list. I'd like to merge this in the next
week or two.
Neil.
Links:
1. https://github.com/jmapio/jmap/pull/175
--_----------=_151847756718478880
Content-Transfer-Encoding: 7bit
Content-Type: text/html; charset="utf-8"
On Tue, 13 Feb 2018, at 6:57 AM, Chris Newman wrote:
I'm fine with this approach, but this does have security considerations.
Agreed. I've already added a security consideration in relation to the truncation of the value, I'll add in your text regarding heuristic determination of content-type and charset.
I've created
a pull request with the changes. Further comments welcome either there or on the list. I'd like to merge this in the next week or two.
Neil.
--_----------=_151847756718478880--
From nobody Mon Feb 19 03:15:16 2018
Return-Path:
X-Original-To: jmap@ietfa.amsl.com
Delivered-To: jmap@ietfa.amsl.com
Received: from localhost (localhost [127.0.0.1]) by ietfa.amsl.com (Postfix) with ESMTP id CBEA21272E1 for ; Mon, 19 Feb 2018 03:15:14 -0800 (PST)
X-Virus-Scanned: amavisd-new at amsl.com
X-Spam-Flag: NO
X-Spam-Score: 4.316
X-Spam-Level: ****
X-Spam-Status: No, score=4.316 tagged_above=-999 required=5 tests=[BAYES_50=0.8, DATE_IN_PAST_96_XX=3.405, DKIM_SIGNED=0.1, FORGED_MUA_EUDORA=0.001, RCVD_IN_DNSWL_NONE=-0.0001, T_DKIM_INVALID=0.01] autolearn=no autolearn_force=no
Authentication-Results: ietfa.amsl.com (amavisd-new); dkim=fail (2048-bit key) reason="fail (message has been altered)" header.d=rdlab.org
Received: from mail.ietf.org ([4.31.198.44]) by localhost (ietfa.amsl.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id yZNYWI2K0rDT for ; Mon, 19 Feb 2018 03:15:14 -0800 (PST)
Received: from host.presenceweb.org (host.presenceweb.org [67.222.106.46]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ietfa.amsl.com (Postfix) with ESMTPS id 1FC24127286 for ; Mon, 19 Feb 2018 03:15:14 -0800 (PST)
DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=rdlab.org; s=default; h=Content-Type:Mime-Version:References:In-Reply-To:Subject:From: To:Date:Sender:Reply-To:Message-ID:Cc:Content-Transfer-Encoding:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=zQf8zlpY1myh0dlKLUi9m8SHvjgG5TxSPURoNNGZTlY=; b=nX9UMtNu2gsWo5Uh2Ay55IX923 MXcTsT8RgZ3pcJ2Jlzr+PkFN5UHiar+ZTYgx+NLAJXP/qjfbk5XCQNYSW9nHm+W27cHcAmhjuRDm2 hPslLZDcQIkyxjVl+I24FhNyQ2Qwo6bGYh85lhTH9l0VDNnBbW6Jlwtnx2q5IPqAE9zfgCVWnKyBr rbrn17ibQH8QD3ZNdzuzaQVN0LOlnP/E9Jf8fljbB8i/TgSA0+X1+SzBoRwo/OADe/008gyMe77PV CWFPd6C6DwlV0KzIJTdQSYTJ5AzWWe/UtmVmgsfCHNk8mn2WzcPoXaFkpbTCwYMzAxUCdprKiBqtH u6TkUEdQ==;
Received: from gra86-h02-176-142-255-40.dsl.sta.abo.bbox.fr ([176.142.255.40]:62335 helo=Morfin-Morfin.rdlab.org) by host.presenceweb.org with esmtpa (Exim 4.89_1) (envelope-from ) id 1enjPc-0008MR-9T for jmap@ietf.org; Mon, 19 Feb 2018 12:15:12 +0100
X-Mailer: QUALCOMM Windows Eudora Version 7.1.0.9
Date: Tue, 13 Feb 2018 09:18:00 +0100
To: IETF JMAP Mailing List
From: JFCM
In-Reply-To: <500E0B79-200E-4DFA-939A-C3419559743E@oracle.com>
References: <1518070284.168650.1263633200.05C7397A@webmail.messagingengine.com> <500E0B79-200E-4DFA-939A-C3419559743E@oracle.com>
Mime-Version: 1.0
Content-Type: text/plain; charset="us-ascii"; format=flowed
X-AntiAbuse: This header was added to track abuse, please include it with any abuse report
X-AntiAbuse: Primary Hostname - host.presenceweb.org
X-AntiAbuse: Original Domain - ietf.org
X-AntiAbuse: Originator/Caller UID/GID - [47 12] / [47 12]
X-AntiAbuse: Sender Address Domain - rdlab.org
X-Get-Message-Sender-Via: host.presenceweb.org: authenticated_id: info+rdlab.org/only user confirmed/virtual account not confirmed
X-Authenticated-Sender: host.presenceweb.org: info@rdlab.org
X-Source:
X-Source-Args:
X-Source-Dir:
Message-Id: <20180219111514.1FC24127286@ietfa.amsl.com>
Archived-At:
Subject: Re: [Jmap] New JSON message representation
X-BeenThere: jmap@ietf.org
X-Mailman-Version: 2.1.22
Precedence: list
List-Id: JSON Message Access Protocol
List-Unsubscribe: ,
List-Archive:
List-Post:
List-Help:
List-Subscribe: ,
X-List-Received-Date: Mon, 19 Feb 2018 11:15:15 -0000
On 20:08 09/02/2018, Chris Newman said:
>> * *receivedAt*: UTCDate (immutable; default: time of creation on
>> server) The date the email was received by the message store. This is
>> the *internal date* in IMAP.Header fields
>
>I note the IMAP APPEND command allows this to be client-specified.
>This is very useful in practice when migrating mail between mail
>stores. The date the user really wants is when the mail first
>entered a mailstore owned by the user (or operated on behalf of the
>user). The date when the mail first entered this particular
>mailstore is less useful to the end user.
I also have difficulty in corellating this with RFC 2244 modtime
requirements. I call "neb" the "nebularity" of a user autoritative
digital resources. The "rgnr" is the immutable "nebReceivedAt" (down
to the receiving machine cpu cycle). It turns to be terse enough when
expressed in alphadigital. This was first introduced to time sort
domain name registration requests (after synchronization in case of
parallel or back-up registry servers).
jfcm
From nobody Mon Feb 19 03:15:20 2018
Return-Path:
X-Original-To: jmap@ietfa.amsl.com
Delivered-To: jmap@ietfa.amsl.com
Received: from localhost (localhost [127.0.0.1]) by ietfa.amsl.com (Postfix) with ESMTP id D57F3127286 for ; Mon, 19 Feb 2018 03:15:14 -0800 (PST)
X-Virus-Scanned: amavisd-new at amsl.com
X-Spam-Flag: NO
X-Spam-Score: 3.516
X-Spam-Level: ***
X-Spam-Status: No, score=3.516 tagged_above=-999 required=5 tests=[BAYES_40=-0.001, DATE_IN_PAST_96_XX=3.405, DKIM_SIGNED=0.1, FORGED_MUA_EUDORA=0.001, HTML_MESSAGE=0.001, RCVD_IN_DNSWL_NONE=-0.0001, T_DKIM_INVALID=0.01] autolearn=no autolearn_force=no
Authentication-Results: ietfa.amsl.com (amavisd-new); dkim=fail (2048-bit key) reason="fail (message has been altered)" header.d=rdlab.org
Received: from mail.ietf.org ([4.31.198.44]) by localhost (ietfa.amsl.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 0Zolq5UTwR4L for ; Mon, 19 Feb 2018 03:15:13 -0800 (PST)
Received: from host.presenceweb.org (host.presenceweb.org [67.222.106.46]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ietfa.amsl.com (Postfix) with ESMTPS id E3559124D6C for ; Mon, 19 Feb 2018 03:15:13 -0800 (PST)
DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=rdlab.org; s=default; h=Content-Type:Mime-Version:References:In-Reply-To:Subject:From: To:Date:Sender:Reply-To:Message-ID:Cc:Content-Transfer-Encoding:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=pzfXTJg1iCutuZ00GMs+Y5aE03d29ze9aawOvQxbtfw=; b=p50B/xVaA6Lo92SBVrvldYUpkf 66f0ST+MOAvlamURXkSJa8mt1ox6IVG6sb5z3UjsVmUtAgSwtINyRZv21R63eCXpCND6BCi2cUPwY 3UiS6UdMbi2jFeltzbFLJP+jmqqCLI6rxJPNEB2myYLgoqfC6teqMwgPNiPtT0q0lroVm6F/uebxz eD9r88PaBayWRqOHpWZZYb132U4q9uKFpJfPZEeXjhl8/Br3XnIZaZq5a6MrowzXr1Fl9oRSvgsxs xqOVRWwaOhKixQnAzoLz0IFegzpNLRsv9QaZqED9Uq0+RfllQsLFLpNDwVCCrXa5zYsDW/985u0iO KmwKKJMQ==;
Received: from gra86-h02-176-142-255-40.dsl.sta.abo.bbox.fr ([176.142.255.40]:62335 helo=Morfin-Morfin.rdlab.org) by host.presenceweb.org with esmtpa (Exim 4.89_1) (envelope-from ) id 1enjPb-0008MR-2R; Mon, 19 Feb 2018 12:15:11 +0100
X-Mailer: QUALCOMM Windows Eudora Version 7.1.0.9
Date: Tue, 13 Feb 2018 08:34:04 +0100
To: Alexey Melnikov , Neil Jenkins , IETF JMAP Mailing List
From: JFCM
In-Reply-To: <0bb7d2f4-bcba-86ea-12f7-43a59a2f951e@isode.com>
References: <1518070284.168650.1263633200.05C7397A@webmail.messagingengine.com> <0bb7d2f4-bcba-86ea-12f7-43a59a2f951e@isode.com>
Mime-Version: 1.0
Content-Type: multipart/alternative; boundary="=====================_360981181==.ALT"
X-AntiAbuse: This header was added to track abuse, please include it with any abuse report
X-AntiAbuse: Primary Hostname - host.presenceweb.org
X-AntiAbuse: Original Domain - ietf.org
X-AntiAbuse: Originator/Caller UID/GID - [47 12] / [47 12]
X-AntiAbuse: Sender Address Domain - rdlab.org
X-Get-Message-Sender-Via: host.presenceweb.org: authenticated_id: info+rdlab.org/only user confirmed/virtual account not confirmed
X-Authenticated-Sender: host.presenceweb.org: info@rdlab.org
X-Source:
X-Source-Args:
X-Source-Dir:
Message-Id: <20180219111513.E3559124D6C@ietfa.amsl.com>
Archived-At:
Subject: Re: [Jmap] New JSON message representation
X-BeenThere: jmap@ietf.org
X-Mailman-Version: 2.1.22
Precedence: list
List-Id: JSON Message Access Protocol
List-Unsubscribe: ,
List-Archive:
List-Post:
List-Help:
List-Subscribe: ,
X-List-Received-Date: Mon, 19 Feb 2018 11:15:15 -0000
--=====================_360981181==.ALT
Content-Type: text/plain; charset="iso-8859-1"; format=flowed
Content-Transfer-Encoding: 8bit
At 12:41 09/02/2018, Alexey Melnikov wrote:
>I haven't digested your whole email yet, but a very quick comment
>about keywords:
>
>On 08/02/2018 06:11, Neil Jenkins wrote:
>>Users may add arbitrary keywords to an email. For compatibility
>>with IMAP, a keyword is a (case-sensitive)
>IMAP keywords are case insensitive. So $MDNSent and $mdnsent are the same.
>> * string of 1–255 characters in the ASCII subset %x21ââ€"%x7e
>> (excludes control chars and space), and MUST NOT include any of
>> these characters: ( ) { ] % * " \
>Probably not including } and [ as well. But I need to double check.
I concur for another reason: internationalization. If we name
"polynyms" strict computed semantic synonym strings in different
character sets that support langague diversity. ASCII lowercases turn
out being a common subset for universal reference (hence English
being used by the IETF, cf. RFC 3935), through internationalization
standardization. The main barrier to polynymy is upper cases that
many languages/charsets do not have. I also note that most of the
world's users are accustomed to Windows paltforms which are case insensitive.
jfcm
--=====================_360981181==.ALT
Content-Type: text/html; charset="iso-8859-1"
Content-Transfer-Encoding: 8bit
At 12:41 09/02/2018, Alexey Melnikov wrote:
I haven't digested your whole
email yet, but a very quick comment about keywords:
On 08/02/2018 06:11, Neil Jenkins
wrote:
Users may add arbitrary keywords to an email. For compatibility with
IMAP, a keyword is a (case-sensitive)
IMAP keywords are case insensitive. So $MDNSent and $mdnsent are the
same.
- string of 1–255 characters in the ASCII subset %x21â–%x7e (excludes
control chars and space), and MUST NOT include any of these characters: (
) { ] % * " \
Probably not including } and [ as well. But I need to double
check.
I concur for another reason: internationalization. If we name
"polynyms" strict computed semantic synonym strings in
different character sets that support langague diversity. ASCII
lowercases turn out being a common subset for universal reference (hence
English being used by the IETF, cf. RFC 3935), through
internationalization standardization. The main barrier to polynymy is
upper cases that many languages/charsets do not have. I also note that
most of the world's users are accustomed to Windows paltforms which are
case insensitive.
jfcm
--=====================_360981181==.ALT--
From nobody Tue Feb 27 15:13:53 2018
Return-Path:
X-Original-To: jmap@ietf.org
Delivered-To: jmap@ietfa.amsl.com
Received: from ietfa.amsl.com (localhost [IPv6:::1]) by ietfa.amsl.com (Postfix) with ESMTP id 95FE012EAAB; Tue, 27 Feb 2018 15:11:11 -0800 (PST)
MIME-Version: 1.0
Content-Type: text/plain; charset="utf-8"
Content-Transfer-Encoding: 7bit
From: "\"IETF Secretariat\""
To: ,
Cc: jmap@ietf.org, aamelnikov@fastmail.fm
X-Test-IDTracker: no
X-IETF-IDTracker: 6.73.0
Auto-Submitted: auto-generated
Precedence: bulk
Message-ID: <151977307160.5200.17504278755307034977.idtracker@ietfa.amsl.com>
Date: Tue, 27 Feb 2018 15:11:11 -0800
Archived-At:
Subject: [Jmap] jmap - Requested session has been scheduled for IETF 101
X-BeenThere: jmap@ietf.org
X-Mailman-Version: 2.1.22
List-Id: JSON Message Access Protocol
List-Unsubscribe: ,
List-Archive:
List-Post:
List-Help:
List-Subscribe: ,
X-List-Received-Date: Tue, 27 Feb 2018 23:11:12 -0000
Dear Bron Gondwana,
The session(s) that you have requested have been scheduled.
Below is the scheduled session information followed by
the original request.
jmap Session 1 (2:00:00)
Thursday, Afternoon Session II 1550-1750
Room Name: Richmond/Chelsea/Tower size: 75
---------------------------------------------
Request Information:
---------------------------------------------------------
Working Group Name: JSON Mail Access Protocol
Area Name: Applications and Real-Time Area
Session Requester: Bron Gondwana
Number of Sessions: 1
Length of Session(s): 2 Hours
Number of Attendees: 40
Conflicts to Avoid:
First Priority: extra dispatch uta artarea dmarc iasa20 mtgvenue saag oauth dcrup doh
Second Priority: tls httpbis ace lamps core
Third Priority: quic
People who must be present:
Neil Jenkins
Alexey Melnikov
Barry Leiba
Bron Gondwana
Resources Requested:
Experimental Room Setup (U-Shape and classroom, subject to availability)
Flipcharts: please specify number in Special Requests field
Special Requests:
One flipchart please
Please avoid Friday as Barry won't be available.
---------------------------------------------------------