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