Repository: james-project Updated Branches: refs/heads/master 76cabea09 -> 9e1ccb37f
JAMES-1913 Extract message content from multipart when inlined text attachment Project: http://git-wip-us.apache.org/repos/asf/james-project/repo Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/8e955557 Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/8e955557 Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/8e955557 Branch: refs/heads/master Commit: 8e95555710c1d947534e146b0fcef0926b6c1433 Parents: d747e7d Author: Raphael Ouazana <raphael.ouaz...@linagora.com> Authored: Fri Jan 27 15:11:11 2017 +0100 Committer: Raphael Ouazana <raphael.ouaz...@linagora.com> Committed: Fri Jan 27 15:11:11 2017 +0100 ---------------------------------------------------------------------- .../cucumber/GetMessagesMethodStepdefs.java | 5 +++ .../test/resources/cucumber/GetMessages.feature | 10 ++++- ...mbeddedMultipartWithInlineTextAttachment.eml | 41 ++++++++++++++++++++ .../jmap/model/MessageContentExtractor.java | 28 +++++++++---- .../jmap/model/MessageContentExtractorTest.java | 28 +++++++++++++ 5 files changed, 104 insertions(+), 8 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/james-project/blob/8e955557/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 85c38d8..e6c4c4c 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 @@ -186,6 +186,11 @@ public class GetMessagesMethodStepdefs { appendMessage(messageName, "eml/longLine.eml"); } + @Given("^the user has a message \"([^\"]*)\" in \"([^\"]*)\" mailbox with plain/text inline attachment$") + public void appendMessageWithPlainTextInlineAttachment(String messageName, String mailbox) throws Throwable { + appendMessage(messageName, "eml/embeddedMultipartWithInlineTextAttachment.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/8e955557/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 d06a81a..9cbd0c1 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 @@ -222,4 +222,12 @@ Feature: GetMessages method Given the user has a message "m1" in "inbox" mailbox with two same attachments in text When the user ask for messages "m1" Then no error is returned - And the list of attachments of the message contains 2 attachments \ No newline at end of file + And the list of attachments of the message contains 2 attachments + + Scenario: Retrieving message should read content from multipart when some inline attachment and both html/text multipart + Given the user has a message "m1" in "inbox" mailbox with plain/text inline attachment + 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/\n*bloblo*\n" + And the htmlBody of the message is "<i>blabla</i>\n<b>bloblo</b>\n" \ No newline at end of file http://git-wip-us.apache.org/repos/asf/james-project/blob/8e955557/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/resources/eml/embeddedMultipartWithInlineTextAttachment.eml ---------------------------------------------------------------------- diff --git a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/resources/eml/embeddedMultipartWithInlineTextAttachment.eml b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/resources/eml/embeddedMultipartWithInlineTextAttachment.eml new file mode 100644 index 0000000..f9c8665 --- /dev/null +++ b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/resources/eml/embeddedMultipartWithInlineTextAttachment.eml @@ -0,0 +1,41 @@ +Date: Tue, 03 Jan 2017 16:05:01 +0100 +From: sender <sen...@james.org> +MIME-Version: 1.0 +To: David DOLCIMASCOLO <david....@linagora.com> +Subject: Re: [Internet] Rendez-vous +References: <9b6a4271-69fb-217a-5c14-c68c68375...@linagora.com> +In-Reply-To: <d5c6f1d6-96e7-8172-9fe6-41fa6c9bd...@linagora.com> +X-Gie-Attachments: none +Cc: +Content-type: multipart/mixed; boundary="----------=_1483455916-7086-3" + +This is a multi-part message in MIME format... + +------------=_1483455916-7086-3 +Content-Type: multipart/alternative; boundary="------------060506070600060108040700" + +This is a multi-part message in MIME format. +--------------060506070600060108040700 +Content-Type: text/plain; charset=ISO-8859-1; format=flowed +Content-Transfer-Encoding: 8bit + +/blabla/ +*bloblo* + +--------------060506070600060108040700 +Content-Type: text/html; charset=ISO-8859-1 +Content-Transfer-Encoding: 7bit + +<i>blabla</i> +<b>bloblo</b> + +--------------060506070600060108040700-- + +------------=_1483455916-7086-3 +Content-Type: text/plain; charset="iso-8859-1"; name="avertissement.txt" +Content-Disposition: inline; filename="avertissement.txt" +Content-Transfer-Encoding: binary + +inline attachment + +------------=_1483455916-7086-3-- http://git-wip-us.apache.org/repos/asf/james-project/blob/8e955557/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 626e5fc..721e641 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 @@ -71,7 +71,7 @@ public class MessageContentExtractor { case "multipart/alternative": return retrieveHtmlAndPlainTextContent(multipart); default: - return retrieveFirstHtmlOrPlainTextContent(multipart); + return retrieveFirstReadablePart(multipart); } } @@ -95,13 +95,27 @@ public class MessageContentExtractor { return new MessageContent(textBody, htmlBody); } - private MessageContent retrieveFirstHtmlOrPlainTextContent(Multipart multipart) throws IOException { - Optional<String> textBody = Optional.empty(); - Optional<String> htmlBody = getFirstMatchingTextBody(multipart, "text/html"); - if (! htmlBody.isPresent()) { - textBody = getFirstMatchingTextBody(multipart, "text/plain"); + private MessageContent retrieveFirstReadablePart(Multipart multipart) throws IOException { + return multipart.getBodyParts() + .stream() + .filter(this::isNotAttachment) + .map(Throwing.function(this::returnIfReadable).sneakyThrow()) + .filter(((Predicate<MessageContent>)MessageContent::isEmpty).negate()) + .findFirst() + .orElse(MessageContent.empty()); + } + + private MessageContent returnIfReadable(Entity entity) throws IOException { + if (entity.getMimeType().equals("text/html") && entity.getBody() instanceof TextBody) { + return MessageContent.ofHtmlOnly(asString((TextBody)entity.getBody())); } - return new MessageContent(textBody, htmlBody); + if (entity.getMimeType().equals("text/plain") && entity.getBody() instanceof TextBody) { + return MessageContent.ofTextOnly(asString((TextBody)entity.getBody())); + } + if (entity.isMultipart() && entity.getBody() instanceof Multipart) { + return parseMultipart(entity, (Multipart)entity.getBody()); + } + return MessageContent.empty(); } private Optional<String> getFirstMatchingTextBody(Multipart multipart, String mimeType) throws IOException { http://git-wip-us.apache.org/repos/asf/james-project/blob/8e955557/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 c015a3b..0a05e5d 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 @@ -69,6 +69,7 @@ public class MessageContentExtractorTest { private BodyPart htmlPart; private BodyPart textPart; private BodyPart textAttachment; + private BodyPart inlineText; @Before public void setup() throws IOException { @@ -79,6 +80,10 @@ public class MessageContentExtractorTest { .setBody(ATTACHMENT_CONTENT, "plain", Charsets.UTF_8) .setContentDisposition("attachment") .build(); + inlineText = BodyPartBuilder.create() + .setBody(ATTACHMENT_CONTENT, "plain", Charsets.UTF_8) + .setContentDisposition("inline") + .build(); } @Test @@ -340,4 +345,27 @@ public class MessageContentExtractorTest { //Then assertThat(actual.getTextBody()).isEmpty(); } + + @Test + public void extractShouldRetrieveTextAndHtmlBodyWhenOneInlinedTextAttachmentAndMainContentInMultipart() throws IOException { + BodyPart multipartAlternative = BodyPartBuilder.create() + .setBody(MultipartBuilder.create("alternative") + .addBodyPart(textPart) + .addBodyPart(htmlPart) + .build()) + .build(); + + Multipart multipartMixed = MultipartBuilder.create("mixed") + .addBodyPart(multipartAlternative) + .addBodyPart(inlineText) + .build(); + + Message message = MessageBuilder.create() + .setBody(multipartMixed) + .build(); + + MessageContent actual = testee.extract(message); + assertThat(actual.getTextBody()).contains(TEXT_CONTENT); + assertThat(actual.getHtmlBody()).contains(HTML_CONTENT); + } } --------------------------------------------------------------------- To unsubscribe, e-mail: server-dev-unsubscr...@james.apache.org For additional commands, e-mail: server-dev-h...@james.apache.org