This is an automated email from the ASF dual-hosted git repository. rcordier pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/james-project.git
commit 0faf47a3cd0f8b25ce680795f13cb1aec85a7839 Author: LanKhuat <[email protected]> AuthorDate: Tue Nov 10 11:14:06 2020 +0700 JAMES-3439 Include inline attachments --- .../rfc8621/contract/EmailSetMethodContract.scala | 164 +++++++++++++++++++++ .../org/apache/james/jmap/mail/EmailSet.scala | 4 +- 2 files changed, 166 insertions(+), 2 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 32322e7..78b89ec 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 @@ -1979,6 +1979,170 @@ trait EmailSetMethodContract { } @Test + def createShouldSupportInlinedAttachmentsMixedWithRegularAttachmentsAndHtmlBody(server: GuiceJamesServer): Unit = { + val bobPath = MailboxPath.inbox(BOB) + val mailboxId = server.getProbe(classOf[MailboxProbeImpl]).createMailbox(bobPath) + val payload = "123456789\r\n".getBytes(StandardCharsets.UTF_8) + val htmlBody: String = "<!DOCTYPE html><html><head><title></title></head><body><div>I have the most <b>brilliant</b> plan. Let me tell you all about it. What we do is, we</div></body></html>" + + val uploadResponse: String = `given` + .basePath("") + .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) + .contentType("text/plain") + .body(payload) + .when + .post(s"/upload/$ACCOUNT_ID/") + .`then` + .statusCode(SC_CREATED) + .extract + .body + .asString + + val blobId: String = Json.parse(uploadResponse).\("blobId").get.asInstanceOf[JsString].value + + 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 + | }, + | "subject": "World domination", + | "attachments": [ + | { + | "blobId": "$blobId", + | "type":"text/plain", + | "charset":"UTF-8", + | "disposition": "inline", + | "cid": "abc" + | }, + | { + | "blobId": "$blobId", + | "type":"text/plain", + | "charset":"UTF-8", + | "disposition": "inline", + | "cid": "def" + | }, + | { + | "blobId": "$blobId", + | "type":"text/plain", + | "charset":"UTF-8", + | "disposition": "attachment" + | } + | ], + | "htmlBody": [ + | { + | "partId": "a49d", + | "type": "text/html" + | } + | ], + | "bodyValues": { + | "a49d": { + | "value": "$htmlBody", + | "isTruncated": false, + | "isEncodingProblem": false + | } + | } + | } + | } + | }, "c1"], + | ["Email/get", + | { + | "accountId": "$ACCOUNT_ID", + | "ids": ["#aaaaaa"], + | "properties": ["mailboxIds", "subject", "attachments", "htmlBody", "bodyValues"], + | "fetchHTMLBodyValues": true + | }, + | "c2"] + | ] + |}""".stripMargin + + val response = `given` + .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) + .body(request) + .when + .post.prettyPeek() + .`then` + .statusCode(SC_OK) + .contentType(JSON) + .extract + .body + .asString + + assertThatJson(response) + .whenIgnoringPaths("methodResponses[0][1].created.aaaaaa.id") + .inPath("methodResponses[0][1].created.aaaaaa") + .isEqualTo("{}".stripMargin) + + val messageId = Json.parse(response) + .\("methodResponses") + .\(1).\(1) + .\("list") + .\(0) + .\("id") + .get.asInstanceOf[JsString].value + + assertThatJson(response) + .whenIgnoringPaths("methodResponses[1][1].list[0].id") + .inPath(s"methodResponses[1][1].list") + .isEqualTo( + s"""[{ + | "mailboxIds": { + | "${mailboxId.serialize}": true + | }, + | "subject": "World domination", + | "attachments": [ + | { + | "partId": "3", + | "blobId": "${messageId}_3", + | "size": 11, + | "type": "text/plain", + | "charset": "UTF-8", + | "disposition": "inline", + | "cid": "abc" + | }, + | { + | "partId": "4", + | "blobId": "${messageId}_4", + | "size": 11, + | "type": "text/plain", + | "charset": "UTF-8", + | "disposition": "inline", + | "cid": "def" + | }, + | { + | "partId": "5", + | "blobId": "${messageId}_5", + | "size": 11, + | "type": "text/plain", + | "charset": "UTF-8", + | "disposition": "attachment" + | } + | ], + | "htmlBody": [ + | { + | "partId": "2", + | "blobId": "${messageId}_2", + | "size": 166, + | "type": "text/html", + | "charset": "UTF-8" + | } + | ], + | "bodyValues": { + | "2": { + | "value": "$htmlBody", + | "isEncodingProblem": false, + | "isTruncated": false + | } + | } + |}]""".stripMargin) + } + + @Test def createShouldSupportAttachmentWithName(server: GuiceJamesServer): Unit = { val bobPath = MailboxPath.inbox(BOB) val mailboxId = server.getProbe(classOf[MailboxProbeImpl]).createMailbox(bobPath) 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 e156674..6533819 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 @@ -29,6 +29,7 @@ import eu.timepit.refined.collection.NonEmpty import org.apache.james.jmap.core.Id.Id import org.apache.james.jmap.core.State.State import org.apache.james.jmap.core.{AccountId, SetError, UTCDate} +import org.apache.james.jmap.mail.Disposition.INLINE import org.apache.james.jmap.mail.EmailSet.{EmailCreationId, UnparsedMessageId} import org.apache.james.jmap.method.WithAccountId import org.apache.james.mailbox.exception.AttachmentNotFoundException @@ -96,7 +97,7 @@ case class Attachment(blobId: BlobId, location: Option[Location], cid: Option[ClientCid]) { - def isInline: Boolean = disposition.contains("inline") + def isInline: Boolean = disposition.contains(INLINE) } case class EmailCreationRequest(mailboxIds: MailboxIds, @@ -154,7 +155,6 @@ case class EmailCreationRequest(mailboxIds: MailboxIds, val maybeAttachments: Either[Exception, List[(Attachment, AttachmentMetadata, Array[Byte])]] = attachments - .filter(!_.isInline) .map(attachment => getAttachmentMetadata(attachment, attachmentManager, mailboxSession)) .map(attachmentMetadataList => attachmentMetadataList .flatMap(attachmentAndMetadata => loadAttachment(attachmentAndMetadata._1, attachmentAndMetadata._2, attachmentContentLoader, mailboxSession))) --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
