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/07 11:47:47 UTC

[4/4] james-project git commit: JAMES-1716 Saving to draft should not send message

JAMES-1716 Saving to draft should not send message

providing both an outside integration test and some unit tests (SetMessageCreationProcessorTest)


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

Branch: refs/heads/master
Commit: d59881815c9c5fcee73addb2a2562c28f3491e16
Parents: fe2c10b
Author: Matthieu Baechler <ma...@linagora.com>
Authored: Mon Jul 4 16:36:05 2016 +0200
Committer: Antoine Duprat <ad...@linagora.com>
Committed: Thu Jul 7 12:04:36 2016 +0200

----------------------------------------------------------------------
 .../store/mail/model/impl/SimpleMailbox.java    |   9 +-
 .../java/org/apache/james/jmap/JMAPModule.java  |   5 +-
 .../integration/SetMessagesMethodTest.java      | 110 +++++++-
 .../java/org/apache/james/jmap/JMAPServlet.java |   4 +
 .../jmap/methods/MIMEMessageConverter.java      |  14 +-
 .../MailboxInvalidMessageCreationException.java |  26 ++
 .../methods/MailboxNotImplementedException.java |  30 ++
 .../MailboxSendingNotAllowedException.java      |  38 +++
 .../james/jmap/methods/MessageWithId.java       |  49 ----
 .../methods/SetMessagesCreationProcessor.java   | 275 ++++++++++---------
 .../apache/james/jmap/methods/ValueWithId.java  |  63 +++++
 .../james/jmap/model/CreationMessage.java       |  17 +-
 .../org/apache/james/jmap/model/Message.java    |   8 +-
 .../org/apache/james/jmap/model/SetError.java   |  14 +
 .../james/jmap/model/SetMessagesRequest.java    |  30 +-
 .../james/jmap/model/SetMessagesResponse.java   |  14 +
 .../james/jmap/send/PostDequeueDecorator.java   |   2 +-
 .../exception/MailboxRoleNotFoundException.java |  30 --
 .../jmap/utils/SystemMailboxesProvider.java     |  30 ++
 .../jmap/utils/SystemMailboxesProviderImpl.java |  70 +++++
 .../jmap/methods/MIMEMessageConverterTest.java  |  25 +-
 .../SetMessagesCreationProcessorTest.java       | 268 +++++++++++-------
 .../apache/james/jmap/model/SetErrorTest.java   |  28 +-
 .../jmap/model/SetMessagesRequestTest.java      |   2 +-
 .../jmap/send/PostDequeueDecoratorTest.java     |   2 +-
 .../utils/SystemMailboxesProviderImplTest.java  |  33 +++
 26 files changed, 848 insertions(+), 348 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/d5988181/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/impl/SimpleMailbox.java
