james-server-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From btell...@apache.org
Subject james-project git commit: JAMES-1734 As an authenticated JMAP user, I can prentend to be someone else in the mails I send
Date Thu, 19 May 2016 02:27:58 GMT
Repository: james-project
Updated Branches:
  refs/heads/master 5a76eee3d -> fef500291


JAMES-1734 As an authenticated JMAP user, I can prentend to be someone else in the mails I
send


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

Branch: refs/heads/master
Commit: fef5002917073088f7c9da2ea1cedf4a958ca2ef
Parents: 5a76eee
Author: Benoit Tellier <btellier@linagora.com>
Authored: Tue May 17 12:06:03 2016 +0700
Committer: Benoit Tellier <btellier@linagora.com>
Committed: Thu May 19 09:23:49 2016 +0700

----------------------------------------------------------------------
 .../integration/SetMessagesMethodTest.java      | 60 +++++++++++++++++---
 .../methods/SetMessagesCreationProcessor.java   | 43 +++++++++++++-
 .../SetMessagesCreationProcessorTest.java       |  2 +-
 .../james/jmap/model/CreationMessageTest.java   | 10 ++++
 4 files changed, 103 insertions(+), 12 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/fef50029/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 8f4d6eb..4f162ef 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
@@ -661,12 +661,13 @@ public abstract class SetMessagesMethodTest {
     @Test
     public void setMessageShouldReturnCreatedMessageWhenSendingMessage() {
         String messageCreationId = "user|inbox|1";
+        String fromAddress = username;
         String requestBody = "[" +
                 "  [" +
                 "    \"setMessages\","+
                 "    {" +
                 "      \"create\": { \"" + messageCreationId  + "\" : {" +
-                "        \"from\": { \"name\": \"MAILER-DAEMON\", \"email\": \"postmaster@example.com\"},"
+
+                "        \"from\": { \"name\": \"Me\", \"email\": \"" + fromAddress + "\"},"
+
                 "        \"to\": [{ \"name\": \"BOB\", \"email\": \"someone@example.com\"}],"
+
                 "        \"subject\": \"Thank you for joining example.com!\"," +
                 "        \"textBody\": \"Hello someone, and thank you for joining example.com!\","
+
@@ -715,6 +716,7 @@ public abstract class SetMessagesMethodTest {
         // Given
         String messageCreationId = "user|inbox|1";
         String presumedMessageId = "username@domain.tld|outbox|1";
+        String fromAddress = username;
         String messageSubject = "Thank you for joining example.com!";
         String outboxId = getOutboxId();
         String requestBody = "[" +
@@ -722,7 +724,7 @@ public abstract class SetMessagesMethodTest {
                 "    \"setMessages\","+
                 "    {" +
                 "      \"create\": { \"" + messageCreationId  + "\" : {" +
-                "        \"from\": { \"name\": \"MAILER-DAEMON\", \"email\": \"postmaster@example.com\"},"
+
+                "        \"from\": { \"name\": \"Me\", \"email\": \"" + fromAddress + "\"},"
+
                 "        \"to\": [{ \"name\": \"BOB\", \"email\": \"someone@example.com\"}],"
+
                 "        \"subject\": \"" + messageSubject + "\"," +
                 "        \"textBody\": \"Hello someone, and thank you for joining example.com!\","
+
@@ -766,6 +768,7 @@ public abstract class SetMessagesMethodTest {
                 .map(x -> x.get("id"))
                 .findFirst().get();
 
+        String fromAddress = username;
         String messageCreationId = "user|inbox|1";
         String messageSubject = "Thank you for joining example.com!";
         String requestBody = "[" +
@@ -773,7 +776,7 @@ public abstract class SetMessagesMethodTest {
                 "    \"setMessages\","+
                 "    {" +
                 "      \"create\": { \"" + messageCreationId  + "\" : {" +
-                "        \"from\": { \"name\": \"MAILER-DAEMON\", \"email\": \"postmaster@example.com\"},"
+
+                "        \"from\": { \"name\": \"Me\", \"email\": \"" + fromAddress + "\"},"
+
                 "        \"to\": [{ \"name\": \"BOB\", \"email\": \"someone@example.com\"}],"
+
                 "        \"subject\": \"" + messageSubject + "\"," +
                 "        \"textBody\": \"Hello someone, and thank you for joining example.com!\","
+
@@ -819,12 +822,13 @@ public abstract class SetMessagesMethodTest {
     @Test
     public void setMessagesShouldRejectWhenSendingMessageHasNoValidAddress() {
         String messageCreationId = "user|inbox|1";
+        String fromAddress = username;
         String requestBody = "[" +
                 "  [" +
                 "    \"setMessages\","+
                 "    {" +
                 "      \"create\": { \"" + messageCreationId  + "\" : {" +
-                "        \"from\": { \"name\": \"MAILER-DAEMON\", \"email\": \"postmaster@example.com\"},"
+
+                "        \"from\": { \"name\": \"Me\", \"email\": \"" + fromAddress + "\"},"
+
                 "        \"to\": [{ \"name\": \"BOB\", \"email\": \"someone@example.com@example.com\"}],"
+
                 "        \"cc\": [{ \"name\": \"ALICE\"}]," +
                 "        \"subject\": \"Thank you for joining example.com!\"," +
@@ -895,7 +899,7 @@ public abstract class SetMessagesMethodTest {
     @Test
     public void setMessagesShouldSucceedWhenSendingMessageWithOnlyFromAddress() {
         String messageCreationId = "user|inbox|1";
-        String fromAddress = "postmaster@example.com";
+        String fromAddress = username;
         String requestBody = "[" +
                 "  [" +
                 "    \"setMessages\","+
@@ -934,7 +938,7 @@ public abstract class SetMessagesMethodTest {
     @Test
     public void setMessagesShouldSucceedWithHtmlBody() {
         String messageCreationId = "user|inbox|1";
-        String fromAddress = "postmaster@example.com";
+        String fromAddress = username;
         String requestBody = "[" +
                 "  [" +
                 "    \"setMessages\","+
@@ -979,7 +983,7 @@ public abstract class SetMessagesMethodTest {
                 .findFirst().get();
 
         String messageCreationId = "user|inbox|1";
-        String fromAddress = "postmaster@example.com";
+        String fromAddress = username;
         String requestBody = "[" +
                 "  [" +
                 "    \"setMessages\","+
@@ -1014,12 +1018,13 @@ public abstract class SetMessagesMethodTest {
     @Test
     public void setMessagesShouldRejectWhenSendingMessageHasMissingSubject() {
         String messageCreationId = "user|inbox|1";
+        String fromAddress = username;
         String requestBody = "[" +
                 "  [" +
                 "    \"setMessages\","+
                 "    {" +
                 "      \"create\": { \"" + messageCreationId  + "\" : {" +
-                "        \"from\": { \"name\": \"MAILER-DAEMON\", \"email\": \"postmaster@example.com\"},"
+
+                "        \"from\": { \"name\": \"Me\", \"email\": \"" + fromAddress + "\"},"
+
                 "        \"to\": [{ \"name\": \"BOB\", \"email\": \"someone@example.com\"}],"
+
                 "        \"cc\": [{ \"name\": \"ALICE\"}]," +
                 "        \"textBody\": \"Hello someone, and thank you for joining example.com!\","
+
@@ -1049,6 +1054,45 @@ public abstract class SetMessagesMethodTest {
                 .body(ARGUMENTS + ".created", aMapWithSize(0));
     }
 
+
+    @Test
+    public void setMessagesShouldRejectWhenSendingMessageUseSomeoneElseFromAddress() {
+        String messageCreationId = "user|inbox|1";
+        String requestBody = "[" +
+            "  [" +
+            "    \"setMessages\","+
+            "    {" +
+            "      \"create\": { \"" + messageCreationId  + "\" : {" +
+            "        \"from\": { \"name\": \"Me\", \"email\": \"other@domain.tld\"}," +
+            "        \"to\": [{ \"name\": \"BOB\", \"email\": \"someone@example.com\"}],"
+
+            "        \"subject\": \"Thank you for joining example.com!\"," +
+            "        \"textBody\": \"Hello someone, and thank you for joining example.com!\","
+
+            "        \"mailboxIds\": [\"" + getOutboxId() + "\"]" +
+            "      }}" +
+            "    }," +
+            "    \"#0\"" +
+            "  ]" +
+            "]";
+
+        given()
+            .accept(ContentType.JSON)
+            .contentType(ContentType.JSON)
+            .header("Authorization", accessToken.serialize())
+            .body(requestBody)
+        .when()
+            .post("/jmap")
+        .then()
+            .log().ifValidationFails()
+            .statusCode(200)
+            .body(NAME, equalTo("messagesSet"))
+            .body(ARGUMENTS + ".notCreated", hasKey(messageCreationId))
+            .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 + ".created", aMapWithSize(0));
+    }
+
     @Test
     public void setMessagesShouldDeliverMessageToRecipient() throws Exception {
         // Sender

http://git-wip-us.apache.org/repos/asf/james-project/blob/fef50029/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 ff89bb1..c7bacc5 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
@@ -72,7 +72,9 @@ import com.github.fge.lambdas.functions.ThrowingFunction;
 import com.google.common.annotations.VisibleForTesting;
 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 {
 
@@ -111,11 +113,18 @@ public class SetMessagesCreationProcessor implements SetMessagesProcessor
{
             throw Throwables.propagate(e);
         }
 
+        List<String> allowedSenders = ImmutableList.of(mailboxSession.getUser().getUserName());
+
         // handle errors
-        Predicate<CreationMessage> validMessagesTester = CreationMessage::isValid;
+        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();
+
         SetMessagesResponse.Builder responseBuilder = SetMessagesResponse.builder()
-                .notCreated(handleCreationErrors(invalidMessagesTester, request));
+                .notCreated(handleCreationErrors(invalidMessagesTester, toValidationResults,
request));
 
         return request.getCreate().entrySet().stream()
                 .filter(e -> validMessagesTester.test(e.getValue()))
@@ -126,11 +135,39 @@ public class SetMessagesCreationProcessor implements SetMessagesProcessor
{
                 .build();
     }
 
+    private boolean isAllowedFromAddress(CreationMessage creationMessage, List<String>
allowedFromMailAddresses) {
+        return creationMessage.getFrom()
+            .map(draftEmailer -> draftEmailer.getEmail()
+                .map(allowedFromMailAddresses::contains)
+                .orElse(false))
+            .orElse(false);
+    }
+
+    private List<ValidationResult> validationResultForIncorrectAddress(CreationMessage
creationMessage, List<String> allowedSenders) {
+        return creationMessage.getFrom()
+            .map(draftEmailer -> draftEmailer
+                .getEmail()
+                .map(mail -> validationResultForIncorrectAddress(allowedSenders, mail))
+                .orElse(Lists.newArrayList()))
+            .orElse(Lists.newArrayList());
+    }
+
+    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());
+        }
+        return Lists.newArrayList();
+    }
+
     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(e.getValue().validate())))
+                .map(e -> new AbstractMap.SimpleEntry<>(e.getKey(), buildSetErrorFromValidationResult(toValidationResults.apply(e.getValue()))))
                 .collect(Collectors.toMap(AbstractMap.SimpleEntry::getKey, AbstractMap.SimpleEntry::getValue));
     }
 

http://git-wip-us.apache.org/repos/asf/james-project/blob/fef50029/server/protocols/jmap/src/test/java/org/apache/james/jmap/methods/SetMessagesCreationProcessorTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/methods/SetMessagesCreationProcessorTest.java
b/server/protocols/jmap/src/test/java/org/apache/james/jmap/methods/SetMessagesCreationProcessorTest.java
index db7b0ec..b8ec9e6 100644
--- a/server/protocols/jmap/src/test/java/org/apache/james/jmap/methods/SetMessagesCreationProcessorTest.java
+++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/methods/SetMessagesCreationProcessorTest.java
@@ -88,7 +88,7 @@ public class SetMessagesCreationProcessorTest {
 
     private MailboxSession buildStubbedSession() {
         MailboxSession.User stubUser = mock(MailboxSession.User.class);
-        when(stubUser.getUserName()).thenReturn("user");
+        when(stubUser.getUserName()).thenReturn("alice@example.com");
         MailboxSession stubSession = mock(MailboxSession.class);
         when(stubSession.getPathDelimiter()).thenReturn('.');
         when(stubSession.getUser()).thenReturn(stubUser);

http://git-wip-us.apache.org/repos/asf/james-project/blob/fef50029/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/CreationMessageTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/CreationMessageTest.java
b/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/CreationMessageTest.java
index 48fca1c..4b23626 100644
--- a/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/CreationMessageTest.java
+++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/CreationMessageTest.java
@@ -84,4 +84,14 @@ public class CreationMessageTest {
         assertThat(sut.validate()).extracting(ValidationResult::getErrorMessage).contains("no
recipient address set");
     }
 
+    @Test
+    public void validateShouldReturnEmptyListWhenNoErrors () {
+        CreationMessage sut = testedBuilder
+            .from(DraftEmailer.builder().name("bob").email("bob@example.com").build())
+            .to(ImmutableList.of(DraftEmailer.builder().name("riri").email("riri@example.com").build()))
+            .build();
+
+        assertThat(sut.validate()).isEmpty();
+    }
+
 }
\ No newline at end of file


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


Mime
View raw message