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/11/23 08:04:10 UTC

[5/6] james-project git commit: JAMES-2224 Assert that the sender of a message is the owner before putting it in outbox

JAMES-2224 Assert that the sender of a message is the owner before putting it 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/564a1a60
Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/564a1a60
Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/564a1a60

Branch: refs/heads/master
Commit: 564a1a60c21da6aae54ba78cbb1b6ad87b92003f
Parents: 9fc7e72
Author: Antoine Duprat <ad...@linagora.com>
Authored: Tue Nov 21 10:47:29 2017 +0100
Committer: Antoine Duprat <ad...@linagora.com>
Committed: Thu Nov 23 09:02:51 2017 +0100

----------------------------------------------------------------------
 .../integration/SetMessagesMethodTest.java      | 85 ++++++++++++++++++++
 .../test/resources/cucumber/SetMessages.feature |  7 ++
 .../james/jmap/methods/MessageSender.java       | 15 ----
 .../methods/SetMessagesCreationProcessor.java   | 11 +++
 .../methods/SetMessagesUpdateProcessor.java     |  9 +++
 5 files changed, 112 insertions(+), 15 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/564a1a60/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 1e78fa6..00a28d1 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
@@ -2213,6 +2213,91 @@ public abstract class SetMessagesMethodTest {
     }
 
     @Test
