Repository: james-project
Updated Branches:
  refs/heads/master 409c8cea6 -> b5c125798


JAMES-1752 Handle multipart mediatype when retrieving text/html body


Project: http://git-wip-us.apache.org/repos/asf/james-project/repo
Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/f973b280
Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/f973b280
Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/f973b280

Branch: refs/heads/master
Commit: f973b280b32efc64422ee85f6e11fa6434c5fd4e
Parents: af7b1c6
Author: Antoine Duprat <adup...@linagora.com>
Authored: Wed Jun 8 09:24:58 2016 +0200
Committer: Antoine Duprat <adup...@linagora.com>
Committed: Fri Jun 10 08:25:59 2016 +0200

----------------------------------------------------------------------
 .../james/jmap/VacationIntegrationTest.java     |  12 +-
 .../integration/GetMessagesMethodTest.java      | 149 ++++++++---
 .../htmlAndTextMultipartWithOneAttachment.eml   |  64 +++++
 .../test/resources/twoAttachmentsTextPlain.eml  |  73 ++++++
 .../org/apache/james/jmap/model/Message.java    |  39 ++-
 .../jmap/model/message/IndexableMessage.java    |  26 +-
 .../james/jmap/model/message/MimePart.java      |  73 ++++--
 .../james/jmap/model/message/MimePartTest.java  | 249 +++++++++++++++++++
 8 files changed, 581 insertions(+), 104 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/f973b280/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/VacationIntegrationTest.java
----------------------------------------------------------------------
diff --git 
a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/VacationIntegrationTest.java
 
b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/VacationIntegrationTest.java
index 3e7c155..50df787 100644
--- 
a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/VacationIntegrationTest.java
+++ 
b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/VacationIntegrationTest.java
@@ -26,7 +26,6 @@ import static 
com.jayway.restassured.config.RestAssuredConfig.newConfig;
 import static org.hamcrest.Matchers.empty;
 import static org.hamcrest.Matchers.equalTo;
 import static org.hamcrest.Matchers.hasSize;
-import static org.hamcrest.Matchers.nullValue;
 
 import java.util.List;
 import java.util.Map;
