You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@james.apache.org by bt...@apache.org on 2022/11/09 02:41:13 UTC
[james-project] branch master updated: [JMAP] Email/set create should add missing mimeMessageId and sentAt (#1286)
This is an automated email from the ASF dual-hosted git repository.
btellier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git
The following commit(s) were added to refs/heads/master by this push:
new 40b37a6dbe [JMAP] Email/set create should add missing mimeMessageId and sentAt (#1286)
40b37a6dbe is described below
commit 40b37a6dbe7677481904c78c43638686204cdd02
Author: Benoit TELLIER <bt...@linagora.com>
AuthorDate: Wed Nov 9 09:41:08 2022 +0700
[JMAP] Email/set create should add missing mimeMessageId and sentAt (#1286)
---
.../rfc8621/contract/EmailSetMethodContract.scala | 50 ++++++++++++++++++++++
.../org/apache/james/jmap/mail/EmailSet.scala | 16 ++++---
2 files changed, 61 insertions(+), 5 deletions(-)
diff --git a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/EmailSetMethodContract.scala b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/EmailSetMethodContract.scala
index 9893e06699..3456cd798f 100644
--- a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/EmailSetMethodContract.scala
+++ b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/EmailSetMethodContract.scala
@@ -327,6 +327,56 @@ trait EmailSetMethodContract {
|}""".stripMargin)
}
+ @Test
+ def emailSetCreateShouldPositionMissingDateAndMessageId(server: GuiceJamesServer): Unit = {
+ val bobPath = MailboxPath.inbox(BOB)
+ val mailboxId = server.getProbe(classOf[MailboxProbeImpl]).createMailbox(bobPath)
+
+ val request =
+ s"""{
+ | "using": ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail"],
+ | "methodCalls": [
+ | ["Email/set", {
+ | "accountId": "$ACCOUNT_ID",
+ | "create": {
+ | "aaaaaa":{
+ | "mailboxIds": {
+ | "${mailboxId.serialize}": true
+ | },
+ | "to": [{"email": "rcpt1@apache.org"}, {"email": "rcpt2@apache.org"}],
+ | "from": [{"email": "${BOB.asString}"}]
+ | }
+ | }
+ | }, "c1"],
+ | ["Email/get",
+ | {
+ | "accountId": "$ACCOUNT_ID",
+ | "ids": ["#aaaaaa"],
+ | "properties": ["sentAt", "messageId"]
+ | },
+ | "c2"]]
+ |}""".stripMargin
+
+ val response = `given`
+ .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
+ .body(request)
+ .when
+ .post
+ .`then`
+ .statusCode(SC_OK)
+ .contentType(JSON)
+ .extract
+ .body
+ .asString
+
+ assertThatJson(response)
+ .inPath("methodResponses[1][1].list.[0].sentAt")
+ .isEqualTo("\"${json-unit.ignore}\"")
+ assertThatJson(response)
+ .inPath("methodResponses[1][1].list.[0].messageId")
+ .isEqualTo("[\"${json-unit.ignore}\"]")
+ }
+
@Test
def createShouldFailWhenBadJsonPayloadForSpecificHeader(server: GuiceJamesServer): Unit = {
val bobPath = MailboxPath.inbox(BOB)
diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/mail/EmailSet.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/mail/EmailSet.scala
index bc91ceb330..c08fa7301f 100644
--- a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/mail/EmailSet.scala
+++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/mail/EmailSet.scala
@@ -35,11 +35,13 @@ import org.apache.james.mailbox.MailboxSession
import org.apache.james.mailbox.model.{Cid, MessageId}
import org.apache.james.mime4j.codec.EncoderUtil.Usage
import org.apache.james.mime4j.codec.{DecodeMonitor, EncoderUtil}
+import org.apache.james.mime4j.dom.address.Mailbox
import org.apache.james.mime4j.dom.field.{ContentIdField, ContentTypeField, FieldName}
import org.apache.james.mime4j.dom.{Entity, Message}
import org.apache.james.mime4j.field.{ContentIdFieldImpl, Fields}
import org.apache.james.mime4j.message.{BodyPartBuilder, MultipartBuilder}
import org.apache.james.mime4j.stream.{Field, NameValuePair, RawField}
+import org.apache.james.mime4j.util.MimeUtil
import org.apache.james.util.html.HtmlTextExtractor
import play.api.libs.json.JsObject
@@ -129,15 +131,16 @@ case class EmailCreationRequest(mailboxIds: MailboxIds,
val builder = Message.Builder.of
references.flatMap(_.asString).map(new RawField("References", _)).foreach(builder.setField)
inReplyTo.flatMap(_.asString).map(new RawField("In-Reply-To", _)).foreach(builder.setField)
- messageId.flatMap(_.asString).map(new RawField(FieldName.MESSAGE_ID, _)).foreach(builder.setField)
subject.foreach(value => builder.setSubject(value.value))
- from.flatMap(_.asMime4JMailboxList).map(_.asJava).foreach(builder.setFrom)
+ val maybeFrom: Option[List[Mailbox]] = from.flatMap(_.asMime4JMailboxList)
+ maybeFrom.map(_.asJava).foreach(builder.setFrom)
to.flatMap(_.asMime4JMailboxList).map(_.asJava).foreach(builder.setTo)
cc.flatMap(_.asMime4JMailboxList).map(_.asJava).foreach(builder.setCc)
bcc.flatMap(_.asMime4JMailboxList).map(_.asJava).foreach(builder.setBcc)
sender.flatMap(_.asMime4JMailboxList).map(_.asJava).map(Fields.addressList(FieldName.SENDER, _)).foreach(builder.setField)
replyTo.flatMap(_.asMime4JMailboxList).map(_.asJava).foreach(builder.setReplyTo)
- sentAt.map(_.asUTC).map(_.toInstant).map(Date.from).foreach(builder.setDate)
+ builder.setDate( sentAt.map(_.asUTC).map(_.toInstant).map(Date.from).getOrElse(new Date()))
+ builder.setField(new RawField(FieldName.MESSAGE_ID, messageId.flatMap(_.asString).getOrElse(generateUniqueMessageId(maybeFrom))))
validateSpecificHeaders(builder)
.flatMap(_ => {
specificHeaders.map(_.asField).foreach(builder.addField)
@@ -154,8 +157,11 @@ case class EmailCreationRequest(mailboxIds: MailboxIds,
})
}
- private def createAlternativeBody(htmlBody: Option[String], textBody: Option[String], htmlTextExtractor: HtmlTextExtractor): MultipartBuilder = {
- val alternativeBuilder: MultipartBuilder = MultipartBuilder.create(SubType.ALTERNATIVE_SUBTYPE)
+ private def generateUniqueMessageId(fromAddress: Option[List[Mailbox]]): String =
+ MimeUtil.createUniqueMessageId(fromAddress.flatMap(_.headOption).map(_.getDomain).orNull)
+
+ private def createAlternativeBody(htmlBody: Option[String], textBody: Option[String], htmlTextExtractor: HtmlTextExtractor) = {
+ val alternativeBuilder = MultipartBuilder.create(SubType.ALTERNATIVE_SUBTYPE)
addBodypart(alternativeBuilder, textBody.getOrElse(htmlTextExtractor.toPlainText(htmlBody.getOrElse(""))), PLAIN_TEXT_UTF_8, StandardCharsets.UTF_8)
htmlBody.foreach(text => addBodypart(alternativeBuilder, text, HTML_UTF_8, StandardCharsets.UTF_8))
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org