----------------------------------------------------------------------
diff --git a/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/impl/SimpleMailbox.java b/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/impl/SimpleMailbox.java
index 05c1ec1..7d70bfd 100644
--- a/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/impl/SimpleMailbox.java
+++ b/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/impl/SimpleMailbox.java
@@ -33,13 +33,18 @@ public class SimpleMailbox implements Mailbox {
     private final long uidValidity;
     private MailboxACL acl = SimpleMailboxACL.EMPTY;
 
-    public SimpleMailbox(MailboxPath path, long uidValidity) {
+    public SimpleMailbox(MailboxPath path, long uidValidity, MailboxId mailboxId) {
+        this.id = mailboxId;
         this.namespace = path.getNamespace();
         this.user = path.getUser();
         this.name = path.getName();
         this.uidValidity = uidValidity;
     }
-    
+
+    public SimpleMailbox(MailboxPath path, long uidValidity) {
+        this(path, uidValidity, null);
+    }
+
     public SimpleMailbox(Mailbox mailbox) {
         this.id = mailbox.getMailboxId();
         this.namespace = mailbox.getNamespace();

http://git-wip-us.apache.org/repos/asf/james-project/blob/d5988181/server/container/guice/guice-common/src/main/java/org/apache/james/jmap/JMAPModule.java
----------------------------------------------------------------------
diff --git a/server/container/guice/guice-common/src/main/java/org/apache/james/jmap/JMAPModule.java b/server/container/guice/guice-common/src/main/java/org/apache/james/jmap/JMAPModule.java
index 6fd9c1f..247c70d 100644
--- a/server/container/guice/guice-common/src/main/java/org/apache/james/jmap/JMAPModule.java
+++ b/server/container/guice/guice-common/src/main/java/org/apache/james/jmap/JMAPModule.java
@@ -30,6 +30,8 @@ import org.apache.james.jmap.mailet.VacationMailet;
 import org.apache.james.jmap.methods.RequestHandler;
 import org.apache.james.jmap.utils.HtmlTextExtractor;
 import org.apache.james.jmap.utils.MailboxBasedHtmlTextExtractor;
+import org.apache.james.jmap.utils.SystemMailboxesProvider;
+import org.apache.james.jmap.utils.SystemMailboxesProviderImpl;
 import org.apache.james.lifecycle.api.Configurable;
 import org.apache.james.mailbox.MailboxManager;
 import org.apache.james.mailetcontainer.impl.MatcherMailetPair;
@@ -64,11 +66,12 @@ public class JMAPModule extends AbstractModule {
 
         bind(HtmlTextExtractor.class).to(MailboxBasedHtmlTextExtractor.class);
         Multibinder.newSetBinder(binder(), ConfigurationPerformer.class).addBinding().to(RequiredCapabilitiesPrecondition.class);
-        Multibinder.newSetBinder(binder(), ConfigurationPerformer.class).addBinding().to(RequiredCapabilitiesPrecondition.class);
 
         Multibinder<CamelMailetContainerModule.TransportProcessorCheck> transportProcessorChecks = Multibinder.newSetBinder(binder(), CamelMailetContainerModule.TransportProcessorCheck.class);
         transportProcessorChecks.addBinding().to(VacationMailetCheck.class);
         transportProcessorChecks.addBinding().to(BccMailetCheck.class);
+        
+        bind(SystemMailboxesProvider.class).to(SystemMailboxesProviderImpl.class);
     }
 
     @Provides

http://git-wip-us.apache.org/repos/asf/james-project/blob/d5988181/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/SetMessagesMethodTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/SetMessagesMethodTest.java b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/SetMessagesMethodTest.java
index ff6ded2..af96309 100644
--- a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/SetMessagesMethodTest.java
+++ b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/SetMessagesMethodTest.java
@@ -23,6 +23,7 @@ import static com.jayway.restassured.RestAssured.given;
 import static com.jayway.restassured.RestAssured.with;
 import static com.jayway.restassured.config.EncoderConfig.encoderConfig;
 import static com.jayway.restassured.config.RestAssuredConfig.newConfig;
+import static org.assertj.core.api.Assertions.assertThat;
 import static org.hamcrest.Matchers.contains;
 import static org.hamcrest.Matchers.empty;
 import static org.hamcrest.Matchers.endsWith;
@@ -128,8 +129,6 @@ public abstract class SetMessagesMethodTest {
                 .findFirst().get();
     }
     
-
-    
     private List<Map<String, String>> getAllMailboxesIds(AccessToken accessToken) {
         return with()
                 .header("Authorization", accessToken.serialize())
@@ -1054,7 +1053,7 @@ public abstract class SetMessagesMethodTest {
             .body(ARGUMENTS + ".notCreated[\""+messageCreationId+"\"].type", equalTo("invalidProperties"))
             .body(ARGUMENTS + ".notCreated[\""+messageCreationId+"\"].properties", hasSize(1))
             .body(ARGUMENTS + ".notCreated[\""+messageCreationId+"\"].properties", contains("from"))
-            .body(ARGUMENTS + ".notCreated[\""+messageCreationId+"\"].description", endsWith("Invalid 'from' field. Must be one of [username@domain.tld]"))
+            .body(ARGUMENTS + ".notCreated[\""+messageCreationId+"\"].description", endsWith("Invalid 'from' field. Must be one of username@domain.tld"))
             .body(ARGUMENTS + ".created", aMapWithSize(0));
     }
 
@@ -1282,10 +1281,10 @@ public abstract class SetMessagesMethodTest {
             .then()
                     .statusCode(200)
                     .body(NAME, equalTo("messageList"))
-                    .body(ARGUMENTS + ".messageIds", hasSize(1))
-            ;
+                    .body(ARGUMENTS + ".messageIds", hasSize(1));
             return true;
-        } catch(AssertionError e) {
+            
+        } catch (AssertionError e) {
             return false;
         }
     }
@@ -1333,6 +1332,101 @@ public abstract class SetMessagesMethodTest {
         calmlyAwait.atMost(30, TimeUnit.SECONDS).until( () -> isHtmlMessageReceived(recipientToken));
     }
 
+
+    @Test
+    public void setMessagesWhenSavingToDraftsShouldNotSendMessage() throws Exception {
+        String sender = username;
+        jmapServer.serverProbe().createMailbox(MailboxConstants.USER_NAMESPACE, sender, "sent");
+        jmapServer.serverProbe().createMailbox(MailboxConstants.USER_NAMESPACE, sender, "drafts");
+        String recipientAddress = "recipient" + "@" + USERS_DOMAIN;
+        String recipientPassword = "password";
+        jmapServer.serverProbe().addUser(recipientAddress, recipientPassword);
+        jmapServer.serverProbe().createMailbox(MailboxConstants.USER_NAMESPACE, recipientAddress, "inbox");
+        await();
+        AccessToken recipientToken = JmapAuthentication.authenticateJamesUser(recipientAddress, recipientPassword);
+
+        String senderDraftsMailboxId = getMailboxId(accessToken, Role.DRAFTS);
+
+        String messageCreationId = "creationId";
+        String fromAddress = username;
+        String requestBody = "[" +
+                "  [" +
+                "    \"setMessages\","+
+                "    {" +
+                "      \"create\": { \"" + messageCreationId  + "\" : {" +
+                "        \"from\": { \"email\": \"" + fromAddress + "\"}," +
+                "        \"to\": [{ \"name\": \"BOB\", \"email\": \"" + recipientAddress + "\"}]," +
+                "        \"cc\": [{ \"name\": \"ALICE\"}]," +
+                "        \"subject\": \"Thank you for joining example.com!\"," +
+                "        \"textBody\": \"Hello someone, and thank you for joining example.com!\"," +
+                "        \"mailboxIds\": [\"" + senderDraftsMailboxId + "\"], " +
+                "        \"isDraft\": false" +
+                "      }}" +
+                "    }," +
+                "    \"#0\"" +
+                "  ]" +
+                "]";
+
+        given()
+            .header("Authorization", this.accessToken.serialize())
+            .body(requestBody)
+        .when()
+            .post("/jmap")
+        .then()
+            .statusCode(200);
+
+        //We need to wait for an async event to not happen, we couldn't found any
+        //robust way to check that.
+        Thread.sleep(TimeUnit.SECONDS.toMillis(5));
+        assertThat(isAnyMessageFoundInRecipientsMailboxes(recipientToken)).isFalse();
+    }
+
+    @Test
+    public void setMessagesWhenSavingToRegularMailboxShouldNotSendMessage() throws Exception {
+        String sender = username;
+        jmapServer.serverProbe().createMailbox(MailboxConstants.USER_NAMESPACE, sender, "sent");
+        jmapServer.serverProbe().createMailbox(MailboxConstants.USER_NAMESPACE, sender, "drafts");
+        jmapServer.serverProbe().createMailbox(MailboxConstants.USER_NAMESPACE, sender, "regular");
+        Mailbox regularMailbox = jmapServer.serverProbe().getMailbox(MailboxConstants.USER_NAMESPACE, sender, "regular");
+        String recipientAddress = "recipient" + "@" + USERS_DOMAIN;
+        String recipientPassword = "password";
+        jmapServer.serverProbe().addUser(recipientAddress, recipientPassword);
+        await();
+
+        String messageCreationId = "creationId";
+        String fromAddress = username;
+        String requestBody = "[" +
+                "  [" +
+                "    \"setMessages\","+
+                "    {" +
+                "      \"create\": { \"" + messageCreationId  + "\" : {" +
+                "        \"from\": { \"email\": \"" + fromAddress + "\"}," +
+                "        \"to\": [{ \"name\": \"BOB\", \"email\": \"" + recipientAddress + "\"}]," +
+                "        \"cc\": [{ \"name\": \"ALICE\"}]," +
+                "        \"subject\": \"Thank you for joining example.com!\"," +
+                "        \"textBody\": \"Hello someone, and thank you for joining example.com!\"," +
+                "        \"mailboxIds\": [\"" + regularMailbox.getMailboxId().serialize() + "\"]" +
+                "      }}" +
+                "    }," +
+                "    \"#0\"" +
+                "  ]" +
+                "]";
+
+        String notCreatedMessage = ARGUMENTS + ".notCreated[\""+messageCreationId+"\"]";
+        given()
+            .header("Authorization", this.accessToken.serialize())
+            .body(requestBody)
+        .when()
+            .post("/jmap")
+        .then()
+            .statusCode(200)
+            .body(ARGUMENTS + ".notCreated", hasKey(messageCreationId))
+            .body(notCreatedMessage + ".type", equalTo("invalidProperties"))
+            .body(notCreatedMessage + ".description", equalTo("Not yet implemented"))
+            .body(ARGUMENTS + ".created", aMapWithSize(0));
+    }
+
+    
     private boolean isHtmlMessageReceived(AccessToken recipientToken) {
         try {
             with()
@@ -1375,7 +1469,7 @@ public abstract class SetMessagesMethodTest {
                 "        \"subject\": \"Thank you for joining example.com!\"," +
                 "        \"htmlBody\": \"Hello <b>someone</b>, and thank you for joining example.com!\"," +
                 "        \"textBody\": \"Hello someone, and thank you for joining example.com, text version!\"," +
-                "        \"mailboxIds\": [\"" + getOutboxId() + "\"]" +
+                "        \"mailboxIds\": [\"" + getOutboxId(accessToken) + "\"]" +
                 "      }}" +
                 "    }," +
                 "    \"#0\"" +
@@ -1439,8 +1533,6 @@ public abstract class SetMessagesMethodTest {
                 "]";
 
         given()
-                .accept(ContentType.JSON)
-                .contentType(ContentType.JSON)
                 .header("Authorization", this.accessToken.serialize())
                 .body(requestBody)
         .when()

http://git-wip-us.apache.org/repos/asf/james-project/blob/d5988181/server/protocols/jmap/src/main/java/org/apache/james/jmap/JMAPServlet.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/JMAPServlet.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/JMAPServlet.java
index 17827d4..832a940 100644
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/JMAPServlet.java
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/JMAPServlet.java
@@ -36,6 +36,8 @@ import org.apache.james.jmap.methods.RequestHandler;
 import org.apache.james.jmap.model.AuthenticatedProtocolRequest;
 import org.apache.james.jmap.model.ProtocolRequest;
 import org.apache.james.jmap.model.ProtocolResponse;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import com.fasterxml.jackson.core.JsonParseException;
 import com.fasterxml.jackson.databind.JsonMappingException;
@@ -44,6 +46,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
 
 public class JMAPServlet extends HttpServlet {
 
+    public static final Logger LOG = LoggerFactory.getLogger(JMAPServlet.class);
     public static final String JSON_CONTENT_TYPE = "application/json";
     public static final String JSON_CONTENT_TYPE_UTF8 = "application/json; charset=UTF-8";
 
@@ -70,6 +73,7 @@ public class JMAPServlet extends HttpServlet {
             resp.setContentType(JSON_CONTENT_TYPE);
             objectMapper.writeValue(resp.getOutputStream(), responses);
         } catch (IOException e) {
+            LOG.error("error handling request", e);
             resp.setStatus(SC_BAD_REQUEST);
         }
     }

http://git-wip-us.apache.org/repos/asf/james-project/blob/d5988181/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/MIMEMessageConverter.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/MIMEMessageConverter.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/MIMEMessageConverter.java
index 19e7c63..25ba906 100644
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/MIMEMessageConverter.java
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/MIMEMessageConverter.java
@@ -68,7 +68,7 @@ public class MIMEMessageConverter {
         this.bodyFactory = new BasicBodyFactory();
     }
 
-    public byte[] convert(MessageWithId.CreationMessageEntry creationMessageEntry) {
+    public byte[] convert(ValueWithId.CreationMessageEntry creationMessageEntry) {
 
         ByteArrayOutputStream buffer = new ByteArrayOutputStream();
         DefaultMessageWriter writer = new DefaultMessageWriter();
@@ -80,18 +80,18 @@ public class MIMEMessageConverter {
         return buffer.toByteArray();
     }
 
-    @VisibleForTesting Message convertToMime(MessageWithId.CreationMessageEntry creationMessageEntry) {
-        if (creationMessageEntry == null || creationMessageEntry.getMessage() == null) {
+    @VisibleForTesting Message convertToMime(ValueWithId.CreationMessageEntry creationMessageEntry) {
+        if (creationMessageEntry == null || creationMessageEntry.getValue() == null) {
             throw new IllegalArgumentException("creationMessageEntry is either null or has null message");
         }
 
         MessageBuilder messageBuilder = MessageBuilder.create();
-        if (mixedTextAndHtml(creationMessageEntry.getMessage())) {
-            messageBuilder.setBody(createMultipartBody(creationMessageEntry.getMessage()));
+        if (mixedTextAndHtml(creationMessageEntry.getValue())) {
+            messageBuilder.setBody(createMultipartBody(creationMessageEntry.getValue()));
         } else {
-            messageBuilder.setBody(createTextBody(creationMessageEntry.getMessage()));
+            messageBuilder.setBody(createTextBody(creationMessageEntry.getValue()));
         }
-        buildMimeHeaders(messageBuilder, creationMessageEntry.getCreationId(), creationMessageEntry.getMessage());
+        buildMimeHeaders(messageBuilder, creationMessageEntry.getCreationId(), creationMessageEntry.getValue());
         return messageBuilder.build();
     }
 

http://git-wip-us.apache.org/repos/asf/james-project/blob/d5988181/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/MailboxInvalidMessageCreationException.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/MailboxInvalidMessageCreationException.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/MailboxInvalidMessageCreationException.java
new file mode 100644
index 0000000..3bcb1be
--- /dev/null
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/MailboxInvalidMessageCreationException.java
@@ -0,0 +1,26 @@
+/****************************************************************
+ * 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;
+
+import org.apache.james.mailbox.exception.MailboxException;
+
+public class MailboxInvalidMessageCreationException extends MailboxException {
+
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/d5988181/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/MailboxNotImplementedException.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/MailboxNotImplementedException.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/MailboxNotImplementedException.java
new file mode 100644
index 0000000..a7da6d4
--- /dev/null
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/MailboxNotImplementedException.java
@@ -0,0 +1,30 @@
+/****************************************************************
+ * 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;
+
+import org.apache.james.mailbox.exception.MailboxException;
+
+public class MailboxNotImplementedException extends MailboxException {
+
+    public MailboxNotImplementedException(String message) {
+        super(message);
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/d5988181/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/MailboxSendingNotAllowedException.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/MailboxSendingNotAllowedException.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/MailboxSendingNotAllowedException.java
new file mode 100644
index 0000000..49d9141
--- /dev/null
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/MailboxSendingNotAllowedException.java
@@ -0,0 +1,38 @@
+/****************************************************************
+ * 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;
+
+import java.util.Collection;
+
+import org.apache.james.mailbox.exception.MailboxException;
+
+public class MailboxSendingNotAllowedException extends MailboxException {
+
+    private Collection<String> allowedFroms;
+
+    public MailboxSendingNotAllowedException(Collection<String> allowedFroms) {
+        super();
+        this.allowedFroms = allowedFroms;
+    }
+    
+    public Collection<String> getAllowedFroms() {
+        return allowedFroms;
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/d5988181/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/MessageWithId.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/MessageWithId.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/MessageWithId.java
deleted file mode 100644
index 0e4e172..0000000
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/MessageWithId.java
+++ /dev/null
@@ -1,49 +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.jmap.methods;
-
-import org.apache.james.jmap.model.CreationMessage;
-import org.apache.james.jmap.model.CreationMessageId;
-
-public class MessageWithId<T> {
-
-    private CreationMessageId creationId;
-    private T message;
-
-    public MessageWithId(CreationMessageId creationId, T message) {
-        this.creationId = creationId;
-        this.message = message;
-    }
-
-    public CreationMessageId getCreationId() {
-        return creationId;
-    }
-
-    public T getMessage() {
-        return message;
-    }
-
-    public static class CreationMessageEntry extends MessageWithId<CreationMessage> {
-        public CreationMessageEntry(CreationMessageId creationId, CreationMessage message) {
-            super(creationId, message);
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/james-project/blob/d5988181/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/SetMessagesCreationProcessor.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/SetMessagesCreationProcessor.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/SetMessagesCreationProcessor.java
index 49f87a9..3da428b 100644
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/SetMessagesCreationProcessor.java
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/SetMessagesCreationProcessor.java
@@ -20,14 +20,11 @@
 package org.apache.james.jmap.methods;
 
 import java.io.IOException;
-import java.util.AbstractMap;
 import java.util.Date;
 import java.util.List;
-import java.util.Map;
 import java.util.Optional;
 import java.util.Set;
 import java.util.function.Function;
-import java.util.function.Predicate;
 import java.util.stream.Collectors;
 
 import javax.inject.Inject;
@@ -36,7 +33,8 @@ import javax.mail.MessagingException;
 import javax.mail.internet.SharedInputStream;
 import javax.mail.util.SharedByteArrayInputStream;
 
-import org.apache.james.jmap.exceptions.MailboxRoleNotFoundException;
+import org.apache.james.jmap.methods.ValueWithId.CreationMessageEntry;
+import org.apache.james.jmap.methods.ValueWithId.MessageWithId;
 import org.apache.james.jmap.model.CreationMessage;
 import org.apache.james.jmap.model.CreationMessageId;
 import org.apache.james.jmap.model.Message;
@@ -47,18 +45,17 @@ import org.apache.james.jmap.model.MessageProperties.MessageProperty;
 import org.apache.james.jmap.model.SetError;
 import org.apache.james.jmap.model.SetMessagesRequest;
 import org.apache.james.jmap.model.SetMessagesResponse;
+import org.apache.james.jmap.model.SetMessagesResponse.Builder;
 import org.apache.james.jmap.model.mailbox.Role;
 import org.apache.james.jmap.send.MailFactory;
 import org.apache.james.jmap.send.MailMetadata;
 import org.apache.james.jmap.send.MailSpool;
-import org.apache.james.mailbox.MailboxManager;
+import org.apache.james.jmap.utils.SystemMailboxesProvider;
 import org.apache.james.mailbox.MailboxSession;
 import org.apache.james.mailbox.exception.MailboxException;
-import org.apache.james.mailbox.model.MailboxMetaData;
+import org.apache.james.mailbox.exception.MailboxNotFoundException;
 import org.apache.james.mailbox.model.MailboxPath;
-import org.apache.james.mailbox.model.MailboxQuery;
 import org.apache.james.mailbox.store.MailboxSessionMapperFactory;
-import org.apache.james.mailbox.store.mail.MailboxMapperFactory;
 import org.apache.james.mailbox.store.mail.MessageMapper;
 import org.apache.james.mailbox.store.mail.model.Mailbox;
 import org.apache.james.mailbox.store.mail.model.MailboxId;
@@ -69,150 +66,186 @@ import org.apache.mailet.Mail;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.github.fge.lambdas.functions.ThrowingFunction;
 import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Joiner;
 import com.google.common.base.Splitter;
-import com.google.common.base.Throwables;
 import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Lists;
 
 public class SetMessagesCreationProcessor implements SetMessagesProcessor {
 
-    private static final Logger LOGGER = LoggerFactory.getLogger(SetMessagesCreationProcessor.class);
-
-    private final MailboxMapperFactory mailboxMapperFactory;
-    private final MailboxManager mailboxManager;
+    private static final Logger LOG = LoggerFactory.getLogger(SetMailboxesCreationProcessor.class);
     private final MailboxSessionMapperFactory mailboxSessionMapperFactory;
     private final MIMEMessageConverter mimeMessageConverter;
     private final MailSpool mailSpool;
     private final MailFactory mailFactory;
     private final MessageFactory messageFactory;
+    private final SystemMailboxesProvider systemMailboxesProvider;
 
-    @Inject
-    @VisibleForTesting
-    SetMessagesCreationProcessor(MailboxMapperFactory mailboxMapperFactory,
-                                 MailboxManager mailboxManager,
-                                 MailboxSessionMapperFactory mailboxSessionMapperFactory,
+    
+    @VisibleForTesting @Inject
+    SetMessagesCreationProcessor(MailboxSessionMapperFactory mailboxSessionMapperFactory,
                                  MIMEMessageConverter mimeMessageConverter,
                                  MailSpool mailSpool,
                                  MailFactory mailFactory,
-                                 MessageFactory messageFactory) {
-        this.mailboxMapperFactory = mailboxMapperFactory;
-        this.mailboxManager = mailboxManager;
+                                 MessageFactory messageFactory,
+                                 SystemMailboxesProvider systemMailboxesProvider) {
         this.mailboxSessionMapperFactory = mailboxSessionMapperFactory;
         this.mimeMessageConverter = mimeMessageConverter;
         this.mailSpool = mailSpool;
         this.mailFactory = mailFactory;
         this.messageFactory = messageFactory;
+        this.systemMailboxesProvider = systemMailboxesProvider;
     }
 
     @Override
     public SetMessagesResponse process(SetMessagesRequest request, MailboxSession mailboxSession) {
-        Mailbox outbox;
+        Builder responseBuilder = SetMessagesResponse.builder();
+        request.getCreate()
+            .stream()
+            .forEach(create -> handleCreate(create, responseBuilder, mailboxSession));
+        return responseBuilder.build();
+    }
+
+    private void handleCreate(CreationMessageEntry create, Builder responseBuilder, MailboxSession mailboxSession) {
         try {
-            outbox = getOutbox(mailboxSession).orElseThrow(() -> new MailboxRoleNotFoundException(Role.OUTBOX));
-        } catch (MailboxException | MailboxRoleNotFoundException e) {
-            LOGGER.error("Unable to find a mailbox with role 'outbox'!");
-            throw Throwables.propagate(e);
-        }
+            validateImplementedFeature(create, mailboxSession);
+            validateArguments(create);
+            validateRights(create, mailboxSession);
+            MessageWithId created = handleOutboxMessages(create, mailboxSession);
+            responseBuilder.created(created.getCreationId(), created.getValue());
 
-        List<String> allowedSenders = ImmutableList.of(mailboxSession.getUser().getUserName());
+        } catch (MailboxSendingNotAllowedException e) {
+            responseBuilder.notCreated(create.getCreationId(), 
+                    SetError.builder()
+                        .type("invalidProperties")
+                        .properties(MessageProperty.from)
+                        .description("Invalid 'from' field. Must be one of " + 
+                                Joiner.on(", ").join(e.getAllowedFroms()))
+                        .build());
 
-        // handle errors
-        Predicate<CreationMessage> validMessagesTester = creationMessage -> creationMessage.isValid() && isAllowedFromAddress(creationMessage, allowedSenders);
-        Predicate<CreationMessage> invalidMessagesTester = validMessagesTester.negate();
-        Function<CreationMessage, List<ValidationResult>> toValidationResults = creationMessage -> ImmutableList.<ValidationResult>builder()
-            .addAll(creationMessage.validate())
-            .addAll(validationResultForIncorrectAddress(creationMessage, allowedSenders))
-            .build();
+        } catch (MailboxNotImplementedException e) {
+            responseBuilder.notCreated(create.getCreationId(), 
+                    SetError.builder()
+                        .type("invalidProperties")
+                        .properties(MessageProperty.mailboxIds)
+                        .description("Not yet implemented")
+                        .build());
 
-        SetMessagesResponse.Builder responseBuilder = SetMessagesResponse.builder()
-                .notCreated(handleCreationErrors(invalidMessagesTester, toValidationResults, request));
+        } catch (MailboxInvalidMessageCreationException e) {
+            responseBuilder.notCreated(create.getCreationId(),
+                    buildSetErrorFromValidationResult(create.getValue().validate()));
 
-        return request.getCreate().entrySet().stream()
-                .filter(e -> validMessagesTester.test(e.getValue()))
-                .map(e -> new MessageWithId.CreationMessageEntry(e.getKey(), e.getValue()))
-                .map(nuMsg -> createMessageInOutboxAndSend(nuMsg, mailboxSession, outbox, buildMessageIdFunc(mailboxSession, outbox)))
-                .map(msg -> SetMessagesResponse.builder().created(ImmutableMap.of(msg.getCreationId(), msg.getMessage())).build())
-                .reduce(responseBuilder, SetMessagesResponse.Builder::accumulator, SetMessagesResponse.Builder::combiner)
-                .build();
-    }
+        } catch (MailboxNotFoundException e) {
+            responseBuilder.notCreated(create.getCreationId(), 
+                    SetError.builder()
+                        .type("error")
+                        .description(e.getMailboxName() + " can't be found")
+                        .build());
 
-    private boolean isAllowedFromAddress(CreationMessage creationMessage, List<String> allowedFromMailAddresses) {
-        return creationMessage.getFrom()
-            .map(draftEmailer -> draftEmailer.getEmail()
-                .map(allowedFromMailAddresses::contains)
-                .orElse(false))
-            .orElse(false);
+        } catch (MailboxException | MessagingException e) {
+            LOG.error("Unexpected error while creating message", e);
+            responseBuilder.notCreated(create.getCreationId(), 
+                    SetError.builder()
+                        .type("error")
+                        .description("unexpected error")
+                        .build());
+        }
     }
-
-    private List<ValidationResult> validationResultForIncorrectAddress(CreationMessage creationMessage, List<String> allowedSenders) {
+    
+    private void validateImplementedFeature(CreationMessageEntry entry, MailboxSession session) throws MailboxNotImplementedException {
+        if (isAppendToMailboxWithRole(Role.DRAFTS, entry.getValue(), session)) {
+            throw new MailboxNotImplementedException("Drafts saving is not implemented");
+        }
+        if (!isAppendToMailboxWithRole(Role.OUTBOX, entry.getValue(), session)) {
+            throw new MailboxNotImplementedException("The only implemented feature is sending via outbox");
+        }
+    }
+    
+    private void validateArguments(CreationMessageEntry entry) throws MailboxInvalidMessageCreationException {
+        CreationMessage message = entry.getValue();
+        if (!message.isValid()) {
+            throw new MailboxInvalidMessageCreationException();
+        }
+    }
+    
+    private void validateRights(CreationMessageEntry entry, MailboxSession session) throws MailboxSendingNotAllowedException {
+        List<String> allowedSenders = ImmutableList.of(session.getUser().getUserName());
+        if (!isAllowedFromAddress(entry.getValue(), allowedSenders)) {
+            throw new MailboxSendingNotAllowedException(allowedSenders);
+        }
+    }
+    
+    private boolean isAllowedFromAddress(CreationMessage creationMessage, List<String> allowedFromMailAddresses) {
         return creationMessage.getFrom()
-            .map(draftEmailer -> draftEmailer
-                .getEmail()
-                .map(mail -> validationResultForIncorrectAddress(allowedSenders, mail))
-                .orElse(Lists.newArrayList()))
-            .orElse(Lists.newArrayList());
+                .map(draftEmailer -> draftEmailer.getEmail()
+                        .map(allowedFromMailAddresses::contains)
+                        .orElse(false))
+                .orElse(false);
     }
 
-    private List<ValidationResult> validationResultForIncorrectAddress(List<String> allowedSenders, String mail) {
-        if (!allowedSenders.contains(mail)) {
-            return Lists.newArrayList(ValidationResult.builder()
-                .message("Invalid 'from' field. Must be one of " + allowedSenders)
-                .property(MessageProperty.from.asFieldName())
-                .build());
+    
+    private MessageWithId handleOutboxMessages(CreationMessageEntry entry, MailboxSession session) throws MailboxException, MessagingException {
+        Mailbox outbox = getMailboxWithRole(session, Role.OUTBOX).orElseThrow(() -> new MailboxNotFoundException(Role.OUTBOX.serialize()));
+        if (!isRequestForSending(entry.getValue(), session)) {
+            throw new IllegalStateException("Messages for everything but outbox should have been filtered earlier");
         }
-        return Lists.newArrayList();
+        Function<Long, MessageId> idGenerator = uid -> generateMessageId(session, outbox, uid);
+        return createMessageInOutboxAndSend(entry, session, outbox, idGenerator);
     }
-
-    private Map<CreationMessageId, SetError> handleCreationErrors(Predicate<CreationMessage> invalidMessagesTester,
-                                                                  Function<CreationMessage, List<ValidationResult>> toValidationResults,
-                                                                  SetMessagesRequest request) {
-        return request.getCreate().entrySet().stream()
-                .filter(e -> invalidMessagesTester.test(e.getValue()))
-                .map(e -> new AbstractMap.SimpleEntry<>(e.getKey(), buildSetErrorFromValidationResult(toValidationResults.apply(e.getValue()))))
-                .collect(Collectors.toMap(AbstractMap.SimpleEntry::getKey, AbstractMap.SimpleEntry::getValue));
+    
+    @VisibleForTesting
+    protected MessageWithId createMessageInOutboxAndSend(CreationMessageEntry createdEntry,
+                                                           MailboxSession session,
+                                                           Mailbox outbox, Function<Long, MessageId> buildMessageIdFromUid) throws MailboxException, MessagingException {
+        
+        CreationMessageId creationId = createdEntry.getCreationId();
+        MessageMapper messageMapper = mailboxSessionMapperFactory.createMessageMapper(session);
+        MailboxMessage newMailboxMessage = buildMailboxMessage(createdEntry, outbox);
+        messageMapper.add(outbox, newMailboxMessage);
+        Message jmapMessage = messageFactory.fromMailboxMessage(newMailboxMessage, ImmutableList.of(), buildMessageIdFromUid);
+        sendMessage(newMailboxMessage, jmapMessage, session);
+        return new MessageWithId(creationId, jmapMessage);
+    }
+    
+    private boolean isAppendToMailboxWithRole(Role role, CreationMessage entry, MailboxSession mailboxSession) {
+        return getMailboxWithRole(mailboxSession, role)
+                .map(box -> entry.isIn(box))
+                .orElse(false);
     }
 
+    private Optional<Mailbox> getMailboxWithRole(MailboxSession mailboxSession, Role role) {
+        return systemMailboxesProvider.listMailboxes(role, mailboxSession).findFirst();
+    }
+    
     private SetError buildSetErrorFromValidationResult(List<ValidationResult> validationErrors) {
-        String formattedValidationErrorMessage = validationErrors.stream()
+        return SetError.builder()
+                .type("invalidProperties")
+                .properties(collectMessageProperties(validationErrors))
+                .description(formatValidationErrorMessge(validationErrors))
+                .build();
+    }
+
+    private String formatValidationErrorMessge(List<ValidationResult> validationErrors) {
+        return validationErrors.stream()
                 .map(err -> err.getProperty() + ": " + err.getErrorMessage())
                 .collect(Collectors.joining("\\n"));
+    }
+
+    private Set<MessageProperties.MessageProperty> collectMessageProperties(List<ValidationResult> validationErrors) {
         Splitter propertiesSplitter = Splitter.on(',').trimResults().omitEmptyStrings();
-        Set<MessageProperties.MessageProperty> properties = validationErrors.stream()
+        return validationErrors.stream()
                 .flatMap(err -> propertiesSplitter.splitToList(err.getProperty()).stream())
                 .flatMap(MessageProperty::find)
                 .collect(Collectors.toSet());
-        return SetError.builder()
-                .type("invalidProperties")
-                .properties(properties)
-                .description(formattedValidationErrorMessage)
-                .build();
     }
 
-    @VisibleForTesting
-    protected MessageWithId<Message> createMessageInOutboxAndSend(MessageWithId.CreationMessageEntry createdEntry,
-                                                           MailboxSession session,
-                                                           Mailbox outbox, Function<Long, MessageId> buildMessageIdFromUid) {
-        try {
-            MessageMapper messageMapper = mailboxSessionMapperFactory.createMessageMapper(session);
-            MailboxMessage newMailboxMessage = buildMailboxMessage(createdEntry, outbox);
-            messageMapper.add(outbox, newMailboxMessage);
-            Message jmapMessage = messageFactory.fromMailboxMessage(newMailboxMessage, ImmutableList.of(), buildMessageIdFromUid);
-            sendMessage(newMailboxMessage, jmapMessage, session);
-            return new MessageWithId<>(createdEntry.getCreationId(), jmapMessage);
-        } catch (MailboxException | MessagingException | IOException e) {
-            throw Throwables.propagate(e);
-        } catch (MailboxRoleNotFoundException e) {
-            LOGGER.error("Could not find mailbox '%s' while trying to save message.", e.getRole().serialize());
-            throw Throwables.propagate(e);
-        }
+    private boolean isRequestForSending(CreationMessage creationMessage, MailboxSession session) {
+        return isAppendToMailboxWithRole(Role.OUTBOX, creationMessage, session);
     }
-
-    private Function<Long, MessageId> buildMessageIdFunc(MailboxSession session, Mailbox outbox) {
+    
+    private MessageId generateMessageId(MailboxSession session, Mailbox outbox, long uid) {
         MailboxPath outboxPath = new MailboxPath(session.getPersonalSpace(), session.getUser().getUserName(), outbox.getName());
-        return uid -> new MessageId(session.getUser(), outboxPath, uid);
+        return new MessageId(session.getUser(), outboxPath, uid);
     }
 
     private MailboxMessage buildMailboxMessage(MessageWithId.CreationMessageEntry createdEntry, Mailbox outbox) {
@@ -221,35 +254,15 @@ public class SetMessagesCreationProcessor implements SetMessagesProcessor {
         long size = messageContent.length;
         int bodyStartOctet = 0;
 
-        Flags flags = getMessageFlags(createdEntry.getMessage());
+        Flags flags = getMessageFlags(createdEntry.getValue());
         PropertyBuilder propertyBuilder = buildPropertyBuilder();
         MailboxId mailboxId = outbox.getMailboxId();
-        Date internalDate = Date.from(createdEntry.getMessage().getDate().toInstant());
+        Date internalDate = Date.from(createdEntry.getValue().getDate().toInstant());
 
         return new SimpleMailboxMessage(internalDate, size,
                 bodyStartOctet, content, flags, propertyBuilder, mailboxId);
     }
 
-    @VisibleForTesting
-    protected Optional<Mailbox> getOutbox(MailboxSession session) throws MailboxException {
-        return mailboxManager.search(MailboxQuery.builder(session)
-                .privateUserMailboxes().build(), session).stream()
-            .map(MailboxMetaData::getPath)
-            .filter(this::hasRoleOutbox)
-            .map(loadMailbox(session))
-            .findFirst();
-    }
-
-    private boolean hasRoleOutbox(MailboxPath mailBoxPath) {
-        return Role.from(mailBoxPath.getName())
-                .map(Role.OUTBOX::equals)
-                .orElse(false);
-    }
-
-    private ThrowingFunction<MailboxPath, Mailbox> loadMailbox(MailboxSession session) {
-        return path -> mailboxMapperFactory.getMailboxMapper(session).findMailboxByPath(path);
-    }
-
     private PropertyBuilder buildPropertyBuilder() {
         return new PropertyBuilder();
     }
@@ -271,9 +284,17 @@ public class SetMessagesCreationProcessor implements SetMessagesProcessor {
         return result;
     }
 
-    private void sendMessage(MailboxMessage mailboxMessage, Message jmapMessage, MailboxSession session) throws MessagingException, IOException {
-        Mail mail = mailFactory.build(mailboxMessage, jmapMessage);
+    private void sendMessage(MailboxMessage mailboxMessage, Message jmapMessage, MailboxSession session) throws MessagingException {
+        Mail mail = buildMessage(mailboxMessage, jmapMessage);
         MailMetadata metadata = new MailMetadata(jmapMessage.getId(), session.getUser().getUserName());
         mailSpool.send(mail, metadata);
     }
+
+    private Mail buildMessage(MailboxMessage mailboxMessage, Message jmapMessage) throws MessagingException {
+        try {
+            return mailFactory.build(mailboxMessage, jmapMessage);
+        } catch (IOException e) {
+            throw new MessagingException("error building message to send", e);
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/d5988181/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/ValueWithId.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/ValueWithId.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/ValueWithId.java
new file mode 100644
index 0000000..a5548c1
--- /dev/null
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/ValueWithId.java
@@ -0,0 +1,63 @@
+/****************************************************************
+ * 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;
+
+import org.apache.james.jmap.model.CreationMessage;
+import org.apache.james.jmap.model.CreationMessageId;
+import org.apache.james.jmap.model.SetError;
+import org.apache.james.jmap.model.Message;
+
+public class ValueWithId<T> {
+
+    private CreationMessageId creationId;
+    private T value;
+
+    private ValueWithId(CreationMessageId creationId, T value) {
+        this.creationId = creationId;
+        this.value = value;
+    }
+
+    public CreationMessageId getCreationId() {
+        return creationId;
+    }
+
+    public T getValue() {
+        return value;
+    }
+
+    public static class CreationMessageEntry extends ValueWithId<CreationMessage> {
+        public CreationMessageEntry(CreationMessageId creationId, CreationMessage message) {
+            super(creationId, message);
+        }
+    }
+
+    public static class ErrorWithId extends ValueWithId<SetError> {
+        public ErrorWithId(CreationMessageId creationId, SetError error) {
+            super(creationId, error);
+        }
+    }
+
+    public static class MessageWithId extends ValueWithId<Message> {
+        public MessageWithId(CreationMessageId creationId, Message message) {
+            super(creationId, message);
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/d5988181/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/CreationMessage.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/CreationMessage.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/CreationMessage.java
index de2453d..60f7b91 100644
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/CreationMessage.java
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/CreationMessage.java
@@ -19,9 +19,8 @@
 
 package org.apache.james.jmap.model;
 
-import static org.apache.james.jmap.model.MessageProperties.MessageProperty;
-
 import java.time.ZonedDateTime;
+import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
@@ -32,6 +31,8 @@ import javax.mail.internet.AddressException;
 import javax.mail.internet.InternetAddress;
 
 import org.apache.james.jmap.methods.ValidationResult;
+import org.apache.james.jmap.model.MessageProperties.MessageProperty;
+import org.apache.james.mailbox.store.mail.model.Mailbox;
 
 import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
 import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
@@ -84,8 +85,12 @@ public class CreationMessage {
             headers = ImmutableMap.builder();
         }
 
-        public Builder mailboxIds(ImmutableList<String> mailboxIds) {
-            this.mailboxIds = mailboxIds;
+        public Builder mailboxId(String... mailboxIds) {
+            return mailboxIds(Arrays.asList(mailboxIds));
+        }
+
+        public Builder mailboxIds(List<String> mailboxIds) {
+            this.mailboxIds = ImmutableList.copyOf(mailboxIds);
             return this;
         }
 
@@ -349,6 +354,10 @@ public class CreationMessage {
         from.filter(f -> !f.hasValidEmail()).ifPresent(f -> errors.add(invalidPropertyFrom));
     }
 
+    public boolean isIn(Mailbox mailbox) {
+        return mailboxIds.contains(mailbox.getMailboxId().serialize());
+    }
+    
     @JsonDeserialize(builder = DraftEmailer.Builder.class)
     public static class DraftEmailer {
 

http://git-wip-us.apache.org/repos/asf/james-project/blob/d5988181/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/Message.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/Message.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/Message.java
index 1c1cd50..94b8517 100644
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/Message.java
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/Message.java
@@ -95,8 +95,12 @@ public class Message {
             return this;
         }
 
-        public Builder mailboxIds(ImmutableList<String> mailboxIds) {
-            this.mailboxIds = mailboxIds;
+        public Builder mailboxId(String mailboxId) {
+            return this.mailboxIds(ImmutableList.of(mailboxId));
+        }
+
+        public Builder mailboxIds(List<String> mailboxIds) {
+            this.mailboxIds = ImmutableList.copyOf(mailboxIds);
             return this;
         }
 

http://git-wip-us.apache.org/repos/asf/james-project/blob/d5988181/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetError.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetError.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetError.java
index 75aacd2..658491c 100644
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetError.java
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetError.java
@@ -28,6 +28,7 @@ import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
 import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
 import com.fasterxml.jackson.databind.annotation.JsonSerialize;
 import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.MoreObjects;
 import com.google.common.base.Objects;
 import com.google.common.base.Preconditions;
 import com.google.common.base.Strings;
@@ -61,6 +62,10 @@ public class SetError {
             return this;
         }
 
+        public Builder properties(MessageProperty... properties) {
+            return properties(ImmutableSet.copyOf(properties));
+        }
+
         public Builder properties(Set<MessageProperty> properties) {
             this.properties = Optional.of(Sets.union(
                     this.properties.orElse(ImmutableSet.of()),
@@ -116,4 +121,13 @@ public class SetError {
     public int hashCode() {
         return Objects.hashCode(type, description, properties);
     }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(this)
+                .add("description", description)
+                .add("type", type)
+                .add("properties", properties)
+                .toString();
+    }
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/d5988181/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetMessagesRequest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetMessagesRequest.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetMessagesRequest.java
index 096e9c6..a064102 100644
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetMessagesRequest.java
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetMessagesRequest.java
@@ -19,13 +19,17 @@
 
 package org.apache.james.jmap.model;
 
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
 import java.util.function.Function;
 
+import org.apache.commons.lang.NotImplementedException;
 import org.apache.james.jmap.methods.JmapRequest;
 import org.apache.james.jmap.methods.UpdateMessagePatchConverter;
+import org.apache.james.jmap.methods.ValueWithId.CreationMessageEntry;
+import org.apache.james.util.streams.ImmutableCollectors;
 
 import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
 import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
@@ -34,7 +38,6 @@ import com.google.common.annotations.VisibleForTesting;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Maps;
-import org.apache.commons.lang.NotImplementedException;
 
 @JsonDeserialize(builder = SetMessagesRequest.Builder.class)
 public class SetMessagesRequest implements JmapRequest {
@@ -48,13 +51,13 @@ public class SetMessagesRequest implements JmapRequest {
 
         private String accountId;
         private String ifInState;
-        private ImmutableMap.Builder<CreationMessageId, CreationMessage> create;
+        private HashMap<CreationMessageId, CreationMessage> create;
         private ImmutableMap.Builder<MessageId, Function<UpdateMessagePatchConverter, UpdateMessagePatch>> updatesProvider;
 
         private ImmutableList.Builder<MessageId> destroy;
 
         private Builder() {
-            create = ImmutableMap.builder();
+            create = new HashMap<>();
             updatesProvider = ImmutableMap.builder();
             destroy = ImmutableList.builder();
         }
@@ -73,6 +76,11 @@ public class SetMessagesRequest implements JmapRequest {
             return this;
         }
 
+        public Builder create(CreationMessageId creationMessageId, CreationMessage creation) {
+            this.create.put(creationMessageId, creation);
+            return this;
+        }
+
         public Builder create(Map<CreationMessageId, CreationMessage> creations) {
             this.create.putAll(creations);
             return this;
@@ -89,17 +97,24 @@ public class SetMessagesRequest implements JmapRequest {
         }
 
         public SetMessagesRequest build() {
-            return new SetMessagesRequest(Optional.ofNullable(accountId), Optional.ofNullable(ifInState), create.build(), updatesProvider.build(), destroy.build());
+            return new SetMessagesRequest(Optional.ofNullable(accountId), Optional.ofNullable(ifInState), 
+                    messageCreations(), updatesProvider.build(), destroy.build());
+        }
+
+        private ImmutableList<CreationMessageEntry> messageCreations() {
+            return create.entrySet().stream()
+                    .map(entry -> new CreationMessageEntry(entry.getKey(), entry.getValue()))
+                    .collect(ImmutableCollectors.toImmutableList());
         }
     }
 
     private final Optional<String> accountId;
     private final Optional<String> ifInState;
-    private final Map<CreationMessageId, CreationMessage> create;
+    private final List<CreationMessageEntry> create;
     private final Map<MessageId, Function<UpdateMessagePatchConverter, UpdateMessagePatch>> update;
     private final List<MessageId> destroy;
 
-    @VisibleForTesting SetMessagesRequest(Optional<String> accountId, Optional<String> ifInState, Map<CreationMessageId, CreationMessage> create, Map<MessageId, Function<UpdateMessagePatchConverter, UpdateMessagePatch>>  update, List<MessageId> destroy) {
+    @VisibleForTesting SetMessagesRequest(Optional<String> accountId, Optional<String> ifInState, List<CreationMessageEntry> create, Map<MessageId, Function<UpdateMessagePatchConverter, UpdateMessagePatch>>  update, List<MessageId> destroy) {
         this.accountId = accountId;
         this.ifInState = ifInState;
         this.create = create;
@@ -115,7 +130,7 @@ public class SetMessagesRequest implements JmapRequest {
         return ifInState;
     }
 
-    public Map<CreationMessageId, CreationMessage> getCreate() {
+    public List<CreationMessageEntry> getCreate() {
         return create;
     }
 
@@ -126,4 +141,5 @@ public class SetMessagesRequest implements JmapRequest {
     public List<MessageId> getDestroy() {
         return destroy;
     }
+
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/d5988181/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetMessagesResponse.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetMessagesResponse.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetMessagesResponse.java
index a536ba4..96286e7 100644
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetMessagesResponse.java
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetMessagesResponse.java
@@ -81,6 +81,11 @@ public class SetMessagesResponse implements Method.Response {
             throw new NotImplementedException();
         }
 
+        public Builder created(CreationMessageId creationMessageId, Message message) {
+            this.created.put(creationMessageId, message);
+            return this;
+        }
+
         public Builder created(Map<CreationMessageId, Message> created) {
             this.created.putAll(created);
             return this;
@@ -105,6 +110,11 @@ public class SetMessagesResponse implements Method.Response {
             this.notCreated.putAll(notCreated);
             return this;
         }
+        
+        public Builder notCreated(CreationMessageId id, SetError error) {
+            this.notCreated.put(id, error);
+            return this;
+        }
 
         public Builder notUpdated(Map<MessageId, SetError> notUpdated) {
             this.notUpdated.putAll(notUpdated);
@@ -121,6 +131,10 @@ public class SetMessagesResponse implements Method.Response {
             return this;
         }
 
+        public Builder mergeWith(Builder otherBuilder) {
+            return otherBuilder.build().mergeInto(this);
+        }
+
         public SetMessagesResponse build() {
             return new SetMessagesResponse(accountId, oldState, newState, 
                     created.build(), updated.build(), destroyed.build(), notCreated.build(), notUpdated.build(), notDestroyed.build());

http://git-wip-us.apache.org/repos/asf/james-project/blob/d5988181/server/protocols/jmap/src/main/java/org/apache/james/jmap/send/PostDequeueDecorator.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/send/PostDequeueDecorator.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/send/PostDequeueDecorator.java
index 6d7f083..52c2dfd 100644
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/send/PostDequeueDecorator.java
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/send/PostDequeueDecorator.java
@@ -21,10 +21,10 @@ package org.apache.james.jmap.send;
 import java.io.Serializable;
 import java.util.Iterator;
 
+import org.apache.james.jmap.exceptions.MailboxRoleNotFoundException;
 import org.apache.james.jmap.model.MessageId;
 import org.apache.james.jmap.model.mailbox.Role;
 import org.apache.james.jmap.send.exception.MailShouldBeInOutboxException;
-import org.apache.james.jmap.send.exception.MailboxRoleNotFoundException;
 import org.apache.james.jmap.send.exception.MessageIdNotFoundException;
 import org.apache.james.mailbox.MailboxManager;
 import org.apache.james.mailbox.MailboxSession;

http://git-wip-us.apache.org/repos/asf/james-project/blob/d5988181/server/protocols/jmap/src/main/java/org/apache/james/jmap/send/exception/MailboxRoleNotFoundException.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/send/exception/MailboxRoleNotFoundException.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/send/exception/MailboxRoleNotFoundException.java
deleted file mode 100644
index 574edf1..0000000
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/send/exception/MailboxRoleNotFoundException.java
+++ /dev/null
@@ -1,30 +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.jmap.send.exception;
-
-import org.apache.james.jmap.model.mailbox.Role;
-import org.apache.james.queue.api.MailQueue.MailQueueException;
-
-public class MailboxRoleNotFoundException extends MailQueueException {
-
-    public MailboxRoleNotFoundException(Role role) {
-        super("Unable to find a mailbox with role " + role.serialize());
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/james-project/blob/d5988181/server/protocols/jmap/src/main/java/org/apache/james/jmap/utils/SystemMailboxesProvider.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/utils/SystemMailboxesProvider.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/utils/SystemMailboxesProvider.java
new file mode 100644
index 0000000..908ef9c
--- /dev/null
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/utils/SystemMailboxesProvider.java
@@ -0,0 +1,30 @@
+/****************************************************************
+ * 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.utils;
+
+import java.util.stream.Stream;
+
+import org.apache.james.jmap.model.mailbox.Role;
+import org.apache.james.mailbox.MailboxSession;
+import org.apache.james.mailbox.store.mail.model.Mailbox;
+
+public interface SystemMailboxesProvider {
+    Stream<Mailbox> listMailboxes(Role aRole, MailboxSession session);
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/d5988181/server/protocols/jmap/src/main/java/org/apache/james/jmap/utils/SystemMailboxesProviderImpl.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/utils/SystemMailboxesProviderImpl.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/utils/SystemMailboxesProviderImpl.java
new file mode 100644
index 0000000..b868c85
--- /dev/null
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/utils/SystemMailboxesProviderImpl.java
@@ -0,0 +1,70 @@
+/****************************************************************
+ * 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.utils;
+
+import java.util.List;
+import java.util.function.Predicate;
+import java.util.stream.Stream;
+
+import javax.inject.Inject;
+
+import org.apache.james.jmap.model.mailbox.Role;
+import org.apache.james.mailbox.MailboxManager;
+import org.apache.james.mailbox.MailboxSession;
+import org.apache.james.mailbox.model.MailboxMetaData;
+import org.apache.james.mailbox.model.MailboxPath;
+import org.apache.james.mailbox.model.MailboxQuery;
+import org.apache.james.mailbox.store.mail.MailboxMapperFactory;
+import org.apache.james.mailbox.store.mail.model.Mailbox;
+
+import com.github.fge.lambdas.functions.ThrowingFunction;
+import com.github.fge.lambdas.supplier.ThrowingSupplier;
+import com.google.common.annotations.VisibleForTesting;
+
+public class SystemMailboxesProviderImpl implements SystemMailboxesProvider {
+
+    private final MailboxMapperFactory mailboxMapperFactory;
+    private final MailboxManager mailboxManager;
+
+    @Inject
+    @VisibleForTesting SystemMailboxesProviderImpl(MailboxMapperFactory mailboxMapperFactory, MailboxManager mailboxManager) {
+        this.mailboxMapperFactory = mailboxMapperFactory;
+        this.mailboxManager = mailboxManager;
+    }
+
+    private boolean hasRole(Role aRole, MailboxPath mailBoxPath) {
+        return Role.from(mailBoxPath.getName())
+                .map(aRole::equals)
+                .orElse(false);
+    }
+
+    public Stream<Mailbox> listMailboxes(Role aRole, MailboxSession session) {
+        ThrowingSupplier<List<MailboxMetaData>> getAllMailboxes = () -> mailboxManager.search(MailboxQuery.builder(session).privateUserMailboxes().build(), session);
+        Predicate<MailboxPath> hasSpecifiedRole = path -> hasRole(aRole, path);
+        return getAllMailboxes.get().stream()
+                .map(MailboxMetaData::getPath)
+                .filter(hasSpecifiedRole)
+                .map(loadMailbox(session));
+    }
+
+    private ThrowingFunction<MailboxPath, Mailbox> loadMailbox(MailboxSession session) {
+        return path -> mailboxMapperFactory.getMailboxMapper(session).findMailboxByPath(path);
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/d5988181/server/protocols/jmap/src/test/java/org/apache/james/jmap/methods/MIMEMessageConverterTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/methods/MIMEMessageConverterTest.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/methods/MIMEMessageConverterTest.java
index c2cf064..e64d6a9 100644
--- a/server/protocols/jmap/src/test/java/org/apache/james/jmap/methods/MIMEMessageConverterTest.java
+++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/methods/MIMEMessageConverterTest.java
@@ -26,6 +26,7 @@ import java.time.Instant;
 import java.time.ZoneId;
 import java.time.ZonedDateTime;
 
+import org.apache.james.jmap.methods.ValueWithId.MessageWithId;
 import org.apache.james.jmap.model.CreationMessage;
 import org.apache.james.jmap.model.CreationMessage.DraftEmailer;
 import org.apache.james.jmap.model.CreationMessageId;
@@ -55,7 +56,7 @@ public class MIMEMessageConverterTest {
                 .build();
 
         // When
-        Message result = sut.convertToMime(new MessageWithId.CreationMessageEntry(
+        Message result = sut.convertToMime(new ValueWithId.CreationMessageEntry(
                 CreationMessageId.of("user|mailbox|1"), messageHavingInReplyTo));
 
         // Then
@@ -67,7 +68,7 @@ public class MIMEMessageConverterTest {
     public void convertToMimeShouldThrowWhenMessageIsNull() {
         MIMEMessageConverter sut = new MIMEMessageConverter();
 
-        sut.convertToMime(new MessageWithId.CreationMessageEntry(CreationMessageId.of("any"), null));
+        sut.convertToMime(new ValueWithId.CreationMessageEntry(CreationMessageId.of("any"), null));
     }
 
     @Test
@@ -83,7 +84,7 @@ public class MIMEMessageConverterTest {
                 .build();
 
         // When
-        Message result = sut.convertToMime(new MessageWithId.CreationMessageEntry(
+        Message result = sut.convertToMime(new ValueWithId.CreationMessageEntry(
                 CreationMessageId.of("user|mailbox|1"), testMessage));
 
         // Then
@@ -107,7 +108,7 @@ public class MIMEMessageConverterTest {
                 .build();
 
         // When
-        Message result = sut.convertToMime(new MessageWithId.CreationMessageEntry(
+        Message result = sut.convertToMime(new ValueWithId.CreationMessageEntry(
                 CreationMessageId.of("user|mailbox|1"), testMessage));
 
         // Then
@@ -128,7 +129,7 @@ public class MIMEMessageConverterTest {
                 .build();
 
         // When
-        Message result = sut.convertToMime(new MessageWithId.CreationMessageEntry(
+        Message result = sut.convertToMime(new ValueWithId.CreationMessageEntry(
                 CreationMessageId.of("user|mailbox|1"), testMessage));
 
         // Then
@@ -148,7 +149,7 @@ public class MIMEMessageConverterTest {
                 .build();
 
         // When
-        Message result = sut.convertToMime(new MessageWithId.CreationMessageEntry(
+        Message result = sut.convertToMime(new ValueWithId.CreationMessageEntry(
                 CreationMessageId.of("user|mailbox|1"), testMessage));
 
         // Then
@@ -169,7 +170,7 @@ public class MIMEMessageConverterTest {
                 .build();
 
         // When
-        Message result = sut.convertToMime(new MessageWithId.CreationMessageEntry(
+        Message result = sut.convertToMime(new ValueWithId.CreationMessageEntry(
                 CreationMessageId.of("user|mailbox|1"), testMessage));
 
         // Then
@@ -190,7 +191,7 @@ public class MIMEMessageConverterTest {
                 .build();
 
         // When
-        Message result = sut.convertToMime(new MessageWithId.CreationMessageEntry(
+        Message result = sut.convertToMime(new ValueWithId.CreationMessageEntry(
                 CreationMessageId.of("user|mailbox|1"), testMessage));
 
         // Then
@@ -247,7 +248,7 @@ public class MIMEMessageConverterTest {
                 .build();
 
         // When
-        Message result = sut.convertToMime(new MessageWithId.CreationMessageEntry(
+        Message result = sut.convertToMime(new ValueWithId.CreationMessageEntry(
                 CreationMessageId.of("user|mailbox|1"), testMessage));
 
         // Then
@@ -267,7 +268,7 @@ public class MIMEMessageConverterTest {
                 .build();
 
         // When
-        Message result = sut.convertToMime(new MessageWithId.CreationMessageEntry(
+        Message result = sut.convertToMime(new ValueWithId.CreationMessageEntry(
                 CreationMessageId.of("user|mailbox|1"), testMessage));
 
         // Then
@@ -288,7 +289,7 @@ public class MIMEMessageConverterTest {
                 .build();
 
         // When
-        Message result = sut.convertToMime(new MessageWithId.CreationMessageEntry(
+        Message result = sut.convertToMime(new ValueWithId.CreationMessageEntry(
                 CreationMessageId.of("user|mailbox|1"), testMessage));
 
         // Then
@@ -310,7 +311,7 @@ public class MIMEMessageConverterTest {
                 .build();
 
         // When
-        Message result = sut.convertToMime(new MessageWithId.CreationMessageEntry(
+        Message result = sut.convertToMime(new ValueWithId.CreationMessageEntry(
                 CreationMessageId.of("user|mailbox|1"), testMessage));
 
         // Then


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