JAMES-1916 Extract html from inner multipart when text/plain in main multipart
Project: http://git-wip-us.apache.org/repos/asf/james-project/repo Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/5fd8641a Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/5fd8641a Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/5fd8641a Branch: refs/heads/master Commit: 5fd8641a99434ecba4215d098f903e6ffe680722 Parents: 8e95555 Author: Raphael Ouazana <raphael.ouaz...@linagora.com> Authored: Fri Jan 27 15:33:09 2017 +0100 Committer: Raphael Ouazana <raphael.ouaz...@linagora.com> Committed: Fri Jan 27 15:33:09 2017 +0100 ---------------------------------------------------------------------- .../cucumber/GetMessagesMethodStepdefs.java | 5 + .../test/resources/cucumber/GetMessages.feature | 10 +- .../textInMainMultipartHtmlInInnerMultipart.eml | 43 +++++++++ .../jmap/model/MessageContentExtractor.java | 17 +++- .../jmap/model/MessageContentExtractorTest.java | 97 ++++++++++++++++++++ 5 files changed, 170 insertions(+), 2 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/james-project/blob/5fd8641a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/cucumber/GetMessagesMethodStepdefs.java ---------------------------------------------------------------------- diff --git a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/cucumber/GetMessagesMethodStepdefs.java b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/cucumber/GetMessagesMethodStepdefs.java index e6c4c4c..450ffb1 100644 --- a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/cucumber/GetMessagesMethodStepdefs.java +++ b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/cucumber/GetMessagesMethodStepdefs.java @@ -191,6 +191,11 @@ public class GetMessagesMethodStepdefs { appendMessage(messageName, "eml/embeddedMultipartWithInlineTextAttachment.eml"); } + @Given("^the user has a message \"([^\"]*)\" in \"([^\"]*)\" mailbox with text in main multipart and html in inner multipart$") + public void appendMessageWithTextInMainMultipartAndHtmlInInnerMultipart(String messageName, String mailbox) throws Throwable { + appendMessage(messageName, "eml/textInMainMultipartHtmlInInnerMultipart.eml"); + } + private void appendMessage(String messageName, String emlFileName) throws Exception { ZonedDateTime dateTime = ZonedDateTime.parse("2014-10-30T14:12:00Z"); MessageId id = mainStepdefs.jmapServer.serverProbe().appendMessage(userStepdefs.lastConnectedUser, http://git-wip-us.apache.org/repos/asf/james-project/blob/5fd8641a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/resources/cucumber/GetMessages.feature ---------------------------------------------------------------------- diff --git a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/resources/cucumber/GetMessages.feature b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/resources/cucumber/GetMessages.feature index 9cbd0c1..0cd93d1 100644 --- a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/resources/cucumber/GetMessages.feature +++ b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/resources/cucumber/GetMessages.feature @@ -230,4 +230,12 @@ Feature: GetMessages method Then no error is returned And the list should contain 1 message And the textBody of the message is "/blabla/\n*bloblo*\n" - And the htmlBody of the message is "<i>blabla</i>\n<b>bloblo</b>\n" \ No newline at end of file + And the htmlBody of the message is "<i>blabla</i>\n<b>bloblo</b>\n" + + Scenario: Retrieving message should find html body when text in main multipart and html in inner multipart + Given the user has a message "m1" in "inbox" mailbox with text in main multipart and html in inner multipart + When the user ask for messages "m1" + Then no error is returned + And the list should contain 1 message + And the textBody of the message is "/blabla/\r\n*bloblo*\r\n" + And the htmlBody of the message is "<i>blabla</i>\r\n<b>bloblo</b>\r\n" \ No newline at end of file http://git-wip-us.apache.org/repos/asf/james-project/blob/5fd8641a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/resources/eml/textInMainMultipartHtmlInInnerMultipart.eml ---------------------------------------------------------------------- diff --git a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/resources/eml/textInMainMultipartHtmlInInnerMultipart.eml b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/resources/eml/textInMainMultipartHtmlInInnerMultipart.eml new file mode 100644 index 0000000..6e42d91 --- /dev/null +++ b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/resources/eml/textInMainMultipartHtmlInInnerMultipart.eml @@ -0,0 +1,43 @@ +To: David DOLCIMASCOLO <david....@linagora.com> +From: David DOLCIMASCOLO <david....@linagora.com> +Subject: Inline twice +Message-ID: <03947d9b-4188-4d3a-b072-475278063...@linagora.com> +Date: Tue, 3 Jan 2017 17:59:01 +0100 +User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 + Thunderbird/45.5.1 +Content-Type: multipart/alternative; + boundary="------------41916E9CB699BB85B7A39ABF" + +This is a multi-part message in MIME format. +--------------41916E9CB699BB85B7A39ABF +Content-Type: text/plain; charset=utf-8; format=flowed +Content-Transfer-Encoding: 8bit + +/blabla/ +*bloblo* + +--------------41916E9CB699BB85B7A39ABF +Content-Type: multipart/related; + boundary="------------7562AB559B6C67B3BE780AA2" + + +--------------7562AB559B6C67B3BE780AA2 +Content-Type: text/html; charset=utf-8 +Content-Transfer-Encoding: 8bit + +<i>blabla</i> +<b>bloblo</b> + +--------------7562AB559B6C67B3BE780AA2 +Content-Type: image/png; + name="=?UTF-8?Q?S=c3=a9lection=5f014.png?=" +Content-Transfer-Encoding: base64 +Content-ID: <part1.c774cd18.95513...@linagora.com> +Content-Disposition: inline; + filename*=utf-8''%53%C3%A9%6C%65%63%74%69%6F%6E%5F%30%31%34%2E%70%6E%67 + +iVBORw0KGgoAAAANSUhEUgAAAUcAAAJCCAIAAADcDpISAAAAA3NCSVQICAjb4U/gAAAAEHRF +ASEB8/ejg6KNLS31fZ+u8hQAPj/AXiuIAuF4TyOAAAAAElFTkSuQmCC +--------------7562AB559B6C67B3BE780AA2-- + +--------------41916E9CB699BB85B7A39ABF-- http://git-wip-us.apache.org/repos/asf/james-project/blob/5fd8641a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/MessageContentExtractor.java ---------------------------------------------------------------------- diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/MessageContentExtractor.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/MessageContentExtractor.java index 721e641..b5baf53 100644 --- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/MessageContentExtractor.java +++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/MessageContentExtractor.java @@ -92,7 +92,12 @@ public class MessageContentExtractor { private MessageContent retrieveHtmlAndPlainTextContent(Multipart multipart) throws IOException { Optional<String> textBody = getFirstMatchingTextBody(multipart, "text/plain"); Optional<String> htmlBody = getFirstMatchingTextBody(multipart, "text/html"); - return new MessageContent(textBody, htmlBody); + MessageContent directChildTextBodies = new MessageContent(textBody, htmlBody); + if (!directChildTextBodies.isComplete()) { + MessageContent fromInnerMultipart = parseFirstFoundMultipart(multipart); + return directChildTextBodies.merge(fromInnerMultipart); + } + return directChildTextBodies; } private MessageContent retrieveFirstReadablePart(Multipart multipart) throws IOException { @@ -180,6 +185,16 @@ public class MessageContentExtractor { return equals(empty()); } + public boolean isComplete() { + return textBody.isPresent() && htmlBody.isPresent(); + } + + public MessageContent merge(MessageContent fromInnerMultipart) { + return new MessageContent( + textBody.map(Optional::of).orElse(fromInnerMultipart.getTextBody()), + htmlBody.map(Optional::of).orElse(fromInnerMultipart.getHtmlBody())); + } + @Override public boolean equals(Object other) { if (other == null || !(other instanceof MessageContent)) { http://git-wip-us.apache.org/repos/asf/james-project/blob/5fd8641a/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/MessageContentExtractorTest.java ---------------------------------------------------------------------- diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/MessageContentExtractorTest.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/MessageContentExtractorTest.java index 0a05e5d..84f78c4 100644 --- a/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/MessageContentExtractorTest.java +++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/MessageContentExtractorTest.java @@ -21,6 +21,7 @@ package org.apache.james.jmap.model; import static org.assertj.core.api.Assertions.assertThat; import java.io.IOException; +import java.util.Optional; import javax.mail.internet.MimeMessage; @@ -45,6 +46,8 @@ public class MessageContentExtractorTest { private static final String BINARY_CONTENT = "binary"; private static final String TEXT_CONTENT = "text content"; private static final String HTML_CONTENT = "<b>html</b> content"; + private static final String TEXT_CONTENT2 = "other text content"; + private static final String HTML_CONTENT2 = "other <b>html</b> content"; private static final String ATTACHMENT_CONTENT = "attachment content"; private static final String ANY_VALUE = "anyValue"; private static final Field CONTENT_ID_FIELD = new Field() { @@ -70,6 +73,7 @@ public class MessageContentExtractorTest { private BodyPart textPart; private BodyPart textAttachment; private BodyPart inlineText; + private BodyPart inlineImage; @Before public void setup() throws IOException { @@ -84,6 +88,10 @@ public class MessageContentExtractorTest { .setBody(ATTACHMENT_CONTENT, "plain", Charsets.UTF_8) .setContentDisposition("inline") .build(); + inlineImage = BodyPartBuilder.create() + .setBody(new byte[0], "image/png") + .setContentDisposition("inline") + .build(); } @Test @@ -368,4 +376,93 @@ public class MessageContentExtractorTest { assertThat(actual.getTextBody()).contains(TEXT_CONTENT); assertThat(actual.getHtmlBody()).contains(HTML_CONTENT); } + + @Test + public void extractShouldRetrieveTextBodyAndHtmlBodyWhenTextBodyInMainMultipartAndHtmlBodyInInnerMultipart() throws IOException { + BodyPart multipartRelated = BodyPartBuilder.create() + .setBody(MultipartBuilder.create("related") + .addBodyPart(htmlPart) + .addBodyPart(inlineImage) + .build()) + .build(); + + Multipart multipartAlternative = MultipartBuilder.create("alternative") + .addBodyPart(textPart) + .addBodyPart(multipartRelated) + .build(); + + Message message = MessageBuilder.create() + .setBody(multipartAlternative) + .build(); + + MessageContent actual = testee.extract(message); + assertThat(actual.getTextBody()).contains(TEXT_CONTENT); + assertThat(actual.getHtmlBody()).contains(HTML_CONTENT); + } + + @Test + public void mergeMessageContentShouldReturnEmptyWhenAllEmpty() { + MessageContent messageContent1 = MessageContent.empty(); + MessageContent messageContent2 = MessageContent.empty(); + MessageContent expected = MessageContent.empty(); + + MessageContent actual = messageContent1.merge(messageContent2); + + assertThat(actual).isEqualTo(expected); + } + + @Test + public void mergeMessageContentShouldReturnFirstWhenSecondEmpty() { + MessageContent messageContent1 = new MessageContent(Optional.of(TEXT_CONTENT), Optional.of(HTML_CONTENT)); + MessageContent messageContent2 = MessageContent.empty(); + MessageContent expected = messageContent1; + + MessageContent actual = messageContent1.merge(messageContent2); + + assertThat(actual).isEqualTo(expected); + } + + @Test + public void mergeMessageContentShouldReturnSecondWhenFirstEmpty() { + MessageContent messageContent1 = MessageContent.empty(); + MessageContent messageContent2 = new MessageContent(Optional.of(TEXT_CONTENT), Optional.of(HTML_CONTENT)); + MessageContent expected = messageContent2; + + MessageContent actual = messageContent1.merge(messageContent2); + + assertThat(actual).isEqualTo(expected); + } + + @Test + public void mergeMessageContentShouldReturnMixWhenFirstTextOnlyAndSecondHtmlOnly() { + MessageContent messageContent1 = MessageContent.ofTextOnly(TEXT_CONTENT); + MessageContent messageContent2 = MessageContent.ofHtmlOnly(HTML_CONTENT); + MessageContent expected = new MessageContent(Optional.of(TEXT_CONTENT), Optional.of(HTML_CONTENT)); + + MessageContent actual = messageContent1.merge(messageContent2); + + assertThat(actual).isEqualTo(expected); + } + + @Test + public void mergeMessageContentShouldReturnMixWhenFirstHtmlOnlyAndSecondTextOnly() { + MessageContent messageContent1 = MessageContent.ofHtmlOnly(HTML_CONTENT); + MessageContent messageContent2 = MessageContent.ofTextOnly(TEXT_CONTENT); + MessageContent expected = new MessageContent(Optional.of(TEXT_CONTENT), Optional.of(HTML_CONTENT)); + + MessageContent actual = messageContent1.merge(messageContent2); + + assertThat(actual).isEqualTo(expected); + } + + @Test + public void mergeMessageContentShouldReturnFirstWhenTwiceAreComplete() { + MessageContent messageContent1 = new MessageContent(Optional.of(TEXT_CONTENT), Optional.of(HTML_CONTENT)); + MessageContent messageContent2 = new MessageContent(Optional.of(TEXT_CONTENT2), Optional.of(HTML_CONTENT2)); + MessageContent expected = messageContent1; + + MessageContent actual = messageContent1.merge(messageContent2); + + assertThat(actual).isEqualTo(expected); + } } --------------------------------------------------------------------- To unsubscribe, e-mail: server-dev-unsubscr...@james.apache.org For additional commands, e-mail: server-dev-h...@james.apache.org