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 2017/12/01 15:37:09 UTC

[1/4] james-project git commit: JAMES-2244 Solve (some) IntelliJ warnings

Repository: james-project
Updated Branches:
  refs/heads/master 06ddc93c5 -> f2005bf0f


JAMES-2244 Solve (some) IntelliJ warnings


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

Branch: refs/heads/master
Commit: d1ea4a20629692f4a1ff92e02e8a0340e5bb3097
Parents: 439e747
Author: benwa <bt...@linagora.com>
Authored: Thu Nov 30 10:49:54 2017 +0700
Committer: Antoine Duprat <ad...@linagora.com>
Committed: Fri Dec 1 13:51:42 2017 +0100

----------------------------------------------------------------------
 .../james/jmap/methods/SetMessagesUpdateProcessor.java       | 8 +++-----
 1 file changed, 3 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/d1ea4a20/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/SetMessagesUpdateProcessor.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/SetMessagesUpdateProcessor.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/SetMessagesUpdateProcessor.java
index f7cbe62..9086ea6 100644
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/SetMessagesUpdateProcessor.java
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/SetMessagesUpdateProcessor.java
@@ -123,9 +123,7 @@ public class SetMessagesUpdateProcessor implements SetMessagesProcessor {
             if (messages.isEmpty()) {
                 addMessageIdNotFoundToResponse(messageId, builder);
             } else {
-                setInMailboxes(messageId, updateMessagePatch,
-                    messages.stream().map(MessageResult::getFlags),
-                    mailboxSession);
+                setInMailboxes(messageId, updateMessagePatch, mailboxSession);
                 Optional<MailboxException> updateError = messages.stream()
                     .flatMap(message -> updateFlags(messageId, updateMessagePatch, mailboxSession, message))
                     .findAny();
@@ -252,7 +250,7 @@ public class SetMessagesUpdateProcessor implements SetMessagesProcessor {
     private List<Flags> flagsFromOldKeyword(List<MessageResult> messagesToBeUpdated, OldKeyword oldKeyword) {
         return messagesToBeUpdated.stream()
                 .map(MessageResult::getFlags)
-                .map(flags -> oldKeyword.applyToState(flags))
+                .map(oldKeyword::applyToState)
                 .collect(Guavate.toImmutableList());
     }
 
@@ -320,7 +318,7 @@ public class SetMessagesUpdateProcessor implements SetMessagesProcessor {
                 .orElse(null);
     }
 
-    private void setInMailboxes(MessageId messageId, UpdateMessagePatch updateMessagePatch, Stream<Flags> originalFlags, MailboxSession mailboxSession) throws MailboxException {
+    private void setInMailboxes(MessageId messageId, UpdateMessagePatch updateMessagePatch, MailboxSession mailboxSession) throws MailboxException {
         Optional<List<String>> serializedMailboxIds = updateMessagePatch.getMailboxIds();
         if (serializedMailboxIds.isPresent()) {
             List<MailboxId> mailboxIds = serializedMailboxIds.get()


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


[3/4] james-project git commit: JAMES-2244 Ensure creation message being sent are just in outbox

Posted by ad...@apache.org.
JAMES-2244 Ensure creation message being sent are just in outbox


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

Branch: refs/heads/master
Commit: fa601b9fb559f68af91b9f4fe958712aa35f5e66
Parents: 1eef6ea
Author: benwa <bt...@linagora.com>
Authored: Thu Nov 30 17:34:33 2017 +0700
Committer: Antoine Duprat <ad...@linagora.com>
Committed: Fri Dec 1 13:51:43 2017 +0100

----------------------------------------------------------------------
 .../integration/SetMessagesMethodTest.java       |  9 ++++++---
 .../methods/SetMessagesCreationProcessor.java    | 19 ++++++++++++++++---
 2 files changed, 22 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/fa601b9f/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 5652090..3842a0e 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
@@ -1496,9 +1496,12 @@ public abstract class SetMessagesMethodTest {
             .log().ifValidationFails()
             .statusCode(200)
             .body(NAME, equalTo("messagesSet"))
-            .body(ARGUMENTS + ".notCreated", aMapWithSize(0))
-            .body(ARGUMENTS + ".created", aMapWithSize(1))
-            .body(ARGUMENTS + ".created", hasKey(messageCreationId));
+            .body(ARGUMENTS + ".created", aMapWithSize(0))
+            .body(ARGUMENTS + ".notCreated", aMapWithSize(1))
+            .body(ARGUMENTS + ".notCreated", hasKey(messageCreationId))
+            .body(ARGUMENTS + ".notCreated." + messageCreationId + ".type", equalTo("invalidProperties"))
+            .body(ARGUMENTS + ".notCreated." + messageCreationId + ".description", equalTo("Message creation is only supported in mailboxes with role Draft and Outbox"))
+            .body(ARGUMENTS + ".notCreated." + messageCreationId + ".properties", contains("mailboxIds"));
     }
 
     @Test

http://git-wip-us.apache.org/repos/asf/james-project/blob/fa601b9f/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 5cd4882..7733b46 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
@@ -178,10 +178,11 @@ public class SetMessagesCreationProcessor implements SetMessagesProcessor {
     }
     
     private void performCreate(CreationMessageEntry entry, Builder responseBuilder, MailboxSession session) throws MailboxException, InvalidMailboxForCreationException, MessagingException, AttachmentsNotFoundException {
-        if (isDraft(entry.getValue())) {
-            saveDraft(entry, responseBuilder, session);
-        } else if (isAppendToMailboxWithRole(Role.OUTBOX, entry.getValue(), session)) {
+        if (isAppendToMailboxWithRole(Role.OUTBOX, entry.getValue(), session)) {
             sendMailViaOutbox(entry, responseBuilder, session);
+        } else if (isDraft(entry.getValue())) {
+            assertNoOutbox(entry, session);
+            saveDraft(entry, responseBuilder, session);
         } else {
             if (isAppendToMailboxWithRole(Role.DRAFTS, entry.getValue(), session)) {
                 throw new InvalidDraftKeywordsException("A draft message should be flagged as Draft");
@@ -190,6 +191,12 @@ public class SetMessagesCreationProcessor implements SetMessagesProcessor {
         }
     }
 
+    private void assertNoOutbox(CreationMessageEntry entry, MailboxSession session) throws MailboxException {
+        if (isTargettingAMailboxWithRole(Role.OUTBOX, entry.getValue(), session)) {
+            throw new InvalidMailboxForCreationException("Mailbox ids can combine Outbox with other mailbox");
+        }
+    }
+
     private void sendMailViaOutbox(CreationMessageEntry entry, Builder responseBuilder, MailboxSession session) throws AttachmentsNotFoundException, MailboxException, MessagingException {
         validateArguments(entry, session);
         MessageWithId created = handleOutboxMessages(entry, session);
@@ -270,6 +277,12 @@ public class SetMessagesCreationProcessor implements SetMessagesProcessor {
                 .orElse(false);
     }
 
+    private boolean isTargettingAMailboxWithRole(Role role, CreationMessage entry, MailboxSession mailboxSession) throws MailboxException {
+        return getMailboxWithRole(mailboxSession, role)
+                .map(entry::isIn)
+                .orElse(false);
+    }
+
     private Optional<MessageManager> getMailboxWithRole(MailboxSession mailboxSession, Role role) throws MailboxException {
         return systemMailboxesProvider.getMailboxByRole(role, mailboxSession).findFirst();
     }


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


[4/4] james-project git commit: Merge remote-tracking branch 'btellier/JAMES-2244'

Posted by ad...@apache.org.
Merge remote-tracking branch 'btellier/JAMES-2244'


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

Branch: refs/heads/master
Commit: f2005bf0f0e9da5c98e60432c26b5551098bad30
Parents: 06ddc93 fa601b9
Author: Antoine Duprat <ad...@linagora.com>
Authored: Fri Dec 1 16:36:38 2017 +0100
Committer: Antoine Duprat <ad...@linagora.com>
Committed: Fri Dec 1 16:36:38 2017 +0100

----------------------------------------------------------------------
 .../integration/SetMessagesMethodTest.java      | 23 +++---
 .../cucumber/GetMessagesMethodStepdefs.java     |  2 +-
 .../cucumber/SetMessagesMethodStepdefs.java     | 10 ++-
 .../test/resources/cucumber/SetMessages.feature | 41 ++++++-----
 .../exceptions/InvalidOutboxMoveException.java  |  3 +
 .../methods/SetMessagesCreationProcessor.java   | 35 ++++-----
 .../methods/SetMessagesUpdateProcessor.java     | 74 +++++---------------
 7 files changed, 82 insertions(+), 106 deletions(-)
----------------------------------------------------------------------



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


[2/4] james-project git commit: JAMES-2244 Relax $Draft conditions

Posted by ad...@apache.org.
JAMES-2244 Relax $Draft conditions

    Still enforced restrictions:
      - Creation should be done with $Draft or in Outbox (Note that it was non explicitly enforced, as $Draft messages were necessarily in Drafts mailbox)
      - Only $Drafts messages can be sent (move)

    Relaxed conditions:
     - Now we can flip $Draft flag
     - Now we can move $Draft messages out of Drafts mailbox
     - Now we can have non $Draft messages in Drafts mailbox
     - Now I can create drafts out of Draft mailbox


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

Branch: refs/heads/master
Commit: 1eef6eabde66824e0e3d5dc9e1d2e3730e044fc1
Parents: d1ea4a2
Author: benwa <bt...@linagora.com>
Authored: Thu Nov 30 17:23:39 2017 +0700
Committer: Antoine Duprat <ad...@linagora.com>
Committed: Fri Dec 1 13:51:43 2017 +0100

----------------------------------------------------------------------
 .../integration/SetMessagesMethodTest.java      | 26 +++-----
 .../cucumber/GetMessagesMethodStepdefs.java     |  2 +-
 .../cucumber/SetMessagesMethodStepdefs.java     | 10 ++-
 .../test/resources/cucumber/SetMessages.feature | 41 ++++++------
 .../exceptions/InvalidOutboxMoveException.java  |  3 +
 .../methods/SetMessagesCreationProcessor.java   | 18 ++----
 .../methods/SetMessagesUpdateProcessor.java     | 66 +++++---------------
 7 files changed, 64 insertions(+), 102 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/1eef6eab/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 2470b51..5652090 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
@@ -1356,7 +1356,7 @@ public abstract class SetMessagesMethodTest {
     }
 
     @Test
-    public void setMessagesShouldFailWhenSavingADraftInSeveralMailboxes() {
+    public void setMessagesShouldNotFailWhenSavingADraftInSeveralMailboxes() {
         String messageCreationId = "creationId1337";
         String fromAddress = USERNAME;
         MailboxId mailboxId = mailboxProbe.createMailbox(MailboxConstants.USER_NAMESPACE, USERNAME, "mailbox");
@@ -1386,12 +1386,9 @@ public abstract class SetMessagesMethodTest {
             .log().ifValidationFails()
             .statusCode(200)
             .body(NAME, equalTo("messagesSet"))
-            .body(ARGUMENTS + ".created", aMapWithSize(0))
-            .body(ARGUMENTS + ".notCreated", aMapWithSize(1))
-            .body(ARGUMENTS + ".notCreated", hasKey(messageCreationId))
-            .body(ARGUMENTS + ".notCreated[\"" + messageCreationId + "\"].type", equalTo("invalidProperties"))
-            .body(ARGUMENTS + ".notCreated[\"" + messageCreationId + "\"].properties", contains("mailboxIds"))
-            .body(ARGUMENTS + ".notCreated[\"" + messageCreationId + "\"].description", equalTo("Message creation is only supported in mailboxes with role Draft and Outbox"));
+            .body(ARGUMENTS + ".notCreated", aMapWithSize(0))
+            .body(ARGUMENTS + ".created", aMapWithSize(1))
+            .body(ARGUMENTS + ".created", hasKey(messageCreationId));
     }
 
     @Test
@@ -1499,12 +1496,9 @@ public abstract class SetMessagesMethodTest {
             .log().ifValidationFails()
             .statusCode(200)
             .body(NAME, equalTo("messagesSet"))
-            .body(ARGUMENTS + ".created", aMapWithSize(0))
-            .body(ARGUMENTS + ".notCreated", aMapWithSize(1))
-            .body(ARGUMENTS + ".notCreated", hasKey(messageCreationId))
-            .body(ARGUMENTS + ".notCreated[\"" + messageCreationId + "\"].type", equalTo("invalidProperties"))
-            .body(ARGUMENTS + ".notCreated[\"" + messageCreationId + "\"].properties", contains("mailboxIds"))
-            .body(ARGUMENTS + ".notCreated[\"" + messageCreationId + "\"].description", equalTo("Message creation is only supported in mailboxes with role Draft and Outbox"));
+            .body(ARGUMENTS + ".notCreated", aMapWithSize(0))
+            .body(ARGUMENTS + ".created", aMapWithSize(1))
+            .body(ARGUMENTS + ".created", hasKey(messageCreationId));
     }
 
     @Test
@@ -1985,8 +1979,8 @@ public abstract class SetMessagesMethodTest {
             .statusCode(200)
             .body(NAME, equalTo("messagesSet"))
             .body(ARGUMENTS + ".notUpdated", hasKey(draftId))
-            .body(ARGUMENTS + ".notUpdated[\""+draftId+"\"].type", equalTo("invalidArguments"))
-            .body(ARGUMENTS + ".notUpdated[\""+draftId+"\"].description", endsWith("One can not have a message in mailboxes that don't have all the `draft` role"))
+            .body(ARGUMENTS + ".notUpdated[\""+draftId+"\"].type", equalTo("invalidProperties"))
+            .body(ARGUMENTS + ".notUpdated[\""+draftId+"\"].description", endsWith("When moving a message to Outbox, only Outboxes mailboxes should be targeted."))
             .body(ARGUMENTS + ".notUpdated[\""+draftId+"\"].properties", hasSize(1))
             .body(ARGUMENTS + ".notUpdated[\""+draftId+"\"].properties", contains("mailboxIds"))
             .body(ARGUMENTS + ".created", aMapWithSize(0));
@@ -2021,7 +2015,7 @@ public abstract class SetMessagesMethodTest {
             .body(NAME, equalTo("messagesSet"))
             .body(ARGUMENTS + ".notUpdated", hasKey(messageId))
             .body(ARGUMENTS + ".notUpdated[\""+messageId+"\"].type", equalTo("invalidProperties"))
-            .body(ARGUMENTS + ".notUpdated[\""+messageId+"\"].description", endsWith("only drafts can be moved to Outbox"))
+            .body(ARGUMENTS + ".notUpdated[\""+messageId+"\"].description", endsWith("Only message with `$Draft` keyword can be moved to Outbox"))
             .body(ARGUMENTS + ".notUpdated[\""+messageId+"\"].properties", hasSize(1))
             .body(ARGUMENTS + ".notUpdated[\""+messageId+"\"].properties", contains("mailboxIds"))
             .body(ARGUMENTS + ".created", aMapWithSize(0));

http://git-wip-us.apache.org/repos/asf/james-project/blob/1eef6eab/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 2717d7e..0d86080 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
@@ -697,7 +697,7 @@ public class GetMessagesMethodStepdefs {
             .isNullOrEmpty();
     }
 
-    @Then("^\"([^\"]*)\" should see message \"([^\"]*)\" with keywords (.*)$")
+    @Then("^\"([^\"]*)\" should see message \"([^\"]*)\" with keywords \"([^\"]*)\"$")
     public void assertKeywordsOfMessage(String user, String messageId, List<String> keywords) throws Exception {
         userStepdefs.execWithUser(user, () -> postWithAListOfIds(ImmutableList.of(messageId)));
 

http://git-wip-us.apache.org/repos/asf/james-project/blob/1eef6eab/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/cucumber/SetMessagesMethodStepdefs.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/cucumber/SetMessagesMethodStepdefs.java b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/cucumber/SetMessagesMethodStepdefs.java
index 026ac90..e3e74a7 100644
--- a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/cucumber/SetMessagesMethodStepdefs.java
+++ b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/cucumber/SetMessagesMethodStepdefs.java
@@ -249,6 +249,8 @@ public class SetMessagesMethodStepdefs {
                 "    {" +
                 "      \"create\": { \"" + message  + "\" : {" +
                 "        \"subject\": \"subject\"," +
+                "        \"from\": { \"name\": \"Me\", \"email\": \"" + username + "\"}," +
+                "        \"to\": [{ \"name\": \"Me\", \"email\": \"" + username + "\"}]," +
                 "        \"keywords\": {\"$Draft\": true}," +
                 "        \"mailboxIds\": [\"" + mailbox.getMailboxId().serialize() + "\"]" +
                 "      }}" +
@@ -319,9 +321,15 @@ public class SetMessagesMethodStepdefs {
     }
 
     @Then("^message \"([^\"]*)\" is not created$")
-    public void assertNotCreated(String messageName) throws Exception {;
+    public void assertNotCreated(String messageName) throws Exception {
         assertThat(httpClient.jsonPath.<Map<String, String>>read("[0][1].notCreated"))
             .containsOnlyKeys(messageName);
     }
 
+    @Then("^message \"([^\"]*)\" is created$")
+    public void assertCreated(String messageName) throws Exception {
+        assertThat(httpClient.jsonPath.<Map<String, String>>read("[0][1].created"))
+            .containsOnlyKeys(messageName);
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/1eef6eab/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/resources/cucumber/SetMessages.feature
----------------------------------------------------------------------
diff --git a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/resources/cucumber/SetMessages.feature b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/resources/cucumber/SetMessages.feature
index f3ac1bf..b3447fb 100644
--- a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/resources/cucumber/SetMessages.feature
+++ b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/resources/cucumber/SetMessages.feature
@@ -55,7 +55,7 @@ Feature: SetMessages method on shared folders
     Given "bob@domain.tld" shares his mailbox "shared" with "alice@domain.tld" with "lriws" rights
     And "alice@domain.tld" sets flags "$Flagged" on message "mAlice"
     And "alice@domain.tld" moves "mAlice" to mailbox "shared" of user "bob@domain.tld"
-    Then "alice@domain.tld" should see message "mAlice" with keywords $Flagged
+    Then "alice@domain.tld" should see message "mAlice" with keywords "$Flagged"
 
   Scenario: A delegated user can add sanitized messages to a shared mailbox when missing "write" right
     Given "bob@domain.tld" shares his mailbox "shared" with "alice@domain.tld" with "lri" rights
@@ -83,12 +83,12 @@ Feature: SetMessages method on shared folders
   Scenario: A user can update the flags on a message
     Given "alice@domain.tld" sets flags "$Flagged,$Seen" on message "mAlice"
     When "alice@domain.tld" sets flags "$Flagged,$Forwarded" on message "mAlice"
-    Then "alice@domain.tld" should see message "mAlice" with keywords $Flagged,$Forwarded
+    Then "alice@domain.tld" should see message "mAlice" with keywords "$Flagged,$Forwarded"
 
   Scenario: A delegated user add keywords on a delegated message when having "write" right
     Given "bob@domain.tld" shares his mailbox "shared" with "alice@domain.tld" with "lrw" rights
     When "alice@domain.tld" sets flags "$Flagged" on message "mBob"
-    Then "alice@domain.tld" should see message "mBob" with keywords $Flagged
+    Then "alice@domain.tld" should see message "mBob" with keywords "$Flagged"
 
   Scenario: A delegated user can not add keywords on a delegated message when missing "write" right
     Given "bob@domain.tld" shares his mailbox "shared" with "alice@domain.tld" with "latires" rights
@@ -113,20 +113,20 @@ Feature: SetMessages method on shared folders
     Given "bob@domain.tld" has a mailbox "Drafts"
     And "bob@domain.tld" tries to create a draft message "mDraft" in mailbox "Drafts"
     When "bob@domain.tld" sets flags "$Draft,$Seen" on message "mDraft"
-    Then "bob@domain.tld" should see message "mDraft" with keywords $Draft,$Seen
+    Then "bob@domain.tld" should see message "mDraft" with keywords "$Draft,$Seen"
 
-  Scenario: A user can not remove a draft flag on a draft messages
+  Scenario: A user can remove a draft flag on a draft messages
     Given "bob@domain.tld" has a mailbox "Drafts"
     And "bob@domain.tld" tries to create a draft message "mDraft" in mailbox "Drafts"
     When "bob@domain.tld" sets flags "$Seen" on message "mDraft"
-    Then message "mDraft" is not updated
-    And "bob@domain.tld" should see message "mDraft" with keywords $Draft
+    Then message "mDraft" is updated
+    And "bob@domain.tld" should see message "mDraft" with keywords "$Seen"
 
   Scenario: A user can add a flag on a draft
     Given "bob@domain.tld" has a mailbox "Drafts"
     And "bob@domain.tld" tries to create a draft message "mDraft" in mailbox "Drafts"
     When "bob@domain.tld" marks the message "mDraft" as flagged
-    Then "bob@domain.tld" should see message "mDraft" with keywords $Draft,$Flagged
+    Then "bob@domain.tld" should see message "mDraft" with keywords "$Draft,$Flagged"
 
   Scenario: A user can destroy a draft
     Given "bob@domain.tld" has a mailbox "Drafts"
@@ -135,16 +135,21 @@ Feature: SetMessages method on shared folders
     Then "bob@domain.tld" ask for message "mDraft"
     And the notFound list should contain "mDraft"
 
-  Scenario: Draft creation in outbox is not allowed
+  Scenario: Draft creation in outbox is allowed
     Given "bob@domain.tld" has a mailbox "Outbox"
     When "bob@domain.tld" tries to create a draft message "mDraft" in mailbox "Outbox"
-    Then message "mDraft" is not created
+    Then message "mDraft" is created
 
-  Scenario: A user can not move draft out of draft mailbox
+  Scenario: Draft creation in any mailbox is allowed
+    Given "bob@domain.tld" has a mailbox "Outbox"
+    When "bob@domain.tld" tries to create a draft message "mDraft" in mailbox "shared"
+    Then message "mDraft" is created
+
+  Scenario: A user can move draft out of draft mailbox
     Given "bob@domain.tld" has a mailbox "Drafts"
     And "bob@domain.tld" tries to create a draft message "mDraft" in mailbox "Drafts"
     When "bob@domain.tld" moves "mDraft" to user mailbox "shared"
-    Then message "mDraft" is not updated
+    Then message "mDraft" is updated
 
   Scenario: A user can move draft out of draft mailbox when removing draft flag
     Given "bob@domain.tld" has a mailbox "Drafts"
@@ -164,18 +169,18 @@ Feature: SetMessages method on shared folders
     When the user moves "mBob" to user mailbox "Drafts" and set flags "$Draft"
     Then message "mBob" is updated
 
-  Scenario: A user can not copy draft out of draft mailbox
+  Scenario: A user can copy draft out of draft mailbox
     Given "bob@domain.tld" has a mailbox "Drafts"
     And "bob@domain.tld" tries to create a draft message "mDraft" in mailbox "Drafts"
     When "bob@domain.tld" copies "mDraft" from mailbox "Drafts" to mailbox "shared"
-    Then message "mDraft" is not updated
+    Then message "mDraft" is updated
 
-  Scenario: A user can not copy draft out of draft mailbox
+  Scenario: A user can copy draft out of draft mailbox
     Given "bob@domain.tld" has a mailbox "Drafts"
     When "bob@domain.tld" moves "mBob" to user mailbox "Drafts"
-    Then message "mBob" is not updated
+    Then message "mBob" is updated
 
-  Scenario: A user can not copy draft out of draft mailbox
+  Scenario: A user can copy draft out of draft mailbox
     Given "bob@domain.tld" has a mailbox "Drafts"
     When "bob@domain.tld" copies "mBob" from mailbox "shared" to mailbox "Drafts"
-    Then message "mBob" is not updated
\ No newline at end of file
+    Then message "mBob" is updated
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/james-project/blob/1eef6eab/server/protocols/jmap/src/main/java/org/apache/james/jmap/exceptions/InvalidOutboxMoveException.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/exceptions/InvalidOutboxMoveException.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/exceptions/InvalidOutboxMoveException.java
index a70a750..dcf4b14 100644
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/exceptions/InvalidOutboxMoveException.java
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/exceptions/InvalidOutboxMoveException.java
@@ -20,4 +20,7 @@
 package org.apache.james.jmap.exceptions;
 
 public class InvalidOutboxMoveException extends RuntimeException {
+    public InvalidOutboxMoveException(String message) {
+        super(message);
+    }
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/1eef6eab/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 2f60b82..5cd4882 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
@@ -178,40 +178,30 @@ public class SetMessagesCreationProcessor implements SetMessagesProcessor {
     }
     
     private void performCreate(CreationMessageEntry entry, Builder responseBuilder, MailboxSession session) throws MailboxException, InvalidMailboxForCreationException, MessagingException, AttachmentsNotFoundException {
-        if (isAppendToMailboxWithRole(Role.DRAFTS, entry.getValue(), session)) {
+        if (isDraft(entry.getValue())) {
             saveDraft(entry, responseBuilder, session);
         } else if (isAppendToMailboxWithRole(Role.OUTBOX, entry.getValue(), session)) {
             sendMailViaOutbox(entry, responseBuilder, session);
         } else {
+            if (isAppendToMailboxWithRole(Role.DRAFTS, entry.getValue(), session)) {
+                throw new InvalidDraftKeywordsException("A draft message should be flagged as Draft");
+            }
             throw new InvalidMailboxForCreationException("The only implemented feature is sending via outbox and draft saving");
         }
     }
 
     private void sendMailViaOutbox(CreationMessageEntry entry, Builder responseBuilder, MailboxSession session) throws AttachmentsNotFoundException, MailboxException, MessagingException {
         validateArguments(entry, session);
-        assertNoDraftKeywords(entry.getValue());
         MessageWithId created = handleOutboxMessages(entry, session);
         responseBuilder.created(created.getCreationId(), created.getValue());
     }
 
     private void saveDraft(CreationMessageEntry entry, Builder responseBuilder, MailboxSession session) throws AttachmentsNotFoundException, MailboxException, MessagingException {
         attachmentChecker.assertAttachmentsExist(entry, session);
-        assertDraftKeywords(entry.getValue());
         MessageWithId created = handleDraftMessages(entry, session);
         responseBuilder.created(created.getCreationId(), created.getValue());
     }
 
-    private void assertDraftKeywords(CreationMessage creationMessage) {
-        if (!isDraft(creationMessage)) {
-            throw new InvalidDraftKeywordsException("A draft message should be flagged as Draft");
-        }
-    }
-
-    private void assertNoDraftKeywords(CreationMessage creationMessage) {
-        if (isDraft(creationMessage)) {
-            throw new InvalidDraftKeywordsException("A draft message can not be created out of draft mailbox");
-        }
-    }
 
     private Boolean isDraft(CreationMessage creationMessage) {
         if (creationMessage.getOldKeyword().isPresent()) {

http://git-wip-us.apache.org/repos/asf/james-project/blob/1eef6eab/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/SetMessagesUpdateProcessor.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/SetMessagesUpdateProcessor.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/SetMessagesUpdateProcessor.java
index 9086ea6..3fd703b 100644
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/SetMessagesUpdateProcessor.java
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/SetMessagesUpdateProcessor.java
@@ -139,7 +139,7 @@ public class SetMessagesUpdateProcessor implements SetMessagesProcessor {
         } catch (InvalidOutboxMoveException e) {
             ValidationResult invalidPropertyMailboxIds = ValidationResult.builder()
                 .property(MessageProperties.MessageProperty.mailboxIds.asFieldName())
-                .message("only drafts can be moved to Outbox")
+                .message(e.getMessage())
                 .build();
 
             handleInvalidRequest(builder, messageId, ImmutableList.of(invalidPropertyMailboxIds));
@@ -180,58 +180,33 @@ public class SetMessagesUpdateProcessor implements SetMessagesProcessor {
     }
 
     private void assertValidUpdate(List<MessageResult> messagesToBeUpdated, UpdateMessagePatch updateMessagePatch, MailboxSession session) throws MailboxException {
-        List<MailboxId> draftMailboxes = mailboxIdFor(Role.DRAFTS, session);
         List<MailboxId> outboxMailboxes = mailboxIdFor(Role.OUTBOX, session);
 
         ImmutableList<MailboxId> previousMailboxes = messagesToBeUpdated.stream()
             .map(MessageResult::getMailboxId)
             .collect(Guavate.toImmutableList());
-        List<Flags> futureFlags = patchFlags(messagesToBeUpdated, updateMessagePatch);
         List<MailboxId> targetMailboxes = getTargetedMailboxes(previousMailboxes, updateMessagePatch);
 
-        boolean originIsDraft = previousMailboxes.stream().allMatch(draftMailboxes::contains);
-        boolean targetIsOutbox = targetMailboxes.stream().anyMatch(outboxMailboxes::contains);
-        boolean targetHasDraft = targetMailboxes.stream().anyMatch(draftMailboxes::contains);
-        boolean targetHasNonDraft = targetMailboxes.stream().anyMatch(id -> !draftMailboxes.contains(id));
+        boolean allMessagesWereDrafts = messagesToBeUpdated.stream()
+            .map(MessageResult::getFlags)
+            .allMatch(flags -> flags.contains(Flags.Flag.DRAFT));
 
-        assertValidUpdate(futureFlags, targetHasDraft, targetHasNonDraft, targetIsOutbox, originIsDraft);
-    }
+        boolean targetContainsOutbox = targetMailboxes.stream().anyMatch(outboxMailboxes::contains);
+        boolean targetIsOnlyOutbox = targetMailboxes.stream().allMatch(outboxMailboxes::contains);
 
-    private void assertValidUpdate(List<Flags> futureFlags, boolean targetHasDraft, boolean targetHasNonDraft,
-                                   boolean targetIsOutbox, boolean originIsDraft) throws DraftMessageMailboxUpdateException {
-        assertMessageIsNotInDraftAndNonDraftMailboxes(targetHasDraft, targetHasNonDraft);
-        assertNoNonDraftMessageInsideDraftMailbox(futureFlags, targetHasDraft);
-        assertNoDraftMessageOutOfDraftMailbox(futureFlags, targetHasNonDraft);
-        assertOutboxMoveOnlyFromDraft(targetIsOutbox, originIsDraft);
+        assertOutboxMoveTargetsOnlyOutBox(targetContainsOutbox, targetIsOnlyOutbox);
+        assertOutboxMoveOriginallyHasDraftKeywordSet(targetContainsOutbox, allMessagesWereDrafts);
     }
 
-    private void assertOutboxMoveOnlyFromDraft(boolean targetIsOutbox, boolean originIsDraft) {
-        if (targetIsOutbox && !originIsDraft) {
-            throw new InvalidOutboxMoveException();
+    private void assertOutboxMoveTargetsOnlyOutBox(boolean targetContainsOutbox, boolean targetIsOnlyOutbox) {
+        if (targetContainsOutbox && !targetIsOnlyOutbox) {
+            throw new InvalidOutboxMoveException("When moving a message to Outbox, only Outboxes mailboxes should be targeted.");
         }
     }
 
-    private void assertMessageIsNotInDraftAndNonDraftMailboxes(boolean targetHasDraft, boolean targetHasNonDraft) throws DraftMessageMailboxUpdateException {
-        if (targetHasDraft && targetHasNonDraft) {
-            throw new DraftMessageMailboxUpdateException("One can not have a message in mailboxes that don't have all the `draft` role");
-        }
-    }
-
-    private void assertNoNonDraftMessageInsideDraftMailbox(List<Flags> futureFlags, boolean targetHasDraft) throws DraftMessageMailboxUpdateException {
-        if (targetHasDraft) {
-            boolean anyNonDraftMessage = futureFlags.stream().anyMatch(flags -> !flags.contains(Flags.Flag.DRAFT));
-            if (anyNonDraftMessage) {
-                throw new DraftMessageMailboxUpdateException("Messages without '$Draft' keyword are prohibited in drafts mailboxes");
-            }
-        }
-    }
-
-    private void assertNoDraftMessageOutOfDraftMailbox(List<Flags> futureFlags, boolean targetHasNonDraft) throws DraftMessageMailboxUpdateException {
-        if (targetHasNonDraft) {
-            boolean anyDraftMessage = futureFlags.stream().anyMatch(flags -> flags.contains(Flags.Flag.DRAFT));
-            if (anyDraftMessage) {
-                throw new DraftMessageMailboxUpdateException("Messages with '$Draft' keyword are prohibited in non drafts mailboxes");
-            }
+    private void assertOutboxMoveOriginallyHasDraftKeywordSet(boolean targetIsOutbox, boolean allMessagesWereDrafts) {
+        if (targetIsOutbox && !allMessagesWereDrafts) {
+            throw new InvalidOutboxMoveException("Only message with `$Draft` keyword can be moved to Outbox");
         }
     }
 
@@ -241,12 +216,6 @@ public class SetMessagesUpdateProcessor implements SetMessagesProcessor {
             .orElse(previousMailboxes);
     }
 
-    private List<Flags> patchFlags(List<MessageResult> messagesToBeUpdated, UpdateMessagePatch updateMessagePatch) {
-        return updateMessagePatch.getOldKeyword()
-                .map(oldKeyword -> flagsFromOldKeyword(messagesToBeUpdated, oldKeyword))
-                .orElse(flagsFromKeywords(messagesToBeUpdated, updateMessagePatch));
-    }
-
     private List<Flags> flagsFromOldKeyword(List<MessageResult> messagesToBeUpdated, OldKeyword oldKeyword) {
         return messagesToBeUpdated.stream()
                 .map(MessageResult::getFlags)
@@ -254,13 +223,6 @@ public class SetMessagesUpdateProcessor implements SetMessagesProcessor {
                 .collect(Guavate.toImmutableList());
     }
 
-    private ImmutableList<Flags> flagsFromKeywords(List<MessageResult> messagesToBeUpdated, UpdateMessagePatch updateMessagePatch) {
-        return messagesToBeUpdated.stream()
-                .map(MessageResult::getFlags)
-                .map(updateMessagePatch::applyToState)
-                .collect(Guavate.toImmutableList());
-    }
-
     private List<MailboxId> mailboxIdFor(Role role, MailboxSession session) throws MailboxException {
         return systemMailboxesProvider.getMailboxByRole(role, session)
             .map(MessageManager::getId)


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