@@ -56,6 +55,7 @@ public abstract class VacationIntegrationTest {
     private static final String USER_2 = "matthieu@" + DOMAIN;
     private static final String PASSWORD = "secret";
     private static final String REASON = "Message explaining my wonderful 
vacations";
+    private static final String HTML_REASON = "<b>" + REASON + "</b>";
     public static final String ORIGINAL_MESSAGE_TEXT_BODY = "Hello someone, 
and thank you for joining example.com!";
 
     private ConditionFactory calmlyAwait;
@@ -137,7 +137,7 @@ public abstract class VacationIntegrationTest {
         calmlyAwait.atMost(10, TimeUnit.SECONDS)
             .until(() -> isTextMessageReceived(user1AccessToken, 
getInboxId(user1AccessToken), ORIGINAL_MESSAGE_TEXT_BODY, USER_2, USER_1));
         calmlyAwait.atMost(10, TimeUnit.SECONDS)
-                .until( () -> 
assertOneMessageWithNullTextBodyReceived(user2AccessToken, 
getInboxId(user2AccessToken), USER_1, USER_2));
+                .until( () -> 
assertOneMessageWithHtmlBodyReceived(user2AccessToken, 
getInboxId(user2AccessToken), HTML_REASON, USER_1, USER_2));
     }
 
     @Test
@@ -278,7 +278,7 @@ public abstract class VacationIntegrationTest {
             "    \"singleton\" : {" +
             "      \"id\": \"singleton\"," +
             "      \"isEnabled\": \"true\"," +
-            "      \"htmlBody\": \"<b>" + REASON + "</b>\"" +
+            "      \"htmlBody\": \"" + HTML_REASON + "\"" +
             "    }" +
             "  }" +
             "}, \"#0\"" +
@@ -376,7 +376,7 @@ public abstract class VacationIntegrationTest {
             .body(SECOND_ARGUMENTS + ".list[0].to.email[0]", 
equalTo(expectedTo));
     }
 
-    private boolean assertOneMessageWithNullTextBodyReceived(AccessToken 
recipientToken, String mailboxId, String expectedFrom, String expectedTo) {
+    private boolean assertOneMessageWithHtmlBodyReceived(AccessToken 
recipientToken, String mailboxId, String expectedHtmlBody, String expectedFrom, 
String expectedTo) {
         try {
             with()
                 .accept(ContentType.JSON)
@@ -385,7 +385,7 @@ public abstract class VacationIntegrationTest {
                 .body("[[\"getMessageList\", " +
                     "{" +
                     "  \"fetchMessages\": true, " +
-                    "  \"fetchMessageProperties\": [\"textBody\", \"from\", 
\"to\", \"mailboxIds\"]," +
+                    "  \"fetchMessageProperties\": [\"htmlBody\", \"from\", 
\"to\", \"mailboxIds\"]," +
                     "  \"filter\": {" +
                     "    \"inMailboxes\":[\"" + mailboxId + "\"]" +
                     "  }" +
@@ -395,7 +395,7 @@ public abstract class VacationIntegrationTest {
                 .statusCode(200)
                 .body(SECOND_NAME, equalTo("messages"))
                 .body(SECOND_ARGUMENTS + ".list", hasSize(1))
-                .body(SECOND_ARGUMENTS + ".list[0].textBody", nullValue())
+                .body(SECOND_ARGUMENTS + ".list[0].htmlBody", 
equalTo(expectedHtmlBody))
                 .body(SECOND_ARGUMENTS + ".list[0].from.email", 
equalTo(expectedFrom))
                 .body(SECOND_ARGUMENTS + ".list[0].to.email", hasSize(1))
                 .body(SECOND_ARGUMENTS + ".list[0].to.email[0]", 
equalTo(expectedTo));

http://git-wip-us.apache.org/repos/asf/james-project/blob/f973b280/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/GetMessagesMethodTest.java
----------------------------------------------------------------------
diff --git 
a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/GetMessagesMethodTest.java
 
b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/GetMessagesMethodTest.java
index 90776d8..cff96a4 100644
--- 
a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/GetMessagesMethodTest.java
+++ 
b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/GetMessagesMethodTest.java
@@ -51,7 +51,8 @@ import com.jayway.restassured.http.ContentType;
 public abstract class GetMessagesMethodTest {
     private static final String NAME = "[0][0]";
     private static final String ARGUMENTS = "[0][1]";
-    private static final String ATTACHMENTS = ARGUMENTS + 
".list[0].attachments";
+    private static final String FIRST_MESSAGE = ARGUMENTS + ".list[0]";
+    private static final String ATTACHMENTS = FIRST_MESSAGE + ".attachments";
     private static final String FIRST_ATTACHMENT = ATTACHMENTS + "[0]";
     private static final String SECOND_ATTACHMENT = ATTACHMENTS + "[1]";
 
@@ -182,15 +183,15 @@ public abstract class GetMessagesMethodTest {
             .statusCode(200)
             .body(NAME, equalTo("messages"))
             .body(ARGUMENTS + ".list", hasSize(1))
-            .body(ARGUMENTS + ".list[0].id", equalTo(username + "|inbox|1"))
-            .body(ARGUMENTS + ".list[0].threadId", equalTo(username + 
"|inbox|1"))
-            .body(ARGUMENTS + ".list[0].subject", equalTo("my test subject"))
-            .body(ARGUMENTS + ".list[0].textBody", equalTo("testmail"))
-            .body(ARGUMENTS + ".list[0].isUnread", equalTo(true))
-            .body(ARGUMENTS + ".list[0].preview", equalTo("testmail"))
-            .body(ARGUMENTS + ".list[0].headers", 
equalTo(ImmutableMap.of("subject", "my test subject")))
-            .body(ARGUMENTS + ".list[0].date", equalTo("2014-10-30T14:12:00Z"))
-            .body(ARGUMENTS + ".list[0].hasAttachment", equalTo(false))
+            .body(FIRST_MESSAGE + ".id", equalTo(username + "|inbox|1"))
+            .body(FIRST_MESSAGE + ".threadId", equalTo(username + "|inbox|1"))
+            .body(FIRST_MESSAGE + ".subject", equalTo("my test subject"))
+            .body(FIRST_MESSAGE + ".textBody", equalTo("testmail"))
+            .body(FIRST_MESSAGE + ".isUnread", equalTo(true))
+            .body(FIRST_MESSAGE + ".preview", equalTo("testmail"))
+            .body(FIRST_MESSAGE + ".headers", 
equalTo(ImmutableMap.of("subject", "my test subject")))
+            .body(FIRST_MESSAGE + ".date", equalTo("2014-10-30T14:12:00Z"))
+            .body(FIRST_MESSAGE + ".hasAttachment", equalTo(false))
             .body(ATTACHMENTS, empty());
     }
 
@@ -215,14 +216,14 @@ public abstract class GetMessagesMethodTest {
             .statusCode(200)
             .body(NAME, equalTo("messages"))
             .body(ARGUMENTS + ".list", hasSize(1))
-            .body(ARGUMENTS + ".list[0].id", equalTo(username + "|inbox|1"))
-            .body(ARGUMENTS + ".list[0].threadId", equalTo(username + 
"|inbox|1"))
-            .body(ARGUMENTS + ".list[0].subject", equalTo("my test subject"))
-            .body(ARGUMENTS + ".list[0].htmlBody", equalTo("This is a 
<b>HTML</b> mail"))
-            .body(ARGUMENTS + ".list[0].isUnread", equalTo(true))
-            .body(ARGUMENTS + ".list[0].preview", equalTo("This is a 
<b>HTML</b> mail"))
-            .body(ARGUMENTS + ".list[0].headers", 
equalTo(ImmutableMap.of("content-type", "text/html", "subject", "my test 
subject")))
-            .body(ARGUMENTS + ".list[0].date", 
equalTo("2014-10-30T14:12:00Z"));
+            .body(FIRST_MESSAGE + ".id", equalTo(username + "|inbox|1"))
+            .body(FIRST_MESSAGE + ".threadId", equalTo(username + "|inbox|1"))
+            .body(FIRST_MESSAGE + ".subject", equalTo("my test subject"))
+            .body(FIRST_MESSAGE + ".htmlBody", equalTo("This is a <b>HTML</b> 
mail"))
+            .body(FIRST_MESSAGE + ".isUnread", equalTo(true))
+            .body(FIRST_MESSAGE + ".preview", equalTo("This is a <b>HTML</b> 
mail"))
+            .body(FIRST_MESSAGE + ".headers", 
equalTo(ImmutableMap.of("content-type", "text/html", "subject", "my test 
subject")))
+            .body(FIRST_MESSAGE + ".date", equalTo("2014-10-30T14:12:00Z"));
     }
     
     @Test
@@ -246,13 +247,13 @@ public abstract class GetMessagesMethodTest {
             .statusCode(200)
             .body(NAME, equalTo("messages"))
             .body(ARGUMENTS + ".list", hasSize(1))
-            .body(ARGUMENTS + ".list[0].id", equalTo(username + "|inbox|1"))
-            .body(ARGUMENTS + ".list[0].subject", equalTo("my test subject"))
-            .body(ARGUMENTS + ".list[0].textBody", nullValue())
-            .body(ARGUMENTS + ".list[0].isUnread", nullValue())
-            .body(ARGUMENTS + ".list[0].preview", nullValue())
-            .body(ARGUMENTS + ".list[0].headers", nullValue())
-            .body(ARGUMENTS + ".list[0].date", nullValue());
+            .body(FIRST_MESSAGE + ".id", equalTo(username + "|inbox|1"))
+            .body(FIRST_MESSAGE + ".subject", equalTo("my test subject"))
+            .body(FIRST_MESSAGE + ".textBody", nullValue())
+            .body(FIRST_MESSAGE + ".isUnread", nullValue())
+            .body(FIRST_MESSAGE + ".preview", nullValue())
+            .body(FIRST_MESSAGE + ".headers", nullValue())
+            .body(FIRST_MESSAGE + ".date", nullValue());
     }
     
     @Test
@@ -281,13 +282,13 @@ public abstract class GetMessagesMethodTest {
             .statusCode(200)
             .body(NAME, equalTo("messages"))
             .body(ARGUMENTS + ".list", hasSize(1))
-            .body(ARGUMENTS + ".list[0].id", equalTo(username + "|inbox|1"))
-            .body(ARGUMENTS + ".list[0].subject", nullValue())
-            .body(ARGUMENTS + ".list[0].textBody", nullValue())
-            .body(ARGUMENTS + ".list[0].isUnread", nullValue())
-            .body(ARGUMENTS + ".list[0].preview", nullValue())
-            .body(ARGUMENTS + ".list[0].headers", 
equalTo(ImmutableMap.of("from", "u...@domain.tld", "header2", 
"Header2Content")))
-            .body(ARGUMENTS + ".list[0].date", nullValue());
+            .body(FIRST_MESSAGE + ".id", equalTo(username + "|inbox|1"))
+            .body(FIRST_MESSAGE + ".subject", nullValue())
+            .body(FIRST_MESSAGE + ".textBody", nullValue())
+            .body(FIRST_MESSAGE + ".isUnread", nullValue())
+            .body(FIRST_MESSAGE + ".preview", nullValue())
+            .body(FIRST_MESSAGE + ".headers", equalTo(ImmutableMap.of("from", 
"u...@domain.tld", "header2", "Header2Content")))
+            .body(FIRST_MESSAGE + ".date", nullValue());
     }
 
     @Test
@@ -334,8 +335,8 @@ public abstract class GetMessagesMethodTest {
             .statusCode(200)
             .body(NAME, equalTo("messages"))
             .body(ARGUMENTS + ".list", hasSize(1))
-            .body(ARGUMENTS + ".list[0].id", 
equalTo("usern...@domain.tld|mailbox|1"))
-            .body(ARGUMENTS + ".list[0].subject", equalTo("my test subject"));
+            .body(FIRST_MESSAGE + ".id", 
equalTo("usern...@domain.tld|mailbox|1"))
+            .body(FIRST_MESSAGE + ".subject", equalTo("my test subject"));
     }
 
     @Test
@@ -359,7 +360,7 @@ public abstract class GetMessagesMethodTest {
             .statusCode(200)
             .body(NAME, equalTo("messages"))
             .body(ARGUMENTS + ".list", hasSize(1))
-            .body(ARGUMENTS + ".list[0].hasAttachment", equalTo(true))
+            .body(FIRST_MESSAGE + ".hasAttachment", equalTo(true))
             .body(ATTACHMENTS, hasSize(2))
             .body(FIRST_ATTACHMENT + ".blobId", 
equalTo("223a76c0e8c1b1762487d8e0598bd88497d73ef2"))
             .body(FIRST_ATTACHMENT + ".type", equalTo("image/jpeg"))
@@ -368,4 +369,82 @@ public abstract class GetMessagesMethodTest {
             .body(SECOND_ATTACHMENT + ".type", equalTo("image/jpeg"))
             .body(SECOND_ATTACHMENT + ".size", equalTo(597));
     }
+
+    @Test
+    public void 
getMessagesShouldReturnHTMLBodyWhenSomeAttachmentsAndHTMLmail() throws 
Exception {
+        
jmapServer.serverProbe().createMailbox(MailboxConstants.USER_NAMESPACE, 
username, "inbox");
+
+        ZonedDateTime dateTime = ZonedDateTime.parse("2014-10-30T14:12:00Z");
+        jmapServer.serverProbe().appendMessage(username, new 
MailboxPath(MailboxConstants.USER_NAMESPACE, username, "inbox"),
+                ClassLoader.getSystemResourceAsStream("twoAttachments.eml"), 
Date.from(dateTime.toInstant()), false, new Flags());
+        
+        given()
+            .accept(ContentType.JSON)
+            .contentType(ContentType.JSON)
+            .header("Authorization", accessToken.serialize())
+            .body("[[\"getMessages\", {\"ids\": [\"" + username + 
"|inbox|1\"]}, \"#0\"]]")
+        .when()
+            .post("/jmap")
+        .then()
+            .statusCode(200)
+            .body(NAME, equalTo("messages"))
+            .body(ARGUMENTS + ".list", hasSize(1))
+            .body(FIRST_MESSAGE + ".hasAttachment", equalTo(true))
+            .body(ATTACHMENTS, hasSize(2))
+            .body(FIRST_MESSAGE + ".preview", equalTo("<b>html</b>\n"))
+            .body(FIRST_MESSAGE + ".textBody", nullValue())
+            .body(FIRST_MESSAGE + ".htmlBody", equalTo("<b>html</b>\n"));
+    }
+
+    @Test
+    public void 
getMessagesShouldReturnTextBodyWhenSomeAttachmentsAndTextmail() throws 
Exception {
+        
jmapServer.serverProbe().createMailbox(MailboxConstants.USER_NAMESPACE, 
username, "inbox");
+
+        ZonedDateTime dateTime = ZonedDateTime.parse("2014-10-30T14:12:00Z");
+        jmapServer.serverProbe().appendMessage(username, new 
MailboxPath(MailboxConstants.USER_NAMESPACE, username, "inbox"),
+                
ClassLoader.getSystemResourceAsStream("twoAttachmentsTextPlain.eml"), 
Date.from(dateTime.toInstant()), false, new Flags());
+        
+        given()
+            .accept(ContentType.JSON)
+            .contentType(ContentType.JSON)
+            .header("Authorization", accessToken.serialize())
+            .body("[[\"getMessages\", {\"ids\": [\"" + username + 
"|inbox|1\"]}, \"#0\"]]")
+        .when()
+            .post("/jmap")
+        .then()
+            .statusCode(200)
+            .body(NAME, equalTo("messages"))
+            .body(ARGUMENTS + ".list", hasSize(1))
+            .body(FIRST_MESSAGE + ".hasAttachment", equalTo(true))
+            .body(ATTACHMENTS, hasSize(2))
+            .body(FIRST_MESSAGE + ".preview", equalTo("html\n"))
+            .body(FIRST_MESSAGE + ".textBody", equalTo("html\n"))
+            .body(FIRST_MESSAGE + ".htmlBody", nullValue());
+    }
+
+    @Test
+    public void 
getMessagesShouldReturnBothHTMLAndTextBodyWhenOneAttachmentAndBothHTMLAndTextmail()
 throws Exception {
+        
jmapServer.serverProbe().createMailbox(MailboxConstants.USER_NAMESPACE, 
username, "inbox");
+
+        ZonedDateTime dateTime = ZonedDateTime.parse("2014-10-30T14:12:00Z");
+        jmapServer.serverProbe().appendMessage(username, new 
MailboxPath(MailboxConstants.USER_NAMESPACE, username, "inbox"),
+                
ClassLoader.getSystemResourceAsStream("htmlAndTextMultipartWithOneAttachment.eml"),
 Date.from(dateTime.toInstant()), false, new Flags());
+        
+        given()
+            .accept(ContentType.JSON)
+            .contentType(ContentType.JSON)
+            .header("Authorization", accessToken.serialize())
+            .body("[[\"getMessages\", {\"ids\": [\"" + username + 
"|inbox|1\"]}, \"#0\"]]")
+        .when()
+            .post("/jmap")
+        .then()
+            .statusCode(200)
+            .body(NAME, equalTo("messages"))
+            .body(ARGUMENTS + ".list", hasSize(1))
+            .body(FIRST_MESSAGE + ".hasAttachment", equalTo(true))
+            .body(ATTACHMENTS, hasSize(1))
+            .body(FIRST_MESSAGE + ".preview", 
equalTo("<i>blabla</i>\n<b>bloblo</b>\n"))
+            .body(FIRST_MESSAGE + ".textBody", equalTo("/blabla/\n*bloblo*\n"))
+            .body(FIRST_MESSAGE + ".htmlBody", 
equalTo("<i>blabla</i>\n<b>bloblo</b>\n"));
+    }
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/f973b280/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/resources/htmlAndTextMultipartWithOneAttachment.eml
----------------------------------------------------------------------
diff --git 
a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/resources/htmlAndTextMultipartWithOneAttachment.eml
 
b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/resources/htmlAndTextMultipartWithOneAttachment.eml
new file mode 100644
index 0000000..a5ddc8b
--- /dev/null
+++ 
b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/resources/htmlAndTextMultipartWithOneAttachment.eml
@@ -0,0 +1,64 @@
+Return-Path: <us...@open-paas.org>
+MIME-Version: 1.0
+Delivered-To: us...@open-paas.org
+Received: from 172.18.0.1 (EHLO [172.18.0.1]) ([172.18.0.1])
+          by open-paas.org (JAMES SMTP Server ) with ESMTP ID -674616268
+          for <us...@open-paas.org>;
+          Tue, 07 Jun 2016 14:23:37 +0000 (UTC)
+To: us...@open-paas.org
+From: user0 <us...@open-paas.org>
+Subject: BOTH
+Message-ID: <1cc7f114-dbc4-42c2-99bd-f1100db6d...@open-paas.org>
+Date: Tue, 7 Jun 2016 16:23:37 +0200
+User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101
+ Thunderbird/45.1.1
+Content-Type: multipart/mixed;
+ boundary="------------7AF1D14DE1DFA16229726B54"
+
+This is a multi-part message in MIME format.
+--------------7AF1D14DE1DFA16229726B54
+Content-Type: multipart/alternative;
+ boundary="------------172F9470CFA3BF3417835D92"
+
+
+--------------172F9470CFA3BF3417835D92
+Content-Type: text/plain; charset=utf-8; format=flowed
+Content-Transfer-Encoding: 7bit
+
+/blabla/
+*bloblo*
+
+--------------172F9470CFA3BF3417835D92
+Content-Type: text/html; charset=utf-8
+Content-Transfer-Encoding: 7bit
+
+<i>blabla</i>
+<b>bloblo</b>
+
+--------------172F9470CFA3BF3417835D92--
+
+--------------7AF1D14DE1DFA16229726B54
+Content-Type: image/jpeg;
+ name="4037_014.jpg"
+Content-Transfer-Encoding: base64
+Content-Disposition: attachment;
+ filename="4037_014.jpg"
+
+/9j/4X2cRXhpZgAASUkqAAgAAAANAA8BAgAKAAAAqgAAABABAgAJAAAAtAAAABIBAwABAAAA
+AQAAABoBBQABAAAAvgAAABsBBQABAAAAxgAAACgBAwABAAAAAgAAADEBAgAKAAAAzgAAADIB
+AgAUAAAA2AAAABMCAwABAAAAAgAAAGmHBAABAAAAfAIAAKXEBwDQAAAA7AAAANLGBwBAAAAA
+vAEAANPGBwCAAAAA/AEAAEwqAABQYW5hc29uaWMARE1DLUZaNDUAALQAAAABAAAAtAAAAAEA
+AABWZXIuMS4wICAAMjAxNDowMjoyNSAxMDozMjowOQBQcmludElNADAyNTAAAA4AAQAWABYA
+AgAAAAAAAwBkAAAABwAAAAAACAAAAAAACQAAAAAACgAAAAAACwCsAAAADAAAAAAADQAAAAAA
+DgDEAAAAAAEFAAAAAQEBAAAAEAGAAAAACREAABAnAAALDwAAECcAAJcFAAAQJwAAsAgAABAn
+AAABHAAAECcAAF4CAAAQJwAAiwAAABAnAADLAwAAECcAAOUbAAAQJwAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+
+--------------7AF1D14DE1DFA16229726B54--

http://git-wip-us.apache.org/repos/asf/james-project/blob/f973b280/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/resources/twoAttachmentsTextPlain.eml
----------------------------------------------------------------------
diff --git 
a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/resources/twoAttachmentsTextPlain.eml
 
b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/resources/twoAttachmentsTextPlain.eml
new file mode 100644
index 0000000..7760185
--- /dev/null
+++ 
b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/resources/twoAttachmentsTextPlain.eml
@@ -0,0 +1,73 @@
+Return-Path: <f...@linagora.com>
+Received: from alderaan.linagora.com (smtp.linagora.dc1 [172.16.18.53])
+        by imap (Cyrus v2.2.13-Debian-2.2.13-19+squeeze3) with LMTPA;
+        Fri, 27 Feb 2015 20:32:14 +0100
+X-Sieve: CMU Sieve 2.2
+Received: from canondir.par.lng (unknown [92.103.166.6])
+       (using TLSv1 with cipher AES256-SHA (256/256 bits))
+       (No client certificate requested)
+       by alderaan.linagora.com (Postfix) with ESMTPSA id BAB0D728
+       for <t...@linagora.com>; Fri, 27 Feb 2015 20:31:38 +0100 (CET)
+X-Priority: 3 (Normal)
+From: "From"
+ <f...@linagora.com>
+To: "To"
+ <t...@linagora.com>
+Subject: [8/10]Attached Image light with text
+Date: Fri, 27 Mar 2015 21:48:38 +0100
+Message-Id: <20150227203838.0011.canontxno.4...@canondir.par.lng>
+Mime-Version: 1.0
+Content-Type: multipart/mixed;
+ boundary="AHNPACBLDCDIDAGGGDDFAABECGCA"
+
+--AHNPACBLDCDIDAGGGDDFAABECGCA
+Content-Type: text/plain; charset=utf-8; format=flowed
+Content-Transfer-Encoding: 8bit
+
+html
+
+--AHNPACBLDCDIDAGGGDDFAABECGCA
+Content-Type: image/jpeg;
+ name="4037_014.jpg"
+Content-Transfer-Encoding: base64
+Content-Disposition: attachment;
+ filename="4037_014.jpg"
+
+/9j/4X2cRXhpZgAASUkqAAgAAAANAA8BAgAKAAAAqgAAABABAgAJAAAAtAAAABIBAwABAAAA
+AQAAABoBBQABAAAAvgAAABsBBQABAAAAxgAAACgBAwABAAAAAgAAADEBAgAKAAAAzgAAADIB
+AgAUAAAA2AAAABMCAwABAAAAAgAAAGmHBAABAAAAfAIAAKXEBwDQAAAA7AAAANLGBwBAAAAA
+vAEAANPGBwCAAAAA/AEAAEwqAABQYW5hc29uaWMARE1DLUZaNDUAALQAAAABAAAAtAAAAAEA
+AABWZXIuMS4wICAAMjAxNDowMjoyNSAxMDozMjowOQBQcmludElNADAyNTAAAA4AAQAWABYA
+AgAAAAAAAwBkAAAABwAAAAAACAAAAAAACQAAAAAACgAAAAAACwCsAAAADAAAAAAADQAAAAAA
+DgDEAAAAAAEFAAAAAQEBAAAAEAGAAAAACREAABAnAAALDwAAECcAAJcFAAAQJwAAsAgAABAn
+AAABHAAAECcAAF4CAAAQJwAAiwAAABAnAADLAwAAECcAAOUbAAAQJwAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+
+--AHNPACBLDCDIDAGGGDDFAABECGCA
+Content-Type: image/jpeg;
+ name="4037_015.jpg"
+Content-Transfer-Encoding: base64
+Content-Disposition: attachment;
+ filename="4037_015.jpg"
+
+iVBORw0KGgoAAAANSUhEUgAABYUAAAL4CAIAAACrzA8fAAAACXBIWXMAAAsTAAALEwEAmpwY
+AAAAB3RJTUUH3wMNDiUMca0XkQAAIABJREFUeNq8vWm0bdlVHja/tc+99zX13qv2VSeVmlIv
+FSqEOhA2AoEhxMRBg8QOyEkG6WMDSZzhMQTGDDcwiJPhBBMby4SMDJthgmOMAYvGMcF0QgIU
+WRKobymp+qpX9fp779nry4+9mjnnWuuc80qMvCpdvXrv3nP22Xutueb85je/D1/3+q+ipF9z
+nGfGdZznGCMjKaSIkJQwBYSAEMI0Tatptdrb21utVqvVtJKAAAABEAAiUP+IiECYfsfyJf1B
+10+cOHH48OGVlZVSypaWlv379zc2Nr722msNDQ2u+y9zaYQeAQAAAACCHgEAAAB0y969e+ON
+KnpOe3v7JZdccj6fwPXr10+aNKnAB956663Zs2fjTgMAAADOKzhOAQAAAFCYs+yO0XfNNQAA
+AAAA/nNBfgQAAADQDVddddW6detSqdQZ7JvL5W655RZIEgAAAAAAEayKigqcBQAAAKAAhw8f
+3rZt25AhQwYNGpTJZHq4V2tr6/bt25csWbJjxw6cQwAAAACACMiPAAAAAAAAAAAAQH8D/wgA
+AAAAAAAAAAD0N9AjAAAAAAAAAAAA0N9AjwAAAAAAAAAAAEB/Az0CAAAAAAAAAAAA/Q30CAAA
+AAAAAAAAAPQ30CMAAAAAAAAAAADQ30CPAAAAAAAAAAAAQH/z/0IKJwmNQbpqAAAAAElFTkSu
+QmCC
+
+--AHNPACBLDCDIDAGGGDDFAABECGCA--

http://git-wip-us.apache.org/repos/asf/james-project/blob/f973b280/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/Message.java
----------------------------------------------------------------------
diff --git 
a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/Message.java 
b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/Message.java
index 58e62a6..8e87a1e 100644
--- 
a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/Message.java
+++ 
b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/Message.java
@@ -28,6 +28,7 @@ import java.util.Set;
 import java.util.function.Function;
 import java.util.function.Predicate;
 import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 import org.apache.james.jmap.methods.GetMessagesMethod;
 import org.apache.james.jmap.methods.JmapResponseWriterImpl;
@@ -46,7 +47,6 @@ import com.google.common.base.Strings;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Multimap;
-import com.google.common.net.MediaType;
 
 @JsonDeserialize(builder = Message.Builder.class)
 @JsonFilter(JmapResponseWriterImpl.PROPERTIES_FILTER)
@@ -121,12 +121,18 @@ public class Message {
     }
     
     private static String getPreview(IndexableMessage im) {
-        return Optional.ofNullable(
-                Strings.emptyToNull(
-                    im.getBodyText()
-                        .map(Message::computePreview)
-                        .orElse(NO_BODY)))
+        Stream<Optional<String>> htmlThenTextStream = Stream.of(
+                im.getBodyHtml(),
+                im.getBodyText());
+
+        String body = htmlThenTextStream
+            .filter(Optional::isPresent)
+            .map(Optional::get)
+            .filter(stringBody -> !stringBody.isEmpty())
+            .findFirst()
             .orElse(NO_BODY);
+        
+        return computePreview(body);
     }
 
     @VisibleForTesting static String computePreview(String body) {
@@ -157,28 +163,11 @@ public class Message {
     }
 
     private static String getTextBody(IndexableMessage im) {
-        if (isText(im) && !isHtml(im)) {
-            return im.getBodyText().map(Strings::emptyToNull).orElse(null);
-        }
-        return null;
+        return im.getBodyText().map(Strings::emptyToNull).orElse(null);
     }
 
     private static String getHtmlBody(IndexableMessage im) {
-        if (isText(im) && isHtml(im)) {
-            return im.getBodyText().map(Strings::emptyToNull).orElse(null);
-        }
-        return null;
-    }
-
-    private static boolean isText(IndexableMessage im) {
-        return im.getMediaType() == null
-            || im.getMediaType().equals(MediaType.ANY_TEXT_TYPE.type());
-    }
-
-    private static boolean isHtml(IndexableMessage im) {
-        return isText(im)
-            && im.getSubType() != null
-            && im.getSubType().equals(MediaType.HTML_UTF_8.subtype());
+        return im.getBodyHtml().map(Strings::emptyToNull).orElse(null);
     }
 
     private static List<Attachment> 
getAttachments(List<org.apache.james.mailbox.store.mail.model.Attachment> 
attachments) {

http://git-wip-us.apache.org/repos/asf/james-project/blob/f973b280/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/message/IndexableMessage.java
----------------------------------------------------------------------
diff --git 
a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/message/IndexableMessage.java
 
b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/message/IndexableMessage.java
index 055533a..972ac63 100644
--- 
a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/message/IndexableMessage.java
+++ 
b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/message/IndexableMessage.java
@@ -33,6 +33,7 @@ import 
org.apache.james.mailbox.store.mail.model.MailboxMessage;
 import org.apache.james.mailbox.store.mail.model.Property;
 import org.apache.james.mime4j.MimeException;
 
+import com.fasterxml.jackson.annotation.JsonIgnore;
 import com.fasterxml.jackson.annotation.JsonProperty;
 import com.google.common.base.Preconditions;
 import com.google.common.base.Throwables;
@@ -45,13 +46,14 @@ public class IndexableMessage {
         IndexableMessage indexableMessage = new IndexableMessage();
         try {
             MimePart parsingResult = new MimePartParser(message, 
textExtractor).parse();
-            indexableMessage.bodyText = parsingResult.locateFirstTextualBody();
+            indexableMessage.bodyText = parsingResult.retrieveTextPlainBody();
+            indexableMessage.bodyHtml = parsingResult.retrieveTextHtmlBody();
             indexableMessage.setFlattenedAttachments(parsingResult);
             
indexableMessage.copyHeaderFields(parsingResult.getHeaderCollection(), 
getSanitizedInternalDate(message, zoneId));
+            indexableMessage.copyMessageFields(message, zoneId);
         } catch (IOException | MimeException e) {
             throw Throwables.propagate(e);
         }
-        indexableMessage.copyMessageFields(message, zoneId);
         return indexableMessage;
     }
 
@@ -77,8 +79,6 @@ public class IndexableMessage {
         this.modSeq = message.getModSeq();
         this.size = message.getFullContentOctets();
         this.date = 
DateResolutionFormater.DATE_TIME_FOMATTER.format(getSanitizedInternalDate(message,
 zoneId));
-        this.mediaType = message.getMediaType();
-        this.subType = message.getSubType();
         this.isAnswered = message.isAnswered();
         this.isDeleted = message.isDeleted();
         this.isDraft = message.isDraft();
@@ -103,8 +103,6 @@ public class IndexableMessage {
     private long modSeq;
     private long size;
     private String date;
-    private String mediaType;
-    private String subType;
     private boolean isUnRead;
     private boolean isRecent;
     private boolean isFlagged;
@@ -123,6 +121,7 @@ public class IndexableMessage {
     private List<Property> properties;
     private List<MimePart> attachments;
     private Optional<String> bodyText;
+    private Optional<String> bodyHtml;
 
     @JsonProperty(JsonMessageConstants.ID)
     public Long getId() {
@@ -149,16 +148,6 @@ public class IndexableMessage {
         return date;
     }
 
-    @JsonProperty(JsonMessageConstants.MEDIA_TYPE)
-    public String getMediaType() {
-        return mediaType;
-    }
-
-    @JsonProperty(JsonMessageConstants.SUBTYPE)
-    public String getSubType() {
-        return subType;
-    }
-
     @JsonProperty(JsonMessageConstants.IS_UNREAD)
     public boolean isUnRead() {
         return isUnRead;
@@ -249,6 +238,11 @@ public class IndexableMessage {
         return bodyText;
     }
 
+    @JsonIgnore
+    public Optional<String> getBodyHtml() {
+        return bodyHtml;
+    }
+
     @JsonProperty(JsonMessageConstants.HAS_ATTACHMENT)
     public boolean getHasAttachment() {
         return attachments.size() > 0;

http://git-wip-us.apache.org/repos/asf/james-project/blob/f973b280/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/message/MimePart.java
----------------------------------------------------------------------
diff --git 
a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/message/MimePart.java
 
b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/message/MimePart.java
index 928d3fa..7f573d3 100644
--- 
a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/message/MimePart.java
+++ 
b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/message/MimePart.java
@@ -19,12 +19,12 @@
 
 package org.apache.james.jmap.model.message;
 
-import com.fasterxml.jackson.annotation.JsonIgnore;
-import com.fasterxml.jackson.annotation.JsonProperty;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.ImmutableMultimap;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Multimap;
+import java.io.InputStream;
+import java.util.List;
+import java.util.Optional;
+import java.util.function.Predicate;
+import java.util.stream.Stream;
+
 import org.apache.commons.io.FilenameUtils;
 import org.apache.james.mailbox.store.extractor.DefaultTextExtractor;
 import org.apache.james.mailbox.store.extractor.ParsedContent;
@@ -33,13 +33,23 @@ import org.apache.james.mime4j.stream.Field;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.io.InputStream;
-import java.util.List;
-import java.util.Optional;
-import java.util.stream.Stream;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableMultimap;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Multimap;
 
 public class MimePart {
 
+    private static final String HTML_SUBTYPE = "html";
+    private static final String PLAIN_SUBTYPE = "plain";
+
+    public static Builder builder() {
+        return new Builder();
+    }
+
     public static class Builder implements MimePartContainerBuilder {
 
         private final HeaderCollection.Builder headerCollectionBuilder;
@@ -160,11 +170,6 @@ public class MimePart {
                 return Optional.empty();
             }
         }
-
-    }
-    
-    public static Builder builder() {
-        return new Builder();
     }
 
     private static final Logger LOGGER = 
LoggerFactory.getLogger(MimePart.class);
@@ -244,14 +249,38 @@ public class MimePart {
     }
 
     @JsonIgnore
-    public Optional<String> locateFirstTextualBody() {
+    public Optional<String> retrieveTextHtmlBody() {
+        return retrieveTextBody(MimePart::isHTML);
+    }
+
+    @JsonIgnore
+    public Optional<String> retrieveTextPlainBody() {
+        return retrieveTextBody(MimePart::isPlain);
+    }
+
+    private Optional<String> retrieveTextBody(Predicate<MimePart> filter) {
         return Stream.concat(
-                    Stream.of(this),
-                    attachments.stream())
-                .map((mimePart) -> mimePart.bodyTextContent)
-                .filter(Optional::isPresent)
-                .map(Optional::get)
-                .findFirst();
+                Stream.of(this),
+                getAttachmentsStream())
+            .filter(filter)
+            .map(MimePart::getTextualBody)
+            .filter(Optional::isPresent)
+            .map(Optional::get)
+            .findFirst();
+    }
+
+    @JsonIgnore
+    @VisibleForTesting boolean isHTML() {
+        return subType
+                .filter(HTML_SUBTYPE::equals)
+                .isPresent();
+    }
+
+    @JsonIgnore
+    @VisibleForTesting boolean isPlain() {
+        return subType
+                .filter(PLAIN_SUBTYPE::equals)
+                .isPresent();
     }
 
     @JsonIgnore

http://git-wip-us.apache.org/repos/asf/james-project/blob/f973b280/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/message/MimePartTest.java
----------------------------------------------------------------------
diff --git 
a/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/message/MimePartTest.java
 
b/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/message/MimePartTest.java
new file mode 100644
index 0000000..c935560
--- /dev/null
+++ 
b/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/message/MimePartTest.java
@@ -0,0 +1,249 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.jmap.model.message;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.apache.commons.io.IOUtils;
+import org.junit.Test;
+
+public class MimePartTest {
+
+    @Test
+    public void isHTMLShouldReturnTrueWhenHTMLSubType() {
+        MimePart mimePart = MimePart.builder()
+            .addSubType("html")
+            .build();
+        assertThat(mimePart.isHTML()).isTrue();
+    }
+
+    @Test
+    public void isHTMLShouldReturnFalseWhenOtherSubType() {
+        MimePart mimePart = MimePart.builder()
+            .addSubType("other")
+            .build();
+        assertThat(mimePart.isHTML()).isFalse();
+    }
+
+    @Test
+    public void isPlainShouldReturnTrueWhenPlainSubType() {
+        MimePart mimePart = MimePart.builder()
+            .addSubType("plain")
+            .build();
+        assertThat(mimePart.isPlain()).isTrue();
+    }
+
+    @Test
+    public void isPlainShouldReturnFalseWhenOtherSubType() {
+        MimePart mimePart = MimePart.builder()
+            .addSubType("other")
+            .build();
+        assertThat(mimePart.isPlain()).isFalse();
+    }
+
+    @Test
+    public void retrieveTextHtmlBodyShouldReturnEmptyWhenOtherSubType() {
+        MimePart mimePart = MimePart.builder()
+            .addSubType("other")
+            .build();
+        assertThat(mimePart.retrieveTextHtmlBody()).isEmpty();
+    }
+
+    @Test
+    public void retrieveTextHtmlBodyShouldReturnHtmlBodyWhenHtmlSubType() {
+        String expectedContent = "<b>content</b>";
+        MimePart htmlMimePart = MimePart.builder()
+                .addMediaType("text")
+                .addSubType("html")
+                .addBodyContent(IOUtils.toInputStream(expectedContent))
+                .build();
+
+        
assertThat(htmlMimePart.retrieveTextHtmlBody()).contains(expectedContent);
+    }
+
+    @Test
+    public void 
retrieveTextHtmlBodyShouldReturnHtmlBodyFromAttachmentsWhenHtmlSubTypeInAttachments()
 {
+        String expectedContent = "<b>content</b>";
+        MimePart htmlMimePart = MimePart.builder()
+                .addMediaType("text")
+                .addSubType("html")
+                .addBodyContent(IOUtils.toInputStream(expectedContent))
+                .build();
+
+        MimePart mimePart = MimePart.builder()
+                .addChild(htmlMimePart)
+                .build();
+
+        assertThat(mimePart.retrieveTextHtmlBody()).contains(expectedContent);
+    }
+
+    @Test
+    public void 
retrieveTextHtmlBodyShouldReturnHtmlBodyWhenMultipleAttachments() {
+        String expectedContent = "<b>content</b>";
+        MimePart htmlMimePart = MimePart.builder()
+                .addMediaType("text")
+                .addSubType("html")
+                .addBodyContent(IOUtils.toInputStream(expectedContent))
+                .build();
+        MimePart plainMimePart = MimePart.builder()
+                .addMediaType("text")
+                .addSubType("plain")
+                .addBodyContent(IOUtils.toInputStream("content"))
+                .build();
+
+        MimePart mimePart = MimePart.builder()
+                .addChild(plainMimePart)
+                .addChild(htmlMimePart)
+                .build();
+
+        assertThat(mimePart.retrieveTextHtmlBody()).contains(expectedContent);
+    }
+
+    @Test
+    public void 
retrieveTextHtmlBodyShouldReturnFirstHtmlBodyWhenMultipleHtml() {
+        String expectedContent = "<b>first</b>";
+        MimePart firstMimePart = MimePart.builder()
+                .addMediaType("text")
+                .addSubType("html")
+                .addBodyContent(IOUtils.toInputStream(expectedContent))
+                .build();
+        MimePart secondMimePart = MimePart.builder()
+                .addMediaType("text")
+                .addSubType("html")
+                .addBodyContent(IOUtils.toInputStream("<b>second</b>"))
+                .build();
+
+        MimePart mimePart = MimePart.builder()
+                .addChild(firstMimePart)
+                .addChild(secondMimePart)
+                .build();
+
+        assertThat(mimePart.retrieveTextHtmlBody()).contains(expectedContent);
+    }
+
+    @Test
+    public void 
retrieveTextHtmlBodyShouldReturnEmptyWhenMultipleAttachmentsAndNoHtmlContent() {
+        MimePart htmlMimePart = MimePart.builder()
+                .addMediaType("text")
+                .addSubType("html")
+                .build();
+        MimePart plainMimePart = MimePart.builder()
+                .addMediaType("text")
+                .addSubType("plain")
+                .addBodyContent(IOUtils.toInputStream("content"))
+                .build();
+
+        MimePart mimePart = MimePart.builder()
+                .addChild(plainMimePart)
+                .addChild(htmlMimePart)
+                .build();
+
+        assertThat(mimePart.retrieveTextHtmlBody()).isEmpty();
+    }
+
+    @Test
+    public void 
retrieveTextPlainMimePartShouldReturnTextBodyWhenPlainSubType() {
+        String expectedContent = "content";
+        MimePart plainMimePart = MimePart.builder()
+                .addMediaType("text")
+                .addSubType("plain")
+                .addBodyContent(IOUtils.toInputStream(expectedContent))
+                .build();
+        
assertThat(plainMimePart.retrieveTextPlainBody()).contains(expectedContent);
+    }
+
+    @Test
+    public void 
retrieveTextPlainMimePartShouldReturnTextBodyFromAttachmentsWhenPlainSubTypeInAttachments()
 {
+        String expectedContent = "content";
+        MimePart plainMimePart = MimePart.builder()
+                .addMediaType("text")
+                .addSubType("plain")
+                .addBodyContent(IOUtils.toInputStream(expectedContent))
+                .build();
+        MimePart mimePart = MimePart.builder()
+                .addChild(plainMimePart)
+                .build();
+        assertThat(mimePart.retrieveTextPlainBody()).contains(expectedContent);
+    }
+
+    @Test
+    public void 
retrieveTextPlainBodyShouldReturnTextBodyWhenMultipleAttachments() {
+        String expectedContent = "content";
+        MimePart plainMimePart = MimePart.builder()
+                .addMediaType("text")
+                .addSubType("plain")
+                .addBodyContent(IOUtils.toInputStream(expectedContent))
+                .build();
+        MimePart htmlMimePart = MimePart.builder()
+                .addMediaType("text")
+                .addSubType("html")
+                .addBodyContent(IOUtils.toInputStream("<b>content</b>"))
+                .build();
+
+        MimePart mimePart = MimePart.builder()
+                .addChild(htmlMimePart)
+                .addChild(plainMimePart)
+                .build();
+
+        assertThat(mimePart.retrieveTextPlainBody()).contains(expectedContent);
+    }
+
+    @Test
+    public void 
retrieveTextPlainBodyShouldReturnTheFirstTextBodyWhenMultipleText() {
+        String expectedContent = "first";
+        MimePart firstMimePart = MimePart.builder()
+                .addMediaType("text")
+                .addSubType("plain")
+                .addBodyContent(IOUtils.toInputStream(expectedContent))
+                .build();
+        MimePart secondMimePart = MimePart.builder()
+                .addMediaType("text")
+                .addSubType("plain")
+                .addBodyContent(IOUtils.toInputStream("second"))
+                .build();
+
+        MimePart mimePart = MimePart.builder()
+                .addChild(firstMimePart)
+                .addChild(secondMimePart)
+                .build();
+
+        assertThat(mimePart.retrieveTextPlainBody()).contains(expectedContent);
+    }
+
+    @Test
+    public void 
retrieveTextPlainBodyShouldReturnEmptyWhenMultipleAttachmentsAndNoTextContent() 
{
+        MimePart plainMimePart = MimePart.builder()
+                .addMediaType("text")
+                .addSubType("plain")
+                .build();
+        MimePart htmlMimePart = MimePart.builder()
+                .addMediaType("text")
+                .addSubType("html")
+                .addBodyContent(IOUtils.toInputStream("<b>content</b>"))
+                .build();
+
+        MimePart mimePart = MimePart.builder()
+                .addChild(htmlMimePart)
+                .addChild(plainMimePart)
+                .build();
+
+        assertThat(mimePart.retrieveTextPlainBody()).isEmpty();
+    }
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscr...@james.apache.org
For additional commands, e-mail: server-dev-h...@james.apache.org

Reply via email to