You are viewing a plain text version of this content. The canonical link for it is here.
Posted to server-dev@james.apache.org by ad...@apache.org on 2016/07/08 10:59:15 UTC

[1/5] james-project git commit: JAMES-1791 Support inline attachments

Repository: james-project
Updated Branches:
  refs/heads/master 85aeb1e45 -> 1c294ddc0


http://git-wip-us.apache.org/repos/asf/james-project/blob/896bc961/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/MailboxMessageTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/MailboxMessageTest.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/MailboxMessageTest.java
index eae0c49..b11edcf 100644
--- a/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/MailboxMessageTest.java
+++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/MailboxMessageTest.java
@@ -35,6 +35,7 @@ import org.apache.james.jmap.utils.HtmlTextExtractor;
 import org.apache.james.mailbox.store.TestId;
 import org.apache.james.mailbox.store.mail.model.AttachmentId;
 import org.apache.james.mailbox.store.mail.model.MailboxMessage;
+import org.apache.james.mailbox.store.mail.model.MessageAttachment;
 import org.apache.james.mailbox.store.mail.model.impl.PropertyBuilder;
 import org.apache.james.mailbox.store.mail.model.impl.SimpleMailboxMessage;
 import org.junit.Before;
@@ -416,12 +417,18 @@ public class MailboxMessageTest {
                 .blobId(blodId)
                 .size(payload.length())
                 .type(type)
+                .cid("cid")
+                .isInline(true)
                 .build();
         Message testee = messageFactory.fromMailboxMessage(testMail,
-                ImmutableList.of(org.apache.james.mailbox.store.mail.model.Attachment.builder()
-                        .attachmentId(AttachmentId.from(blodId))
-                        .bytes(payload.getBytes())
-                        .type(type)
+                ImmutableList.of(MessageAttachment.builder()
+                        .attachment(org.apache.james.mailbox.store.mail.model.Attachment.builder()
+                            .attachmentId(AttachmentId.from(blodId))
+                            .bytes(payload.getBytes())
+                            .type(type)
+                            .build())
+                        .cid("cid")
+                        .isInline(true)
                         .build()), 
                 x -> MessageId.of("user|box|" + x));
 


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


[2/5] james-project git commit: JAMES-1791 Support inline attachments

Posted by ad...@apache.org.
http://git-wip-us.apache.org/repos/asf/james-project/blob/896bc961/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageAttachmentTest.java
----------------------------------------------------------------------
diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageAttachmentTest.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageAttachmentTest.java
new file mode 100644
index 0000000..5d8ebcd
--- /dev/null
+++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageAttachmentTest.java
@@ -0,0 +1,100 @@
+/****************************************************************
+ * 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.mailbox.store.mail.model;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.junit.Test;
+
+import com.google.common.base.Optional;
+
+public class MessageAttachmentTest {
+
+    @Test(expected=IllegalStateException.class)
+    public void buildShouldThrowWhenAttachmentIsNotGiven() {
+        MessageAttachment.builder()
+            .build();
+    }
+
+    @Test(expected=IllegalArgumentException.class)
+    public void builderShouldThrowWhenAttachmentIsNull() {
+        MessageAttachment.builder()
+            .attachment(null);
+    }
+
+    @Test
+    public void buildShouldWorkWhenMandatoryAttributesAreGiven() {
+        Attachment attachment = Attachment.builder()
+                .bytes("content".getBytes())
+                .type("type")
+                .build();
+        MessageAttachment expectedMessageAttachment = new MessageAttachment(attachment, Optional.<String> absent(), false);
+
+        MessageAttachment messageAttachment = MessageAttachment.builder()
+            .attachment(attachment)
+            .build();
+
+        assertThat(messageAttachment).isEqualTo(expectedMessageAttachment);
+    }
+
+    @Test
+    public void buildShouldSetIsInlineDefaultValueWhenNotGiven() {
+        Attachment attachment = Attachment.builder()
+                .bytes("content".getBytes())
+                .type("type")
+                .build();
+
+        MessageAttachment messageAttachment = MessageAttachment.builder()
+            .attachment(attachment)
+            .build();
+
+        assertThat(messageAttachment.isInline()).isFalse();
+    }
+
+    @Test(expected=IllegalStateException.class)
+    public void buildShouldThrowWhenIsInlineAndNoCid() {
+        Attachment attachment = Attachment.builder()
+                .bytes("content".getBytes())
+                .type("type")
+                .build();
+
+        MessageAttachment.builder()
+            .attachment(attachment)
+            .isInline(true)
+            .build();
+    }
+
+    @Test
+    public void buildShouldSetAttributesWhenAllAreGiven() {
+        Attachment attachment = Attachment.builder()
+                .bytes("content".getBytes())
+                .type("type")
+                .build();
+        MessageAttachment expectedMessageAttachment = new MessageAttachment(attachment, Optional.of("cid"), true);
+
+        MessageAttachment messageAttachment = MessageAttachment.builder()
+            .attachment(attachment)
+            .cid("cid")
+            .isInline(true)
+            .build();
+
+        assertThat(messageAttachment).isEqualTo(expectedMessageAttachment);
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/896bc961/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageMapperTest.java
----------------------------------------------------------------------
diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageMapperTest.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageMapperTest.java
index f0d614b..82ac2a3 100644
--- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageMapperTest.java
+++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageMapperTest.java
@@ -38,6 +38,7 @@ import org.apache.james.mailbox.model.MessageMetaData;
 import org.apache.james.mailbox.model.MessageRange;
 import org.apache.james.mailbox.model.UpdatedFlags;
 import org.apache.james.mailbox.store.FlagsUpdateCalculator;
+import org.apache.james.mailbox.store.mail.AttachmentMapper;
 import org.apache.james.mailbox.store.mail.MessageMapper;
 import org.apache.james.mailbox.store.mail.MessageMapper.FetchType;
 import org.apache.james.mailbox.store.mail.model.impl.PropertyBuilder;
@@ -65,6 +66,7 @@ public class MessageMapperTest<T extends MapperProvider> {
     private IProducer<T> producer;
     private MapperProvider mapperProvider;
     private MessageMapper messageMapper;
+    private AttachmentMapper attachmentMapper;
 
     private SimpleMailbox benwaInboxMailbox;
     private SimpleMailbox benwaWorkMailbox;
@@ -87,7 +89,8 @@ public class MessageMapperTest<T extends MapperProvider> {
         this.producer = producer;
         this.mapperProvider = producer.newInstance();
         this.mapperProvider.ensureMapperPrepared();
-        this. messageMapper = mapperProvider.createMessageMapper();
+        this.messageMapper = mapperProvider.createMessageMapper();
+        this.attachmentMapper = mapperProvider.createAttachmentMapper();
 
         benwaInboxMailbox = createMailbox(new MailboxPath("#private", "benwa", "INBOX"));
         benwaWorkMailbox = createMailbox( new MailboxPath("#private", "benwa", "INBOX"+DELIMITER+"work"));
@@ -99,8 +102,37 @@ public class MessageMapperTest<T extends MapperProvider> {
         message4 = createMessage(benwaInboxMailbox, "Subject: Test4 \n\nBody4\n.\n", BODY_START, new PropertyBuilder());
         message5 = createMessage(benwaInboxMailbox, "Subject: Test5 \n\nBody5\n.\n", BODY_START, new PropertyBuilder());
         message6 = createMessage(benwaWorkMailbox, "Subject: Test6 \n\nBody6\n.\n", BODY_START, new PropertyBuilder());
-        message7With1Attachment = createMessage(attachmentsMailbox, "Subject: Test7 \n\nBody7\n.\n", BODY_START, new PropertyBuilder(), ImmutableList.of(AttachmentId.from("123")));
-        message8With2Attachments = createMessage(attachmentsMailbox, "Subject: Test8 \n\nBody8\n.\n", BODY_START, new PropertyBuilder(), ImmutableList.of(AttachmentId.from("123"), AttachmentId.from("456")));
+
+        Attachment attachment = Attachment.builder()
+                .attachmentId(AttachmentId.from("123"))
+                .bytes("attachment".getBytes())
+                .type("content")
+                .build();
+        attachmentMapper.storeAttachment(attachment);
+        Attachment attachment2 = Attachment.builder()
+                .attachmentId(AttachmentId.from("456"))
+                .bytes("attachment2".getBytes())
+                .type("content")
+                .build();
+        attachmentMapper.storeAttachment(attachment2);
+        message7With1Attachment = createMessage(attachmentsMailbox, "Subject: Test7 \n\nBody7\n.\n", BODY_START, new PropertyBuilder(), 
+                ImmutableList.of(MessageAttachment.builder()
+                        .attachment(attachment)
+                        .cid("cid")
+                        .isInline(true)
+                        .build()));
+        message8With2Attachments = createMessage(attachmentsMailbox, "Subject: Test8 \n\nBody8\n.\n", BODY_START, new PropertyBuilder(), 
+                ImmutableList.of(
+                        MessageAttachment.builder()
+                            .attachment(attachment)
+                            .cid("cid")
+                            .isInline(true)
+                            .build(),
+                        MessageAttachment.builder()
+                            .attachment(attachment2)
+                            .cid("cid2")
+                            .isInline(false)
+                            .build()));
 
     }
 
@@ -268,53 +300,53 @@ public class MessageMapperTest<T extends MapperProvider> {
     }
 
     @ContractTest
-    public void messagesRetrievedUsingFetchTypeFullShouldHaveAttachmentsIdsEmptyWhenNoAttachment() throws MailboxException, IOException{
+    public void messagesRetrievedUsingFetchTypeFullShouldHaveAttachmentsEmptyWhenNoAttachment() throws MailboxException, IOException{
         saveMessages();
         MessageMapper.FetchType fetchType = MessageMapper.FetchType.Full;
         Iterator<MailboxMessage> retrievedMessageIterator = messageMapper.findInMailbox(benwaInboxMailbox, MessageRange.one(message1.getUid()), fetchType, LIMIT);
-        assertThat(retrievedMessageIterator.next().getAttachmentsIds()).isEmpty();
+        assertThat(retrievedMessageIterator.next().getAttachments()).isEmpty();
     }
 
     @ContractTest
-    public void messagesRetrievedUsingFetchTypeFullShouldHaveAttachmentsIdsLoadedWhenOneAttachment() throws MailboxException, IOException{
+    public void messagesRetrievedUsingFetchTypeFullShouldHaveAttachmentsLoadedWhenOneAttachment() throws MailboxException, IOException{
         saveMessages();
         MessageMapper.FetchType fetchType = MessageMapper.FetchType.Full;
         Iterator<MailboxMessage> retrievedMessageIterator = messageMapper.findInMailbox(attachmentsMailbox, MessageRange.one(message7With1Attachment.getUid()), fetchType, LIMIT);
-        assertThat(retrievedMessageIterator.next().getAttachmentsIds()).isEqualTo(message7With1Attachment.getAttachmentsIds());
+        assertThat(retrievedMessageIterator.next().getAttachments()).isEqualTo(message7With1Attachment.getAttachments());
     }
 
     @ContractTest
-    public void messagesRetrievedUsingFetchTypeFullShouldHaveAttachmentsIdsLoadedWhenTwoAttachments() throws MailboxException, IOException{
+    public void messagesRetrievedUsingFetchTypeFullShouldHaveAttachmentsLoadedWhenTwoAttachments() throws MailboxException, IOException{
         saveMessages();
         MessageMapper.FetchType fetchType = MessageMapper.FetchType.Full;
         Iterator<MailboxMessage> retrievedMessageIterator = messageMapper.findInMailbox(attachmentsMailbox, MessageRange.one(message8With2Attachments.getUid()), fetchType, LIMIT);
-        assertThat(retrievedMessageIterator.next().getAttachmentsIds()).isEqualTo(message8With2Attachments.getAttachmentsIds());
+        assertThat(retrievedMessageIterator.next().getAttachments()).isEqualTo(message8With2Attachments.getAttachments());
     }
 
     @ContractTest
-    public void messagesRetrievedUsingFetchTypeBodyShouldHaveAttachmentsIdsLoadedWhenOneAttachment() throws MailboxException, IOException{
+    public void messagesRetrievedUsingFetchTypeBodyShouldHaveAttachmentsLoadedWhenOneAttachment() throws MailboxException, IOException{
         saveMessages();
         MessageMapper.FetchType fetchType = MessageMapper.FetchType.Body;
         Iterator<MailboxMessage> retrievedMessageIterator = messageMapper.findInMailbox(attachmentsMailbox, MessageRange.one(message7With1Attachment.getUid()), fetchType, LIMIT);
-        assertThat(retrievedMessageIterator.next().getAttachmentsIds()).isEqualTo(message7With1Attachment.getAttachmentsIds());
+        assertThat(retrievedMessageIterator.next().getAttachments()).isEqualTo(message7With1Attachment.getAttachments());
     }
 
     @ContractTest
-    public void messagesRetrievedUsingFetchTypeHeadersShouldHaveAttachmentsIdsEmptyWhenOneAttachment() throws MailboxException, IOException{
+    public void messagesRetrievedUsingFetchTypeHeadersShouldHaveAttachmentsEmptyWhenOneAttachment() throws MailboxException, IOException{
         Assume.assumeTrue(mapperProvider.supportPartialAttachmentFetch());
         saveMessages();
         MessageMapper.FetchType fetchType = MessageMapper.FetchType.Headers;
         Iterator<MailboxMessage> retrievedMessageIterator = messageMapper.findInMailbox(attachmentsMailbox, MessageRange.one(message7With1Attachment.getUid()), fetchType, LIMIT);
-        assertThat(retrievedMessageIterator.next().getAttachmentsIds()).isEmpty();
+        assertThat(retrievedMessageIterator.next().getAttachments()).isEmpty();
     }
 
     @ContractTest
-    public void messagesRetrievedUsingFetchTypeMetadataShouldHaveAttachmentsIdsEmptyWhenOneAttachment() throws MailboxException, IOException{
+    public void messagesRetrievedUsingFetchTypeMetadataShouldHaveAttachmentsEmptyWhenOneAttachment() throws MailboxException, IOException{
         Assume.assumeTrue(mapperProvider.supportPartialAttachmentFetch());
         saveMessages();
         MessageMapper.FetchType fetchType = MessageMapper.FetchType.Metadata;
         Iterator<MailboxMessage> retrievedMessageIterator = messageMapper.findInMailbox(attachmentsMailbox, MessageRange.one(message7With1Attachment.getUid()), fetchType, LIMIT);
-        assertThat(retrievedMessageIterator.next().getAttachmentsIds()).isEmpty();
+        assertThat(retrievedMessageIterator.next().getAttachments()).isEmpty();
     }
 
     @ContractTest
@@ -742,8 +774,8 @@ public class MessageMapperTest<T extends MapperProvider> {
         return messageMapper.findInMailbox(benwaInboxMailbox, MessageRange.one(message.getUid()), MessageMapper.FetchType.Metadata, LIMIT).next();
     }
     
-    private SimpleMailboxMessage createMessage(Mailbox mailbox, String content, int bodyStart, PropertyBuilder propertyBuilder, List<AttachmentId> attachmentsIds) {
-        return new SimpleMailboxMessage(new Date(), content.length(), bodyStart, new SharedByteArrayInputStream(content.getBytes()), new Flags(), propertyBuilder, mailbox.getMailboxId(), attachmentsIds);
+    private SimpleMailboxMessage createMessage(Mailbox mailbox, String content, int bodyStart, PropertyBuilder propertyBuilder, List<MessageAttachment> attachments) {
+        return new SimpleMailboxMessage(new Date(), content.length(), bodyStart, new SharedByteArrayInputStream(content.getBytes()), new Flags(), propertyBuilder, mailbox.getMailboxId(), attachments);
     }
     
     private SimpleMailboxMessage createMessage(Mailbox mailbox, String content, int bodyStart, PropertyBuilder propertyBuilder) {

http://git-wip-us.apache.org/repos/asf/james-project/blob/896bc961/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/impl/MessageParserTest.java
----------------------------------------------------------------------
diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/impl/MessageParserTest.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/impl/MessageParserTest.java
index ca6847d..2512123 100644
--- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/impl/MessageParserTest.java
+++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/impl/MessageParserTest.java
@@ -24,6 +24,7 @@ import static org.assertj.core.api.Assertions.assertThat;
 import java.util.List;
 
 import org.apache.james.mailbox.store.mail.model.Attachment;
+import org.apache.james.mailbox.store.mail.model.MessageAttachment;
 import org.junit.Before;
 import org.junit.Test;
 
@@ -40,101 +41,117 @@ public class MessageParserTest {
 
     @Test
     public void getAttachmentsShouldBeEmptyWhenNoAttachment() throws Exception {
-        List<Attachment> attachments = testee.retrieveAttachments(ClassLoader.getSystemResourceAsStream("eml/noAttachment.eml"));
+        List<MessageAttachment> attachments = testee.retrieveAttachments(ClassLoader.getSystemResourceAsStream("eml/noAttachment.eml"));
 
         assertThat(attachments).isEmpty();
     }
 
     @Test
     public void getAttachmentsShouldRetrieveAttachmentsWhenOneAttachment() throws Exception {
-        List<Attachment> attachments = testee.retrieveAttachments(ClassLoader.getSystemResourceAsStream("eml/oneAttachmentAndSomeInlined.eml"));
+        List<MessageAttachment> attachments = testee.retrieveAttachments(ClassLoader.getSystemResourceAsStream("eml/oneAttachmentAndSomeTextInlined.eml"));
 
         assertThat(attachments).hasSize(1);
     }
 
     @Test
     public void getAttachmentsShouldRetrieveAttachmentNameWhenOne() throws Exception {
-        List<Attachment> attachments = testee.retrieveAttachments(ClassLoader.getSystemResourceAsStream("eml/oneAttachmentAndSomeInlined.eml"));
+        List<MessageAttachment> attachments = testee.retrieveAttachments(ClassLoader.getSystemResourceAsStream("eml/oneAttachmentAndSomeTextInlined.eml"));
 
         assertThat(attachments).hasSize(1);
         Optional<String> expectedName = Optional.of("exploits_of_a_mom.png");
-        assertThat(attachments.get(0).getName()).isEqualTo(expectedName);
+        assertThat(attachments.get(0).getAttachment().getName()).isEqualTo(expectedName);
     }
 
     @Test
     public void getAttachmentsShouldRetrieveEmptyNameWhenNone() throws Exception {
-        List<Attachment> attachments = testee.retrieveAttachments(ClassLoader.getSystemResourceAsStream("eml/oneAttachmentWithoutName.eml"));
+        List<MessageAttachment> attachments = testee.retrieveAttachments(ClassLoader.getSystemResourceAsStream("eml/oneAttachmentWithoutName.eml"));
 
         assertThat(attachments).hasSize(1);
-        assertThat(attachments.get(0).getName()).isEqualTo(Optional.absent());
+        assertThat(attachments.get(0).getAttachment().getName()).isEqualTo(Optional.absent());
     }
 
     @Test
     public void getAttachmentsShouldNotFailWhenContentTypeIsNotHere() throws Exception {
-        List<Attachment> attachments = testee.retrieveAttachments(ClassLoader.getSystemResourceAsStream("eml/oneAttachmentWithoutContentType.eml"));
+        List<MessageAttachment> attachments = testee.retrieveAttachments(ClassLoader.getSystemResourceAsStream("eml/oneAttachmentWithoutContentType.eml"));
 
         assertThat(attachments).hasSize(1);
-        assertThat(attachments.get(0).getType()).isEqualTo("application/octet-stream");
+        assertThat(attachments.get(0).getAttachment().getType()).isEqualTo("application/octet-stream");
     }
 
     @Test
     public void getAttachmentsShouldNotFailWhenContentTypeIsEmpty() throws Exception {
-        List<Attachment> attachments = testee.retrieveAttachments(ClassLoader.getSystemResourceAsStream("eml/oneAttachmentWithEmptyContentType.eml"));
+        List<MessageAttachment> attachments = testee.retrieveAttachments(ClassLoader.getSystemResourceAsStream("eml/oneAttachmentWithEmptyContentType.eml"));
 
         assertThat(attachments).hasSize(1);
-        assertThat(attachments.get(0).getType()).isEqualTo("application/octet-stream");
+        assertThat(attachments.get(0).getAttachment().getType()).isEqualTo("application/octet-stream");
     }
 
     @Test
     public void getAttachmentsShouldRetrieveTheAttachmentContentTypeWhenOneAttachment() throws Exception {
-        List<Attachment> attachments = testee.retrieveAttachments(ClassLoader.getSystemResourceAsStream("eml/oneAttachmentAndSomeInlined.eml"));
+        List<MessageAttachment> attachments = testee.retrieveAttachments(ClassLoader.getSystemResourceAsStream("eml/oneAttachmentAndSomeTextInlined.eml"));
 
         assertThat(attachments).hasSize(1);
-        assertThat(attachments.get(0).getType()).isEqualTo("application/octet-stream");
+        assertThat(attachments.get(0).getAttachment().getType()).isEqualTo("application/octet-stream");
     }
 
     @Test
     public void getAttachmentsShouldRetrieveTheAttachmentContentTypeWhenOneAttachmentWithSimpleContentType() throws Exception {
-        List<Attachment> attachments = testee.retrieveAttachments(ClassLoader.getSystemResourceAsStream("eml/oneAttachmentWithSimpleContentType.eml"));
+        List<MessageAttachment> attachments = testee.retrieveAttachments(ClassLoader.getSystemResourceAsStream("eml/oneAttachmentWithSimpleContentType.eml"));
 
         assertThat(attachments).hasSize(1);
-        assertThat(attachments.get(0).getType()).isEqualTo("application/octet-stream");
+        assertThat(attachments.get(0).getAttachment().getType()).isEqualTo("application/octet-stream");
     }
 
     @Test
     public void getAttachmentsShouldRetrieveTheAttachmentSizeWhenOneAttachment() throws Exception {
-        List<Attachment> attachments = testee.retrieveAttachments(ClassLoader.getSystemResourceAsStream("eml/oneAttachmentAndSomeInlined.eml"));
+        List<MessageAttachment> attachments = testee.retrieveAttachments(ClassLoader.getSystemResourceAsStream("eml/oneAttachmentAndSomeTextInlined.eml"));
 
         assertThat(attachments).hasSize(1);
-        assertThat(attachments.get(0).getSize()).isEqualTo(3071);
+        assertThat(attachments.get(0).getAttachment().getSize()).isEqualTo(3071);
     }
 
     @Test
     public void getAttachmentsShouldReturnTheExpectedAttachment() throws Exception {
-        List<Attachment> attachments = testee.retrieveAttachments(ClassLoader.getSystemResourceAsStream("eml/oneAttachmentAndSomeInlined.eml"));
+        List<MessageAttachment> attachments = testee.retrieveAttachments(ClassLoader.getSystemResourceAsStream("eml/oneAttachmentAndSomeTextInlined.eml"));
 
-        Attachment attachment = attachments.get(0);
+        Attachment attachment = attachments.get(0).getAttachment();
         assertThat(attachment.getStream()).hasContentEqualTo(ClassLoader.getSystemResourceAsStream("eml/gimp.png"));
     }
 
     @Test
     public void getAttachmentsShouldRetrieveAttachmentsWhenTwo() throws Exception {
-        List<Attachment> attachments = testee.retrieveAttachments(ClassLoader.getSystemResourceAsStream("eml/twoAttachments.eml"));
+        List<MessageAttachment> attachments = testee.retrieveAttachments(ClassLoader.getSystemResourceAsStream("eml/twoAttachments.eml"));
 
         assertThat(attachments).hasSize(2);
     }
 
     @Test
     public void getAttachmentsShouldNotRetrieveEmbeddedAttachmentsWhenSome() throws Exception {
-        List<Attachment> attachments = testee.retrieveAttachments(ClassLoader.getSystemResourceAsStream("eml/embeddedAttachmentWithInline.eml"));
+        List<MessageAttachment> attachments = testee.retrieveAttachments(ClassLoader.getSystemResourceAsStream("eml/embeddedAttachmentWithInline.eml"));
 
         assertThat(attachments).hasSize(1);
     }
 
     @Test
     public void getAttachmentsShouldNotRetrieveInlineAttachmentsWhenSome() throws Exception {
-        List<Attachment> attachments = testee.retrieveAttachments(ClassLoader.getSystemResourceAsStream("eml/embeddedAttachmentWithAttachment.eml"));
+        List<MessageAttachment> attachments = testee.retrieveAttachments(ClassLoader.getSystemResourceAsStream("eml/embeddedAttachmentWithAttachment.eml"));
 
         assertThat(attachments).hasSize(1);
     }
+
+    @Test
+    public void getAttachmentsShouldRetrieveTheAttachmentCIDWhenOne() throws Exception {
+        List<MessageAttachment> attachments = testee.retrieveAttachments(ClassLoader.getSystemResourceAsStream("eml/oneInlinedAttachment.eml"));
+
+        assertThat(attachments).hasSize(1);
+        assertThat(attachments.get(0).getCid()).isEqualTo(Optional.of("<pa...@linagora.com>"));
+    }
+
+    @Test
+    public void getAttachmentsShouldSetInlineWhenOneInlinedAttachment() throws Exception {
+        List<MessageAttachment> attachments = testee.retrieveAttachments(ClassLoader.getSystemResourceAsStream("eml/oneInlinedAttachment.eml"));
+
+        assertThat(attachments).hasSize(1);
+        assertThat(attachments.get(0).isInline()).isTrue();
+    }
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/896bc961/mailbox/store/src/test/resources/eml/oneAttachmentAndSomeInlined.eml
----------------------------------------------------------------------
diff --git a/mailbox/store/src/test/resources/eml/oneAttachmentAndSomeInlined.eml b/mailbox/store/src/test/resources/eml/oneAttachmentAndSomeInlined.eml
deleted file mode 100644
index 578af96..0000000
--- a/mailbox/store/src/test/resources/eml/oneAttachmentAndSomeInlined.eml
+++ /dev/null
@@ -1,39 +0,0 @@
-Mail content:
-To: "=?utf-8?B?UmFuaSBBc3NhZg==?=" <ra...@jri.obm.lng.org>
-Subject: =?utf-8?B?VHIuIDogUGhvdG9zICE=?=
-Importance: Normal
-MIME-Version: 1.0
-Content-Type: multipart/mixed;
-	boundary="----=_Part_0_1330682067197"
-
-------=_Part_0_1330682067197
-Content-Type: multipart/alternative;
-	boundary="----=_Part_2_1330682067197"
-
-------=_Part_2_1330682067197
-Content-Type: text/plain;
-	charset= utf-8
-Content-Transfer-Encoding: 8bit
-Content-Disposition: inline
-
-Content of part 1-1
-------=_Part_2_1330682067197
-Content-Type: text/html;
-	charset= utf-8
-Content-Transfer-Encoding: 8bit
-Content-Disposition: inline
-
-<b>Content of part 1-2</b>
-------=_Part_2_1330682067197--
-
-------=_Part_0_1330682067197
-Content-Type: application/octet-stream;
-	name="exploits_of_a_mom.png"
-Content-Transfer-Encoding: base64
-Content-Disposition: attachment;
-	filename="gimp.png"
-
-iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAALxklEQVR4Ae2Xe0xUZ97H5X4RiyAXEARURBSYCzNnLjMwwAx3huGOIBcUFJERAUVRq+KlwHABFdu+b9+0766x1W21ttnUtE3rul6aGNtm3XbdWncjaa3VXrZRK6IgfPd3Tp6wOGmyo0v/cOMknxwy5xzO7/P8LueZaWlpaU80TwWeCvy3CcRwXJlUqp39RApIOE4i5hQPxBz30hMpIJIrjktkseMimfzPUyoglilTf/XVl8u1Ik4xrOJEEMu4wSkVEMmVZ6VSTeivFXy0TDZfIlfc0qil0KpIQM59P6UCUk71lVShPD1t2jT7qQ4+Sq32prq/GhfHjSXFSxGvEfMCQ1MsoLzOadT3pArFwBQ3LSdRqK4mJyfcz0xRwaCLRVKcBDEybmxqBRTKH8uXpEOj0/1MD3wuMTHR8T9adY4LoOD3KuPj7xYVGlGYo0e6gUNKoowkpKBmHpXJZO5TKXCrpjwT5pWFSM1IvROrVH0hksujf+laAHYWi8XT+nsKyIlvVKlSeVSu0twtXpI/Yq4rR2lBKoxpamQmK5Gm55CcIAP1wxAvOWUCEk4xVLvchIaVedi8rgq1NSXjqnjdHcrGayK5yhStVPpbLLvE/Xt6Tnf3Wu529XSM9fZ13Wzbse2kJiGhK1ap/ETCqe5lGLNum+trxnZsbca6tcuwJM+AvKw4mNI1yEpVURYUSE2S8wJ3RSKN35QJUJPdM6/IQ8vaCmzdZMbObU2w7G7BhhbzeEFR4e2SsrIRChqnz5zE999/h9HREXz19SDefOt1dPW0Y8e2Frywtx0vDnRg57NrUVdTgJJ8PYpyEpBvjEdOhvahLIg55YOioiKHRxKgjwPBEaHEQzfz/3DH9mb07+nGsbeO4MjRw+jts8DS3or/GdiNnr4ufP6XC/jhh+9w587PuHdvGLdv38SNG9fwwYfvon9vN3Zvb0Td8
 lxUlqSirCgZpSRQnJuIgmwdcikL2elqZKUwAbni0aaQvb19M3HT2dnlloODw5Cdnd0d+rKVRFz48xkm0+i+gX5cv34NP/30I86fP4ePPjqL3n4LOjq24O2338CVK1/i22+v4ssvL+HTTz+B2WzGqlUrcfr0HzCwvw9Na8pRXZaBqtI0VBSnYGmBgUooEYUmHYQyyhDKCClJCl7gus0C9DE5OjkNpefkoXvPPugzjIiMEcN9+vQ7JHKFzvs1tzTdO3P2lBD8wYMHce3aNVBTYk1DPXp62/HHUx/g0qXPSOIyBgcHwX/u37+PiMhIiCViHP7dAbRuqAc/CJbxAktIoJAXSEKRiZURCRhJwJCoAPXcRZsF7B0dL8cq1RgeHgb/+fziX6E1pPCjDJ5e3iOUmcHWzRvHz398ThAoKSnB5b/9HYbUdMwJmUPl04GTJ9/DhQvn8cYbh/D++++D/1y/cYOvZbi6uWHvvj48u7kRgsDSdEGgjARKSOChPiCBpAQFpBx3ymYBWuXR9Zu2gH0wPj6O7KISyNRxiBJLMeMZz/GcXOP4a4cOCAJ5eXmY5eMDL29v6PUJ6O7aQX1xGOfOncLx429h5syZMDc2I05vQJQ0Fq6uriTZifWNy60yYCXAMqDVcmMiTtlrswAZPMgtLsXY2Jgg8PXVb5CYngWpSoMFi6MRsTAS7rSKnZZdeP3IIarv89ixow21tTXoaN9KE6kefdQLJ04cx5kzH0Cp5OA9axYCgoIx08sLCQlxsHS3o646F9XlGSQwuQeSJveAICBTKm49yuaRb+Drco0W6zdTM75zHJW1dVAlGvjXOULDF2ABCQQFz4FcEomdbc3o7qGpQ+za3oQtzWXY3LwUHc9twfPP9+Gd40ephN5GW9tmJCXpsHnLBrq+HS1N1VhRkYnlZemooilUzk+hgokpNPEuyExWUdlx99lb2GaBV+eGh48kJKciVq0VSofqX1j9wDkhCA4Ng0gihb+vF5
 pXF2K9uQgta4qxoWEJNq4l6LihoQRtW5vQRSu9d6AH//vSAI1cCzq7dmNdQxVWVmahhq3+RP3n/6t8cjO1yE5TQ59EDaxQsN8Ctk+hUH50JhqSESONFQKfF0GrToH7+AfAf3YQdIlJcHNzwdrafDTWFaCJRJqJdfVFAvzfTfR9c30xrfYytLbUotlchtXVOULwND6FICuXPLz61uWj1iruUePv4gvbZgGWhv2+fn5DesrCXCob34BAPniBoJBQJOj18KMM1NfkYM2KXGFL0VCbxwsJ0N/Cd2Y6x1+zmrYdq5YZJ1Z+OU2ejGTK6rwg4QX20Phkq59mUPLz/264SBRMAva2Sky8hWka/T4gMPBuVnY2OJUaIXPnYU7YXCQlJ0MsFkMaE05BZdPbNJtW1iRQTytMCH9T0MK5VVVC4ELN8ytPZSNsG6IjQ5C4wAkVWl+UZsYiP1sonYl9kIpWPzpW9gLFMp1wJhyYhM1bCUfqh5dp7A3J5PIHqWnpyDQaIZFKMMvbU3iD0hikwLKEAGt5KFhCWGUKlk2ZdGGrUEQlkqaXC+LBgV4ok7tik8Edr1fOwKbkGajXeaBcH4aclFik6hXC9sE7ICCK4vAhZhAutkj8UlMsopL6jZ2d/acOjo7fBAbPuW/Qax7QHkYoBZIQgqUjQ5guQm3nG3VCqeg0IsSKFmDRwlBERYZBHDUPxvhICvoZdGR54IudEfisg8Nva+aiQTcDpVq/B4qY8Ffo2QuIYCsJVk62C9gRTiyVPkFhYSqxnLuk0qqH83P0FGwmVi3PpbLJp2MeZSSbxGjlSa6yRJjxgsxSNmmWUCZo2gjjMj9LgwpDGMzxbji20h9Xu6JxpV+FI+aF4016z/u1atcPq/P1DTqdOoae7U24E46PI+DMVsCfCHN2do6OWBzdS9vqf3Bq1bAxM4FKJZMalqbQmkq00N6+eU0FGlaV0gurgErJiPLiNHpZJfN7fiqnJNawwrYZJoMYtfF
 eVErT8fG6WbjaGYHBPg6v1EWNdXa2Yeuz6w75+PgEshicHkfAhXiGCCDmEosJGaELCgnpiJJIByUK5YjBED++tDANtctoGq0uw4amGmxaX0vHFSRUhfqVJVhRlYeK0iwSSSaBeCoxJTQablwk40aTYvwvrta6DL9c7DF6eYsPeixtOPjqAbzw4v6hrp7OC+XV5QsfV8CJ2fsRIUQkISXURCpR6enl1b1g0eLP+d8KsQrlqEqjGtHr48ezMmhMFmWiqsyEylIjivNSKPBEJBu0UKoVD0Qy+djC6Oir7h4eA/R/mvw87FdXK13PbsyPHOnt7aAtyQmBQ4dfHe3p7by187ntOXTdPCKDcLZVwIFwI7yIQGLepCxomUQ50Ui0UTD/5+Pr925waOifFi6OuiaKlQ1JOOUYMU6CozGx8uHIqJjr/kFBJ11cXJ6ne7YSZmIpkUJoWxqXv2fp2n133/49d44de1OQOHr0CAIC/Meio6MhkUhA110jNhL21gLWEvaTGtmbmM0kFk3KRCKRRZQR9cQGoo3oIHppJPfTsY/oJtqJbUQLUUeUshVNIJSExMvLK9rT03P+upbGVd09nZfo9/XPJlM2/P390dnZKRAWFsZL8JT+OwG7SRLuxEzCn5VTOBHFRJREPKEn0ggTUcRWtoJRyr4zscwlEXHsXinLbDgbn37sWW7bdm2L9/Pzu+nu7o6NGzeitbWVshEAlokvCPsJARskXFlPeDORYJaRCCYjZuWlYNnREFqGhlCxczJ27WJ279xJgXsRHmyAOLJnnyTAQxkVjvPnz4evry94eWuBX5RgOEwSmU54ErOYzGxiDhHGpMKJCCvC2bkwFvBsFrQ3m3bTWeBO7Fl2jPUErKFy44/p1gK2ijgSzkzGnfBgQcxkAfkwfBk+DG9iJrvWg93ryoJ2nBy41bMPWQvQ7pk/LrMSeCQRe8JhkpATk3JhQblZ4crOOVsFLGwTrAOfDLv3AAErWq0FHldm
 ktQEDlbYM+yseYTnLSOGCDD6H1/ARilrpuD/LyYuMoFDVgJPBqx3/p84YS3wpInonmQBxlOBpwJPBf4JszXhha5WvGwAAAAASUVORK5CYII=
-
-------=_Part_0_1330682067197--
-

http://git-wip-us.apache.org/repos/asf/james-project/blob/896bc961/mailbox/store/src/test/resources/eml/oneAttachmentAndSomeTextInlined.eml
----------------------------------------------------------------------
diff --git a/mailbox/store/src/test/resources/eml/oneAttachmentAndSomeTextInlined.eml b/mailbox/store/src/test/resources/eml/oneAttachmentAndSomeTextInlined.eml
new file mode 100644
index 0000000..578af96
--- /dev/null
+++ b/mailbox/store/src/test/resources/eml/oneAttachmentAndSomeTextInlined.eml
@@ -0,0 +1,39 @@
+Mail content:
+To: "=?utf-8?B?UmFuaSBBc3NhZg==?=" <ra...@jri.obm.lng.org>
+Subject: =?utf-8?B?VHIuIDogUGhvdG9zICE=?=
+Importance: Normal
+MIME-Version: 1.0
+Content-Type: multipart/mixed;
+	boundary="----=_Part_0_1330682067197"
+
+------=_Part_0_1330682067197
+Content-Type: multipart/alternative;
+	boundary="----=_Part_2_1330682067197"
+
+------=_Part_2_1330682067197
+Content-Type: text/plain;
+	charset= utf-8
+Content-Transfer-Encoding: 8bit
+Content-Disposition: inline
+
+Content of part 1-1
+------=_Part_2_1330682067197
+Content-Type: text/html;
+	charset= utf-8
+Content-Transfer-Encoding: 8bit
+Content-Disposition: inline
+
+<b>Content of part 1-2</b>
+------=_Part_2_1330682067197--
+
+------=_Part_0_1330682067197
+Content-Type: application/octet-stream;
+	name="exploits_of_a_mom.png"
+Content-Transfer-Encoding: base64
+Content-Disposition: attachment;
+	filename="gimp.png"
+
+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
+
+------=_Part_0_1330682067197--
+

http://git-wip-us.apache.org/repos/asf/james-project/blob/896bc961/mailbox/store/src/test/resources/eml/oneInlinedAttachment.eml
----------------------------------------------------------------------
diff --git a/mailbox/store/src/test/resources/eml/oneInlinedAttachment.eml b/mailbox/store/src/test/resources/eml/oneInlinedAttachment.eml
new file mode 100644
index 0000000..50c0b80
--- /dev/null
+++ b/mailbox/store/src/test/resources/eml/oneInlinedAttachment.eml
@@ -0,0 +1,201 @@
+Return-Path: <ad...@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;
+	 Tue, 05 Jul 2016 11:47:47 +0200
+X-Sieve: CMU Sieve 2.2
+Received: from [10.69.0.107] (mne69-10-88-173-78-196.fbx.proxad.net [88.173.78.196])
+	(using TLSv1 with cipher DHE-RSA-AES128-SHA (128/128 bits))
+	(No client certificate requested)
+	by alderaan.linagora.com (Postfix) with ESMTPSA id F1F3E74E
+	for <ad...@linagora.com>; Tue,  5 Jul 2016 11:47:46 +0200 (CEST)
+To: Antoine DUPRAT <ad...@linagora.com>
+From: Antoine DUPRAT <ad...@linagora.com>
+Subject: Inline attachment
+Message-ID: <26...@linagora.com>
+Date: Tue, 5 Jul 2016 11:47:46 +0200
+User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101
+ Thunderbird/45.1.1
+MIME-Version: 1.0
+Content-Type: multipart/alternative;
+ boundary="------------FC06E08B3CDF05E9A3E28077"
+
+This is a multi-part message in MIME format.
+--------------FC06E08B3CDF05E9A3E28077
+Content-Type: text/plain; charset=utf-8; format=flowed
+Content-Transfer-Encoding: 7bit
+
+This is an inline attachment:
+
+
+
+
+Cheers!
+
+--------------FC06E08B3CDF05E9A3E28077
+Content-Type: multipart/related;
+ boundary="------------47107B0D40019CDFED2C4263"
+
+
+--------------47107B0D40019CDFED2C4263
+Content-Type: text/html; charset=utf-8
+Content-Transfer-Encoding: 7bit
+
+<html>
+  <head>
+
+    <meta http-equiv="content-type" content="text/html; charset=utf-8">
+  </head>
+  <body bgcolor="#FFFFFF" text="#000000">
+    This is an inline attachment:<br>
+    <br>
+    <img alt="" src="cid:part1.37A15C92.A7C3488D@linagora.com"
+      height="73" width="73"><br>
+    <br>
+    <br>
+    Cheers!<br>
+  </body>
+</html>
+
+--------------47107B0D40019CDFED2C4263
+Content-Type: image/png;
+ name="james-logo-square.png"
+Content-Transfer-Encoding: base64
+Content-ID: <pa...@linagora.com>
+Content-Disposition: inline;
+ filename="james-logo-square.png"
+
+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
+--------------47107B0D40019CDFED2C4263--
+
+--------------FC06E08B3CDF05E9A3E28077--

http://git-wip-us.apache.org/repos/asf/james-project/blob/896bc961/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 8907f98..252afd0 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
@@ -39,6 +39,7 @@ import java.util.stream.Collectors;
 import javax.inject.Inject;
 import javax.mail.Flags;
 
+import org.apache.james.jmap.methods.integration.cucumber.util.TableRow;
 import org.apache.james.mailbox.model.MailboxConstants;
 import org.apache.james.mailbox.model.MailboxPath;
 import org.javatuples.Pair;
@@ -317,8 +318,8 @@ public class GetMessagesMethodStepdefs {
     }
 
     private void assertAttachment(String attachment, DataTable attachmentProperties) {
-        attachmentProperties.asMap(String.class, String.class).entrySet()
+        attachmentProperties.asList(TableRow.class)
             .stream()
-            .map(entry -> response.body(attachment + "." + entry.getKey(), equalTo(entry.getValue())));
+            .forEach(row -> response.body(attachment + "." + row.getKey(), equalTo(row.getValue())));
     }
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/896bc961/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/cucumber/util/BooleanFromString.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/cucumber/util/BooleanFromString.java b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/cucumber/util/BooleanFromString.java
new file mode 100644
index 0000000..2a98f56
--- /dev/null
+++ b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/cucumber/util/BooleanFromString.java
@@ -0,0 +1,34 @@
+/****************************************************************
+ * 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.methods.integration.cucumber.util;
+
+import java.util.Optional;
+
+public class BooleanFromString implements ObjectFromString<Boolean> {
+
+    @Override
+    public Optional<Boolean> extract(String source) {
+        if (source.equals("true") || source.equals("false")) {
+            return Optional.of(Boolean.valueOf(source));
+        }
+        return Optional.empty();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/896bc961/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/cucumber/util/IntegerFromString.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/cucumber/util/IntegerFromString.java b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/cucumber/util/IntegerFromString.java
new file mode 100644
index 0000000..94a2dd8
--- /dev/null
+++ b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/cucumber/util/IntegerFromString.java
@@ -0,0 +1,35 @@
+/****************************************************************
+ * 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.methods.integration.cucumber.util;
+
+import java.util.Optional;
+
+public class IntegerFromString implements ObjectFromString<Integer> {
+
+    @Override
+    public Optional<Integer> extract(String source) {
+        try {
+            return Optional.of(Integer.valueOf(source));
+        } catch (Exception e) {
+            return Optional.empty();
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/896bc961/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/cucumber/util/ObjectFromString.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/cucumber/util/ObjectFromString.java b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/cucumber/util/ObjectFromString.java
new file mode 100644
index 0000000..776a0a8
--- /dev/null
+++ b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/cucumber/util/ObjectFromString.java
@@ -0,0 +1,27 @@
+/****************************************************************
+ * 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.methods.integration.cucumber.util;
+
+import java.util.Optional;
+
+public interface ObjectFromString<T> {
+
+    Optional<T> extract(String source);
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/896bc961/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/cucumber/util/ObjectFromStringExtractor.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/cucumber/util/ObjectFromStringExtractor.java b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/cucumber/util/ObjectFromStringExtractor.java
new file mode 100644
index 0000000..1e50b14
--- /dev/null
+++ b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/cucumber/util/ObjectFromStringExtractor.java
@@ -0,0 +1,42 @@
+/****************************************************************
+ * 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.methods.integration.cucumber.util;
+
+import java.util.List;
+import java.util.Optional;
+
+import com.google.common.collect.ImmutableList;
+
+public class ObjectFromStringExtractor {
+
+    private static final List<ObjectFromString<?>> EXTRACTORS = ImmutableList.of(
+            new StringFromString(),
+            new IntegerFromString(),
+            new BooleanFromString());
+
+    public Object extract(String value) {
+        return EXTRACTORS.stream()
+            .map(extractor -> extractor.extract(value))
+            .filter(Optional::isPresent)
+            .map(Optional::get)
+            .findFirst()
+            .orElse(null);
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/896bc961/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/cucumber/util/StringFromString.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/cucumber/util/StringFromString.java b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/cucumber/util/StringFromString.java
new file mode 100644
index 0000000..4cc33fd
--- /dev/null
+++ b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/cucumber/util/StringFromString.java
@@ -0,0 +1,35 @@
+/****************************************************************
+ * 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.methods.integration.cucumber.util;
+
+import java.util.Optional;
+
+public class StringFromString implements ObjectFromString<String> {
+
+    @Override
+    public Optional<String> extract(String source) {
+        if (source.startsWith("\"") && source.endsWith("\"")) {
+            return Optional.of(source.substring(1, source.length() - 1));
+        }
+        return Optional.empty();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/896bc961/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/cucumber/util/TableRow.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/cucumber/util/TableRow.java b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/cucumber/util/TableRow.java
new file mode 100644
index 0000000..b806e8c
--- /dev/null
+++ b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/cucumber/util/TableRow.java
@@ -0,0 +1,50 @@
+/****************************************************************
+ * 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.methods.integration.cucumber.util;
+
+import com.google.common.base.MoreObjects;
+
+public class TableRow {
+
+    private String key;
+    private String value;
+
+    public TableRow(String key, String value) {
+        this.key = key;
+        this.value = value;
+    }
+
+    public String getKey() {
+        return key;
+    }
+
+    public Object getValue() {
+        return new ObjectFromStringExtractor().extract(value);
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects
+                .toStringHelper(this)
+                .add("key", key)
+                .add("value", value)
+                .toString();
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/james-project/blob/896bc961/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 0ec32fd..9b77a3f 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
@@ -142,13 +142,19 @@ Feature: GetMessages method
     And the hasAttachment of the message is "true"
     And the list of attachments of the message contains 2 attachments
     And the first attachment is:
-      |blobId |"223a76c0e8c1b1762487d8e0598bd88497d73ef2" |
-      |type   |"image/jpeg"                               |
-      |size   |846                                        |
+      |key      | value                                     |
+      |blobId   |"223a76c0e8c1b1762487d8e0598bd88497d73ef2" |
+      |type     |"image/jpeg"                               |
+      |size     |846                                        |
+      |cid      |null                                       |
+      |isInline |false                                      |
     And the second attachment is:
-      |blobId |"58aa22c2ec5770fb9e574ba19008dbfc647eba43" |
-      |type   |"image/jpeg"                               |
-      |size   |597                                        |
+      |key      | value                                     |
+      |blobId   |"58aa22c2ec5770fb9e574ba19008dbfc647eba43" |
+      |type     |"image/jpeg"                               |
+      |size     |597                                        |
+      |cid      |"<pa...@linagora.com>"   |
+      |isInline |true                                       |
 
   Scenario: Retrieving message should return attachments and html body when some attachments and html message
     Given the user has a message in "inbox" mailbox with two attachments

http://git-wip-us.apache.org/repos/asf/james-project/blob/896bc961/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/resources/eml/twoAttachments.eml
----------------------------------------------------------------------
diff --git a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/resources/eml/twoAttachments.eml b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/resources/eml/twoAttachments.eml
index 85f0e3b..f6c18fc 100644
--- a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/resources/eml/twoAttachments.eml
+++ b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/resources/eml/twoAttachments.eml
@@ -54,7 +54,8 @@ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 Content-Type: image/jpeg;
  name="4037_015.jpg"
 Content-Transfer-Encoding: base64
-Content-Disposition: attachment;
+Content-ID: <pa...@linagora.com>
+Content-Disposition: inline;
  filename="4037_015.jpg"
 
 iVBORw0KGgoAAAANSUhEUgAABYUAAAL4CAIAAACrzA8fAAAACXBIWXMAAAsTAAALEwEAmpwY

http://git-wip-us.apache.org/repos/asf/james-project/blob/896bc961/server/protocols/jmap/doc/specs/spec/message.mdwn
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/doc/specs/spec/message.mdwn b/server/protocols/jmap/doc/specs/spec/message.mdwn
index 55d9523..ab144cb 100644
--- a/server/protocols/jmap/doc/specs/spec/message.mdwn
+++ b/server/protocols/jmap/doc/specs/spec/message.mdwn
@@ -112,9 +112,6 @@ An **Attachment** object has the following properties:
   The id used within the message body to reference this attachment. This is only unique when paired with the message id, and has no meaning without reference to that.
 - **isInline**: `Boolean`
   True if the attachment is referenced by a `cid:` link from within the HTML body of the message.
-  <aside class="warning">
-  Inlined attachments are not parsed yet.
-  </aside>
 - **width**: `Number|null`
   The width (in px) of the image, if the attachment is an image.
 - **height**: `Number|null`

http://git-wip-us.apache.org/repos/asf/james-project/blob/896bc961/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/GetMessagesMethod.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/GetMessagesMethod.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/GetMessagesMethod.java
index 39319c5..5d6cb7e 100644
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/GetMessagesMethod.java
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/GetMessagesMethod.java
@@ -42,15 +42,12 @@ import org.apache.james.mailbox.MailboxSession;
 import org.apache.james.mailbox.exception.MailboxException;
 import org.apache.james.mailbox.model.MailboxPath;
 import org.apache.james.mailbox.model.MessageRange;
-import org.apache.james.mailbox.store.mail.AttachmentMapper;
-import org.apache.james.mailbox.store.mail.AttachmentMapperFactory;
 import org.apache.james.mailbox.store.mail.MailboxMapperFactory;
 import org.apache.james.mailbox.store.mail.MessageMapper;
 import org.apache.james.mailbox.store.mail.MessageMapperFactory;
-import org.apache.james.mailbox.store.mail.model.Attachment;
-import org.apache.james.mailbox.store.mail.model.AttachmentId;
 import org.apache.james.mailbox.store.mail.model.Mailbox;
 import org.apache.james.mailbox.store.mail.model.MailboxMessage;
+import org.apache.james.mailbox.store.mail.model.MessageAttachment;
 import org.apache.james.util.streams.ImmutableCollectors;
 import org.javatuples.Pair;
 
@@ -68,18 +65,15 @@ public class GetMessagesMethod implements Method {
     private static final Method.Response.Name RESPONSE_NAME = Method.Response.name("messages");
     private final MessageMapperFactory messageMapperFactory;
     private final MailboxMapperFactory mailboxMapperFactory;
-    private final AttachmentMapperFactory attachmentMapperFactory;
     private final MessageFactory messageFactory;
 
     @Inject
     @VisibleForTesting GetMessagesMethod(
             MessageMapperFactory messageMapperFactory,
             MailboxMapperFactory mailboxMapperFactory,
-            AttachmentMapperFactory attachmentMapperFactory,
             MessageFactory messageFactory) {
         this.messageMapperFactory = messageMapperFactory;
         this.mailboxMapperFactory = mailboxMapperFactory;
-        this.attachmentMapperFactory = attachmentMapperFactory;
         this.messageFactory = messageFactory;
     }
     
@@ -165,13 +159,10 @@ public class GetMessagesMethod implements Method {
         Iterable<MailboxMessage> iterable = () -> value.getValue0();
         Stream<MailboxMessage> targetStream = StreamSupport.stream(iterable.spliterator(), false);
 
-        Function<List<AttachmentId>, List<Attachment>> retrieveAttachments = retrieveAttachments(attachmentMapperFactory.getAttachmentMapper(mailboxSession));
-
         MailboxPath mailboxPath = value.getValue1();
         return targetStream
-                .map(message -> CompletedMailboxMessage.builder().mailboxMessage(message).attachmentIds(message.getAttachmentsIds()))
+                .map(message -> CompletedMailboxMessage.builder().mailboxMessage(message).attachments(message.getAttachments()))
                 .map(builder -> builder.mailboxPath(mailboxPath))
-                .map(builder -> builder.retrieveAttachments(retrieveAttachments))
                 .map(builder -> builder.build()); 
     }
 
@@ -184,9 +175,8 @@ public class GetMessagesMethod implements Method {
         public static class Builder {
 
             private MailboxMessage mailboxMessage;
-            private List<AttachmentId> attachmentIds;
+            private List<MessageAttachment> attachments;
             private MailboxPath mailboxPath;
-            private Function<List<AttachmentId>, List<Attachment>> retrieveAttachments;
 
             private Builder() {
             }
@@ -197,9 +187,9 @@ public class GetMessagesMethod implements Method {
                 return this;
             }
 
-            public Builder attachmentIds(List<AttachmentId> attachmentIds) {
-                Preconditions.checkArgument(attachmentIds != null);
-                this.attachmentIds = attachmentIds;
+            public Builder attachments(List<MessageAttachment> attachments) {
+                Preconditions.checkArgument(attachments != null);
+                this.attachments = attachments;
                 return this;
             }
 
@@ -209,37 +199,22 @@ public class GetMessagesMethod implements Method {
                 return this;
             }
 
-            public Builder retrieveAttachments(Function<List<AttachmentId>, List<Attachment>> retrieveAttachments) {
-                Preconditions.checkArgument(retrieveAttachments != null);
-                this.retrieveAttachments = retrieveAttachments;
-                return this;
-            }
-
             public CompletedMailboxMessage build() {
                 Preconditions.checkState(mailboxMessage != null);
-                Preconditions.checkState(attachmentIds != null);
+                Preconditions.checkState(attachments != null);
                 Preconditions.checkState(mailboxPath != null);
-                Preconditions.checkState(retrieveAttachments != null);
-                return new CompletedMailboxMessage(mailboxMessage, retrieveAttachments.apply(attachmentIds), mailboxPath);
+                return new CompletedMailboxMessage(mailboxMessage, attachments, mailboxPath);
             }
         }
 
         private final MailboxMessage mailboxMessage;
-        private final List<Attachment> attachments;
+        private final List<MessageAttachment> attachments;
         private final MailboxPath mailboxPath;
 
-        public CompletedMailboxMessage(MailboxMessage mailboxMessage, List<Attachment> attachments, MailboxPath mailboxPath) {
+        public CompletedMailboxMessage(MailboxMessage mailboxMessage, List<MessageAttachment> attachments, MailboxPath mailboxPath) {
             this.mailboxMessage = mailboxMessage;
             this.attachments = attachments;
             this.mailboxPath = mailboxPath;
         }
     }
-
-    private Function<List<AttachmentId>, List<Attachment>> retrieveAttachments(AttachmentMapper attachmentMapper) {
-        return (attachmentsIds) -> {
-            return attachmentsIds.stream()
-                    .map(Throwing.function(id -> attachmentMapper.getAttachment(id)))
-                    .collect(ImmutableCollectors.toImmutableList());
-        };
-    }
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/896bc961/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/Attachment.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/Attachment.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/Attachment.java
index 8aa0927..2cbed7f 100644
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/Attachment.java
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/Attachment.java
@@ -135,7 +135,7 @@ public class Attachment {
         return cid;
     }
 
-    public boolean isInline() {
+    public boolean isIsInline() {
         return isInline;
     }
 

http://git-wip-us.apache.org/repos/asf/james-project/blob/896bc961/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/MessageFactory.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/MessageFactory.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/MessageFactory.java
index b31f403..126dcb9 100644
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/MessageFactory.java
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/MessageFactory.java
@@ -33,6 +33,7 @@ import org.apache.james.jmap.model.message.EMailer;
 import org.apache.james.jmap.model.message.IndexableMessage;
 import org.apache.james.mailbox.store.extractor.DefaultTextExtractor;
 import org.apache.james.mailbox.store.mail.model.MailboxMessage;
+import org.apache.james.mailbox.store.mail.model.MessageAttachment;
 import org.apache.james.util.streams.ImmutableCollectors;
 
 import com.google.common.base.Strings;
@@ -54,7 +55,7 @@ public class MessageFactory {
     }
 
     public Message fromMailboxMessage(MailboxMessage mailboxMessage,
-            List<org.apache.james.mailbox.store.mail.model.Attachment> attachments,
+            List<MessageAttachment> attachments,
             Function<Long, MessageId> uidToMessageId) {
 
         IndexableMessage im = IndexableMessage.from(mailboxMessage, new DefaultTextExtractor(), UTC_ZONE_ID);
@@ -150,18 +151,20 @@ public class MessageFactory {
         return im.getBodyHtml().map(Strings::emptyToNull).orElse(null);
     }
 
-    private List<Attachment> getAttachments(List<org.apache.james.mailbox.store.mail.model.Attachment> attachments) {
+    private List<Attachment> getAttachments(List<MessageAttachment> attachments) {
         return attachments.stream()
                 .map(this::fromMailboxAttachment)
                 .collect(ImmutableCollectors.toImmutableList());
     }
 
-    private Attachment fromMailboxAttachment(org.apache.james.mailbox.store.mail.model.Attachment attachment) {
+    private Attachment fromMailboxAttachment(MessageAttachment attachment) {
         return Attachment.builder()
                     .blobId(attachment.getAttachmentId().getId())
-                    .type(attachment.getType())
-                    .name(attachment.getName().orNull())
-                    .size(attachment.getSize())
+                    .type(attachment.getAttachment().getType())
+                    .name(attachment.getAttachment().getName().orNull())
+                    .size(attachment.getAttachment().getSize())
+                    .cid(attachment.getCid().orNull())
+                    .isInline(attachment.isInline())
                     .build();
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/james-project/blob/896bc961/server/protocols/jmap/src/test/java/org/apache/james/jmap/methods/GetMessagesMethodTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/methods/GetMessagesMethodTest.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/methods/GetMessagesMethodTest.java
index 9bfafe7..6bca35f 100644
--- a/server/protocols/jmap/src/test/java/org/apache/james/jmap/methods/GetMessagesMethodTest.java
+++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/methods/GetMessagesMethodTest.java
@@ -133,28 +133,28 @@ public class GetMessagesMethodTest {
     
     @Test
     public void processShouldThrowWhenNullRequest() {
-        GetMessagesMethod testee = new GetMessagesMethod(mailboxSessionMapperFactory, mailboxSessionMapperFactory, mailboxSessionMapperFactory, messageFactory);
+        GetMessagesMethod testee = new GetMessagesMethod(mailboxSessionMapperFactory, mailboxSessionMapperFactory, messageFactory);
         GetMessagesRequest request = null;
         assertThatThrownBy(() -> testee.process(request, mock(ClientId.class), mock(MailboxSession.class))).isInstanceOf(NullPointerException.class);
     }
 
     @Test
     public void processShouldThrowWhenNullSession() {
-        GetMessagesMethod testee = new GetMessagesMethod(mailboxSessionMapperFactory, mailboxSessionMapperFactory, mailboxSessionMapperFactory, messageFactory);
+        GetMessagesMethod testee = new GetMessagesMethod(mailboxSessionMapperFactory, mailboxSessionMapperFactory, messageFactory);
         MailboxSession mailboxSession = null;
         assertThatThrownBy(() -> testee.process(mock(GetMessagesRequest.class), mock(ClientId.class), mailboxSession)).isInstanceOf(NullPointerException.class);
     }
 
     @Test
     public void processShouldThrowWhenNullClientId() {
-        GetMessagesMethod testee = new GetMessagesMethod(mailboxSessionMapperFactory, mailboxSessionMapperFactory, mailboxSessionMapperFactory, messageFactory);
+        GetMessagesMethod testee = new GetMessagesMethod(mailboxSessionMapperFactory, mailboxSessionMapperFactory, messageFactory);
         ClientId clientId = null;
         assertThatThrownBy(() -> testee.process(mock(GetMessagesRequest.class), clientId, mock(MailboxSession.class))).isInstanceOf(NullPointerException.class);
     }
 
     @Test
     public void processShouldThrowWhenRequestHasAccountId() {
-        GetMessagesMethod testee = new GetMessagesMethod(mailboxSessionMapperFactory, mailboxSessionMapperFactory, mailboxSessionMapperFactory, messageFactory);
+        GetMessagesMethod testee = new GetMessagesMethod(mailboxSessionMapperFactory, mailboxSessionMapperFactory, messageFactory);
         assertThatThrownBy(() -> testee.process(
                 GetMessagesRequest.builder().accountId("abc").build(), mock(ClientId.class), mock(MailboxSession.class))).isInstanceOf(NotImplementedException.class);
     }
@@ -176,7 +176,7 @@ public class GetMessagesMethodTest {
                           new MessageId(ROBERT, inboxPath, message3Uid)))
                 .build();
 
-        GetMessagesMethod testee = new GetMessagesMethod(mailboxSessionMapperFactory, mailboxSessionMapperFactory, mailboxSessionMapperFactory, messageFactory);
+        GetMessagesMethod testee = new GetMessagesMethod(mailboxSessionMapperFactory, mailboxSessionMapperFactory, messageFactory);
         List<JmapResponse> result = testee.process(request, clientId, session).collect(Collectors.toList());
         
         assertThat(result).hasSize(1)
@@ -205,7 +205,7 @@ public class GetMessagesMethodTest {
                 .ids(ImmutableList.of(new MessageId(ROBERT, inboxPath, messageUid)))
                 .build();
 
-        GetMessagesMethod testee = new GetMessagesMethod(mailboxSessionMapperFactory, mailboxSessionMapperFactory, mailboxSessionMapperFactory, messageFactory);
+        GetMessagesMethod testee = new GetMessagesMethod(mailboxSessionMapperFactory, mailboxSessionMapperFactory, messageFactory);
         List<JmapResponse> result = testee.process(request, clientId, session).collect(Collectors.toList());
         
         assertThat(result).hasSize(1)
@@ -229,7 +229,7 @@ public class GetMessagesMethodTest {
                 .properties(ImmutableList.of())
                 .build();
 
-        GetMessagesMethod testee = new GetMessagesMethod(mailboxSessionMapperFactory, mailboxSessionMapperFactory, mailboxSessionMapperFactory, messageFactory);
+        GetMessagesMethod testee = new GetMessagesMethod(mailboxSessionMapperFactory, mailboxSessionMapperFactory, messageFactory);
         List<JmapResponse> result = testee.process(request, clientId, session).collect(Collectors.toList());
 
         assertThat(result).hasSize(1)
@@ -250,7 +250,7 @@ public class GetMessagesMethodTest {
                 .ids(ImmutableList.of(new MessageId(ROBERT, inboxPath, message1Uid)))
                 .build();
 
-        GetMessagesMethod testee = new GetMessagesMethod(mailboxSessionMapperFactory, mailboxSessionMapperFactory, mailboxSessionMapperFactory, messageFactory);
+        GetMessagesMethod testee = new GetMessagesMethod(mailboxSessionMapperFactory, mailboxSessionMapperFactory, messageFactory);
         Stream<JmapResponse> result = testee.process(request, clientId, session);
 
         assertThat(result).hasSize(1)
@@ -274,7 +274,7 @@ public class GetMessagesMethodTest {
 
         Set<MessageProperty> expected = Sets.newHashSet(MessageProperty.id, MessageProperty.subject);
 
-        GetMessagesMethod testee = new GetMessagesMethod(mailboxSessionMapperFactory, mailboxSessionMapperFactory, mailboxSessionMapperFactory, messageFactory);
+        GetMessagesMethod testee = new GetMessagesMethod(mailboxSessionMapperFactory, mailboxSessionMapperFactory, messageFactory);
         List<JmapResponse> result = testee.process(request, clientId, session).collect(Collectors.toList());
 
         assertThat(result).hasSize(1)
@@ -298,7 +298,7 @@ public class GetMessagesMethodTest {
 
         Set<MessageProperty> expected = Sets.newHashSet(MessageProperty.id, MessageProperty.textBody);
 
-        GetMessagesMethod testee = new GetMessagesMethod(mailboxSessionMapperFactory, mailboxSessionMapperFactory, mailboxSessionMapperFactory, messageFactory);
+        GetMessagesMethod testee = new GetMessagesMethod(mailboxSessionMapperFactory, mailboxSessionMapperFactory, messageFactory);
         List<JmapResponse> result = testee.process(request, clientId, session).collect(Collectors.toList());
 
         assertThat(result).hasSize(1)
@@ -325,7 +325,7 @@ public class GetMessagesMethodTest {
 
         Set<MessageProperty> expected = Sets.newHashSet(MessageProperty.id, MessageProperty.headers);
 
-        GetMessagesMethod testee = new GetMessagesMethod(mailboxSessionMapperFactory, mailboxSessionMapperFactory, mailboxSessionMapperFactory, messageFactory);
+        GetMessagesMethod testee = new GetMessagesMethod(mailboxSessionMapperFactory, mailboxSessionMapperFactory, messageFactory);
         List<JmapResponse> result = testee.process(request, clientId, session).collect(Collectors.toList());
 
         assertThat(result)
@@ -351,7 +351,7 @@ public class GetMessagesMethodTest {
                 .properties(ImmutableList.of("headers.from", "headers.heADER2"))
                 .build();
 
-        GetMessagesMethod testee = new GetMessagesMethod(mailboxSessionMapperFactory, mailboxSessionMapperFactory, mailboxSessionMapperFactory, messageFactory);
+        GetMessagesMethod testee = new GetMessagesMethod(mailboxSessionMapperFactory, mailboxSessionMapperFactory, messageFactory);
         List<JmapResponse> result = testee.process(request, clientId, session).collect(Collectors.toList());
 
         assertThat(result)


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


[4/5] james-project git commit: JAMES-1791 Fix memory mapper tests

Posted by ad...@apache.org.
JAMES-1791 Fix memory mapper tests


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

Branch: refs/heads/master
Commit: 2d1fe094f8ca4732914b2f5fe6ebe092884030cf
Parents: 896bc96
Author: Antoine Duprat <ad...@linagora.com>
Authored: Thu Jul 7 09:41:43 2016 +0200
Committer: Antoine Duprat <ad...@linagora.com>
Committed: Fri Jul 8 11:28:31 2016 +0200

----------------------------------------------------------------------
 .../inmemory/mail/InMemoryAnnotationMapper.java |  2 +
 .../inmemory/mail/MemoryMappersTest.java        | 59 ++++++++++++++++++++
 .../inmemory/mail/MemoryMappersTests.java       | 59 --------------------
 3 files changed, 61 insertions(+), 59 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/2d1fe094/mailbox/memory/src/main/java/org/apache/james/mailbox/inmemory/mail/InMemoryAnnotationMapper.java
----------------------------------------------------------------------
diff --git a/mailbox/memory/src/main/java/org/apache/james/mailbox/inmemory/mail/InMemoryAnnotationMapper.java b/mailbox/memory/src/main/java/org/apache/james/mailbox/inmemory/mail/InMemoryAnnotationMapper.java
index 66def77..f07166e 100644
--- a/mailbox/memory/src/main/java/org/apache/james/mailbox/inmemory/mail/InMemoryAnnotationMapper.java
+++ b/mailbox/memory/src/main/java/org/apache/james/mailbox/inmemory/mail/InMemoryAnnotationMapper.java
@@ -32,6 +32,7 @@ import org.apache.james.mailbox.model.MailboxAnnotation;
 import org.apache.james.mailbox.store.mail.AnnotationMapper;
 
 import com.google.common.base.Function;
+import com.google.common.base.Preconditions;
 import com.google.common.base.Predicate;
 import com.google.common.collect.HashBasedTable;
 import com.google.common.collect.ImmutableList;
@@ -91,6 +92,7 @@ public class InMemoryAnnotationMapper implements AnnotationMapper {
 
     @Override
     public void insertAnnotation(MailboxAnnotation mailboxAnnotation) {
+        Preconditions.checkArgument(!mailboxAnnotation.isNil());
         lock.writeLock().lock();
         try {
             mailboxesAnnotations.put(mailboxId, mailboxAnnotation.getKey(), mailboxAnnotation.getValue().get());

http://git-wip-us.apache.org/repos/asf/james-project/blob/2d1fe094/mailbox/memory/src/test/java/org/apache/james/mailbox/inmemory/mail/MemoryMappersTest.java
----------------------------------------------------------------------
diff --git a/mailbox/memory/src/test/java/org/apache/james/mailbox/inmemory/mail/MemoryMappersTest.java b/mailbox/memory/src/test/java/org/apache/james/mailbox/inmemory/mail/MemoryMappersTest.java
new file mode 100644
index 0000000..86c8617
--- /dev/null
+++ b/mailbox/memory/src/test/java/org/apache/james/mailbox/inmemory/mail/MemoryMappersTest.java
@@ -0,0 +1,59 @@
+/****************************************************************
+ * 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.mailbox.inmemory.mail;
+
+import org.apache.james.mailbox.exception.MailboxException;
+import org.junit.runner.RunWith;
+import org.xenei.junit.contract.Contract;
+import org.xenei.junit.contract.ContractImpl;
+import org.xenei.junit.contract.ContractSuite;
+import org.xenei.junit.contract.IProducer;
+
+import com.google.common.base.Throwables;
+
+@RunWith(ContractSuite.class)
+@ContractImpl(InMemoryMapperProvider.class)
+public class MemoryMappersTest {
+
+    private IProducer<InMemoryMapperProvider> producer = new IProducer<InMemoryMapperProvider>() {
+
+        private final InMemoryMapperProvider mapperProvider = new InMemoryMapperProvider();
+
+        @Override
+        public InMemoryMapperProvider newInstance() {
+            return mapperProvider;
+        }
+
+        @Override
+        public void cleanUp() {
+            try {
+                mapperProvider.clearMapper();
+            } catch (MailboxException e) {
+                throw Throwables.propagate(e);
+            }
+        }
+    };
+
+    @Contract.Inject
+    public IProducer<InMemoryMapperProvider> getProducer() {
+        return producer;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/2d1fe094/mailbox/memory/src/test/java/org/apache/james/mailbox/inmemory/mail/MemoryMappersTests.java
----------------------------------------------------------------------
diff --git a/mailbox/memory/src/test/java/org/apache/james/mailbox/inmemory/mail/MemoryMappersTests.java b/mailbox/memory/src/test/java/org/apache/james/mailbox/inmemory/mail/MemoryMappersTests.java
deleted file mode 100644
index 099021b..0000000
--- a/mailbox/memory/src/test/java/org/apache/james/mailbox/inmemory/mail/MemoryMappersTests.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/****************************************************************
- * 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.mailbox.inmemory.mail;
-
-import org.apache.james.mailbox.exception.MailboxException;
-import org.junit.runner.RunWith;
-import org.xenei.junit.contract.Contract;
-import org.xenei.junit.contract.ContractImpl;
-import org.xenei.junit.contract.ContractSuite;
-import org.xenei.junit.contract.IProducer;
-
-import com.google.common.base.Throwables;
-
-@RunWith(ContractSuite.class)
-@ContractImpl(InMemoryMapperProvider.class)
-public class MemoryMappersTests {
-
-    private IProducer<InMemoryMapperProvider> producer = new IProducer<InMemoryMapperProvider>() {
-
-        private final InMemoryMapperProvider mapperProvider = new InMemoryMapperProvider();
-
-        @Override
-        public InMemoryMapperProvider newInstance() {
-            return mapperProvider;
-        }
-
-        @Override
-        public void cleanUp() {
-            try {
-                mapperProvider.clearMapper();
-            } catch (MailboxException e) {
-                throw Throwables.propagate(e);
-            }
-        }
-    };
-
-    @Contract.Inject
-    public IProducer<InMemoryMapperProvider> getProducer() {
-        return producer;
-    }
-
-}


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


[5/5] james-project git commit: JAMES-1791 Move attachment name from Attachment to MessageAttachment

Posted by ad...@apache.org.
JAMES-1791 Move attachment name from Attachment to MessageAttachment


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

Branch: refs/heads/master
Commit: 1c294ddc02e008f57de3451ac72fb6e404847c46
Parents: 2d1fe09
Author: Antoine Duprat <ad...@linagora.com>
Authored: Thu Jul 7 11:12:41 2016 +0200
Committer: Antoine Duprat <ad...@linagora.com>
Committed: Fri Jul 8 12:02:06 2016 +0200

----------------------------------------------------------------------
 .../mail/CassandraAttachmentMapper.java         |  4 ---
 .../cassandra/mail/CassandraMessageMapper.java  | 10 +++++---
 .../modules/CassandraAttachmentModule.java      |  1 -
 .../modules/CassandraMessageModule.java         |  1 +
 .../table/CassandraAttachmentTable.java         |  3 +--
 .../cassandra/table/CassandraMessageTable.java  |  1 +
 .../mailbox/store/mail/model/Attachment.java    | 26 +++-----------------
 .../store/mail/model/MessageAttachment.java     | 21 +++++++++++++---
 .../store/mail/model/impl/MessageParser.java    |  2 +-
 .../AbstractMailboxManagerAttachmentTest.java   |  2 +-
 .../store/mail/model/AttachmentTest.java        | 21 ----------------
 .../store/mail/model/MessageAttachmentTest.java |  5 ++--
 .../mail/model/impl/MessageParserTest.java      |  4 +--
 .../apache/james/jmap/model/MessageFactory.java |  2 +-
 14 files changed, 39 insertions(+), 64 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/1c294ddc/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraAttachmentMapper.java
----------------------------------------------------------------------
diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraAttachmentMapper.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraAttachmentMapper.java
index 0cceb19..bd764c3 100644
--- a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraAttachmentMapper.java
+++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraAttachmentMapper.java
@@ -25,7 +25,6 @@ import static com.datastax.driver.core.querybuilder.QueryBuilder.insertInto;
 import static com.datastax.driver.core.querybuilder.QueryBuilder.select;
 import static org.apache.james.mailbox.cassandra.table.CassandraAttachmentTable.FIELDS;
 import static org.apache.james.mailbox.cassandra.table.CassandraAttachmentTable.ID;
-import static org.apache.james.mailbox.cassandra.table.CassandraAttachmentTable.NAME;
 import static org.apache.james.mailbox.cassandra.table.CassandraAttachmentTable.PAYLOAD;
 import static org.apache.james.mailbox.cassandra.table.CassandraAttachmentTable.SIZE;
 import static org.apache.james.mailbox.cassandra.table.CassandraAttachmentTable.TABLE_NAME;
@@ -51,7 +50,6 @@ import com.datastax.driver.core.Row;
 import com.datastax.driver.core.Session;
 import com.github.fge.lambdas.Throwing;
 import com.github.fge.lambdas.ThrownByLambdaException;
-import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableList.Builder;
@@ -90,7 +88,6 @@ public class CassandraAttachmentMapper implements AttachmentMapper {
                 .attachmentId(AttachmentId.from(row.getString(ID)))
                 .bytes(row.getBytes(PAYLOAD).array())
                 .type(row.getString(TYPE))
-                .name(Optional.fromNullable(row.getString(NAME)))
                 .build();
     }
 
@@ -129,7 +126,6 @@ public class CassandraAttachmentMapper implements AttachmentMapper {
                 .value(ID, attachment.getAttachmentId().getId())
                 .value(PAYLOAD, ByteBuffer.wrap(IOUtils.toByteArray(attachment.getStream())))
                 .value(TYPE, attachment.getType())
-                .value(NAME, attachment.getName().orNull())
                 .value(SIZE, attachment.getSize())
         );
     }

http://git-wip-us.apache.org/repos/asf/james-project/blob/1c294ddc/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMapper.java
----------------------------------------------------------------------
diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMapper.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMapper.java
index 0232cfb..1d1bc16 100644
--- a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMapper.java
+++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMapper.java
@@ -59,12 +59,12 @@ import java.io.InputStream;
 import java.nio.ByteBuffer;
 import java.util.Arrays;
 import java.util.Comparator;
+import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
 import java.util.Set;
-import java.util.function.Function;
 import java.util.stream.Collectors;
 
 import javax.mail.Flags;
@@ -353,6 +353,7 @@ public class CassandraMessageMapper implements MessageMapper {
                     .map(Throwing.function(x -> 
                         MessageAttachment.builder()
                             .attachment(attachmentsById.get(attachmentIdFrom(x)))
+                            .name(x.getString(Attachments.NAME))
                             .cid(x.getString(Attachments.CID))
                             .isInline(x.getBool(Attachments.IS_INLINE))
                             .build()))
@@ -363,8 +364,10 @@ public class CassandraMessageMapper implements MessageMapper {
     }
 
     private Map<AttachmentId,Attachment> attachmentsById(Row row, List<UDTValue> udtValues) {
-        return attachmentMapper.getAttachments(attachmentIds(udtValues)).stream()
-            .collect(ImmutableCollectors.toImmutableMap(Attachment::getAttachmentId, Function.identity()));
+        Map<AttachmentId, Attachment> map = new HashMap<>();
+        attachmentMapper.getAttachments(attachmentIds(udtValues)).stream()
+                .forEach(att -> map.put(att.getAttachmentId(), att));
+        return map;
     }
 
     private List<AttachmentId> attachmentIds(List<UDTValue> udtValues) {
@@ -420,6 +423,7 @@ public class CassandraMessageMapper implements MessageMapper {
         return typesProvider.getDefinedUserType(ATTACHMENTS)
             .newValue()
             .setString(Attachments.ID, messageAttachment.getAttachmentId().getId())
+            .setString(Attachments.NAME, messageAttachment.getName().orNull())
             .setString(Attachments.CID, messageAttachment.getCid().orNull())
             .setBool(Attachments.IS_INLINE, messageAttachment.isInline());
     }

http://git-wip-us.apache.org/repos/asf/james-project/blob/1c294ddc/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/modules/CassandraAttachmentModule.java
----------------------------------------------------------------------
diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/modules/CassandraAttachmentModule.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/modules/CassandraAttachmentModule.java
index b26fe71..0108161 100644
--- a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/modules/CassandraAttachmentModule.java
+++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/modules/CassandraAttachmentModule.java
@@ -48,7 +48,6 @@ public class CassandraAttachmentModule implements CassandraModule {
                     .addPartitionKey(CassandraAttachmentTable.ID, text())
                     .addColumn(CassandraAttachmentTable.PAYLOAD, blob())
                     .addColumn(CassandraAttachmentTable.TYPE, text())
-                    .addColumn(CassandraAttachmentTable.NAME, text())
                     .addColumn(CassandraAttachmentTable.SIZE, bigint())));
         index = Collections.emptyList();
         types = Collections.emptyList();

http://git-wip-us.apache.org/repos/asf/james-project/blob/1c294ddc/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/modules/CassandraMessageModule.java
----------------------------------------------------------------------
diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/modules/CassandraMessageModule.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/modules/CassandraMessageModule.java
index 03494e9..2e9c3b9 100644
--- a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/modules/CassandraMessageModule.java
+++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/modules/CassandraMessageModule.java
@@ -98,6 +98,7 @@ public class CassandraMessageModule implements CassandraModule {
                     SchemaBuilder.createType(CassandraMessageTable.ATTACHMENTS)
                         .ifNotExists()
                         .addColumn(CassandraMessageTable.Attachments.ID, text())
+                        .addColumn(CassandraMessageTable.Attachments.NAME, text())
                         .addColumn(CassandraMessageTable.Attachments.CID, text())
                         .addColumn(CassandraMessageTable.Attachments.IS_INLINE, cboolean())));
     }

http://git-wip-us.apache.org/repos/asf/james-project/blob/1c294ddc/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/table/CassandraAttachmentTable.java
----------------------------------------------------------------------
diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/table/CassandraAttachmentTable.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/table/CassandraAttachmentTable.java
index 17158d1..a7115eb 100644
--- a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/table/CassandraAttachmentTable.java
+++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/table/CassandraAttachmentTable.java
@@ -25,8 +25,7 @@ public interface CassandraAttachmentTable {
     String ID = "id";
     String PAYLOAD = "payload";
     String TYPE = "type";
-    String NAME = "name";
     String SIZE = "size";
-    String[] FIELDS = { ID, PAYLOAD, TYPE, NAME, SIZE };
+    String[] FIELDS = { ID, PAYLOAD, TYPE, SIZE };
 
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/1c294ddc/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/table/CassandraMessageTable.java
----------------------------------------------------------------------
diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/table/CassandraMessageTable.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/table/CassandraMessageTable.java
index cbd89bf..8566881 100644
--- a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/table/CassandraMessageTable.java
+++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/table/CassandraMessageTable.java
@@ -74,6 +74,7 @@ public interface CassandraMessageTable {
 
     interface Attachments {
         String ID = "id";
+        String NAME = "name";
         String CID = "cid";
         String IS_INLINE = "isInline";
     }

http://git-wip-us.apache.org/repos/asf/james-project/blob/1c294ddc/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/Attachment.java
----------------------------------------------------------------------
diff --git a/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/Attachment.java b/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/Attachment.java
index 6205647..441b690 100644
--- a/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/Attachment.java
+++ b/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/Attachment.java
@@ -26,7 +26,6 @@ import java.util.Arrays;
 
 import com.google.common.base.MoreObjects;
 import com.google.common.base.Objects;
-import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
 import com.google.common.base.Strings;
 
@@ -41,11 +40,6 @@ public class Attachment {
         private AttachmentId attachmentId;
         private byte[] bytes;
         private String type;
-        private Optional<String> name;
-
-        private Builder() {
-            name = Optional.absent();
-        }
 
         public Builder attachmentId(AttachmentId attachmentId) {
             Preconditions.checkArgument(attachmentId != null);
@@ -65,18 +59,12 @@ public class Attachment {
             return this;
         }
 
-        public Builder name(Optional<String> name) {
-            Preconditions.checkArgument(name != null);
-            this.name = name;
-            return this;
-        }
-
         public Attachment build() {
             Preconditions.checkState(bytes != null, "'bytes' is mandatory");
             AttachmentId builtAttachmentId = attachmentId();
             Preconditions.checkState(builtAttachmentId != null, "'attachmentId' is mandatory");
             Preconditions.checkState(type != null, "'type' is mandatory");
-            return new Attachment(bytes, builtAttachmentId, type, name, size());
+            return new Attachment(bytes, builtAttachmentId, type, size());
         }
 
         private AttachmentId attachmentId() {
@@ -94,14 +82,12 @@ public class Attachment {
     private final byte[] bytes;
     private final AttachmentId attachmentId;
     private final String type;
-    private final Optional<String> name;
     private final long size;
 
-    private Attachment(byte[] bytes, AttachmentId attachmentId, String type, Optional<String> name, long size) {
+    private Attachment(byte[] bytes, AttachmentId attachmentId, String type, long size) {
         this.bytes = bytes;
         this.attachmentId = attachmentId;
         this.type = type;
-        this.name = name;
         this.size = size;
     }
 
@@ -113,10 +99,6 @@ public class Attachment {
         return type;
     }
 
-    public Optional<String> getName() {
-        return name;
-    }
-
     public long getSize() {
         return size;
     }
@@ -132,7 +114,6 @@ public class Attachment {
             return Objects.equal(attachmentId, other.attachmentId)
                 && Arrays.equals(bytes, other.bytes)
                 && Objects.equal(type, other.type)
-                && Objects.equal(name, other.name)
                 && Objects.equal(size, other.size);
         }
         return false;
@@ -140,7 +121,7 @@ public class Attachment {
 
     @Override
     public int hashCode() {
-        return Objects.hashCode(attachmentId, bytes, type, name, size);
+        return Objects.hashCode(attachmentId, bytes, type, size);
     }
 
     @Override
@@ -150,7 +131,6 @@ public class Attachment {
                 .add("attachmentId", attachmentId)
                 .add("bytes", bytes)
                 .add("type", type)
-                .add("name", name)
                 .add("size", size)
                 .toString();
     }

http://git-wip-us.apache.org/repos/asf/james-project/blob/1c294ddc/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/MessageAttachment.java
----------------------------------------------------------------------
diff --git a/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/MessageAttachment.java b/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/MessageAttachment.java
index 6004e92..23cfc55 100644
--- a/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/MessageAttachment.java
+++ b/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/MessageAttachment.java
@@ -34,10 +34,12 @@ public class MessageAttachment {
     public static class Builder {
 
         private Attachment attachment;
+        private Optional<String> name;
         private Optional<String> cid;
         private Boolean isInline;
 
         private Builder() {
+            name = Optional.absent();
             cid = Optional.absent();
         }
 
@@ -47,6 +49,11 @@ public class MessageAttachment {
             return this;
         }
 
+        public Builder name(String name) {
+            this.name = Optional.fromNullable(name);
+            return this;
+        }
+
         public Builder cid(String cid) {
             this.cid = Optional.fromNullable(cid);
             return this;
@@ -65,16 +72,18 @@ public class MessageAttachment {
             if (isInline && !cid.isPresent()) {
                 throw new IllegalStateException("'cid' is mandatory for inline attachments");
             }
-            return new MessageAttachment(attachment, cid, isInline);
+            return new MessageAttachment(attachment, name, cid, isInline);
         }
     }
 
     private final Attachment attachment;
+    private final Optional<String> name;
     private final Optional<String> cid;
     private final boolean isInline;
 
-    @VisibleForTesting MessageAttachment(Attachment attachment, Optional<String> cid, boolean isInline) {
+    @VisibleForTesting MessageAttachment(Attachment attachment, Optional<String> name, Optional<String> cid, boolean isInline) {
         this.attachment = attachment;
+        this.name = name;
         this.cid = cid;
         this.isInline = isInline;
     }
@@ -87,6 +96,10 @@ public class MessageAttachment {
         return attachment.getAttachmentId();
     }
 
+    public Optional<String> getName() {
+        return name;
+    }
+
     public Optional<String> getCid() {
         return cid;
     }
@@ -100,6 +113,7 @@ public class MessageAttachment {
         if (obj instanceof MessageAttachment) {
             MessageAttachment other = (MessageAttachment) obj;
             return Objects.equal(attachment, other.attachment)
+                && Objects.equal(name, other.name)
                 && Objects.equal(cid, other.cid)
                 && Objects.equal(isInline, other.isInline);
         }
@@ -108,7 +122,7 @@ public class MessageAttachment {
 
     @Override
     public int hashCode() {
-        return Objects.hashCode(attachment, cid, isInline);
+        return Objects.hashCode(attachment, name, cid, isInline);
     }
 
     @Override
@@ -116,6 +130,7 @@ public class MessageAttachment {
         return MoreObjects
                 .toStringHelper(this)
                 .add("attachment", attachment)
+                .add("name", name)
                 .add("cid", cid)
                 .add("isInline", isInline)
                 .toString();

http://git-wip-us.apache.org/repos/asf/james-project/blob/1c294ddc/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/impl/MessageParser.java
----------------------------------------------------------------------
diff --git a/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/impl/MessageParser.java b/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/impl/MessageParser.java
index dd99f29..9096efa 100644
--- a/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/impl/MessageParser.java
+++ b/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/impl/MessageParser.java
@@ -95,8 +95,8 @@ public class MessageParser {
                 .attachment(Attachment.builder()
                     .bytes(getBytes(messageWriter, entity.getBody()))
                     .type(contentType.or(DEFAULT_CONTENT_TYPE))
-                    .name(name)
                     .build())
+                .name(name.orNull())
                 .cid(cid.orNull())
                 .isInline(isInline)
                 .build();

http://git-wip-us.apache.org/repos/asf/james-project/blob/1c294ddc/mailbox/store/src/test/java/org/apache/james/mailbox/store/AbstractMailboxManagerAttachmentTest.java
----------------------------------------------------------------------
diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/AbstractMailboxManagerAttachmentTest.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/AbstractMailboxManagerAttachmentTest.java
index 9527afa..025df51 100644
--- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/AbstractMailboxManagerAttachmentTest.java
+++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/AbstractMailboxManagerAttachmentTest.java
@@ -118,7 +118,7 @@ public abstract class AbstractMailboxManagerAttachmentTest {
 
         Iterator<MailboxMessage> messages = messageMapper.findInMailbox(inbox, MessageRange.all(), FetchType.Full, 1);
         List<MessageAttachment> attachments = messages.next().getAttachments();
-        assertThat(attachmentMapper.getAttachment(attachments.get(0).getAttachmentId()).getName()).isEqualTo(expectedName);
+        assertThat(attachments.get(0).getName()).isEqualTo(expectedName);
     }
 
     @Test

http://git-wip-us.apache.org/repos/asf/james-project/blob/1c294ddc/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/AttachmentTest.java
----------------------------------------------------------------------
diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/AttachmentTest.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/AttachmentTest.java
index f3505f4..a0018ba 100644
--- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/AttachmentTest.java
+++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/AttachmentTest.java
@@ -27,8 +27,6 @@ import java.io.InputStream;
 import org.apache.commons.io.IOUtils;
 import org.junit.Test;
 
-import com.google.common.base.Optional;
-
 public class AttachmentTest {
 
     @Test
@@ -82,12 +80,6 @@ public class AttachmentTest {
             .type("");
     }
 
-    @Test (expected = IllegalArgumentException.class)
-    public void builderShouldThrowWhenNameIsNull() {
-        Attachment.builder()
-            .name(null);
-    }
-
     @Test (expected = IllegalStateException.class)
     public void buildShouldThrowWhenAttachmentIdIsNotProvided() {
         Attachment.builder().build();
@@ -130,17 +122,4 @@ public class AttachmentTest {
 
         assertThat(attachment.getSize()).isEqualTo(input.getBytes().length);
     }
-
-    @Test
-    public void buildShouldSetTheName() throws Exception {
-        String input = "mystream";
-        Optional<String> expectedName = Optional.of("myName");
-        Attachment attachment = Attachment.builder()
-                .bytes(input.getBytes())
-                .type("content")
-                .name(expectedName)
-                .build();
-
-        assertThat(attachment.getName()).isEqualTo(expectedName);
-    }
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/1c294ddc/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageAttachmentTest.java
----------------------------------------------------------------------
diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageAttachmentTest.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageAttachmentTest.java
index 5d8ebcd..115a568 100644
--- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageAttachmentTest.java
+++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageAttachmentTest.java
@@ -45,7 +45,7 @@ public class MessageAttachmentTest {
                 .bytes("content".getBytes())
                 .type("type")
                 .build();
-        MessageAttachment expectedMessageAttachment = new MessageAttachment(attachment, Optional.<String> absent(), false);
+        MessageAttachment expectedMessageAttachment = new MessageAttachment(attachment, Optional.<String> absent(), Optional.<String> absent(), false);
 
         MessageAttachment messageAttachment = MessageAttachment.builder()
             .attachment(attachment)
@@ -87,10 +87,11 @@ public class MessageAttachmentTest {
                 .bytes("content".getBytes())
                 .type("type")
                 .build();
-        MessageAttachment expectedMessageAttachment = new MessageAttachment(attachment, Optional.of("cid"), true);
+        MessageAttachment expectedMessageAttachment = new MessageAttachment(attachment, Optional.of("name"), Optional.of("cid"), true);
 
         MessageAttachment messageAttachment = MessageAttachment.builder()
             .attachment(attachment)
+            .name("name")
             .cid("cid")
             .isInline(true)
             .build();

http://git-wip-us.apache.org/repos/asf/james-project/blob/1c294ddc/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/impl/MessageParserTest.java
----------------------------------------------------------------------
diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/impl/MessageParserTest.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/impl/MessageParserTest.java
index 2512123..2e3a15e 100644
--- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/impl/MessageParserTest.java
+++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/impl/MessageParserTest.java
@@ -59,7 +59,7 @@ public class MessageParserTest {
 
         assertThat(attachments).hasSize(1);
         Optional<String> expectedName = Optional.of("exploits_of_a_mom.png");
-        assertThat(attachments.get(0).getAttachment().getName()).isEqualTo(expectedName);
+        assertThat(attachments.get(0).getName()).isEqualTo(expectedName);
     }
 
     @Test
@@ -67,7 +67,7 @@ public class MessageParserTest {
         List<MessageAttachment> attachments = testee.retrieveAttachments(ClassLoader.getSystemResourceAsStream("eml/oneAttachmentWithoutName.eml"));
 
         assertThat(attachments).hasSize(1);
-        assertThat(attachments.get(0).getAttachment().getName()).isEqualTo(Optional.absent());
+        assertThat(attachments.get(0).getName()).isEqualTo(Optional.absent());
     }
 
     @Test

http://git-wip-us.apache.org/repos/asf/james-project/blob/1c294ddc/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/MessageFactory.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/MessageFactory.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/MessageFactory.java
index 126dcb9..a430627 100644
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/MessageFactory.java
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/MessageFactory.java
@@ -161,8 +161,8 @@ public class MessageFactory {
         return Attachment.builder()
                     .blobId(attachment.getAttachmentId().getId())
                     .type(attachment.getAttachment().getType())
-                    .name(attachment.getAttachment().getName().orNull())
                     .size(attachment.getAttachment().getSize())
+                    .name(attachment.getName().orNull())
                     .cid(attachment.getCid().orNull())
                     .isInline(attachment.isInline())
                     .build();


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


[3/5] james-project git commit: JAMES-1791 Support inline attachments

Posted by ad...@apache.org.
JAMES-1791 Support inline attachments


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

Branch: refs/heads/master
Commit: 896bc961ab22b4ec0b979a7c6fab9f37561d581c
Parents: 85aeb1e
Author: Antoine Duprat <ad...@linagora.com>
Authored: Tue Jul 5 15:52:20 2016 +0200
Committer: Antoine Duprat <ad...@linagora.com>
Committed: Fri Jul 8 11:28:30 2016 +0200

----------------------------------------------------------------------
 .../CassandraMailboxSessionMapperFactory.java   |   2 +-
 .../mail/CassandraAttachmentMapper.java         |  26 +++
 .../cassandra/mail/CassandraMessageMapper.java  |  55 ++++-
 .../modules/CassandraMessageModule.java         |  36 ++--
 .../cassandra/table/CassandraMessageTable.java  |  12 +-
 .../cassandra/mail/CassandraMappersTest.java    |  59 ++++++
 .../cassandra/mail/CassandraMappersTests.java   |  59 ------
 .../mailbox/hbase/mail/HBaseMailboxMessage.java |   6 +-
 .../james/mailbox/jcr/JCRMessageManager.java    |   4 +-
 .../jcr/mail/model/JCRMailboxMessage.java       |   6 +-
 .../james/mailbox/jpa/JPAMessageManager.java    |   4 +-
 .../openjpa/AbstractJPAMailboxMessage.java      |   6 +-
 .../jpa/openjpa/OpenJPAMessageManager.java      |   4 +-
 .../maildir/mail/model/MaildirMessage.java      |  25 +--
 .../inmemory/mail/InMemoryAttachmentMapper.java |  15 ++
 .../mailbox/store/StoreMessageManager.java      |  22 +-
 .../mailbox/store/mail/AttachmentMapper.java    |   3 +
 .../store/mail/NoopAttachmentMapper.java        |   6 +
 .../mail/model/DelegatingMailboxMessage.java    |   4 +-
 .../james/mailbox/store/mail/model/Message.java |   6 +-
 .../store/mail/model/MessageAttachment.java     | 123 ++++++++++++
 .../store/mail/model/impl/MessageParser.java    | 105 ++++++++--
 .../mail/model/impl/SimpleMailboxMessage.java   |  10 +-
 .../store/mail/model/impl/SimpleMessage.java    |  14 +-
 .../AbstractMailboxManagerAttachmentTest.java   |  50 ++---
 .../mailbox/store/SimpleMailboxMembership.java  |   4 +-
 .../store/mail/model/AttachmentMapperTest.java  |  38 ++++
 .../mailbox/store/mail/model/MessageAssert.java |   4 +-
 .../store/mail/model/MessageAttachmentTest.java | 100 +++++++++
 .../store/mail/model/MessageMapperTest.java     |  66 ++++--
 .../mail/model/impl/MessageParserTest.java      |  59 ++++--
 .../eml/oneAttachmentAndSomeInlined.eml         |  39 ----
 .../eml/oneAttachmentAndSomeTextInlined.eml     |  39 ++++
 .../test/resources/eml/oneInlinedAttachment.eml | 201 +++++++++++++++++++
 .../cucumber/GetMessagesMethodStepdefs.java     |   5 +-
 .../cucumber/util/BooleanFromString.java        |  34 ++++
 .../cucumber/util/IntegerFromString.java        |  35 ++++
 .../cucumber/util/ObjectFromString.java         |  27 +++
 .../util/ObjectFromStringExtractor.java         |  42 ++++
 .../cucumber/util/StringFromString.java         |  35 ++++
 .../integration/cucumber/util/TableRow.java     |  50 +++++
 .../test/resources/cucumber/GetMessages.feature |  18 +-
 .../src/test/resources/eml/twoAttachments.eml   |   3 +-
 .../protocols/jmap/doc/specs/spec/message.mdwn  |   3 -
 .../james/jmap/methods/GetMessagesMethod.java   |  45 +----
 .../org/apache/james/jmap/model/Attachment.java |   2 +-
 .../apache/james/jmap/model/MessageFactory.java |  15 +-
 .../jmap/methods/GetMessagesMethodTest.java     |  24 +--
 .../james/jmap/model/MailboxMessageTest.java    |  15 +-
 49 files changed, 1229 insertions(+), 336 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/896bc961/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraMailboxSessionMapperFactory.java
----------------------------------------------------------------------
diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraMailboxSessionMapperFactory.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraMailboxSessionMapperFactory.java
index 77cf9d7..639db36 100644
--- a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraMailboxSessionMapperFactory.java
+++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraMailboxSessionMapperFactory.java
@@ -68,7 +68,7 @@ public class CassandraMailboxSessionMapperFactory extends MailboxSessionMapperFa
 
     @Override
     public CassandraMessageMapper createMessageMapper(MailboxSession mailboxSession) {
-        return new CassandraMessageMapper(session, uidProvider, modSeqProvider, null, maxRetry, typesProvider);
+        return new CassandraMessageMapper(session, uidProvider, modSeqProvider, null, maxRetry, typesProvider, createAttachmentMapper(mailboxSession));
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/james-project/blob/896bc961/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraAttachmentMapper.java
----------------------------------------------------------------------
diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraAttachmentMapper.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraAttachmentMapper.java
index fcbfec8..0cceb19 100644
--- a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraAttachmentMapper.java
+++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraAttachmentMapper.java
@@ -20,6 +20,7 @@
 package org.apache.james.mailbox.cassandra.mail;
 
 import static com.datastax.driver.core.querybuilder.QueryBuilder.eq;
+import static com.datastax.driver.core.querybuilder.QueryBuilder.in;
 import static com.datastax.driver.core.querybuilder.QueryBuilder.insertInto;
 import static com.datastax.driver.core.querybuilder.QueryBuilder.select;
 import static org.apache.james.mailbox.cassandra.table.CassandraAttachmentTable.FIELDS;
@@ -33,6 +34,7 @@ import static org.apache.james.mailbox.cassandra.table.CassandraAttachmentTable.
 import java.io.IOException;
 import java.nio.ByteBuffer;
 import java.util.Collection;
+import java.util.List;
 import java.util.concurrent.CompletableFuture;
 
 import org.apache.commons.io.IOUtils;
@@ -42,13 +44,17 @@ import org.apache.james.mailbox.exception.MailboxException;
 import org.apache.james.mailbox.store.mail.AttachmentMapper;
 import org.apache.james.mailbox.store.mail.model.Attachment;
 import org.apache.james.mailbox.store.mail.model.AttachmentId;
+import org.apache.james.util.streams.ImmutableCollectors;
 
+import com.datastax.driver.core.ResultSet;
 import com.datastax.driver.core.Row;
 import com.datastax.driver.core.Session;
 import com.github.fge.lambdas.Throwing;
 import com.github.fge.lambdas.ThrownByLambdaException;
 import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableList.Builder;
 
 public class CassandraAttachmentMapper implements AttachmentMapper {
 
@@ -89,6 +95,26 @@ public class CassandraAttachmentMapper implements AttachmentMapper {
     }
 
     @Override
+    public List<Attachment> getAttachments(List<AttachmentId> attachmentIds) {
+        Preconditions.checkArgument(attachmentIds != null);
+        List<String> ids = attachmentIds.stream()
+                .map(AttachmentId::getId)
+                .collect(ImmutableCollectors.toImmutableList());
+        return cassandraAsyncExecutor.execute(
+            select(FIELDS)
+                .from(TABLE_NAME)
+                .where(in(ID, ids)))
+            .thenApply(this::attachments)
+            .join();
+    }
+
+    private List<Attachment> attachments(ResultSet resultSet) {
+        Builder<Attachment> builder = ImmutableList.<Attachment> builder();
+        resultSet.forEach(row -> builder.add(attachment(row)));
+        return builder.build();
+    }
+
+    @Override
     public void storeAttachment(Attachment attachment) throws MailboxException {
         try {
             asyncStoreAttachment(attachment).join();

http://git-wip-us.apache.org/repos/asf/james-project/blob/896bc961/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMapper.java
----------------------------------------------------------------------
diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMapper.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMapper.java
index 22fe268..0232cfb 100644
--- a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMapper.java
+++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMapper.java
@@ -28,7 +28,7 @@ import static com.datastax.driver.core.querybuilder.QueryBuilder.lte;
 import static com.datastax.driver.core.querybuilder.QueryBuilder.select;
 import static com.datastax.driver.core.querybuilder.QueryBuilder.set;
 import static com.datastax.driver.core.querybuilder.QueryBuilder.update;
-import static org.apache.james.mailbox.cassandra.table.CassandraMessageTable.ATTACHMENTS_IDS;
+import static org.apache.james.mailbox.cassandra.table.CassandraMessageTable.ATTACHMENTS;
 import static org.apache.james.mailbox.cassandra.table.CassandraMessageTable.BODY;
 import static org.apache.james.mailbox.cassandra.table.CassandraMessageTable.BODY_CONTENT;
 import static org.apache.james.mailbox.cassandra.table.CassandraMessageTable.BODY_OCTECTS;
@@ -64,6 +64,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.Optional;
 import java.util.Set;
+import java.util.function.Function;
 import java.util.stream.Collectors;
 
 import javax.mail.Flags;
@@ -80,6 +81,7 @@ import org.apache.james.mailbox.cassandra.CassandraId;
 import org.apache.james.mailbox.cassandra.mail.utils.MessageDeletedDuringFlagsUpdateException;
 import org.apache.james.mailbox.cassandra.table.CassandraMailboxCountersTable;
 import org.apache.james.mailbox.cassandra.table.CassandraMessageTable;
+import org.apache.james.mailbox.cassandra.table.CassandraMessageTable.Attachments;
 import org.apache.james.mailbox.cassandra.table.CassandraMessageTable.Properties;
 import org.apache.james.mailbox.exception.MailboxException;
 import org.apache.james.mailbox.model.MessageMetaData;
@@ -87,12 +89,15 @@ import org.apache.james.mailbox.model.MessageRange;
 import org.apache.james.mailbox.model.UpdatedFlags;
 import org.apache.james.mailbox.store.FlagsUpdateCalculator;
 import org.apache.james.mailbox.store.SimpleMessageMetaData;
+import org.apache.james.mailbox.store.mail.AttachmentMapper;
 import org.apache.james.mailbox.store.mail.MessageMapper;
 import org.apache.james.mailbox.store.mail.ModSeqProvider;
 import org.apache.james.mailbox.store.mail.UidProvider;
+import org.apache.james.mailbox.store.mail.model.Attachment;
 import org.apache.james.mailbox.store.mail.model.AttachmentId;
 import org.apache.james.mailbox.store.mail.model.Mailbox;
 import org.apache.james.mailbox.store.mail.model.MailboxMessage;
+import org.apache.james.mailbox.store.mail.model.MessageAttachment;
 import org.apache.james.mailbox.store.mail.model.impl.PropertyBuilder;
 import org.apache.james.mailbox.store.mail.model.impl.SimpleMailboxMessage;
 import org.apache.james.mailbox.store.mail.model.impl.SimpleProperty;
@@ -107,6 +112,7 @@ import com.datastax.driver.core.querybuilder.Assignment;
 import com.datastax.driver.core.querybuilder.QueryBuilder;
 import com.datastax.driver.core.querybuilder.Select;
 import com.datastax.driver.core.querybuilder.Select.Where;
+import com.github.fge.lambdas.Throwing;
 import com.google.common.base.Throwables;
 import com.google.common.collect.ImmutableList;
 import com.google.common.io.ByteStreams;
@@ -120,14 +126,16 @@ public class CassandraMessageMapper implements MessageMapper {
     private final UidProvider uidProvider;
     private final CassandraTypesProvider typesProvider;
     private final int maxRetries;
+    private final AttachmentMapper attachmentMapper;
 
-    public CassandraMessageMapper(Session session, UidProvider uidProvider, ModSeqProvider modSeqProvider, MailboxSession mailboxSession, int maxRetries, CassandraTypesProvider typesProvider) {
+    public CassandraMessageMapper(Session session, UidProvider uidProvider, ModSeqProvider modSeqProvider, MailboxSession mailboxSession, int maxRetries, CassandraTypesProvider typesProvider, AttachmentMapper attachmentMapper) {
         this.session = session;
         this.uidProvider = uidProvider;
         this.modSeqProvider = modSeqProvider;
         this.mailboxSession = mailboxSession;
         this.maxRetries = maxRetries;
         this.typesProvider = typesProvider;
+        this.attachmentMapper = attachmentMapper;
     }
 
     @Override
@@ -305,7 +313,7 @@ public class CassandraMessageMapper implements MessageMapper {
                 getFlags(row),
                 getPropertyBuilder(row),
                 CassandraId.of(row.getUUID(MAILBOX_ID)),
-                getAttachmentsIds(row, fetchType));
+                getAttachments(row, fetchType));
         message.setUid(row.getLong(IMAP_UID));
         message.setModSeq(row.getLong(MOD_SEQ));
         return message;
@@ -333,19 +341,42 @@ public class CassandraMessageMapper implements MessageMapper {
         return property;
     }
 
-    private List<AttachmentId> getAttachmentsIds(Row row, FetchType fetchType) {
+    private List<MessageAttachment> getAttachments(Row row, FetchType fetchType) {
         switch (fetchType) {
         case Full:
         case Body:
-            return row.getList(ATTACHMENTS_IDS, String.class)
+            List<UDTValue> udtValues = row.getList(ATTACHMENTS, UDTValue.class);
+            Map<AttachmentId,Attachment> attachmentsById = attachmentsById(row, udtValues);
+
+            return udtValues
                     .stream()
-                    .map(AttachmentId::from)
+                    .map(Throwing.function(x -> 
+                        MessageAttachment.builder()
+                            .attachment(attachmentsById.get(attachmentIdFrom(x)))
+                            .cid(x.getString(Attachments.CID))
+                            .isInline(x.getBool(Attachments.IS_INLINE))
+                            .build()))
                     .collect(ImmutableCollectors.toImmutableList());
         default:
             return ImmutableList.of();
         }
     }
 
+    private Map<AttachmentId,Attachment> attachmentsById(Row row, List<UDTValue> udtValues) {
+        return attachmentMapper.getAttachments(attachmentIds(udtValues)).stream()
+            .collect(ImmutableCollectors.toImmutableMap(Attachment::getAttachmentId, Function.identity()));
+    }
+
+    private List<AttachmentId> attachmentIds(List<UDTValue> udtValues) {
+        return udtValues.stream()
+            .map(this::attachmentIdFrom)
+            .collect(ImmutableCollectors.toImmutableList());
+    }
+
+    private AttachmentId attachmentIdFrom(UDTValue udtValue) {
+        return AttachmentId.from(udtValue.getString(Attachments.ID));
+    }
+
     private MessageMetaData save(Mailbox mailbox, MailboxMessage message) throws MailboxException {
         try {
             CassandraId mailboxId = (CassandraId) mailbox.getMailboxId();
@@ -375,8 +406,8 @@ public class CassandraMessageMapper implements MessageMapper {
                         .setString(Properties.VALUE, x.getValue()))
                     .collect(Collectors.toList()))
                 .value(TEXTUAL_LINE_COUNT, message.getTextualLineCount())
-                .value(ATTACHMENTS_IDS, message.getAttachmentsIds().stream()
-                    .map(AttachmentId::getId)
+                .value(ATTACHMENTS, message.getAttachments().stream()
+                    .map(this::toUDT)
                     .collect(Collectors.toList())));
 
             return new SimpleMessageMetaData(message);
@@ -385,6 +416,14 @@ public class CassandraMessageMapper implements MessageMapper {
         }
     }
 
+    private UDTValue toUDT(MessageAttachment messageAttachment) {
+        return typesProvider.getDefinedUserType(ATTACHMENTS)
+            .newValue()
+            .setString(Attachments.ID, messageAttachment.getAttachmentId().getId())
+            .setString(Attachments.CID, messageAttachment.getCid().orNull())
+            .setBool(Attachments.IS_INLINE, messageAttachment.isInline());
+    }
+
     private Set<String> userFlagsSet(MailboxMessage message) {
         return Arrays.stream(message.createFlags().getUserFlags()).collect(Collectors.toSet());
     }

http://git-wip-us.apache.org/repos/asf/james-project/blob/896bc961/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/modules/CassandraMessageModule.java
----------------------------------------------------------------------
diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/modules/CassandraMessageModule.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/modules/CassandraMessageModule.java
index 3565213..03494e9 100644
--- a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/modules/CassandraMessageModule.java
+++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/modules/CassandraMessageModule.java
@@ -19,27 +19,27 @@
 
 package org.apache.james.mailbox.cassandra.modules;
 
-import com.datastax.driver.core.schemabuilder.SchemaBuilder;
-import org.apache.james.backends.cassandra.components.CassandraIndex;
-import org.apache.james.backends.cassandra.components.CassandraModule;
-import org.apache.james.backends.cassandra.components.CassandraTable;
-import org.apache.james.backends.cassandra.components.CassandraType;
-import org.apache.james.mailbox.cassandra.table.CassandraMessageTable;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-
 import static com.datastax.driver.core.DataType.bigint;
 import static com.datastax.driver.core.DataType.blob;
 import static com.datastax.driver.core.DataType.cboolean;
 import static com.datastax.driver.core.DataType.cint;
-import static com.datastax.driver.core.DataType.frozenList;
 import static com.datastax.driver.core.DataType.set;
 import static com.datastax.driver.core.DataType.text;
 import static com.datastax.driver.core.DataType.timestamp;
 import static com.datastax.driver.core.DataType.timeuuid;
 
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.james.backends.cassandra.components.CassandraIndex;
+import org.apache.james.backends.cassandra.components.CassandraModule;
+import org.apache.james.backends.cassandra.components.CassandraTable;
+import org.apache.james.backends.cassandra.components.CassandraType;
+import org.apache.james.mailbox.cassandra.table.CassandraMessageTable;
+
+import com.datastax.driver.core.schemabuilder.SchemaBuilder;
+
 public class CassandraMessageModule implements CassandraModule {
 
     private final List<CassandraTable> tables;
@@ -69,7 +69,7 @@ public class CassandraMessageModule implements CassandraModule {
                     .addColumn(CassandraMessageTable.Flag.SEEN, cboolean())
                     .addColumn(CassandraMessageTable.Flag.USER, cboolean())
                     .addColumn(CassandraMessageTable.Flag.USER_FLAGS, set(text()))
-                    .addColumn(CassandraMessageTable.ATTACHMENTS_IDS, frozenList(text()))
+                    .addUDTListColumn(CassandraMessageTable.ATTACHMENTS, SchemaBuilder.frozen(CassandraMessageTable.ATTACHMENTS))
                     .addUDTListColumn(CassandraMessageTable.PROPERTIES, SchemaBuilder.frozen(CassandraMessageTable.PROPERTIES))));
         index = Arrays.asList(
             new CassandraIndex(
@@ -87,13 +87,19 @@ public class CassandraMessageModule implements CassandraModule {
                     .ifNotExists()
                     .onTable(CassandraMessageTable.TABLE_NAME)
                     .andColumn(CassandraMessageTable.Flag.DELETED)));
-        types = Collections.singletonList(
+        types = Arrays.asList(
             new CassandraType(CassandraMessageTable.PROPERTIES,
                 SchemaBuilder.createType(CassandraMessageTable.PROPERTIES)
                     .ifNotExists()
                     .addColumn(CassandraMessageTable.Properties.NAMESPACE, text())
                     .addColumn(CassandraMessageTable.Properties.NAME, text())
-                    .addColumn(CassandraMessageTable.Properties.VALUE, text())));
+                    .addColumn(CassandraMessageTable.Properties.VALUE, text())),
+            new CassandraType(CassandraMessageTable.ATTACHMENTS,
+                    SchemaBuilder.createType(CassandraMessageTable.ATTACHMENTS)
+                        .ifNotExists()
+                        .addColumn(CassandraMessageTable.Attachments.ID, text())
+                        .addColumn(CassandraMessageTable.Attachments.CID, text())
+                        .addColumn(CassandraMessageTable.Attachments.IS_INLINE, cboolean())));
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/james-project/blob/896bc961/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/table/CassandraMessageTable.java
----------------------------------------------------------------------
diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/table/CassandraMessageTable.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/table/CassandraMessageTable.java
index e2e19af..cbd89bf 100644
--- a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/table/CassandraMessageTable.java
+++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/table/CassandraMessageTable.java
@@ -37,12 +37,12 @@ public interface CassandraMessageTable {
     String BODY_CONTENT = "bodyContent";
     String HEADER_CONTENT = "headerContent";
     String PROPERTIES = "properties";
-    String ATTACHMENTS_IDS = "attachmentsIds";
+    String ATTACHMENTS = "attachments";
 
-    String[] FIELDS = { MAILBOX_ID, IMAP_UID, INTERNAL_DATE, MOD_SEQ, BODY_START_OCTET, FULL_CONTENT_OCTETS, BODY_OCTECTS, Flag.ANSWERED, Flag.DELETED, Flag.DRAFT, Flag.FLAGGED, Flag.RECENT, Flag.SEEN, Flag.USER, Flag.USER_FLAGS, BODY_CONTENT, HEADER_CONTENT, TEXTUAL_LINE_COUNT, PROPERTIES, ATTACHMENTS_IDS };
+    String[] FIELDS = { MAILBOX_ID, IMAP_UID, INTERNAL_DATE, MOD_SEQ, BODY_START_OCTET, FULL_CONTENT_OCTETS, BODY_OCTECTS, Flag.ANSWERED, Flag.DELETED, Flag.DRAFT, Flag.FLAGGED, Flag.RECENT, Flag.SEEN, Flag.USER, Flag.USER_FLAGS, BODY_CONTENT, HEADER_CONTENT, TEXTUAL_LINE_COUNT, PROPERTIES, ATTACHMENTS };
     String[] METADATA = { MAILBOX_ID, IMAP_UID, INTERNAL_DATE, MOD_SEQ, BODY_START_OCTET, FULL_CONTENT_OCTETS, BODY_OCTECTS, Flag.ANSWERED, Flag.DELETED, Flag.DRAFT, Flag.FLAGGED, Flag.RECENT, Flag.SEEN, Flag.USER, Flag.USER_FLAGS, TEXTUAL_LINE_COUNT, PROPERTIES };
     String[] HEADERS = { MAILBOX_ID, IMAP_UID, INTERNAL_DATE, MOD_SEQ, BODY_START_OCTET, FULL_CONTENT_OCTETS, BODY_OCTECTS, Flag.ANSWERED, Flag.DELETED, Flag.DRAFT, Flag.FLAGGED, Flag.RECENT, Flag.SEEN, Flag.USER, Flag.USER_FLAGS, HEADER_CONTENT, TEXTUAL_LINE_COUNT, PROPERTIES };
-    String[] BODY = { MAILBOX_ID, IMAP_UID, INTERNAL_DATE, MOD_SEQ, BODY_START_OCTET, FULL_CONTENT_OCTETS, BODY_OCTECTS, Flag.ANSWERED, Flag.DELETED, Flag.DRAFT, Flag.FLAGGED, Flag.RECENT, Flag.SEEN, Flag.USER, Flag.USER_FLAGS, BODY_CONTENT, TEXTUAL_LINE_COUNT, PROPERTIES, ATTACHMENTS_IDS };
+    String[] BODY = { MAILBOX_ID, IMAP_UID, INTERNAL_DATE, MOD_SEQ, BODY_START_OCTET, FULL_CONTENT_OCTETS, BODY_OCTECTS, Flag.ANSWERED, Flag.DELETED, Flag.DRAFT, Flag.FLAGGED, Flag.RECENT, Flag.SEEN, Flag.USER, Flag.USER_FLAGS, BODY_CONTENT, TEXTUAL_LINE_COUNT, PROPERTIES, ATTACHMENTS };
 
     interface Flag {
         String ANSWERED = "flagAnswered";
@@ -71,4 +71,10 @@ public interface CassandraMessageTable {
         String NAME = "name";
         String VALUE = "value";
     }
+
+    interface Attachments {
+        String ID = "id";
+        String CID = "cid";
+        String IS_INLINE = "isInline";
+    }
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/896bc961/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMappersTest.java
----------------------------------------------------------------------
diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMappersTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMappersTest.java
new file mode 100644
index 0000000..bf2eb64
--- /dev/null
+++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMappersTest.java
@@ -0,0 +1,59 @@
+/****************************************************************
+ * 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.mailbox.cassandra.mail;
+
+import org.apache.james.mailbox.exception.MailboxException;
+import org.junit.runner.RunWith;
+import org.xenei.junit.contract.Contract;
+import org.xenei.junit.contract.ContractImpl;
+import org.xenei.junit.contract.ContractSuite;
+import org.xenei.junit.contract.IProducer;
+
+import com.google.common.base.Throwables;
+
+@RunWith(ContractSuite.class)
+@ContractImpl(CassandraMapperProvider.class)
+public class CassandraMappersTest {
+
+    private IProducer<CassandraMapperProvider> producer = new IProducer<CassandraMapperProvider>() {
+
+        private final CassandraMapperProvider cassandraMapperProvider = new CassandraMapperProvider();
+
+        @Override
+        public CassandraMapperProvider newInstance() {
+            return cassandraMapperProvider;
+        }
+
+        @Override
+        public void cleanUp() {
+            try {
+                cassandraMapperProvider.clearMapper();
+            } catch (MailboxException e) {
+                throw Throwables.propagate(e);
+            }
+        }
+    };
+
+    @Contract.Inject
+    public IProducer<CassandraMapperProvider> getProducer() {
+        return producer;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/896bc961/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMappersTests.java
----------------------------------------------------------------------
diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMappersTests.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMappersTests.java
deleted file mode 100644
index 9f37d64..0000000
--- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMappersTests.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/****************************************************************
- * 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.mailbox.cassandra.mail;
-
-import org.apache.james.mailbox.exception.MailboxException;
-import org.junit.runner.RunWith;
-import org.xenei.junit.contract.Contract;
-import org.xenei.junit.contract.ContractImpl;
-import org.xenei.junit.contract.ContractSuite;
-import org.xenei.junit.contract.IProducer;
-
-import com.google.common.base.Throwables;
-
-@RunWith(ContractSuite.class)
-@ContractImpl(CassandraMapperProvider.class)
-public class CassandraMappersTests {
-
-    private IProducer<CassandraMapperProvider> producer = new IProducer<CassandraMapperProvider>() {
-
-        private final CassandraMapperProvider cassandraMapperProvider = new CassandraMapperProvider();
-
-        @Override
-        public CassandraMapperProvider newInstance() {
-            return cassandraMapperProvider;
-        }
-
-        @Override
-        public void cleanUp() {
-            try {
-                cassandraMapperProvider.clearMapper();
-            } catch (MailboxException e) {
-                throw Throwables.propagate(e);
-            }
-        }
-    };
-
-    @Contract.Inject
-    public IProducer<CassandraMapperProvider> getProducer() {
-        return producer;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/james-project/blob/896bc961/mailbox/hbase/src/main/java/org/apache/james/mailbox/hbase/mail/HBaseMailboxMessage.java
----------------------------------------------------------------------
diff --git a/mailbox/hbase/src/main/java/org/apache/james/mailbox/hbase/mail/HBaseMailboxMessage.java b/mailbox/hbase/src/main/java/org/apache/james/mailbox/hbase/mail/HBaseMailboxMessage.java
index ae8c54b..8e8266c 100644
--- a/mailbox/hbase/src/main/java/org/apache/james/mailbox/hbase/mail/HBaseMailboxMessage.java
+++ b/mailbox/hbase/src/main/java/org/apache/james/mailbox/hbase/mail/HBaseMailboxMessage.java
@@ -38,10 +38,10 @@ import org.apache.hadoop.conf.Configuration;
 import org.apache.james.mailbox.exception.MailboxException;
 import org.apache.james.mailbox.hbase.HBaseId;
 import org.apache.james.mailbox.hbase.io.ChunkInputStream;
-import org.apache.james.mailbox.store.mail.model.AttachmentId;
 import org.apache.james.mailbox.store.mail.model.DefaultMessageId;
 import org.apache.james.mailbox.store.mail.model.FlagsBuilder;
 import org.apache.james.mailbox.store.mail.model.MailboxMessage;
+import org.apache.james.mailbox.store.mail.model.MessageAttachment;
 import org.apache.james.mailbox.store.mail.model.MessageId;
 import org.apache.james.mailbox.store.mail.model.Property;
 import org.apache.james.mailbox.store.mail.model.impl.MessageUidComparator;
@@ -355,7 +355,7 @@ public class HBaseMailboxMessage implements MailboxMessage {
     }
 
     @Override
-    public List<AttachmentId> getAttachmentsIds() {
-        throw new NotImplementedException("Attachments Ids not implemented");
+    public List<MessageAttachment> getAttachments() {
+        throw new NotImplementedException("Attachments are not implemented");
     }
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/896bc961/mailbox/jcr/src/main/java/org/apache/james/mailbox/jcr/JCRMessageManager.java
----------------------------------------------------------------------
diff --git a/mailbox/jcr/src/main/java/org/apache/james/mailbox/jcr/JCRMessageManager.java b/mailbox/jcr/src/main/java/org/apache/james/mailbox/jcr/JCRMessageManager.java
index dcfaed4..59448ca 100644
--- a/mailbox/jcr/src/main/java/org/apache/james/mailbox/jcr/JCRMessageManager.java
+++ b/mailbox/jcr/src/main/java/org/apache/james/mailbox/jcr/JCRMessageManager.java
@@ -36,8 +36,8 @@ import org.apache.james.mailbox.quota.QuotaRootResolver;
 import org.apache.james.mailbox.store.MailboxSessionMapperFactory;
 import org.apache.james.mailbox.store.StoreMessageManager;
 import org.apache.james.mailbox.store.event.MailboxEventDispatcher;
-import org.apache.james.mailbox.store.mail.model.Attachment;
 import org.apache.james.mailbox.store.mail.model.MailboxMessage;
+import org.apache.james.mailbox.store.mail.model.MessageAttachment;
 import org.apache.james.mailbox.store.mail.model.impl.MessageParser;
 import org.apache.james.mailbox.store.mail.model.impl.PropertyBuilder;
 import org.apache.james.mailbox.store.search.MessageSearchIndex;
@@ -59,7 +59,7 @@ public class JCRMessageManager extends StoreMessageManager {
 
 
     @Override
-    protected MailboxMessage createMessage(Date internalDate, int size, int bodyStartOctet, SharedInputStream content, Flags flags, PropertyBuilder propertyBuilder, List<Attachment> attachments) throws MailboxException{
+    protected MailboxMessage createMessage(Date internalDate, int size, int bodyStartOctet, SharedInputStream content, Flags flags, PropertyBuilder propertyBuilder, List<MessageAttachment> attachments) throws MailboxException{
         JCRId mailboxId = (JCRId) getMailboxEntity().getMailboxId();
         return new JCRMailboxMessage(mailboxId, internalDate,
                 size, flags, content, bodyStartOctet, propertyBuilder, log);

http://git-wip-us.apache.org/repos/asf/james-project/blob/896bc961/mailbox/jcr/src/main/java/org/apache/james/mailbox/jcr/mail/model/JCRMailboxMessage.java
----------------------------------------------------------------------
diff --git a/mailbox/jcr/src/main/java/org/apache/james/mailbox/jcr/mail/model/JCRMailboxMessage.java b/mailbox/jcr/src/main/java/org/apache/james/mailbox/jcr/mail/model/JCRMailboxMessage.java
index 62d17dd..eecb9e0 100644
--- a/mailbox/jcr/src/main/java/org/apache/james/mailbox/jcr/mail/model/JCRMailboxMessage.java
+++ b/mailbox/jcr/src/main/java/org/apache/james/mailbox/jcr/mail/model/JCRMailboxMessage.java
@@ -42,10 +42,10 @@ import org.apache.james.mailbox.exception.MailboxException;
 import org.apache.james.mailbox.jcr.JCRId;
 import org.apache.james.mailbox.jcr.JCRImapConstants;
 import org.apache.james.mailbox.jcr.Persistent;
-import org.apache.james.mailbox.store.mail.model.AttachmentId;
 import org.apache.james.mailbox.store.mail.model.DefaultMessageId;
 import org.apache.james.mailbox.store.mail.model.FlagsBuilder;
 import org.apache.james.mailbox.store.mail.model.MailboxMessage;
+import org.apache.james.mailbox.store.mail.model.MessageAttachment;
 import org.apache.james.mailbox.store.mail.model.MessageId;
 import org.apache.james.mailbox.store.mail.model.Property;
 import org.apache.james.mailbox.store.mail.model.impl.MessageUidComparator;
@@ -680,7 +680,7 @@ public class JCRMailboxMessage implements MailboxMessage, JCRImapConstants, Pers
     }
 
     @Override
-    public List<AttachmentId> getAttachmentsIds() {
-        throw new NotImplementedException("Attachments Ids not implemented");
+    public List<MessageAttachment> getAttachments() {
+        throw new NotImplementedException("Attachments are not implemented");
     }
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/896bc961/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/JPAMessageManager.java
----------------------------------------------------------------------
diff --git a/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/JPAMessageManager.java b/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/JPAMessageManager.java
index ce36f27..6dcb8c1 100644
--- a/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/JPAMessageManager.java
+++ b/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/JPAMessageManager.java
@@ -36,9 +36,9 @@ import org.apache.james.mailbox.quota.QuotaRootResolver;
 import org.apache.james.mailbox.store.MailboxSessionMapperFactory;
 import org.apache.james.mailbox.store.StoreMessageManager;
 import org.apache.james.mailbox.store.event.MailboxEventDispatcher;
-import org.apache.james.mailbox.store.mail.model.Attachment;
 import org.apache.james.mailbox.store.mail.model.Mailbox;
 import org.apache.james.mailbox.store.mail.model.MailboxMessage;
+import org.apache.james.mailbox.store.mail.model.MessageAttachment;
 import org.apache.james.mailbox.store.mail.model.impl.MessageParser;
 import org.apache.james.mailbox.store.mail.model.impl.PropertyBuilder;
 import org.apache.james.mailbox.store.search.MessageSearchIndex;
@@ -60,7 +60,7 @@ public class JPAMessageManager extends StoreMessageManager {
     
     @Override
     protected MailboxMessage createMessage(Date internalDate, int size, int bodyStartOctet, SharedInputStream content,
-                                                  final Flags flags, PropertyBuilder propertyBuilder, List<Attachment> attachments) throws MailboxException{
+                                                  final Flags flags, PropertyBuilder propertyBuilder, List<MessageAttachment> attachments) throws MailboxException{
 
         return new JPAMailboxMessage((JPAMailbox) getMailboxEntity(), internalDate, size, flags, content,  bodyStartOctet,  propertyBuilder);
     }

http://git-wip-us.apache.org/repos/asf/james-project/blob/896bc961/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/mail/model/openjpa/AbstractJPAMailboxMessage.java
----------------------------------------------------------------------
diff --git a/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/mail/model/openjpa/AbstractJPAMailboxMessage.java b/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/mail/model/openjpa/AbstractJPAMailboxMessage.java
index 3488127..c1aa3fa 100644
--- a/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/mail/model/openjpa/AbstractJPAMailboxMessage.java
+++ b/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/mail/model/openjpa/AbstractJPAMailboxMessage.java
@@ -46,11 +46,11 @@ import org.apache.james.mailbox.jpa.JPAId;
 import org.apache.james.mailbox.jpa.mail.model.JPAMailbox;
 import org.apache.james.mailbox.jpa.mail.model.JPAProperty;
 import org.apache.james.mailbox.jpa.mail.model.JPAUserFlag;
-import org.apache.james.mailbox.store.mail.model.AttachmentId;
 import org.apache.james.mailbox.store.mail.model.DefaultMessageId;
 import org.apache.james.mailbox.store.mail.model.DelegatingMailboxMessage;
 import org.apache.james.mailbox.store.mail.model.FlagsBuilder;
 import org.apache.james.mailbox.store.mail.model.MailboxMessage;
+import org.apache.james.mailbox.store.mail.model.MessageAttachment;
 import org.apache.james.mailbox.store.mail.model.MessageId;
 import org.apache.james.mailbox.store.mail.model.Property;
 import org.apache.james.mailbox.store.mail.model.impl.MessageUidComparator;
@@ -577,8 +577,8 @@ public abstract class AbstractJPAMailboxMessage implements MailboxMessage {
     
 
     @Override
-    public List<AttachmentId> getAttachmentsIds() {
-        throw new NotImplementedException("Attachments Ids not implemented");
+    public List<MessageAttachment> getAttachments() {
+        throw new NotImplementedException("Attachments are not implemented");
     }
 
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/896bc961/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/openjpa/OpenJPAMessageManager.java
----------------------------------------------------------------------
diff --git a/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/openjpa/OpenJPAMessageManager.java b/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/openjpa/OpenJPAMessageManager.java
index 332ded6..3ae70a3 100644
--- a/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/openjpa/OpenJPAMessageManager.java
+++ b/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/openjpa/OpenJPAMessageManager.java
@@ -37,9 +37,9 @@ import org.apache.james.mailbox.quota.QuotaManager;
 import org.apache.james.mailbox.quota.QuotaRootResolver;
 import org.apache.james.mailbox.store.MailboxSessionMapperFactory;
 import org.apache.james.mailbox.store.event.MailboxEventDispatcher;
-import org.apache.james.mailbox.store.mail.model.Attachment;
 import org.apache.james.mailbox.store.mail.model.Mailbox;
 import org.apache.james.mailbox.store.mail.model.MailboxMessage;
+import org.apache.james.mailbox.store.mail.model.MessageAttachment;
 import org.apache.james.mailbox.store.mail.model.impl.MessageParser;
 import org.apache.james.mailbox.store.mail.model.impl.PropertyBuilder;
 import org.apache.james.mailbox.store.search.MessageSearchIndex;
@@ -76,7 +76,7 @@ public class OpenJPAMessageManager extends JPAMessageManager {
     }
 
     @Override
-    protected MailboxMessage createMessage(Date internalDate, int size, int bodyStartOctet, SharedInputStream content, Flags flags, PropertyBuilder propertyBuilder, List<Attachment> attachments) throws MailboxException {
+    protected MailboxMessage createMessage(Date internalDate, int size, int bodyStartOctet, SharedInputStream content, Flags flags, PropertyBuilder propertyBuilder, List<MessageAttachment> attachments) throws MailboxException {
         int headerEnd = bodyStartOctet -2;
         if (headerEnd < 0) {
             headerEnd = 0;

http://git-wip-us.apache.org/repos/asf/james-project/blob/896bc961/mailbox/maildir/src/main/java/org/apache/james/mailbox/maildir/mail/model/MaildirMessage.java
----------------------------------------------------------------------
diff --git a/mailbox/maildir/src/main/java/org/apache/james/mailbox/maildir/mail/model/MaildirMessage.java b/mailbox/maildir/src/main/java/org/apache/james/mailbox/maildir/mail/model/MaildirMessage.java
index be2ecaa..c537f96 100644
--- a/mailbox/maildir/src/main/java/org/apache/james/mailbox/maildir/mail/model/MaildirMessage.java
+++ b/mailbox/maildir/src/main/java/org/apache/james/mailbox/maildir/mail/model/MaildirMessage.java
@@ -18,11 +18,21 @@
  ****************************************************************/
 package org.apache.james.mailbox.maildir.mail.model;
 
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PushbackInputStream;
+import java.util.Date;
+import java.util.List;
+
+import javax.mail.util.SharedFileInputStream;
+
 import org.apache.commons.io.IOUtils;
 import org.apache.commons.lang.NotImplementedException;
 import org.apache.james.mailbox.maildir.MaildirMessageName;
-import org.apache.james.mailbox.store.mail.model.AttachmentId;
 import org.apache.james.mailbox.store.mail.model.Message;
+import org.apache.james.mailbox.store.mail.model.MessageAttachment;
 import org.apache.james.mailbox.store.mail.model.MessageId;
 import org.apache.james.mailbox.store.mail.model.Property;
 import org.apache.james.mailbox.store.mail.model.impl.PropertyBuilder;
@@ -36,15 +46,6 @@ import org.apache.james.mime4j.stream.MimeConfig;
 import org.apache.james.mime4j.stream.MimeTokenStream;
 import org.apache.james.mime4j.stream.RecursionMode;
 
-import javax.mail.util.SharedFileInputStream;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.PushbackInputStream;
-import java.util.Date;
-import java.util.List;
-
 public class MaildirMessage implements Message {
 
     private final MaildirMessageName messageName;
@@ -277,8 +278,8 @@ public class MaildirMessage implements Message {
     }
 
     @Override
-    public List<AttachmentId> getAttachmentsIds() {
-        throw new NotImplementedException("Attachments Ids not implemented");
+    public List<MessageAttachment> getAttachments() {
+        throw new NotImplementedException("Attachments are not implemented");
     }
 
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/896bc961/mailbox/memory/src/main/java/org/apache/james/mailbox/inmemory/mail/InMemoryAttachmentMapper.java
----------------------------------------------------------------------
diff --git a/mailbox/memory/src/main/java/org/apache/james/mailbox/inmemory/mail/InMemoryAttachmentMapper.java b/mailbox/memory/src/main/java/org/apache/james/mailbox/inmemory/mail/InMemoryAttachmentMapper.java
index a790456..188318e 100644
--- a/mailbox/memory/src/main/java/org/apache/james/mailbox/inmemory/mail/InMemoryAttachmentMapper.java
+++ b/mailbox/memory/src/main/java/org/apache/james/mailbox/inmemory/mail/InMemoryAttachmentMapper.java
@@ -19,6 +19,7 @@
 package org.apache.james.mailbox.inmemory.mail;
 
 import java.util.Collection;
+import java.util.List;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 
@@ -29,6 +30,8 @@ import org.apache.james.mailbox.store.mail.model.Attachment;
 import org.apache.james.mailbox.store.mail.model.AttachmentId;
 
 import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableList.Builder;
 
 public class InMemoryAttachmentMapper implements AttachmentMapper {
     
@@ -49,6 +52,18 @@ public class InMemoryAttachmentMapper implements AttachmentMapper {
     }
 
     @Override
+    public List<Attachment> getAttachments(List<AttachmentId> attachmentIds) {
+        Preconditions.checkArgument(attachmentIds != null);
+        Builder<Attachment> builder = ImmutableList.<Attachment> builder();
+        for (AttachmentId attachmentId : attachmentIds) {
+            if (attachmentsById.containsKey(attachmentId)) {
+                builder.add(attachmentsById.get(attachmentId));
+            }
+        }
+        return builder.build();
+    }
+
+    @Override
     public void storeAttachment(Attachment attachment) throws MailboxException {
         attachmentsById.put(attachment.getAttachmentId(), attachment);
     }

http://git-wip-us.apache.org/repos/asf/james-project/blob/896bc961/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMessageManager.java
----------------------------------------------------------------------
diff --git a/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMessageManager.java b/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMessageManager.java
index e5295f7..7e57f85 100644
--- a/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMessageManager.java
+++ b/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMessageManager.java
@@ -65,9 +65,9 @@ import org.apache.james.mailbox.store.mail.AttachmentMapper;
 import org.apache.james.mailbox.store.mail.MessageMapper;
 import org.apache.james.mailbox.store.mail.MessageMapper.FetchType;
 import org.apache.james.mailbox.store.mail.model.Attachment;
-import org.apache.james.mailbox.store.mail.model.AttachmentId;
 import org.apache.james.mailbox.store.mail.model.Mailbox;
 import org.apache.james.mailbox.store.mail.model.MailboxMessage;
+import org.apache.james.mailbox.store.mail.model.MessageAttachment;
 import org.apache.james.mailbox.store.mail.model.impl.MessageParser;
 import org.apache.james.mailbox.store.mail.model.impl.PropertyBuilder;
 import org.apache.james.mailbox.store.mail.model.impl.SimpleMailboxMessage;
@@ -383,7 +383,7 @@ public class StoreMessageManager implements org.apache.james.mailbox.MessageMana
             contentIn = new SharedFileInputStream(file);
             final int size = (int) file.length();
 
-            final List<Attachment> attachments = extractAttachments(contentIn);
+            final List<MessageAttachment> attachments = extractAttachments(contentIn);
             final MailboxMessage message = createMessage(internalDate, size, bodyStartOctet, contentIn, flags, propertyBuilder, attachments);
 
             new QuotaChecker(quotaManager, quotaRootResolver, mailbox).tryAddition(1, size);
@@ -423,7 +423,7 @@ public class StoreMessageManager implements org.apache.james.mailbox.MessageMana
 
     }
 
-    private List<Attachment> extractAttachments(SharedFileInputStream contentIn) {
+    private List<MessageAttachment> extractAttachments(SharedFileInputStream contentIn) {
         try {
             return messageParser.retrieveAttachments(contentIn);
         } catch (Exception e) {
@@ -444,12 +444,8 @@ public class StoreMessageManager implements org.apache.james.mailbox.MessageMana
      * @return membership
      * @throws MailboxException
      */
-    protected MailboxMessage createMessage(Date internalDate, int size, int bodyStartOctet, SharedInputStream content, Flags flags, PropertyBuilder propertyBuilder, List<Attachment> attachments) throws MailboxException {
-        ImmutableList.Builder<AttachmentId> attachmentsIds = ImmutableList.builder();
-        for (Attachment attachment: attachments) {
-            attachmentsIds.add(attachment.getAttachmentId());
-        }
-        return new SimpleMailboxMessage(internalDate, size, bodyStartOctet, content, flags, propertyBuilder, getMailboxEntity().getMailboxId(), attachmentsIds.build());
+    protected MailboxMessage createMessage(Date internalDate, int size, int bodyStartOctet, SharedInputStream content, Flags flags, PropertyBuilder propertyBuilder, List<MessageAttachment> attachments) throws MailboxException {
+        return new SimpleMailboxMessage(internalDate, size, bodyStartOctet, content, flags, propertyBuilder, getMailboxEntity().getMailboxId(), attachments);
     }
 
     /**
@@ -635,13 +631,17 @@ public class StoreMessageManager implements org.apache.james.mailbox.MessageMana
         }, true);
     }
 
-    protected MessageMetaData appendMessageToStore(final MailboxMessage message, final List<Attachment> attachments, MailboxSession session) throws MailboxException {
+    protected MessageMetaData appendMessageToStore(final MailboxMessage message, final List<MessageAttachment> messageAttachments, MailboxSession session) throws MailboxException {
         final MessageMapper messageMapper = mapperFactory.getMessageMapper(session);
         final AttachmentMapper attachmentMapper = mapperFactory.getAttachmentMapper(session);
         return mapperFactory.getMessageMapper(session).execute(new Mapper.Transaction<MessageMetaData>() {
 
             public MessageMetaData run() throws MailboxException {
-                attachmentMapper.storeAttachments(attachments);
+                ImmutableList.Builder<Attachment> attachments = ImmutableList.builder();
+                for (MessageAttachment attachment : messageAttachments) {
+                    attachments.add(attachment.getAttachment());
+                }
+                attachmentMapper.storeAttachments(attachments.build());
                 return messageMapper.add(getMailboxEntity(), message);
             }
 

http://git-wip-us.apache.org/repos/asf/james-project/blob/896bc961/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/AttachmentMapper.java
----------------------------------------------------------------------
diff --git a/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/AttachmentMapper.java b/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/AttachmentMapper.java
index e7386da..946a460 100644
--- a/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/AttachmentMapper.java
+++ b/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/AttachmentMapper.java
@@ -19,6 +19,7 @@
 package org.apache.james.mailbox.store.mail;
 
 import java.util.Collection;
+import java.util.List;
 
 import org.apache.james.mailbox.exception.AttachmentNotFoundException;
 import org.apache.james.mailbox.exception.MailboxException;
@@ -30,6 +31,8 @@ public interface AttachmentMapper extends Mapper {
 
     Attachment getAttachment(AttachmentId attachmentId) throws AttachmentNotFoundException;
 
+    List<Attachment> getAttachments(List<AttachmentId> attachmentIds);
+
     void storeAttachment(Attachment attachment) throws MailboxException;
 
     void storeAttachments(Collection<Attachment> attachments) throws MailboxException;

http://git-wip-us.apache.org/repos/asf/james-project/blob/896bc961/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/NoopAttachmentMapper.java
----------------------------------------------------------------------
diff --git a/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/NoopAttachmentMapper.java b/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/NoopAttachmentMapper.java
index e783174..36000e8 100644
--- a/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/NoopAttachmentMapper.java
+++ b/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/NoopAttachmentMapper.java
@@ -20,6 +20,7 @@
 package org.apache.james.mailbox.store.mail;
 
 import java.util.Collection;
+import java.util.List;
 
 import org.apache.james.mailbox.exception.AttachmentNotFoundException;
 import org.apache.james.mailbox.exception.MailboxException;
@@ -44,6 +45,11 @@ public class NoopAttachmentMapper implements AttachmentMapper {
     }
 
     @Override
+    public List<Attachment> getAttachments(List<AttachmentId> attachmentIds) {
+        return null;
+    }
+
+    @Override
     public void storeAttachment(Attachment attachment) throws MailboxException {
     }
 

http://git-wip-us.apache.org/repos/asf/james-project/blob/896bc961/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/DelegatingMailboxMessage.java
----------------------------------------------------------------------
diff --git a/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/DelegatingMailboxMessage.java b/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/DelegatingMailboxMessage.java
index c8bc67e..828ba56 100644
--- a/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/DelegatingMailboxMessage.java
+++ b/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/DelegatingMailboxMessage.java
@@ -117,7 +117,7 @@ public abstract class DelegatingMailboxMessage implements MailboxMessage {
     }
 
     @Override
-    public List<AttachmentId> getAttachmentsIds() {
-        return message.getAttachmentsIds();
+    public List<MessageAttachment> getAttachments() {
+        return message.getAttachments();
     }
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/896bc961/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/Message.java
----------------------------------------------------------------------
diff --git a/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/Message.java b/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/Message.java
index 4d3999b..dbe2a04 100644
--- a/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/Message.java
+++ b/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/Message.java
@@ -105,10 +105,10 @@ public interface Message {
     List<Property> getProperties();
     
     /**
-     * Return the list of ids of parsed attachments
+     * Return the list of attachments
      * 
-     * @return a read only list of attachments ids
+     * @return a read only list of attachments
      */
-    List<AttachmentId> getAttachmentsIds();
+    List<MessageAttachment> getAttachments();
 
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/896bc961/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/MessageAttachment.java
----------------------------------------------------------------------
diff --git a/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/MessageAttachment.java b/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/MessageAttachment.java
new file mode 100644
index 0000000..6004e92
--- /dev/null
+++ b/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/MessageAttachment.java
@@ -0,0 +1,123 @@
+/****************************************************************
+ * 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.mailbox.store.mail.model;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.MoreObjects;
+import com.google.common.base.Objects;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+
+public class MessageAttachment {
+
+    public static Builder builder() {
+        return new Builder();
+    }
+
+    public static class Builder {
+
+        private Attachment attachment;
+        private Optional<String> cid;
+        private Boolean isInline;
+
+        private Builder() {
+            cid = Optional.absent();
+        }
+
+        public Builder attachment(Attachment attachment) {
+            Preconditions.checkArgument(attachment != null);
+            this.attachment = attachment;
+            return this;
+        }
+
+        public Builder cid(String cid) {
+            this.cid = Optional.fromNullable(cid);
+            return this;
+        }
+
+        public Builder isInline(boolean isInline) {
+            this.isInline = isInline;
+            return this;
+        }
+
+        public MessageAttachment build() {
+            Preconditions.checkState(attachment != null, "'attachment' is mandatory");
+            if (isInline == null) {
+                isInline = false;
+            }
+            if (isInline && !cid.isPresent()) {
+                throw new IllegalStateException("'cid' is mandatory for inline attachments");
+            }
+            return new MessageAttachment(attachment, cid, isInline);
+        }
+    }
+
+    private final Attachment attachment;
+    private final Optional<String> cid;
+    private final boolean isInline;
+
+    @VisibleForTesting MessageAttachment(Attachment attachment, Optional<String> cid, boolean isInline) {
+        this.attachment = attachment;
+        this.cid = cid;
+        this.isInline = isInline;
+    }
+
+    public Attachment getAttachment() {
+        return attachment;
+    }
+
+    public AttachmentId getAttachmentId() {
+        return attachment.getAttachmentId();
+    }
+
+    public Optional<String> getCid() {
+        return cid;
+    }
+
+    public boolean isInline() {
+        return isInline;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj instanceof MessageAttachment) {
+            MessageAttachment other = (MessageAttachment) obj;
+            return Objects.equal(attachment, other.attachment)
+                && Objects.equal(cid, other.cid)
+                && Objects.equal(isInline, other.isInline);
+        }
+        return false;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(attachment, cid, isInline);
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects
+                .toStringHelper(this)
+                .add("attachment", attachment)
+                .add("cid", cid)
+                .add("isInline", isInline)
+                .toString();
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/896bc961/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/impl/MessageParser.java
----------------------------------------------------------------------
diff --git a/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/impl/MessageParser.java b/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/impl/MessageParser.java
index 56099ff..dd99f29 100644
--- a/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/impl/MessageParser.java
+++ b/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/impl/MessageParser.java
@@ -25,13 +25,16 @@ import java.io.InputStream;
 import java.util.List;
 
 import org.apache.james.mailbox.store.mail.model.Attachment;
+import org.apache.james.mailbox.store.mail.model.MessageAttachment;
 import org.apache.james.mime4j.MimeException;
 import org.apache.james.mime4j.dom.Body;
 import org.apache.james.mime4j.dom.Entity;
 import org.apache.james.mime4j.dom.MessageWriter;
 import org.apache.james.mime4j.dom.Multipart;
 import org.apache.james.mime4j.dom.field.ContentDispositionField;
+import org.apache.james.mime4j.dom.field.ContentIdField;
 import org.apache.james.mime4j.dom.field.ContentTypeField;
+import org.apache.james.mime4j.dom.field.ParsedField;
 import org.apache.james.mime4j.message.DefaultMessageBuilder;
 import org.apache.james.mime4j.message.DefaultMessageWriter;
 import org.apache.james.mime4j.stream.Field;
@@ -42,10 +45,16 @@ import com.google.common.collect.ImmutableList;
 
 public class MessageParser {
 
+    private static final String TEXT_MEDIA_TYPE = "text";
     private static final String CONTENT_TYPE = "Content-Type";
+    private static final String CONTENT_ID = "Content-ID";
+    private static final String CONTENT_DISPOSITION = "Content-Disposition";
     private static final String DEFAULT_CONTENT_TYPE = "application/octet-stream";
+    private static final List<String> ATTACHMENT_CONTENT_DISPOSITIONS = ImmutableList.of(
+            ContentDispositionField.DISPOSITION_TYPE_ATTACHMENT.toLowerCase(),
+            ContentDispositionField.DISPOSITION_TYPE_INLINE.toLowerCase());
 
-    public List<Attachment> retrieveAttachments(InputStream fullContent) throws MimeException, IOException {
+    public List<MessageAttachment> retrieveAttachments(InputStream fullContent) throws MimeException, IOException {
         Body body = new DefaultMessageBuilder()
                 .parseMessage(fullContent)
                 .getBody();
@@ -60,25 +69,51 @@ public class MessageParser {
         }
     }
 
-    private List<Attachment> listAttachments(Multipart multipart) throws IOException {
-        ImmutableList.Builder<Attachment> attachments = ImmutableList.builder();
+    private List<MessageAttachment> listAttachments(Multipart multipart) throws IOException {
+        ImmutableList.Builder<MessageAttachment> attachments = ImmutableList.builder();
         MessageWriter messageWriter = new DefaultMessageWriter();
         for (Entity entity : multipart.getBodyParts()) {
-            if (isAttachment(entity)) {
-                Optional<ContentTypeField> contentTypeField = contentTypeField(entity.getHeader().getField(CONTENT_TYPE));
-                Optional<String> contentType = contentType(contentTypeField);
-                Optional<String> name = name(contentTypeField);
-                
-                attachments.add(Attachment.builder()
-                        .bytes(getBytes(messageWriter, entity.getBody()))
-                        .type(contentType.or(DEFAULT_CONTENT_TYPE))
-                        .name(name)
-                        .build());
+            if (entity.isMultipart() && entity.getBody() instanceof Multipart) {
+                attachments.addAll(listAttachments((Multipart) entity.getBody()));
+            } else {
+                if (isAttachment(entity)) {
+                    attachments.add(retrieveAttachment(messageWriter, entity));
+                }
             }
         }
         return attachments.build();
     }
 
+    private MessageAttachment retrieveAttachment(MessageWriter messageWriter, Entity entity) throws IOException {
+        Optional<ContentTypeField> contentTypeField = getContentTypeField(entity);
+        Optional<String> contentType = contentType(contentTypeField);
+        Optional<String> name = name(contentTypeField);
+        Optional<String> cid = cid(castField(entity.getHeader().getField(CONTENT_ID), ContentIdField.class));
+        boolean isInline = isInline(castField(entity.getHeader().getField(CONTENT_DISPOSITION), ContentDispositionField.class));
+
+        return MessageAttachment.builder()
+                .attachment(Attachment.builder()
+                    .bytes(getBytes(messageWriter, entity.getBody()))
+                    .type(contentType.or(DEFAULT_CONTENT_TYPE))
+                    .name(name)
+                    .build())
+                .cid(cid.orNull())
+                .isInline(isInline)
+                .build();
+    }
+
+    private Optional<ContentTypeField> getContentTypeField(Entity entity) {
+        return castField(entity.getHeader().getField(CONTENT_TYPE), ContentTypeField.class);
+    }
+
+    @SuppressWarnings("unchecked")
+    private <U extends ParsedField> Optional<U> castField(Field field, Class<U> clazz) {
+        if (field == null || !clazz.isInstance(field)) {
+            return Optional.absent();
+        }
+        return Optional.of((U) field);
+    }
+
     private Optional<String> contentType(Optional<ContentTypeField> contentTypeField) {
         return contentTypeField.transform(new Function<ContentTypeField, Optional<String>>() {
             @Override
@@ -97,15 +132,47 @@ public class MessageParser {
         }).or(Optional.<String> absent());
     }
 
-    private Optional<ContentTypeField> contentTypeField(Field contentType) {
-        if (contentType == null || !(contentType instanceof ContentTypeField)) {
-            return Optional.absent();
-        }
-        return Optional.of((ContentTypeField) contentType);
+    private Optional<String> cid(Optional<ContentIdField> contentIdField) {
+        return contentIdField.transform(new Function<ContentIdField, Optional<String>>() {
+            @Override
+            public Optional<String> apply(ContentIdField field) {
+                return Optional.fromNullable(field.getId());
+            }
+        }).or(Optional.<String> absent());
+    }
+
+    private boolean isInline(Optional<ContentDispositionField> contentDispositionField) {
+        return contentDispositionField.transform(new Function<ContentDispositionField, Boolean>() {
+            @Override
+            public Boolean apply(ContentDispositionField field) {
+                return field.isInline();
+            }
+        }).or(false);
     }
 
     private boolean isAttachment(Entity part) {
-        return ContentDispositionField.DISPOSITION_TYPE_ATTACHMENT.equalsIgnoreCase(part.getDispositionType());
+        if (isTextPart(part)) {
+            return false;
+        }
+        return Optional.fromNullable(part.getDispositionType())
+                .transform(new Function<String, Boolean>() {
+
+                    @Override
+                    public Boolean apply(String dispositionType) {
+                        return ATTACHMENT_CONTENT_DISPOSITIONS.contains(dispositionType.toLowerCase());
+                    }
+                }).isPresent();
+    }
+
+    private boolean isTextPart(Entity part) {
+        Optional<ContentTypeField> contentTypeField = getContentTypeField(part);
+        if (contentTypeField.isPresent()) {
+            String mediaType = contentTypeField.get().getMediaType();
+            if (mediaType != null && mediaType.equals(TEXT_MEDIA_TYPE)) {
+                return true;
+            }
+        }
+        return false;
     }
 
     private byte[] getBytes(MessageWriter messageWriter, Body body) throws IOException {

http://git-wip-us.apache.org/repos/asf/james-project/blob/896bc961/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/impl/SimpleMailboxMessage.java
----------------------------------------------------------------------
diff --git a/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/impl/SimpleMailboxMessage.java b/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/impl/SimpleMailboxMessage.java
index 0122cb1..f7c7c80 100644
--- a/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/impl/SimpleMailboxMessage.java
+++ b/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/impl/SimpleMailboxMessage.java
@@ -29,10 +29,10 @@ import javax.mail.util.SharedByteArrayInputStream;
 
 import org.apache.commons.io.IOUtils;
 import org.apache.james.mailbox.exception.MailboxException;
-import org.apache.james.mailbox.store.mail.model.AttachmentId;
 import org.apache.james.mailbox.store.mail.model.DelegatingMailboxMessage;
 import org.apache.james.mailbox.store.mail.model.MailboxId;
 import org.apache.james.mailbox.store.mail.model.MailboxMessage;
+import org.apache.james.mailbox.store.mail.model.MessageAttachment;
 
 import com.google.common.base.MoreObjects;
 import com.google.common.collect.ImmutableList;
@@ -48,7 +48,7 @@ public class SimpleMailboxMessage extends DelegatingMailboxMessage {
         int bodyStartOctet = Ints.checkedCast(original.getFullContentOctets() - original.getBodyOctets());
         PropertyBuilder pBuilder = new PropertyBuilder(original.getProperties());
         pBuilder.setTextualLineCount(original.getTextualLineCount());
-        return new SimpleMailboxMessage(internalDate, size, bodyStartOctet, content, flags, pBuilder, mailboxId, original.getAttachmentsIds());
+        return new SimpleMailboxMessage(internalDate, size, bodyStartOctet, content, flags, pBuilder, mailboxId, original.getAttachments());
     }
 
     private static SharedByteArrayInputStream copyFullContent(MailboxMessage original) throws MailboxException {
@@ -72,14 +72,14 @@ public class SimpleMailboxMessage extends DelegatingMailboxMessage {
 
     public SimpleMailboxMessage(Date internalDate, long size, int bodyStartOctet,
             SharedInputStream content, Flags flags,
-            PropertyBuilder propertyBuilder, MailboxId mailboxId, List<AttachmentId> attachmentsIds) {
+            PropertyBuilder propertyBuilder, MailboxId mailboxId, List<MessageAttachment> attachments) {
         super(new SimpleMessage(
                 content, size, internalDate, propertyBuilder.getSubType(),
                 propertyBuilder.getMediaType(),
                 bodyStartOctet,
                 propertyBuilder.getTextualLineCount(),
                 propertyBuilder.toProperties(),
-                attachmentsIds
+                attachments
                 ));
 
             setFlags(flags);
@@ -92,7 +92,7 @@ public class SimpleMailboxMessage extends DelegatingMailboxMessage {
                                 PropertyBuilder propertyBuilder, MailboxId mailboxId) {
         this(internalDate, size, bodyStartOctet,
                 content, flags,
-                propertyBuilder, mailboxId, ImmutableList.<AttachmentId>of());
+                propertyBuilder, mailboxId, ImmutableList.<MessageAttachment>of());
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/james-project/blob/896bc961/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/impl/SimpleMessage.java
----------------------------------------------------------------------
diff --git a/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/impl/SimpleMessage.java b/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/impl/SimpleMessage.java
index d77571e..19c98d2 100644
--- a/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/impl/SimpleMessage.java
+++ b/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/impl/SimpleMessage.java
@@ -25,8 +25,8 @@ import java.util.List;
 
 import javax.mail.internet.SharedInputStream;
 
-import org.apache.james.mailbox.store.mail.model.AttachmentId;
 import org.apache.james.mailbox.store.mail.model.Message;
+import org.apache.james.mailbox.store.mail.model.MessageAttachment;
 import org.apache.james.mailbox.store.mail.model.MessageId;
 import org.apache.james.mailbox.store.mail.model.Property;
 
@@ -42,9 +42,9 @@ public class SimpleMessage implements Message {
     private final long size;
     private final Long textualLineCount;
     private final List<Property> properties;
-    private final List<AttachmentId> attachmentsIds;
+    private final List<MessageAttachment> attachments;
 
-    public SimpleMessage(SharedInputStream content, long size, Date internalDate, String subType, String mediaType, int bodyStartOctet, Long textualLineCount, List<Property> properties, List<AttachmentId> attachmentsIds) {
+    public SimpleMessage(SharedInputStream content, long size, Date internalDate, String subType, String mediaType, int bodyStartOctet, Long textualLineCount, List<Property> properties, List<MessageAttachment> attachments) {
         this.subType = subType;
         this.mediaType = mediaType;
         this.content = content;
@@ -53,11 +53,11 @@ public class SimpleMessage implements Message {
         this.size = size;
         this.textualLineCount = textualLineCount;
         this.properties = properties;
-        this.attachmentsIds = attachmentsIds;
+        this.attachments = attachments;
     }
 
     public SimpleMessage(SharedInputStream content, long size, Date internalDate, String subType, String mediaType, int bodyStartOctet, Long textualLineCount, List<Property> properties) {
-        this(content, size, internalDate, subType, mediaType, bodyStartOctet, textualLineCount, properties, ImmutableList.<AttachmentId>of());
+        this(content, size, internalDate, subType, mediaType, bodyStartOctet, textualLineCount, properties, ImmutableList.<MessageAttachment>of());
     }
 
     @Override
@@ -120,7 +120,7 @@ public class SimpleMessage implements Message {
     }
 
     @Override
-    public List<AttachmentId> getAttachmentsIds() {
-        return attachmentsIds;
+    public List<MessageAttachment> getAttachments() {
+        return attachments;
     }
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/896bc961/mailbox/store/src/test/java/org/apache/james/mailbox/store/AbstractMailboxManagerAttachmentTest.java
----------------------------------------------------------------------
diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/AbstractMailboxManagerAttachmentTest.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/AbstractMailboxManagerAttachmentTest.java
index 5f14fda..9527afa 100644
--- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/AbstractMailboxManagerAttachmentTest.java
+++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/AbstractMailboxManagerAttachmentTest.java
@@ -41,9 +41,9 @@ import org.apache.james.mailbox.store.mail.AttachmentMapper;
 import org.apache.james.mailbox.store.mail.MailboxMapper;
 import org.apache.james.mailbox.store.mail.MessageMapper;
 import org.apache.james.mailbox.store.mail.MessageMapper.FetchType;
-import org.apache.james.mailbox.store.mail.model.AttachmentId;
 import org.apache.james.mailbox.store.mail.model.Mailbox;
 import org.apache.james.mailbox.store.mail.model.MailboxMessage;
+import org.apache.james.mailbox.store.mail.model.MessageAttachment;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -96,41 +96,41 @@ public abstract class AbstractMailboxManagerAttachmentTest {
         
         Iterator<MailboxMessage> messages = messageMapper.findInMailbox(inbox, MessageRange.all(), FetchType.Full, 1);
         assertThat(messages.hasNext()).isTrue();
-        assertThat(messages.next().getAttachmentsIds()).isEmpty();
+        assertThat(messages.next().getAttachments()).isEmpty();
     }
 
     @Test
     public void appendMessageShouldStoreAttachmentWhenMailWithOneAttachment() throws Exception {
-        InputStream mailInputStream = ClassLoader.getSystemResourceAsStream("eml/oneAttachmentAndSomeInlined.eml");
+        InputStream mailInputStream = ClassLoader.getSystemResourceAsStream("eml/oneAttachmentAndSomeTextInlined.eml");
         inboxMessageManager.appendMessage(mailInputStream, SUN_SEP_9TH_2001, mailboxSession, true, new Flags(Flags.Flag.RECENT));
         
         Iterator<MailboxMessage> messages = messageMapper.findInMailbox(inbox, MessageRange.all(), FetchType.Full, 1);
         assertThat(messages.hasNext()).isTrue();
-        assertThat(messages.next().getAttachmentsIds()).hasSize(1);
+        assertThat(messages.next().getAttachments()).hasSize(1);
     }
 
     @Test
     public void appendMessageShouldStoreAttachmentNameWhenMailWithOneAttachment() throws Exception {
-        InputStream mailInputStream = ClassLoader.getSystemResourceAsStream("eml/oneAttachmentAndSomeInlined.eml");
+        InputStream mailInputStream = ClassLoader.getSystemResourceAsStream("eml/oneAttachmentAndSomeTextInlined.eml");
         inboxMessageManager.appendMessage(mailInputStream, SUN_SEP_9TH_2001, mailboxSession, true, new Flags(Flags.Flag.RECENT));
 
         Optional<String> expectedName = Optional.of("exploits_of_a_mom.png");
 
         Iterator<MailboxMessage> messages = messageMapper.findInMailbox(inbox, MessageRange.all(), FetchType.Full, 1);
-        List<AttachmentId> attachmentsIds = messages.next().getAttachmentsIds();
-        assertThat(attachmentMapper.getAttachment(attachmentsIds.get(0)).getName()).isEqualTo(expectedName);
+        List<MessageAttachment> attachments = messages.next().getAttachments();
+        assertThat(attachmentMapper.getAttachment(attachments.get(0).getAttachmentId()).getName()).isEqualTo(expectedName);
     }
 
     @Test
     public void appendMessageShouldStoreARetrievableAttachmentWhenMailWithOneAttachment() throws Exception {
-        InputStream mailInputStream = ClassLoader.getSystemResourceAsStream("eml/oneAttachmentAndSomeInlined.eml");
+        InputStream mailInputStream = ClassLoader.getSystemResourceAsStream("eml/oneAttachmentAndSomeTextInlined.eml");
         inboxMessageManager.appendMessage(mailInputStream, SUN_SEP_9TH_2001, mailboxSession, true, new Flags(Flags.Flag.RECENT));
         
         Iterator<MailboxMessage> messages = messageMapper.findInMailbox(inbox, MessageRange.all(), FetchType.Full, 1);
         assertThat(messages.hasNext()).isTrue();
-        List<AttachmentId> attachmentsIds = messages.next().getAttachmentsIds();
-        assertThat(attachmentsIds).hasSize(1);
-        assertThat(attachmentMapper.getAttachment(attachmentsIds.get(0)).getStream())
+        List<MessageAttachment> attachments = messages.next().getAttachments();
+        assertThat(attachments).hasSize(1);
+        assertThat(attachmentMapper.getAttachment(attachments.get(0).getAttachmentId()).getStream())
             .hasContentEqualTo(ClassLoader.getSystemResourceAsStream("eml/gimp.png"));
     }
 
@@ -141,7 +141,7 @@ public abstract class AbstractMailboxManagerAttachmentTest {
         
         Iterator<MailboxMessage> messages = messageMapper.findInMailbox(inbox, MessageRange.all(), FetchType.Full, 1);
         assertThat(messages.hasNext()).isTrue();
-        assertThat(messages.next().getAttachmentsIds()).hasSize(2);
+        assertThat(messages.next().getAttachments()).hasSize(2);
     }
 
     @Test
@@ -151,11 +151,11 @@ public abstract class AbstractMailboxManagerAttachmentTest {
         
         Iterator<MailboxMessage> messages = messageMapper.findInMailbox(inbox, MessageRange.all(), FetchType.Full, 1);
         assertThat(messages.hasNext()).isTrue();
-        List<AttachmentId> attachmentsIds = messages.next().getAttachmentsIds();
-        assertThat(attachmentsIds).hasSize(2);
-        assertThat(attachmentMapper.getAttachment(attachmentsIds.get(0)).getStream())
+        List<MessageAttachment> attachments = messages.next().getAttachments();
+        assertThat(attachments).hasSize(2);
+        assertThat(attachmentMapper.getAttachment(attachments.get(0).getAttachmentId()).getStream())
             .hasContentEqualTo(ClassLoader.getSystemResourceAsStream("eml/4037_014.jpg"));
-        assertThat(attachmentMapper.getAttachment(attachmentsIds.get(1)).getStream())
+        assertThat(attachmentMapper.getAttachment(attachments.get(1).getAttachmentId()).getStream())
             .hasContentEqualTo(ClassLoader.getSystemResourceAsStream("eml/4037_015.jpg"));
     }
 
@@ -166,7 +166,7 @@ public abstract class AbstractMailboxManagerAttachmentTest {
         
         Iterator<MailboxMessage> messages = messageMapper.findInMailbox(inbox, MessageRange.all(), FetchType.Full, 1);
         assertThat(messages.hasNext()).isTrue();
-        assertThat(messages.next().getAttachmentsIds()).hasSize(1);
+        assertThat(messages.next().getAttachments()).hasSize(1);
     }
 
     @Test
@@ -178,14 +178,14 @@ public abstract class AbstractMailboxManagerAttachmentTest {
 
         Iterator<MailboxMessage> messages = messageMapper.findInMailbox(inbox, MessageRange.all(), FetchType.Full, 1);
         assertThat(messages.hasNext()).isTrue();
-        List<AttachmentId> attachmentsIds = messages.next().getAttachmentsIds();
-        assertThat(attachmentsIds).hasSize(0);
+        List<MessageAttachment> attachments = messages.next().getAttachments();
+        assertThat(attachments).hasSize(0);
     }
 
     @Test
     public void appendMessageShouldStoreOnceWhenDuplicateAttachment() throws Exception {
-        InputStream mailInputStream = ClassLoader.getSystemResourceAsStream("eml/oneAttachmentAndSomeInlined.eml");
-        InputStream mailInputStream2 = ClassLoader.getSystemResourceAsStream("eml/oneAttachmentAndSomeInlined.eml");
+        InputStream mailInputStream = ClassLoader.getSystemResourceAsStream("eml/oneAttachmentAndSomeTextInlined.eml");
+        InputStream mailInputStream2 = ClassLoader.getSystemResourceAsStream("eml/oneAttachmentAndSomeTextInlined.eml");
         String user2 = "user2@domain.tld";
         MailboxSession user2MailboxSession = new MockMailboxSession(user2);
         MessageMapper user2MessageMapper = getMailboxSessionMapperFactory().getMessageMapper(user2MailboxSession);
@@ -201,11 +201,11 @@ public abstract class AbstractMailboxManagerAttachmentTest {
         Iterator<MailboxMessage> messages = messageMapper.findInMailbox(inbox, MessageRange.all(), FetchType.Full, 1);
         Iterator<MailboxMessage> user2Messages = user2MessageMapper.findInMailbox(user2Inbox, MessageRange.all(), FetchType.Full, 1);
         assertThat(messages.hasNext()).isTrue();
-        List<AttachmentId> attachmentsIds = messages.next().getAttachmentsIds();
-        assertThat(attachmentsIds).hasSize(1);
+        List<MessageAttachment> attachments = messages.next().getAttachments();
+        assertThat(attachments).hasSize(1);
         assertThat(user2Messages.hasNext()).isTrue();
-        List<AttachmentId> user2AttachmentsIds = user2Messages.next().getAttachmentsIds();
-        assertThat(attachmentsIds.equals(user2AttachmentsIds)).isTrue();
+        List<MessageAttachment> user2Attachments = user2Messages.next().getAttachments();
+        assertThat(attachments.equals(user2Attachments)).isTrue();
     }
 }
 

http://git-wip-us.apache.org/repos/asf/james-project/blob/896bc961/mailbox/store/src/test/java/org/apache/james/mailbox/store/SimpleMailboxMembership.java
----------------------------------------------------------------------
diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/SimpleMailboxMembership.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/SimpleMailboxMembership.java
index 4d1eb4f..28fad25 100644
--- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/SimpleMailboxMembership.java
+++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/SimpleMailboxMembership.java
@@ -36,9 +36,9 @@ import java.util.Map.Entry;
 import javax.mail.Flags;
 
 import org.apache.commons.lang.NotImplementedException;
-import org.apache.james.mailbox.store.mail.model.AttachmentId;
 import org.apache.james.mailbox.store.mail.model.DefaultMessageId;
 import org.apache.james.mailbox.store.mail.model.MailboxMessage;
+import org.apache.james.mailbox.store.mail.model.MessageAttachment;
 import org.apache.james.mailbox.store.mail.model.Property;
 
 public class SimpleMailboxMembership implements MailboxMessage {
@@ -274,7 +274,7 @@ public class SimpleMailboxMembership implements MailboxMessage {
     }
 
     @Override
-    public List<AttachmentId> getAttachmentsIds() {
+    public List<MessageAttachment> getAttachments() {
         throw new NotImplementedException("Attachments Ids not implemented");
     }
     

http://git-wip-us.apache.org/repos/asf/james-project/blob/896bc961/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/AttachmentMapperTest.java
----------------------------------------------------------------------
diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/AttachmentMapperTest.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/AttachmentMapperTest.java
index 39b26e6..830cbf5 100644
--- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/AttachmentMapperTest.java
+++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/AttachmentMapperTest.java
@@ -21,6 +21,8 @@ package org.apache.james.mailbox.store.mail.model;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
+import java.util.List;
+
 import org.apache.james.mailbox.exception.AttachmentNotFoundException;
 import org.apache.james.mailbox.exception.MailboxException;
 import org.apache.james.mailbox.store.mail.AttachmentMapper;
@@ -102,4 +104,40 @@ public class AttachmentMapperTest<T extends MapperProvider> {
         assertThat(attachment1).isEqualTo(expected1);
         assertThat(attachment2).isEqualTo(expected2);
     }
+
+    @ContractTest
+    public void getAttachmentsShouldThrowWhenNullAttachmentId() throws Exception {
+        expected.expect(IllegalArgumentException.class);
+        attachmentMapper.getAttachments(null);
+    }
+
+    @ContractTest
+    public void getAttachmentsShouldReturnEmptyListWhenNonReferencedAttachmentId() throws Exception {
+        List<Attachment> attachments = attachmentMapper.getAttachments(ImmutableList.of(AttachmentId.forPayload("unknown".getBytes(Charsets.UTF_8))));
+
+        assertThat(attachments).isEmpty();
+    }
+
+    @ContractTest
+    public void getAttachmentsShouldReturnTheAttachmentsWhenSome() throws Exception {
+        //Given
+        Attachment expected = Attachment.builder()
+                .bytes("payload".getBytes(Charsets.UTF_8))
+                .type("content")
+                .build();
+        AttachmentId attachmentId = expected.getAttachmentId();
+        attachmentMapper.storeAttachment(expected);
+
+        Attachment expected2 = Attachment.builder()
+                .bytes("payload2".getBytes(Charsets.UTF_8))
+                .type("content")
+                .build();
+        AttachmentId attachmentId2 = expected2.getAttachmentId();
+        attachmentMapper.storeAttachment(expected2);
+
+        //When
+        List<Attachment> attachments = attachmentMapper.getAttachments(ImmutableList.of(attachmentId, attachmentId2));
+        //Then
+        assertThat(attachments).contains(expected, expected2);
+    }
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/896bc961/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageAssert.java
----------------------------------------------------------------------
diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageAssert.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageAssert.java
index ab7a8bb..b002da4 100644
--- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageAssert.java
+++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageAssert.java
@@ -75,8 +75,8 @@ public class MessageAssert extends AbstractAssert<MessageAssert, MailboxMessage>
             }
         }
         if (usedFetchType == MessageMapper.FetchType.Full || usedFetchType == MessageMapper.FetchType.Body) {
-            if (!Objects.equal(actual.getAttachmentsIds(), expected.getAttachmentsIds())) {
-                failWithMessage("Expected attachments ids to be <%s> but was <%s>", expected.getAttachmentsIds(), actual.getAttachmentsIds());
+            if (!Objects.equal(actual.getAttachments(), expected.getAttachments())) {
+                failWithMessage("Expected attachments to be <%s> but was <%s>", expected.getAttachments(), actual.getAttachments());
             }
         }
         return this;


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