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 ma...@apache.org on 2017/09/27 08:00:10 UTC
[1/6] james-project git commit: JAMES-2161 Keyword should support
underscore character in flags
Repository: james-project
Updated Branches:
refs/heads/master 0e5872cdf -> 4c3e0403c
JAMES-2161 Keyword should support underscore character in flags
Project: http://git-wip-us.apache.org/repos/asf/james-project/repo
Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/9c5b001b
Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/9c5b001b
Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/9c5b001b
Branch: refs/heads/master
Commit: 9c5b001b6670ef1667e6ef3d67e8815a2b9a0a42
Parents: 0e5872c
Author: Antoine Duprat <ad...@linagora.com>
Authored: Tue Sep 26 12:31:12 2017 +0200
Committer: Antoine Duprat <ad...@linagora.com>
Committed: Tue Sep 26 12:31:12 2017 +0200
----------------------------------------------------------------------
.../java/org/apache/james/jmap/model/Keyword.java | 6 +++++-
.../java/org/apache/james/jmap/model/KeywordTest.java | 14 ++++++++++++--
2 files changed, 17 insertions(+), 3 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/james-project/blob/9c5b001b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/Keyword.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/Keyword.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/Keyword.java
index ff1a2f0..72918d0 100644
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/Keyword.java
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/Keyword.java
@@ -20,6 +20,7 @@
package org.apache.james.jmap.model;
import java.util.Optional;
+
import javax.mail.Flags;
import org.apache.commons.lang.StringUtils;
@@ -34,7 +35,10 @@ import com.google.common.collect.ImmutableList;
public class Keyword {
private final static int FLAG_NAME_MIN_LENGTH = 1;
private final static int FLAG_NAME_MAX_LENGTH = 255;
- private final static CharMatcher FLAG_NAME_PATTERN = CharMatcher.JAVA_LETTER_OR_DIGIT.or(CharMatcher.is('$'));
+ private final static CharMatcher FLAG_NAME_PATTERN =
+ CharMatcher.JAVA_LETTER_OR_DIGIT
+ .or(CharMatcher.is('$'))
+ .or(CharMatcher.is('_'));
public final static Keyword DRAFT = new Keyword("$Draft");
public final static Keyword SEEN = new Keyword("$Seen");
http://git-wip-us.apache.org/repos/asf/james-project/blob/9c5b001b/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/KeywordTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/KeywordTest.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/KeywordTest.java
index 3eeb6f5..58fdb24 100644
--- a/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/KeywordTest.java
+++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/KeywordTest.java
@@ -20,16 +20,18 @@
package org.apache.james.jmap.model;
import static org.assertj.core.api.Assertions.assertThat;
+
import java.util.Optional;
+
import javax.mail.Flags;
import org.apache.commons.lang3.StringUtils;
-
-import nl.jqno.equalsverifier.EqualsVerifier;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
+import nl.jqno.equalsverifier.EqualsVerifier;
+
public class KeywordTest {
private final static int FLAG_NAME_MAX_LENTH = 255;
private final static String ANY_KEYWORD = "AnyKeyword";
@@ -185,4 +187,12 @@ public class KeywordTest {
assertThat(keyword.asFlags())
.isEqualTo(new Flags(ANY_KEYWORD));
}
+
+ @Test
+ public void asFlagsShouldReturnFlagsWhenUserFlagContainsUnderscore() throws Exception {
+ String userFlag = "$has_cal";
+ Keyword keyword = new Keyword(userFlag);
+ assertThat(keyword.asFlags())
+ .isEqualTo(new Flags(userFlag));
+ }
}
\ 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
[4/6] james-project git commit: JAMES-2160 Handle JMAP headers
provided at creation time
Posted by ma...@apache.org.
JAMES-2160 Handle JMAP headers provided at creation time
Project: http://git-wip-us.apache.org/repos/asf/james-project/repo
Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/93cef1dd
Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/93cef1dd
Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/93cef1dd
Branch: refs/heads/master
Commit: 93cef1ddd0ef1deb8092710f473cacc2e5328e50
Parents: 0e5872c
Author: Raphael Ouazana <ra...@linagora.com>
Authored: Mon Sep 25 15:22:13 2017 +0200
Committer: Matthieu Baechler <ma...@apache.org>
Committed: Wed Sep 27 09:58:16 2017 +0200
----------------------------------------------------------------------
.../integration/SetMessagesMethodTest.java | 151 +++++++++++++++++++
.../jmap/methods/MIMEMessageConverter.java | 40 ++++-
.../jmap/methods/MIMEMessageConverterTest.java | 138 +++++++++++++++++
3 files changed, 321 insertions(+), 8 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/james-project/blob/93cef1dd/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 f22b2de..f22472b 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
@@ -3375,6 +3375,157 @@ public abstract class SetMessagesMethodTest {
}
@Test
+ public void setMessagesShouldSetUserAddedHeaders() throws Exception {
+ String messageCreationId = "creationId1337";
+ String requestBody = "[" +
+ " [" +
+ " \"setMessages\","+
+ " {" +
+ " \"create\": { \"" + messageCreationId + "\" : {" +
+ " \"from\": { \"name\": \"Me\", \"email\": \"" + USERNAME + "\"}," +
+ " \"to\": [{ \"name\": \"Me\", \"email\": \"" + USERNAME + "\"}]," +
+ " \"headers\": { \"X-MY-SPECIAL-HEADER\": \"first header value\", \"OTHER-HEADER\": \"other value\"}," +
+ " \"subject\": \"Thank you for joining example.com!\"," +
+ " \"textBody\": \"Hello someone, and thank you for joining example.com!\"," +
+ " \"mailboxIds\": [\"" + getOutboxId(accessToken) + "\"]" +
+ " }}" +
+ " }," +
+ " \"#0\"" +
+ " ]" +
+ "]";
+
+ String messageId = given()
+ .header("Authorization", accessToken.serialize())
+ .body(requestBody)
+ // When
+ .post("/jmap")
+ .then()
+ .extract()
+ .body()
+ .<String>path(ARGUMENTS + ".created."+ messageCreationId +".id");
+
+ calmlyAwait.atMost(30, TimeUnit.SECONDS).until( () -> isAnyMessageFoundInInbox(accessToken));
+
+ String message = ARGUMENTS + ".list[0]";
+
+ with()
+ .header("Authorization", accessToken.serialize())
+ .body("[[\"getMessages\", {\"ids\": [\"" + messageId + "\"]}, \"#0\"]]")
+ .when()
+ .post("/jmap")
+ .then()
+ .statusCode(200)
+ .log().ifValidationFails()
+ .body(NAME, equalTo("messages"))
+ .body(ARGUMENTS + ".list", hasSize(1))
+ .body(message + ".headers", Matchers.allOf(
+ hasEntry("X-MY-SPECIAL-HEADER", "first header value"),
+ hasEntry("OTHER-HEADER", "other value")));
+ }
+
+ @Test
+ public void setMessagesShouldSetUserAddedHeadersInSent() throws Exception {
+ String toUsername = "username1@" + USERS_DOMAIN;
+ String password = "password";
+ dataProbe.addUser(toUsername, password);
+ mailboxProbe.createMailbox(MailboxConstants.USER_NAMESPACE, toUsername, DefaultMailboxes.INBOX);
+
+ String messageCreationId = "creationId1337";
+ String fromAddress = USERNAME;
+ String requestBody = "[" +
+ " [" +
+ " \"setMessages\","+
+ " {" +
+ " \"create\": { \"" + messageCreationId + "\" : {" +
+ " \"from\": { \"name\": \"Me\", \"email\": \"" + fromAddress + "\"}," +
+ " \"to\": [{ \"name\": \"BOB\", \"email\": \"" + toUsername + "\"}]," +
+ " \"headers\": { \"X-MY-SPECIAL-HEADER\": \"first header value\", \"OTHER-HEADER\": \"other value\"}," +
+ " \"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)
+ .post("/jmap");
+
+ String sentMailboxId = getMailboxId(accessToken, Role.SENT);
+
+ calmlyAwait.atMost(30, TimeUnit.SECONDS).until( () -> messageHasBeenMovedToSentBox(sentMailboxId));
+
+ String message = SECOND_ARGUMENTS + ".list[0]";
+ with()
+ .header("Authorization", this.accessToken.serialize())
+ .body("[[\"getMessageList\", {\"fetchMessages\":true, \"fetchMessageProperties\": [\"headers\"], \"filter\":{\"inMailboxes\":[\"" + sentMailboxId + "\"]}}, \"#0\"]]")
+ .when()
+ .post("/jmap")
+ .then()
+ .log().ifValidationFails()
+ .statusCode(200)
+ .body(SECOND_NAME, equalTo("messages"))
+ .body(SECOND_ARGUMENTS + ".list", hasSize(1))
+ .body(message + ".headers", Matchers.allOf(
+ hasEntry("X-MY-SPECIAL-HEADER", "first header value"),
+ hasEntry("OTHER-HEADER", "other value")));
+ }
+
+ @Test
+ public void setMessagesShouldFilterComputedHeadersFromUserAddedHeaders() throws Exception {
+ String messageCreationId = "creationId1337";
+ String requestBody = "[" +
+ " [" +
+ " \"setMessages\","+
+ " {" +
+ " \"create\": { \"" + messageCreationId + "\" : {" +
+ " \"from\": { \"name\": \"Me\", \"email\": \"" + USERNAME + "\"}," +
+ " \"to\": [{ \"name\": \"Me\", \"email\": \"" + USERNAME + "\"}]," +
+ " \"headers\": { \"From\": \"hacker@example.com\", \"X-MY-SPECIAL-HEADER\": \"first header value\", \"OTHER-HEADER\": \"other value\"}," +
+ " \"subject\": \"Thank you for joining example.com!\"," +
+ " \"textBody\": \"Hello someone, and thank you for joining example.com!\"," +
+ " \"mailboxIds\": [\"" + getOutboxId(accessToken) + "\"]" +
+ " }}" +
+ " }," +
+ " \"#0\"" +
+ " ]" +
+ "]";
+
+ String messageId = with()
+ .header("Authorization", accessToken.serialize())
+ .body(requestBody)
+ // When
+ .post("/jmap")
+ .then()
+ .extract()
+ .body()
+ .<String>path(ARGUMENTS + ".created."+ messageCreationId +".id");
+
+ calmlyAwait.atMost(30, TimeUnit.SECONDS).until( () -> isAnyMessageFoundInInbox(accessToken));
+
+ String message = ARGUMENTS + ".list[0]";
+
+ given()
+ .header("Authorization", accessToken.serialize())
+ .body("[[\"getMessages\", {\"ids\": [\"" + messageId + "\"]}, \"#0\"]]")
+ .when()
+ .post("/jmap")
+ .then()
+ .statusCode(200)
+ .log().ifValidationFails()
+ .body(NAME, equalTo("messages"))
+ .body(ARGUMENTS + ".list", hasSize(1))
+ .body(message + ".headers", Matchers.allOf(
+ hasEntry("X-MY-SPECIAL-HEADER", "first header value"),
+ hasEntry("OTHER-HEADER", "other value"),
+ not(hasEntry("From", "hacker@example.com")),
+ hasEntry("From", "Me <" + USERNAME + ">")));
+ }
+
+ @Test
public void setMessagesShouldCreateMessageWhenSendingMessageWithNonIndexableAttachment() throws Exception {
Attachment nonIndexableAttachment = Attachment.builder()
.bytes(IOUtils.toByteArray(ClassLoader.getSystemResourceAsStream("attachment/nonIndexableAttachment.html")))
http://git-wip-us.apache.org/repos/asf/james-project/blob/93cef1dd/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/MIMEMessageConverter.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/MIMEMessageConverter.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/MIMEMessageConverter.java
index 4fdecf1..c964c7d 100644
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/MIMEMessageConverter.java
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/MIMEMessageConverter.java
@@ -22,6 +22,8 @@ package org.apache.james.jmap.methods;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Date;
+import java.util.List;
+import java.util.Locale;
import java.util.Optional;
import java.util.TimeZone;
import java.util.function.Consumer;
@@ -42,6 +44,7 @@ import org.apache.james.mime4j.dom.TextBody;
import org.apache.james.mime4j.dom.address.Mailbox;
import org.apache.james.mime4j.dom.field.ContentDispositionField;
import org.apache.james.mime4j.dom.field.ContentTypeField;
+import org.apache.james.mime4j.dom.field.FieldName;
import org.apache.james.mime4j.dom.field.UnstructuredField;
import org.apache.james.mime4j.field.Fields;
import org.apache.james.mime4j.field.UnstructuredFieldImpl;
@@ -50,12 +53,12 @@ import org.apache.james.mime4j.message.BodyPart;
import org.apache.james.mime4j.message.BodyPartBuilder;
import org.apache.james.mime4j.message.DefaultMessageWriter;
import org.apache.james.mime4j.message.MultipartBuilder;
-import org.apache.james.mime4j.stream.Field;
import org.apache.james.mime4j.stream.NameValuePair;
import org.apache.james.mime4j.stream.RawField;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.github.steveash.guavate.Guavate;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Splitter;
import com.google.common.base.Throwables;
@@ -77,6 +80,24 @@ public class MIMEMessageConverter {
private static final String FIELD_PARAMETERS_SEPARATOR = ";";
private static final String QUOTED_PRINTABLE = "quoted-printable";
private static final String BASE64 = "base64";
+ private static final String IN_REPLY_TO_HEADER = "In-Reply-To";
+ private static final List<String> COMPUTED_HEADERS = ImmutableList.of(
+ FieldName.FROM,
+ FieldName.SENDER,
+ FieldName.REPLY_TO,
+ FieldName.TO,
+ FieldName.CC,
+ FieldName.BCC,
+ FieldName.SUBJECT,
+ FieldName.MESSAGE_ID,
+ FieldName.DATE,
+ IN_REPLY_TO_HEADER,
+ FieldName.CONTENT_TYPE,
+ FieldName.MIME_VERSION,
+ FieldName.CONTENT_TRANSFER_ENCODING);
+ private static final List<String> LOWERCASED_COMPUTED_HEADERS = COMPUTED_HEADERS.stream()
+ .map(s -> s.toLowerCase(Locale.ENGLISH))
+ .collect(Guavate.toImmutableList());
private final BasicBodyFactory bodyFactory;
@@ -137,18 +158,21 @@ public class MIMEMessageConverter {
// note that date conversion probably lose milliseconds!
messageBuilder.setDate(Date.from(newMessage.getDate().toInstant()), TimeZone.getTimeZone(newMessage.getDate().getZone()));
- newMessage.getInReplyToMessageId().ifPresent(addInReplyToHeader(messageBuilder::addField));
+ newMessage.getInReplyToMessageId()
+ .ifPresent(id -> addHeader(messageBuilder, IN_REPLY_TO_HEADER, id));
if (!isMultipart(newMessage, messageAttachments)) {
newMessage.getHtmlBody().ifPresent(x -> messageBuilder.setContentType(HTML_MEDIA_TYPE, UTF_8_CHARSET));
}
+ newMessage.getHeaders().entrySet().stream()
+ .filter(header -> ! header.getKey().trim().isEmpty())
+ .filter(header -> ! LOWERCASED_COMPUTED_HEADERS.contains(header.getKey().toLowerCase(Locale.ENGLISH)))
+ .forEach(header -> addHeader(messageBuilder, header.getKey(), header.getValue()));
}
- private Consumer<String> addInReplyToHeader(Consumer<Field> headerAppender) {
- return msgId -> {
- FieldParser<UnstructuredField> parser = UnstructuredFieldImpl.PARSER;
- RawField rawField = new RawField("In-Reply-To", msgId);
- headerAppender.accept(parser.parse(rawField, DecodeMonitor.SILENT));
- };
+ private void addHeader(Message.Builder messageBuilder, String fieldName, String value) {
+ FieldParser<UnstructuredField> parser = UnstructuredFieldImpl.PARSER;
+ RawField rawField = new RawField(fieldName, value);
+ messageBuilder.addField(parser.parse(rawField, DecodeMonitor.SILENT));
}
private boolean isMultipart(CreationMessage newMessage, ImmutableList<MessageAttachment> messageAttachments) {
http://git-wip-us.apache.org/repos/asf/james-project/blob/93cef1dd/server/protocols/jmap/src/test/java/org/apache/james/jmap/methods/MIMEMessageConverterTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/methods/MIMEMessageConverterTest.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/methods/MIMEMessageConverterTest.java
index 6fbb98d..9e9a2cf 100644
--- a/server/protocols/jmap/src/test/java/org/apache/james/jmap/methods/MIMEMessageConverterTest.java
+++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/methods/MIMEMessageConverterTest.java
@@ -47,6 +47,7 @@ import org.apache.james.mime4j.stream.Field;
import org.junit.Test;
import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
public class MIMEMessageConverterTest {
@Test
@@ -71,6 +72,143 @@ public class MIMEMessageConverterTest {
.containsOnly(matchingMessageId);
}
+ @Test
+ public void convertToMimeShouldAddHeaderWhenProvided() {
+ // Given
+ MIMEMessageConverter sut = new MIMEMessageConverter();
+
+ CreationMessage messageHavingInReplyTo = CreationMessage.builder()
+ .from(DraftEmailer.builder().name("sender").build())
+ .headers(ImmutableMap.of("FIRST", "first value"))
+ .mailboxIds(ImmutableList.of("dead-beef-1337"))
+ .subject("subject")
+ .build();
+
+ // When
+ Message result = sut.convertToMime(new ValueWithId.CreationMessageEntry(
+ CreationMessageId.of("user|mailbox|1"), messageHavingInReplyTo), ImmutableList.of());
+
+ // Then
+ assertThat(result.getHeader().getFields("FIRST")).extracting(Field::getBody)
+ .containsOnly("first value");
+ }
+
+ @Test
+ public void convertToMimeShouldAddHeadersWhenProvided() {
+ // Given
+ MIMEMessageConverter sut = new MIMEMessageConverter();
+
+ CreationMessage messageHavingInReplyTo = CreationMessage.builder()
+ .from(DraftEmailer.builder().name("sender").build())
+ .headers(ImmutableMap.of("FIRST", "first value", "SECOND", "second value"))
+ .mailboxIds(ImmutableList.of("dead-beef-1337"))
+ .subject("subject")
+ .build();
+
+ // When
+ Message result = sut.convertToMime(new ValueWithId.CreationMessageEntry(
+ CreationMessageId.of("user|mailbox|1"), messageHavingInReplyTo), ImmutableList.of());
+
+ // Then
+ assertThat(result.getHeader().getFields("FIRST")).extracting(Field::getBody)
+ .containsOnly("first value");
+ assertThat(result.getHeader().getFields("SECOND")).extracting(Field::getBody)
+ .containsOnly("second value");
+ }
+
+ @Test
+ public void convertToMimeShouldFilterGeneratedHeadersWhenProvided() {
+ // Given
+ MIMEMessageConverter sut = new MIMEMessageConverter();
+
+ String joesEmail = "joe@example.com";
+ CreationMessage messageHavingInReplyTo = CreationMessage.builder()
+ .from(DraftEmailer.builder().email(joesEmail).name("joe").build())
+ .headers(ImmutableMap.of("From", "hacker@example.com", "VALID", "valid header value"))
+ .mailboxIds(ImmutableList.of("dead-beef-1337"))
+ .subject("subject")
+ .build();
+
+ // When
+ Message result = sut.convertToMime(new ValueWithId.CreationMessageEntry(
+ CreationMessageId.of("user|mailbox|1"), messageHavingInReplyTo), ImmutableList.of());
+
+ // Then
+ assertThat(result.getFrom()).extracting(Mailbox::getAddress)
+ .allMatch(f -> f.equals(joesEmail));
+ assertThat(result.getHeader().getFields("VALID")).extracting(Field::getBody)
+ .containsOnly("valid header value");
+ assertThat(result.getHeader().getFields("From")).extracting(Field::getBody)
+ .containsOnly("joe <jo...@example.com>");
+ }
+
+ @Test
+ public void convertToMimeShouldFilterGeneratedHeadersRegardlessOfCaseWhenProvided() {
+ // Given
+ MIMEMessageConverter sut = new MIMEMessageConverter();
+
+ String joesEmail = "joe@example.com";
+ CreationMessage messageHavingInReplyTo = CreationMessage.builder()
+ .from(DraftEmailer.builder().email(joesEmail).name("joe").build())
+ .headers(ImmutableMap.of("frOM", "hacker@example.com", "VALID", "valid header value"))
+ .mailboxIds(ImmutableList.of("dead-beef-1337"))
+ .subject("subject")
+ .build();
+
+ // When
+ Message result = sut.convertToMime(new ValueWithId.CreationMessageEntry(
+ CreationMessageId.of("user|mailbox|1"), messageHavingInReplyTo), ImmutableList.of());
+
+ // Then
+ assertThat(result.getFrom()).extracting(Mailbox::getAddress)
+ .allMatch(f -> f.equals(joesEmail));
+ assertThat(result.getHeader().getFields("VALID")).extracting(Field::getBody)
+ .containsOnly("valid header value");
+ assertThat(result.getHeader().getFields("From")).extracting(Field::getBody)
+ .containsOnly("joe <jo...@example.com>");
+ }
+
+ @Test
+ public void convertToMimeShouldFilterEmptyHeaderNames() {
+ // Given
+ MIMEMessageConverter sut = new MIMEMessageConverter();
+
+ CreationMessage messageHavingInReplyTo = CreationMessage.builder()
+ .from(DraftEmailer.builder().name("joe").build())
+ .headers(ImmutableMap.of("", "empty header name value"))
+ .mailboxIds(ImmutableList.of("dead-beef-1337"))
+ .subject("subject")
+ .build();
+
+ // When
+ Message result = sut.convertToMime(new ValueWithId.CreationMessageEntry(
+ CreationMessageId.of("user|mailbox|1"), messageHavingInReplyTo), ImmutableList.of());
+
+ // Then
+ assertThat(result.getHeader().getFields("")).isEmpty();
+ }
+
+ @Test
+ public void convertToMimeShouldFilterWhiteSpacesOnlyHeaderNames() {
+ // Given
+ MIMEMessageConverter sut = new MIMEMessageConverter();
+
+ CreationMessage messageHavingInReplyTo = CreationMessage.builder()
+ .from(DraftEmailer.builder().name("joe").build())
+ .headers(ImmutableMap.of(" ", "only spaces header name values"))
+ .mailboxIds(ImmutableList.of("dead-beef-1337"))
+ .subject("subject")
+ .build();
+
+ // When
+ Message result = sut.convertToMime(new ValueWithId.CreationMessageEntry(
+ CreationMessageId.of("user|mailbox|1"), messageHavingInReplyTo), ImmutableList.of());
+
+ // Then
+ assertThat(result.getHeader().getFields(" ")).isEmpty();
+ assertThat(result.getHeader().getFields("")).isEmpty();
+ }
+
@Test(expected = IllegalArgumentException.class)
public void convertToMimeShouldThrowWhenMessageIsNull() {
MIMEMessageConverter sut = new MIMEMessageConverter();
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org
[2/6] james-project git commit: JAMES-2161 Don't throw when failing
to parse a flag
Posted by ma...@apache.org.
JAMES-2161 Don't throw when failing to parse a flag
Project: http://git-wip-us.apache.org/repos/asf/james-project/repo
Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/036096bb
Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/036096bb
Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/036096bb
Branch: refs/heads/master
Commit: 036096bb92ffb4896faf8ad4fd8873d71591495d
Parents: 9c5b001
Author: Antoine Duprat <ad...@linagora.com>
Authored: Tue Sep 26 12:33:30 2017 +0200
Committer: Antoine Duprat <ad...@linagora.com>
Committed: Wed Sep 27 08:52:04 2017 +0200
----------------------------------------------------------------------
.../org/apache/james/jmap/model/Keywords.java | 16 +++++++-
.../apache/james/jmap/model/MessageTest.java | 43 ++++++++++++++++++++
2 files changed, 58 insertions(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/james-project/blob/036096bb/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/Keywords.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/Keywords.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/Keywords.java
index 91aff31..ed07982 100644
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/Keywords.java
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/Keywords.java
@@ -25,9 +25,12 @@ import java.util.Optional;
import java.util.Set;
import java.util.function.Predicate;
import java.util.stream.Stream;
+
import javax.mail.Flags;
import org.apache.james.mailbox.FlagsBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import com.github.steveash.guavate.Guavate;
import com.google.common.annotations.VisibleForTesting;
@@ -38,7 +41,9 @@ import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
public class Keywords {
+
public static final Keywords DEFAULT_VALUE = factory().fromSet(ImmutableSet.of());
+ private static final Logger LOGGER = LoggerFactory.getLogger(Keywords.class);
public interface KeywordsValidator {
void validate(Set<Keyword> keywords);
@@ -121,12 +126,21 @@ public class Keywords {
public Keywords fromFlags(Flags flags) {
return fromSet(Stream.concat(
Stream.of(flags.getUserFlags())
- .map(Keyword::new),
+ .flatMap(this::asKeyword),
Stream.of(flags.getSystemFlags())
.map(Keyword::fromFlag))
.collect(Guavate.toImmutableSet()));
}
+ private Stream<Keyword> asKeyword(String flagName) {
+ try {
+ return Stream.of(new Keyword(flagName));
+ } catch (IllegalArgumentException e) {
+ LOGGER.warn("Fail to parse {} flag", flagName);
+ return Stream.of();
+ }
+ }
+
public Optional<Keywords> fromMapOrOldKeyword(Optional<Map<String, Boolean>> mapKeyword, Optional<OldKeyword> oldKeyword) {
Preconditions.checkArgument(!(mapKeyword.isPresent() && oldKeyword.isPresent()), "Does not support keyword and is* at the same time");
http://git-wip-us.apache.org/repos/asf/james-project/blob/036096bb/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/MessageTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/MessageTest.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/MessageTest.java
index d1c0914..2e690ba 100644
--- a/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/MessageTest.java
+++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/MessageTest.java
@@ -32,6 +32,7 @@ import org.junit.Test;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Maps;
public class MessageTest {
@@ -262,6 +263,48 @@ public class MessageTest {
}
@Test
+ public void buildShouldNotThrowWhenNonValidFlags() throws Exception {
+ Message.builder()
+ .id(TestMessageId.of(1))
+ .blobId(BlobId.of("blobId"))
+ .threadId("threadId")
+ .mailboxId(InMemoryId.of(456))
+ .headers(ImmutableMap.of("key", "value"))
+ .subject("subject")
+ .size(1)
+ .date(Instant.now())
+ .preview("preview")
+ .attachments(ImmutableList.of())
+ .flags(FlagsBuilder.builder()
+ .add("@ert", "t^a", "op§")
+ .build())
+ .build();
+ }
+
+ @Test
+ public void buildShouldIgnoreNonValidFlag() throws Exception {
+ Message message = Message.builder()
+ .id(TestMessageId.of(1))
+ .blobId(BlobId.of("blobId"))
+ .threadId("threadId")
+ .mailboxId(InMemoryId.of(456))
+ .headers(ImmutableMap.of("key", "value"))
+ .subject("subject")
+ .size(1)
+ .date(Instant.now())
+ .preview("preview")
+ .attachments(ImmutableList.of())
+ .flags(FlagsBuilder.builder()
+ .add("$Draft", "@ert", "t^a", "op§", "$user_flag")
+ .build())
+ .build();
+
+ assertThat(message.getKeywords()).containsOnly(
+ Maps.immutableEntry("$Draft", true),
+ Maps.immutableEntry("$user_flag", true));
+ }
+
+ @Test
public void hasAttachmentShouldReturnFalseWhenNoAttachment() throws Exception {
Message message = Message.builder()
.id(TestMessageId.of(1))
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org
[3/6] james-project git commit: JAMES-2160 Following the JMAP
specification, multi-valued fields should be separated by \n
Posted by ma...@apache.org.
JAMES-2160 Following the JMAP specification, multi-valued fields should be separated by \n
Project: http://git-wip-us.apache.org/repos/asf/james-project/repo
Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/4258cc6a
Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/4258cc6a
Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/4258cc6a
Branch: refs/heads/master
Commit: 4258cc6adbe78b14d8f5f963d47d73ac519c348e
Parents: 93cef1d
Author: Raphael Ouazana <ra...@linagora.com>
Authored: Mon Sep 25 16:43:38 2017 +0200
Committer: Matthieu Baechler <ma...@apache.org>
Committed: Wed Sep 27 09:58:16 2017 +0200
----------------------------------------------------------------------
.../integration/SetMessagesMethodTest.java | 125 ++++++++++++++++---
.../java/org/apache/james/jmap/JMAPServlet.java | 2 +
.../jmap/methods/MIMEMessageConverter.java | 8 +-
.../apache/james/jmap/model/MessageFactory.java | 4 +-
.../jmap/methods/MIMEMessageConverterTest.java | 21 ++++
.../james/jmap/model/MessageFactoryTest.java | 49 ++++++++
6 files changed, 187 insertions(+), 22 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/james-project/blob/4258cc6a/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 f22472b..0e2e40f 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
@@ -77,6 +77,7 @@ import org.apache.james.modules.MailboxProbeImpl;
import org.apache.james.probe.DataProbe;
import org.apache.james.util.ZeroedInputStream;
import org.apache.james.utils.DataProbeImpl;
+import org.apache.james.utils.IMAPMessageReader;
import org.apache.james.utils.JmapGuiceProbe;
import org.apache.james.utils.MessageIdProbe;
import org.apache.james.utils.SMTPMessageSender;
@@ -101,11 +102,13 @@ import com.jayway.restassured.RestAssured;
import com.jayway.restassured.builder.RequestSpecBuilder;
import com.jayway.restassured.builder.ResponseSpecBuilder;
import com.jayway.restassured.http.ContentType;
+import com.jayway.restassured.parsing.Parser;
import com.jayway.restassured.specification.ResponseSpecification;
public abstract class SetMessagesMethodTest {
private static final String LOCALHOST_IP = "127.0.0.1";
private static final int SMTP_PORT = 1025;
+ private static final int IMAP_PORT = 1143;
private static final String FORWARDED = "$Forwarded";
private static final int _1MB = 1024*1024;
private static final String NAME = "[0][0]";
@@ -114,7 +117,8 @@ public abstract class SetMessagesMethodTest {
private static final String SECOND_ARGUMENTS = "[1][1]";
private static final String USERS_DOMAIN = "domain.tld";
private static final String USERNAME = "username@" + USERS_DOMAIN;
- public static final MailboxPath USER_MAILBOX = new MailboxPath(MailboxConstants.USER_NAMESPACE, USERNAME, "mailbox");
+ private static final String PASSWORD = "password";
+ private static final MailboxPath USER_MAILBOX = new MailboxPath(MailboxConstants.USER_NAMESPACE, USERNAME, "mailbox");
private static final String NOT_UPDATED = ARGUMENTS + ".notUpdated";
private ConditionFactory calmlyAwait;
@@ -146,12 +150,12 @@ public abstract class SetMessagesMethodTest {
.setPort(jmapServer.getProbe(JmapGuiceProbe.class).getJmapPort())
.build();
RestAssured.enableLoggingOfRequestAndResponseIfValidationFails();
+ RestAssured.defaultParser = Parser.JSON;
- String password = "password";
dataProbe.addDomain(USERS_DOMAIN);
- dataProbe.addUser(USERNAME, password);
+ dataProbe.addUser(USERNAME, PASSWORD);
mailboxProbe.createMailbox("#private", USERNAME, DefaultMailboxes.INBOX);
- accessToken = HttpJmapAuthentication.authenticateJamesUser(baseUri(), USERNAME, password);
+ accessToken = HttpJmapAuthentication.authenticateJamesUser(baseUri(), USERNAME, PASSWORD);
mailboxProbe.createMailbox(MailboxConstants.USER_NAMESPACE, USERNAME, DefaultMailboxes.OUTBOX);
mailboxProbe.createMailbox(MailboxConstants.USER_NAMESPACE, USERNAME, DefaultMailboxes.TRASH);
@@ -3433,23 +3437,23 @@ public abstract class SetMessagesMethodTest {
String messageCreationId = "creationId1337";
String fromAddress = USERNAME;
String requestBody = "[" +
- " [" +
- " \"setMessages\","+
- " {" +
- " \"create\": { \"" + messageCreationId + "\" : {" +
- " \"from\": { \"name\": \"Me\", \"email\": \"" + fromAddress + "\"}," +
- " \"to\": [{ \"name\": \"BOB\", \"email\": \"" + toUsername + "\"}]," +
- " \"headers\": { \"X-MY-SPECIAL-HEADER\": \"first header value\", \"OTHER-HEADER\": \"other value\"}," +
- " \"subject\": \"Thank you for joining example.com!\"," +
- " \"textBody\": \"Hello someone, and thank you for joining example.com!\"," +
- " \"mailboxIds\": [\"" + getOutboxId(accessToken) + "\"]" +
- " }}" +
- " }," +
- " \"#0\"" +
- " ]" +
- "]";
+ " [" +
+ " \"setMessages\","+
+ " {" +
+ " \"create\": { \"" + messageCreationId + "\" : {" +
+ " \"from\": { \"name\": \"Me\", \"email\": \"" + fromAddress + "\"}," +
+ " \"to\": [{ \"name\": \"BOB\", \"email\": \"" + toUsername + "\"}]," +
+ " \"headers\": { \"X-MY-SPECIAL-HEADER\": \"first header value\", \"OTHER-HEADER\": \"other value\"}," +
+ " \"subject\": \"Thank you for joining example.com!\"," +
+ " \"textBody\": \"Hello someone, and thank you for joining example.com!\"," +
+ " \"mailboxIds\": [\"" + getOutboxId(accessToken) + "\"]" +
+ " }}" +
+ " }," +
+ " \"#0\"" +
+ " ]" +
+ "]";
- given()
+ with()
.header("Authorization", accessToken.serialize())
.body(requestBody)
.post("/jmap");
@@ -3475,6 +3479,87 @@ public abstract class SetMessagesMethodTest {
}
@Test
+ public void setMessagesShouldSetMultivaluedUserAddedHeaders() throws Exception {
+ String messageCreationId = "creationId1337";
+ String requestBody = "[" +
+ " [" +
+ " \"setMessages\","+
+ " {" +
+ " \"create\": { \"" + messageCreationId + "\" : {" +
+ " \"from\": { \"name\": \"Me\", \"email\": \"" + USERNAME + "\"}," +
+ " \"to\": [{ \"name\": \"Me\", \"email\": \"" + USERNAME + "\"}]," +
+ " \"headers\": { \"X-MY-MULTIVALUATED-HEADER\": \"first value\nsecond value\"}," +
+ " \"subject\": \"Thank you for joining example.com!\"," +
+ " \"textBody\": \"Hello someone, and thank you for joining example.com!\"," +
+ " \"mailboxIds\": [\"" + getOutboxId(accessToken) + "\"]" +
+ " }}" +
+ " }," +
+ " \"#0\"" +
+ " ]" +
+ "]";
+
+ String messageId = given()
+ .header("Authorization", accessToken.serialize())
+ .body(requestBody)
+ // When
+ .post("/jmap")
+ .then()
+ .extract()
+ .body()
+ .<String>path(ARGUMENTS + ".created."+ messageCreationId +".id");
+
+ calmlyAwait.atMost(30, TimeUnit.SECONDS).until( () -> isAnyMessageFoundInInbox(accessToken));
+
+ String message = ARGUMENTS + ".list[0]";
+
+ with()
+ .header("Authorization", accessToken.serialize())
+ .body("[[\"getMessages\", {\"ids\": [\"" + messageId + "\"]}, \"#0\"]]")
+ .when()
+ .post("/jmap")
+ .then()
+ .statusCode(200)
+ .log().ifValidationFails()
+ .body(NAME, equalTo("messages"))
+ .body(ARGUMENTS + ".list", hasSize(1))
+ .body(message + ".headers", hasEntry("X-MY-MULTIVALUATED-HEADER", "first value\nsecond value"));
+ }
+
+ @Test
+ public void setMessagesShouldRenderCorrectlyInIMAPMultivaluedUserAddedHeaders() throws Exception {
+ String messageCreationId = "creationId1337";
+ String requestBody = "[" +
+ " [" +
+ " \"setMessages\","+
+ " {" +
+ " \"create\": { \"" + messageCreationId + "\" : {" +
+ " \"from\": { \"name\": \"Me\", \"email\": \"" + USERNAME + "\"}," +
+ " \"to\": [{ \"name\": \"Me\", \"email\": \"" + USERNAME + "\"}]," +
+ " \"headers\": { \"X-MY-MULTIVALUATED-HEADER\": \"first value\nsecond value\"}," +
+ " \"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)
+ .post("/jmap");
+
+ calmlyAwait.atMost(30, TimeUnit.SECONDS).until( () -> isAnyMessageFoundInInbox(accessToken));
+
+ try (IMAPMessageReader imapMessageReader = new IMAPMessageReader(LOCALHOST_IP, IMAP_PORT);) {
+ assertThat(imapMessageReader.readFirstMessageHeadersInInbox(USERNAME, PASSWORD))
+ .contains("X-MY-MULTIVALUATED-HEADER: first value")
+ .contains("X-MY-MULTIVALUATED-HEADER: second value");
+ }
+ }
+
+ @Test
public void setMessagesShouldFilterComputedHeadersFromUserAddedHeaders() throws Exception {
String messageCreationId = "creationId1337";
String requestBody = "[" +
http://git-wip-us.apache.org/repos/asf/james-project/blob/4258cc6a/server/protocols/jmap/src/main/java/org/apache/james/jmap/JMAPServlet.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/JMAPServlet.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/JMAPServlet.java
index 8ace83e..c1f1fea 100644
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/JMAPServlet.java
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/JMAPServlet.java
@@ -42,6 +42,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.core.JsonParser.Feature;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
@@ -62,6 +63,7 @@ public class JMAPServlet extends HttpServlet {
this.requestHandler = requestHandler;
this.metricFactory = metricFactory;
this.objectMapper = new ObjectMapper();
+ objectMapper.configure(Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true);
}
@Override
http://git-wip-us.apache.org/repos/asf/james-project/blob/4258cc6a/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/MIMEMessageConverter.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/MIMEMessageConverter.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/MIMEMessageConverter.java
index c964c7d..cf6ce7e 100644
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/MIMEMessageConverter.java
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/MIMEMessageConverter.java
@@ -32,6 +32,7 @@ import java.util.stream.Collectors;
import org.apache.james.jmap.model.CreationMessage;
import org.apache.james.jmap.model.CreationMessage.DraftEmailer;
import org.apache.james.jmap.model.CreationMessageId;
+import org.apache.james.jmap.model.MessageFactory;
import org.apache.james.mailbox.model.MessageAttachment;
import org.apache.james.mime4j.Charsets;
import org.apache.james.mime4j.codec.DecodeMonitor;
@@ -166,9 +167,14 @@ public class MIMEMessageConverter {
newMessage.getHeaders().entrySet().stream()
.filter(header -> ! header.getKey().trim().isEmpty())
.filter(header -> ! LOWERCASED_COMPUTED_HEADERS.contains(header.getKey().toLowerCase(Locale.ENGLISH)))
- .forEach(header -> addHeader(messageBuilder, header.getKey(), header.getValue()));
+ .forEach(header -> addMultivaluedHeader(messageBuilder, header.getKey(), header.getValue()));
}
+ private void addMultivaluedHeader(Message.Builder messageBuilder, String fieldName, String multipleValues) {
+ Splitter.on(MessageFactory.JMAP_MULTIVALUED_FIELD_DELIMITER).split(multipleValues)
+ .forEach(value -> addHeader(messageBuilder, fieldName, value));
+ }
+
private void addHeader(Message.Builder messageBuilder, String fieldName, String value) {
FieldParser<UnstructuredField> parser = UnstructuredFieldImpl.PARSER;
RawField rawField = new RawField(fieldName, value);
http://git-wip-us.apache.org/repos/asf/james-project/blob/4258cc6a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/MessageFactory.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/MessageFactory.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/MessageFactory.java
index 236be87..05f2589 100644
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/MessageFactory.java
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/MessageFactory.java
@@ -63,6 +63,8 @@ import com.google.common.collect.Sets;
public class MessageFactory {
+ public static final String JMAP_MULTIVALUED_FIELD_DELIMITER = "\n";
+
private static final MimeConfig MIME_ENTITY_CONFIG = MimeConfig.custom()
.setMaxContentLen(-1)
.setMaxHeaderCount(-1)
@@ -196,7 +198,7 @@ public class MessageFactory {
.map(MimeUtil::unscrambleHeaderValue)
.collect(Collectors.toList())
.stream()
- .collect(Collectors.joining(","));
+ .collect(Collectors.joining(JMAP_MULTIVALUED_FIELD_DELIMITER));
return Multimaps.index(fields, Field::getName)
.asMap()
.entrySet()
http://git-wip-us.apache.org/repos/asf/james-project/blob/4258cc6a/server/protocols/jmap/src/test/java/org/apache/james/jmap/methods/MIMEMessageConverterTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/methods/MIMEMessageConverterTest.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/methods/MIMEMessageConverterTest.java
index 9e9a2cf..167408b 100644
--- a/server/protocols/jmap/src/test/java/org/apache/james/jmap/methods/MIMEMessageConverterTest.java
+++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/methods/MIMEMessageConverterTest.java
@@ -169,6 +169,27 @@ public class MIMEMessageConverterTest {
}
@Test
+ public void convertToMimeShouldAddMultivaluedHeadersWhenProvided() {
+ // Given
+ MIMEMessageConverter sut = new MIMEMessageConverter();
+
+ CreationMessage messageHavingInReplyTo = CreationMessage.builder()
+ .from(DraftEmailer.builder().name("sender").build())
+ .headers(ImmutableMap.of("FIRST", "first value\nsecond value"))
+ .mailboxIds(ImmutableList.of("dead-beef-1337"))
+ .subject("subject")
+ .build();
+
+ // When
+ Message result = sut.convertToMime(new ValueWithId.CreationMessageEntry(
+ CreationMessageId.of("user|mailbox|1"), messageHavingInReplyTo), ImmutableList.of());
+
+ // Then
+ assertThat(result.getHeader().getFields("FIRST")).extracting(Field::getBody)
+ .containsOnly("first value", "second value");
+ }
+
+ @Test
public void convertToMimeShouldFilterEmptyHeaderNames() {
// Given
MIMEMessageConverter sut = new MIMEMessageConverter();
http://git-wip-us.apache.org/repos/asf/james-project/blob/4258cc6a/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/MessageFactoryTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/MessageFactoryTest.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/MessageFactoryTest.java
index 2d86294..24b0a1e 100644
--- a/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/MessageFactoryTest.java
+++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/MessageFactoryTest.java
@@ -233,6 +233,55 @@ public class MessageFactoryTest {
}
@Test
+ public void multivaluedHeadersShouldBeSeparatedByLineFeed() throws Exception {
+ Flags flags = new Flags(Flag.SEEN);
+ String headers = "From: user <us...@domain>\n"
+ + "Subject: test subject\n"
+ + "Multi-header: first value\n"
+ + "To: user1 <us...@domain>\n"
+ + "Multi-header: second value\n";
+ MetaDataWithContent testMail = MetaDataWithContent.builder()
+ .uid(MessageUid.of(2))
+ .flags(flags)
+ .size(headers.length())
+ .internalDate(INTERNAL_DATE)
+ .content(new ByteArrayInputStream(headers.getBytes(Charsets.UTF_8)))
+ .attachments(ImmutableList.of())
+ .mailboxId(MAILBOX_ID)
+ .messageId(TestMessageId.of(2))
+ .build();
+
+ Emailer user = Emailer.builder().name("user").email("user@domain").build();
+ Emailer user1 = Emailer.builder().name("user1").email("user1@domain").build();
+ ImmutableMap<String, String> headersMap = ImmutableMap.<String, String>builder()
+ .put("From", "user <us...@domain>")
+ .put("Subject", "test subject")
+ .put("Multi-header", "first value\nsecond value")
+ .put("To", "user1 <us...@domain>")
+ .put("MIME-Version", "1.0")
+ .build();
+ Message testee = messageFactory.fromMetaDataWithContent(testMail);
+ Message expected = Message.builder()
+ .id(TestMessageId.of(2))
+ .blobId(BlobId.of("blobId"))
+ .threadId("2")
+ .mailboxId(MAILBOX_ID)
+ .headers(headersMap)
+ .from(user)
+ .to(ImmutableList.of(user1))
+ .subject("test subject")
+ .date(Instant.parse("2012-02-03T14:30:42.000Z"))
+ .size(headers.length())
+ .preview("(Empty)")
+ .textBody(Optional.of(""))
+ .htmlBody(Optional.empty())
+ .flags(flags)
+ .build();
+
+ assertThat(testee).isEqualToComparingFieldByField(expected);
+ }
+
+ @Test
public void textBodyShouldBeSetIntoMessage() throws Exception {
String headers = "Subject: test subject\n";
String body = "Mail body";
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org
[6/6] james-project git commit: Merge remote-tracking branch
'linagora/pr/988'
Posted by ma...@apache.org.
Merge remote-tracking branch 'linagora/pr/988'
Project: http://git-wip-us.apache.org/repos/asf/james-project/repo
Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/4c3e0403
Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/4c3e0403
Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/4c3e0403
Branch: refs/heads/master
Commit: 4c3e0403c860beab9ace2df0e212375d9592011d
Parents: 28282fe 036096b
Author: Matthieu Baechler <ma...@apache.org>
Authored: Wed Sep 27 09:59:31 2017 +0200
Committer: Matthieu Baechler <ma...@apache.org>
Committed: Wed Sep 27 09:59:31 2017 +0200
----------------------------------------------------------------------
.../org/apache/james/jmap/model/Keyword.java | 6 ++-
.../org/apache/james/jmap/model/Keywords.java | 16 +++++++-
.../apache/james/jmap/model/KeywordTest.java | 14 ++++++-
.../apache/james/jmap/model/MessageTest.java | 43 ++++++++++++++++++++
4 files changed, 75 insertions(+), 4 deletions(-)
----------------------------------------------------------------------
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org
[5/6] james-project git commit: JAMES-2160 Indent: no space between
two open parenthesis
Posted by ma...@apache.org.
JAMES-2160 Indent: no space between two open parenthesis
Project: http://git-wip-us.apache.org/repos/asf/james-project/repo
Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/28282fe0
Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/28282fe0
Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/28282fe0
Branch: refs/heads/master
Commit: 28282fe0b89d2f924f144c62e06c75ab878f8ae3
Parents: 4258cc6
Author: Raphael Ouazana <ra...@linagora.com>
Authored: Tue Sep 26 14:23:32 2017 +0200
Committer: Matthieu Baechler <ma...@apache.org>
Committed: Wed Sep 27 09:58:16 2017 +0200
----------------------------------------------------------------------
.../james/jmap/VacationIntegrationTest.java | 6 +--
.../integration/SetMessagesMethodTest.java | 48 ++++++++++----------
2 files changed, 27 insertions(+), 27 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/james-project/blob/28282fe0/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/VacationIntegrationTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/VacationIntegrationTest.java b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/VacationIntegrationTest.java
index 7b37044..de160b9 100644
--- a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/VacationIntegrationTest.java
+++ b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/VacationIntegrationTest.java
@@ -151,7 +151,7 @@ public abstract class VacationIntegrationTest {
.until(() -> isTextMessageReceived(user1AccessToken, getInboxId(user1AccessToken), ORIGINAL_MESSAGE_TEXT_BODY, USER_2, USER_1));
// User 2 should well receive a notification about user 1 vacation
calmlyAwait.atMost(30, TimeUnit.SECONDS)
- .until( () -> isTextMessageReceived(user2AccessToken, getInboxId(user2AccessToken), REASON, USER_1, USER_2));
+ .until(() -> isTextMessageReceived(user2AccessToken, getInboxId(user2AccessToken), REASON, USER_1, USER_2));
}
@Test
@@ -175,7 +175,7 @@ public abstract class VacationIntegrationTest {
.until(() -> isTextMessageReceived(user1AccessToken, getInboxId(user1AccessToken), ORIGINAL_MESSAGE_TEXT_BODY, USER_2, USER_1));
// User 2 should well receive a notification about user 1 vacation
calmlyAwait.atMost(30, TimeUnit.SECONDS)
- .until( () -> isTextMessageReceived(user2AccessToken, getInboxId(user2AccessToken), "", USER_1, USER_2));
+ .until(() -> isTextMessageReceived(user2AccessToken, getInboxId(user2AccessToken), "", USER_1, USER_2));
}
@Test
@@ -193,7 +193,7 @@ public abstract class VacationIntegrationTest {
calmlyAwait.atMost(10, TimeUnit.SECONDS)
.until(() -> isTextMessageReceived(user1AccessToken, getInboxId(user1AccessToken), ORIGINAL_MESSAGE_TEXT_BODY, USER_2, USER_1));
calmlyAwait.atMost(10, TimeUnit.SECONDS)
- .until( () -> assertOneMessageWithHtmlBodyReceived(user2AccessToken, getInboxId(user2AccessToken), HTML_REASON, USER_1, USER_2));
+ .until(() -> assertOneMessageWithHtmlBodyReceived(user2AccessToken, getInboxId(user2AccessToken), HTML_REASON, USER_1, USER_2));
}
@Test
http://git-wip-us.apache.org/repos/asf/james-project/blob/28282fe0/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 0e2e40f..06e2cec 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
@@ -1367,7 +1367,7 @@ public abstract class SetMessagesMethodTest {
.post("/jmap");
// Then
- calmlyAwait.atMost(30, TimeUnit.SECONDS).until( () -> messageHasBeenMovedToSentBox(sentMailboxId));
+ calmlyAwait.atMost(30, TimeUnit.SECONDS).until(() -> messageHasBeenMovedToSentBox(sentMailboxId));
}
private boolean messageHasBeenMovedToSentBox(String sentMailboxId) {
@@ -1565,7 +1565,7 @@ public abstract class SetMessagesMethodTest {
.when()
.post("/jmap");
// Then
- calmlyAwait.atMost(30, TimeUnit.SECONDS).until( () -> messageHasBeenMovedToSentBox(sentMailboxId));
+ calmlyAwait.atMost(30, TimeUnit.SECONDS).until(() -> messageHasBeenMovedToSentBox(sentMailboxId));
}
@Test
@@ -1676,7 +1676,7 @@ public abstract class SetMessagesMethodTest {
.post("/jmap");
// Then
- calmlyAwait.atMost(30, TimeUnit.SECONDS).until( () -> isAnyMessageFoundInRecipientsMailboxes(recipientToken));
+ calmlyAwait.atMost(30, TimeUnit.SECONDS).until(() -> isAnyMessageFoundInRecipientsMailboxes(recipientToken));
}
@Test
@@ -1720,7 +1720,7 @@ public abstract class SetMessagesMethodTest {
.post("/jmap");
// Then
- calmlyAwait.atMost(30, TimeUnit.SECONDS).until( () -> isAnyMessageFoundInRecipientsMailboxes(recipientToken));
+ calmlyAwait.atMost(30, TimeUnit.SECONDS).until(() -> isAnyMessageFoundInRecipientsMailboxes(recipientToken));
with()
.header("Authorization", recipientToken.serialize())
.body("[[\"getMessageList\", {\"fetchMessages\": true, \"fetchMessageProperties\": [\"bcc\"] }, \"#0\"]]")
@@ -1775,7 +1775,7 @@ public abstract class SetMessagesMethodTest {
.post("/jmap");
// Then
- calmlyAwait.atMost(30, TimeUnit.SECONDS).until( () -> messageHasBeenMovedToSentBox(sentMailboxId));
+ calmlyAwait.atMost(30, TimeUnit.SECONDS).until(() -> messageHasBeenMovedToSentBox(sentMailboxId));
with()
.header("Authorization", this.accessToken.serialize())
.body("[[\"getMessageList\", {\"fetchMessages\":true, \"fetchMessageProperties\": [\"bcc\"], \"filter\":{\"inMailboxes\":[\"" + sentMailboxId + "\"]}}, \"#0\"]]")
@@ -1834,7 +1834,7 @@ public abstract class SetMessagesMethodTest {
.post("/jmap");
// Then
- calmlyAwait.atMost(30, TimeUnit.SECONDS).until( () -> isAnyMessageFoundInRecipientsMailboxes(bccToken));
+ calmlyAwait.atMost(30, TimeUnit.SECONDS).until(() -> isAnyMessageFoundInRecipientsMailboxes(bccToken));
with()
.header("Authorization", bccToken.serialize())
.body("[[\"getMessageList\", {\"fetchMessages\": true, \"fetchMessageProperties\": [\"bcc\"] }, \"#0\"]]")
@@ -1904,7 +1904,7 @@ public abstract class SetMessagesMethodTest {
.post("/jmap");
// Then
- calmlyAwait.atMost(30, TimeUnit.SECONDS).until( () -> isHtmlMessageReceived(recipientToken));
+ calmlyAwait.atMost(30, TimeUnit.SECONDS).until(() -> isHtmlMessageReceived(recipientToken));
}
@@ -2053,7 +2053,7 @@ public abstract class SetMessagesMethodTest {
.post("/jmap");
// Then
- calmlyAwait.atMost(30, TimeUnit.SECONDS).until( () -> isTextPlusHtmlMessageReceived(recipientToken));
+ calmlyAwait.atMost(30, TimeUnit.SECONDS).until(() -> isTextPlusHtmlMessageReceived(recipientToken));
}
private boolean isTextPlusHtmlMessageReceived(AccessToken recipientToken) {
@@ -2827,7 +2827,7 @@ public abstract class SetMessagesMethodTest {
.when()
.post("/jmap").then();
- calmlyAwait.atMost(30, TimeUnit.SECONDS).until( () -> isAnyMessageFoundInInbox(accessToken));
+ calmlyAwait.atMost(30, TimeUnit.SECONDS).until(() -> isAnyMessageFoundInInbox(accessToken));
String message = ARGUMENTS + ".list[0]";
String firstAttachment = message + ".attachments[0]";
@@ -2923,7 +2923,7 @@ public abstract class SetMessagesMethodTest {
.body(requestBody)
.post("/jmap");
- calmlyAwait.atMost(30, TimeUnit.SECONDS).until( () -> isAnyMessageFoundInInbox(accessToken));
+ calmlyAwait.atMost(30, TimeUnit.SECONDS).until(() -> isAnyMessageFoundInInbox(accessToken));
String inboxId = getMailboxId(accessToken, Role.INBOX);
String receivedMessageId =
@@ -2995,7 +2995,7 @@ public abstract class SetMessagesMethodTest {
.when()
.post("/jmap");
- calmlyAwait.atMost(30, TimeUnit.SECONDS).until( () -> isAnyMessageFoundInInbox(accessToken));
+ calmlyAwait.atMost(30, TimeUnit.SECONDS).until(() -> isAnyMessageFoundInInbox(accessToken));
String inboxId = getMailboxId(accessToken, Role.INBOX);
String receivedMessageId =
@@ -3087,7 +3087,7 @@ public abstract class SetMessagesMethodTest {
.when()
.post("/jmap");
- calmlyAwait.atMost(30, TimeUnit.SECONDS).until( () -> isAnyMessageFoundInInbox(accessToken));
+ calmlyAwait.atMost(30, TimeUnit.SECONDS).until(() -> isAnyMessageFoundInInbox(accessToken));
String inboxId = getMailboxId(accessToken, Role.INBOX);
String receivedMessageId =
@@ -3160,7 +3160,7 @@ public abstract class SetMessagesMethodTest {
.when()
.post("/jmap");
- calmlyAwait.atMost(30, TimeUnit.SECONDS).until( () -> isAnyMessageFoundInInbox(accessToken));
+ calmlyAwait.atMost(30, TimeUnit.SECONDS).until(() -> isAnyMessageFoundInInbox(accessToken));
String inboxId = getMailboxId(accessToken, Role.INBOX);
String receivedMessageId =
@@ -3229,7 +3229,7 @@ public abstract class SetMessagesMethodTest {
.when()
.post("/jmap");
- calmlyAwait.atMost(30, TimeUnit.SECONDS).until( () -> isAnyMessageFoundInInbox(accessToken));
+ calmlyAwait.atMost(30, TimeUnit.SECONDS).until(() -> isAnyMessageFoundInInbox(accessToken));
String inboxId = getMailboxId(accessToken, Role.INBOX);
String receivedMessageId =
@@ -3293,7 +3293,7 @@ public abstract class SetMessagesMethodTest {
accessToken = HttpJmapAuthentication.authenticateJamesUser(baseUri(), toUsername, password);
String inboxMailboxId = getMailboxId(accessToken, Role.INBOX);
- calmlyAwait.atMost(60, TimeUnit.SECONDS).until( () -> messageInMailboxHasHeaders(inboxMailboxId, buildExpectedHeaders()));
+ calmlyAwait.atMost(60, TimeUnit.SECONDS).until(() -> messageInMailboxHasHeaders(inboxMailboxId, buildExpectedHeaders()));
}
@@ -3329,7 +3329,7 @@ public abstract class SetMessagesMethodTest {
String sentMailboxId = getMailboxId(accessToken, Role.SENT);
- calmlyAwait.atMost(60, TimeUnit.SECONDS).until( () -> messageInMailboxHasHeaders(sentMailboxId, buildExpectedHeaders()));
+ calmlyAwait.atMost(60, TimeUnit.SECONDS).until(() -> messageInMailboxHasHeaders(sentMailboxId, buildExpectedHeaders()));
}
@@ -3408,7 +3408,7 @@ public abstract class SetMessagesMethodTest {
.body()
.<String>path(ARGUMENTS + ".created."+ messageCreationId +".id");
- calmlyAwait.atMost(30, TimeUnit.SECONDS).until( () -> isAnyMessageFoundInInbox(accessToken));
+ calmlyAwait.atMost(30, TimeUnit.SECONDS).until(() -> isAnyMessageFoundInInbox(accessToken));
String message = ARGUMENTS + ".list[0]";
@@ -3460,7 +3460,7 @@ public abstract class SetMessagesMethodTest {
String sentMailboxId = getMailboxId(accessToken, Role.SENT);
- calmlyAwait.atMost(30, TimeUnit.SECONDS).until( () -> messageHasBeenMovedToSentBox(sentMailboxId));
+ calmlyAwait.atMost(30, TimeUnit.SECONDS).until(() -> messageHasBeenMovedToSentBox(sentMailboxId));
String message = SECOND_ARGUMENTS + ".list[0]";
with()
@@ -3508,7 +3508,7 @@ public abstract class SetMessagesMethodTest {
.body()
.<String>path(ARGUMENTS + ".created."+ messageCreationId +".id");
- calmlyAwait.atMost(30, TimeUnit.SECONDS).until( () -> isAnyMessageFoundInInbox(accessToken));
+ calmlyAwait.atMost(30, TimeUnit.SECONDS).until(() -> isAnyMessageFoundInInbox(accessToken));
String message = ARGUMENTS + ".list[0]";
@@ -3550,7 +3550,7 @@ public abstract class SetMessagesMethodTest {
.body(requestBody)
.post("/jmap");
- calmlyAwait.atMost(30, TimeUnit.SECONDS).until( () -> isAnyMessageFoundInInbox(accessToken));
+ calmlyAwait.atMost(30, TimeUnit.SECONDS).until(() -> isAnyMessageFoundInInbox(accessToken));
try (IMAPMessageReader imapMessageReader = new IMAPMessageReader(LOCALHOST_IP, IMAP_PORT);) {
assertThat(imapMessageReader.readFirstMessageHeadersInInbox(USERNAME, PASSWORD))
@@ -3589,7 +3589,7 @@ public abstract class SetMessagesMethodTest {
.body()
.<String>path(ARGUMENTS + ".created."+ messageCreationId +".id");
- calmlyAwait.atMost(30, TimeUnit.SECONDS).until( () -> isAnyMessageFoundInInbox(accessToken));
+ calmlyAwait.atMost(30, TimeUnit.SECONDS).until(() -> isAnyMessageFoundInInbox(accessToken));
String message = ARGUMENTS + ".list[0]";
@@ -3705,7 +3705,7 @@ public abstract class SetMessagesMethodTest {
.body()
.<String>path(ARGUMENTS + ".created."+ messageCreationId +".id");
- calmlyAwait.atMost(30, TimeUnit.SECONDS).until( () -> isAnyMessageFoundInInbox(accessToken));
+ calmlyAwait.atMost(30, TimeUnit.SECONDS).until(() -> isAnyMessageFoundInInbox(accessToken));
String message = ARGUMENTS + ".list[0]";
@@ -3765,7 +3765,7 @@ public abstract class SetMessagesMethodTest {
.body()
.<String>path(ARGUMENTS + ".created."+ messageCreationId +".id");
- calmlyAwait.atMost(30, TimeUnit.SECONDS).until( () -> isAnyMessageFoundInInbox(accessToken));
+ calmlyAwait.atMost(30, TimeUnit.SECONDS).until(() -> isAnyMessageFoundInInbox(accessToken));
given()
.header("Authorization", accessToken.serialize())
@@ -3949,7 +3949,7 @@ public abstract class SetMessagesMethodTest {
calmlyAwait.atMost(Duration.ONE_MINUTE).until(messageSender::messageHasBeenSent);
}
- calmlyAwait.atMost(30, TimeUnit.SECONDS).until( () -> isAnyMessageFoundInInbox(accessToken));
+ calmlyAwait.atMost(30, TimeUnit.SECONDS).until(() -> isAnyMessageFoundInInbox(accessToken));
String message = ARGUMENTS + ".list[0]";
String firstAttachment = message + ".attachments[0]";
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org