+    public void setMessagesShouldReturnNotCreatedWhenSendingMessageWithAnotherFromAddressThanTheConnectedUser() {
+        String messageCreationId = "creationId1337";
+        String requestBody = "[" +
+            "  [" +
+            "    \"setMessages\","+
+            "    {" +
+            "      \"create\": { \"" + messageCreationId  + "\" : {" +
+            "        \"from\": { \"email\": \"wrongaddress@otherdomain.org\"}," +
+            "        \"to\": [{ \"name\": \"BOB\", \"email\": \"someone@example.com\"}]," +
+            "        \"cc\": [{ \"name\": \"ALICE\"}]," +
+            "        \"subject\": \"Thank you for joining example.com!\"," +
+            "        \"textBody\": \"Hello someone, and thank you for joining example.com!\"," +
+            "        \"mailboxIds\": [\"" + getOutboxId(accessToken) + "\"]" +
+            "      }}" +
+            "    }," +
+            "    \"#0\"" +
+            "  ]" +
+            "]";
+
+        given()
+            .header("Authorization", accessToken.serialize())
+            .body(requestBody)
+        .when()
+            .post("/jmap")
+        .then()
+            .log().ifValidationFails()
+            .statusCode(200)
+            .body(NAME, equalTo("messagesSet"))
+            .body(ARGUMENTS + ".notCreated", aMapWithSize(1))
+            .body(ARGUMENTS + ".notCreated", hasKey(messageCreationId))
+            .body(ARGUMENTS + ".notCreated." + messageCreationId + ".type", equalTo("invalidProperties"))
+            .body(ARGUMENTS + ".notCreated." + messageCreationId + ".description", equalTo("Invalid 'from' field. Must be " + USERNAME));
+    }
+
+    @Test
+    public void setMessagesShouldNotCreateMessageInOutboxWhenSendingMessageWithAnotherFromAddressThanTheConnectedUser() {
+        String messageCreationId = "creationId1337";
+        String requestBody = "[" +
+            "  [" +
+            "    \"setMessages\","+
+            "    {" +
+            "      \"create\": { \"" + messageCreationId  + "\" : {" +
+            "        \"from\": { \"email\": \"wrongaddress@otherdomain.org\"}," +
+            "        \"to\": [{ \"name\": \"BOB\", \"email\": \"someone@example.com\"}]," +
+            "        \"cc\": [{ \"name\": \"ALICE\"}]," +
+            "        \"subject\": \"Thank you for joining example.com!\"," +
+            "        \"textBody\": \"Hello someone, and thank you for joining example.com!\"," +
+            "        \"mailboxIds\": [\"" + getOutboxId(accessToken) + "\"]" +
+            "      }}" +
+            "    }," +
+            "    \"#0\"" +
+            "  ]" +
+            "]";
+
+        given()
+            .header("Authorization", accessToken.serialize())
+            .body(requestBody)
+        .when()
+            .post("/jmap")
+        .then()
+            .log().ifValidationFails()
+            .statusCode(200);
+
+        String outboxId = getMailboxId(accessToken, Role.OUTBOX);
+        assertThat(hasNoMessageIn(bobAccessToken, outboxId)).isTrue();
+    }
+    
+    private boolean hasNoMessageIn(AccessToken accessToken, String mailboxId) {
+        try {
+            with()
+                .header("Authorization", accessToken.serialize())
+                .body("[[\"getMessageList\", {\"filter\":{\"inMailboxes\":[\"" + mailboxId + "\"]}}, \"#0\"]]")
+            .when()
+                .post("/jmap")
+            .then()
+                .statusCode(200)
+                .body(NAME, equalTo("messageList"))
+                .body(ARGUMENTS + ".messageIds", empty());
+            return true;
+        } catch (AssertionError e) {
+            return false;
+        } 
+    }
+
+    @Test
     public void setMessagesShouldSucceedWhenSendingMessageWithOnlyFromAddress() {
         String messageCreationId = "creationId1337";
         String fromAddress = USERNAME;

http://git-wip-us.apache.org/repos/asf/james-project/blob/564a1a60/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 2fdc88d..46ede38 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
@@ -141,6 +141,13 @@ Feature: SetMessages method on shared folders
     When the user moves "mDraft" to user mailbox "shared" and set flags ""
     Then message "mDraft" is updated
 
+  Scenario: A delegated user can not move draft from draft mailbox to outbox
+    Given "bob@domain.tld" has a mailbox "Drafts"
+    And "bob@domain.tld" tries to create a draft message "mDraft" in mailbox "Drafts"
+    When "alice@domain.tld" moves "mDraft" to mailbox "Outbox" of user "bob@domain.tld"
+    Then message "mDraft" is not updated
+    And message "mBob" has flags $Draft in mailbox "Drafts" of user "bob@domain.tld"
+
   Scenario: A user can move non-draft messages to draft mailbox when setting $Draft
     Given "bob@domain.tld" has a mailbox "Drafts"
     When the user moves "mBob" to user mailbox "Drafts" and set flags "$Draft"

http://git-wip-us.apache.org/repos/asf/james-project/blob/564a1a60/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/MessageSender.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/MessageSender.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/MessageSender.java
index d6835c9..ef18346 100644
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/MessageSender.java
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/MessageSender.java
@@ -22,7 +22,6 @@ package org.apache.james.jmap.methods;
 import javax.inject.Inject;
 import javax.mail.MessagingException;
 
-import org.apache.james.core.MailAddress;
 import org.apache.james.jmap.model.Envelope;
 import org.apache.james.jmap.model.MessageFactory;
 import org.apache.james.jmap.send.MailFactory;
@@ -47,7 +46,6 @@ public class MessageSender {
     public void sendMessage(MessageFactory.MetaDataWithContent message,
                             Envelope envelope,
                             MailboxSession session) throws MailboxException, MessagingException {
-        assertUserIsInSenders(envelope, session);
         Mail mail = mailFactory.build(message, envelope);
         try {
             MailMetadata metadata = new MailMetadata(message.getMessageId(), session.getUser().getUserName());
@@ -60,20 +58,7 @@ public class MessageSender {
     public void sendMessage(MessageId messageId,
                             Mail mail,
                             MailboxSession session) throws MailboxException, MessagingException {
-        assertUserIsSender(session, mail.getSender());
         MailMetadata metadata = new MailMetadata(messageId, session.getUser().getUserName());
         mailSpool.send(mail, metadata);
     }
-
-    private void assertUserIsInSenders(Envelope envelope, MailboxSession session) throws MailboxSendingNotAllowedException {
-        MailAddress sender = envelope.getFrom();
-        assertUserIsSender(session, sender);
-    }
-
-    private void assertUserIsSender(MailboxSession session, MailAddress sender) throws MailboxSendingNotAllowedException {
-        if (!session.getUser().isSameUser(sender.asString())) {
-            String allowedSender = session.getUser().getUserName();
-            throw new MailboxSendingNotAllowedException(allowedSender);
-        }
-    }
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/564a1a60/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 f9cf560..964ceeb 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
@@ -36,6 +36,7 @@ import org.apache.james.jmap.exceptions.MailboxNotOwnedException;
 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.CreationMessage.DraftEmailer;
 import org.apache.james.jmap.model.Envelope;
 import org.apache.james.jmap.model.Keyword;
 import org.apache.james.jmap.model.Message;
@@ -243,6 +244,7 @@ public class SetMessagesCreationProcessor implements SetMessagesProcessor {
     }
 
     private MessageWithId handleOutboxMessages(CreationMessageEntry entry, MailboxSession session) throws MailboxException, MessagingException {
+        assertUserIsSender(session, entry.getValue().getFrom());
         MessageManager outbox = getMailboxWithRole(session, Role.OUTBOX).orElseThrow(() -> new MailboxNotFoundException(Role.OUTBOX.serialize()));
         MetaDataWithContent newMessage = messageAppender.appendMessageInMailbox(entry, outbox, session);
         Message jmapMessage = messageFactory.fromMetaDataWithContent(newMessage);
@@ -251,6 +253,15 @@ public class SetMessagesCreationProcessor implements SetMessagesProcessor {
         return new ValueWithId.MessageWithId(entry.getCreationId(), jmapMessage);
     }
 
+    private void assertUserIsSender(MailboxSession session, Optional<DraftEmailer> from) throws MailboxSendingNotAllowedException {
+        if (!from.flatMap(DraftEmailer::getEmail)
+                .filter(email -> session.getUser().isSameUser(email))
+                .isPresent()) {
+            String allowedSender = session.getUser().getUserName();
+            throw new MailboxSendingNotAllowedException(allowedSender);
+        }
+    }
+
     private MessageWithId handleDraftMessages(CreationMessageEntry entry, MailboxSession session) throws MailboxException, MessagingException {
         MessageManager draftMailbox = getMailboxWithRole(session, Role.DRAFTS).orElseThrow(() -> new MailboxNotFoundException(Role.DRAFTS.serialize()));
         MetaDataWithContent newMessage = messageAppender.appendMessageInMailbox(entry, draftMailbox, session);

http://git-wip-us.apache.org/repos/asf/james-project/blob/564a1a60/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 e3865c0..e9de2f9 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
@@ -36,6 +36,7 @@ import javax.mail.MessagingException;
 import javax.mail.Session;
 import javax.mail.internet.MimeMessage;
 
+import org.apache.james.core.MailAddress;
 import org.apache.james.jmap.exceptions.DraftMessageMailboxUpdateException;
 import org.apache.james.jmap.exceptions.InvalidOutboxMoveException;
 import org.apache.james.jmap.model.MessageProperties;
@@ -163,6 +164,7 @@ public class SetMessagesUpdateProcessor implements SetMessagesProcessor {
                     .findFirst();
             if (messagesToSend.isPresent()) {
                 MailImpl mail = buildMailFromMessage(messagesToSend.get());
+                assertUserIsSender(mailboxSession, mail.getSender());
                 messageSender.sendMessage(messageId, mail, mailboxSession);
             } else {
                 addMessageIdNotFoundToResponse(messageId, builder);
@@ -170,6 +172,13 @@ public class SetMessagesUpdateProcessor implements SetMessagesProcessor {
         }
     }
 
+    private void assertUserIsSender(MailboxSession session, MailAddress sender) throws MailboxSendingNotAllowedException {
+        if (!session.getUser().isSameUser(sender.asString())) {
+            String allowedSender = session.getUser().getUserName();
+            throw new MailboxSendingNotAllowedException(allowedSender);
+        }
+    }
+
     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);


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