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 bt...@apache.org on 2016/05/19 02:27:58 UTC
james-project git commit: JAMES-1734 As an authenticated JMAP user,
I can prentend to be someone else in the mails I send
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 <bt...@linagora.com>
Authored: Tue May 17 12:06:03 2016 +0700
Committer: Benoit Tellier <bt...@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