You are viewing a plain text version of this content. The canonical link for it is here.
Posted to server-dev@james.apache.org by ad...@apache.org on 2016/07/08 14:46:36 UTC
[1/5] james-project git commit: JAMES-1790 blobId deserves a real type
Repository: james-project
Updated Branches:
refs/heads/master 1c294ddc0 -> 662fa4a95
JAMES-1790 blobId deserves a real type
Project: http://git-wip-us.apache.org/repos/asf/james-project/repo
Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/7be2166e
Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/7be2166e
Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/7be2166e
Branch: refs/heads/master
Commit: 7be2166ecb1fe3e7ed0711b67b5b506b14366d0d
Parents: a8d2de9
Author: Matthieu Baechler <ma...@linagora.com>
Authored: Tue Jul 5 17:01:32 2016 +0200
Committer: Antoine Duprat <ad...@linagora.com>
Committed: Fri Jul 8 14:24:55 2016 +0200
----------------------------------------------------------------------
.../org/apache/james/jmap/model/Attachment.java | 12 ++--
.../org/apache/james/jmap/model/BlobId.java | 58 +++++++++++++++++++
.../org/apache/james/jmap/model/Message.java | 28 +++++-----
.../apache/james/jmap/model/MessageFactory.java | 4 +-
.../org/apache/james/jmap/model/SubMessage.java | 12 ++--
.../james/jmap/json/ParsingWritingObjects.java | 3 +-
.../SetMessagesCreationProcessorTest.java | 3 +-
.../apache/james/jmap/model/AttachmentTest.java | 21 +++----
.../org/apache/james/jmap/model/BlobIdTest.java | 49 ++++++++++++++++
.../james/jmap/model/MailboxMessageTest.java | 59 +++++++++-----------
.../jmap/model/SetMessagesResponseTest.java | 4 +-
.../james/jmap/model/SubMailboxMessageTest.java | 8 +--
12 files changed, 180 insertions(+), 81 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/james-project/blob/7be2166e/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/Attachment.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/Attachment.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/Attachment.java
index 2cbed7f..2a62684 100644
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/Attachment.java
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/Attachment.java
@@ -38,7 +38,7 @@ public class Attachment {
@JsonPOJOBuilder(withPrefix = "")
public static class Builder {
- private String blobId;
+ private BlobId blobId;
private String type;
private String name;
private Long size;
@@ -47,7 +47,7 @@ public class Attachment {
private Long width;
private Long height;
- public Builder blobId(String blobId) {
+ public Builder blobId(BlobId blobId) {
this.blobId = blobId;
return this;
}
@@ -88,14 +88,14 @@ public class Attachment {
}
public Attachment build() {
- Preconditions.checkState(!Strings.isNullOrEmpty(blobId), "'blobId' is mandatory");
+ Preconditions.checkState(blobId != null, "'blobId' is mandatory");
Preconditions.checkState(!Strings.isNullOrEmpty(type), "'type' is mandatory");
Preconditions.checkState(size != null, "'size' is mandatory");
return new Attachment(blobId, type, Optional.ofNullable(name), size, Optional.ofNullable(cid), isInline, Optional.ofNullable(width), Optional.ofNullable(height));
}
}
- private final String blobId;
+ private final BlobId blobId;
private final String type;
private final Optional<String> name;
private final long size;
@@ -104,7 +104,7 @@ public class Attachment {
private final Optional<Long> width;
private final Optional<Long> height;
- @VisibleForTesting Attachment(String blobId, String type, Optional<String> name, long size, Optional<String> cid, boolean isInline, Optional<Long> width, Optional<Long> height) {
+ @VisibleForTesting Attachment(BlobId blobId, String type, Optional<String> name, long size, Optional<String> cid, boolean isInline, Optional<Long> width, Optional<Long> height) {
this.blobId = blobId;
this.type = type;
this.name = name;
@@ -115,7 +115,7 @@ public class Attachment {
this.height = height;
}
- public String getBlobId() {
+ public BlobId getBlobId() {
return blobId;
}
http://git-wip-us.apache.org/repos/asf/james-project/blob/7be2166e/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/BlobId.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/BlobId.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/BlobId.java
new file mode 100644
index 0000000..578c09f
--- /dev/null
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/BlobId.java
@@ -0,0 +1,58 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you under the Apache License, Version 2.0 (the *
+ * "License"); you may not use this file except in compliance *
+ * with the License. You may obtain a copy of the License at *
+ * *
+ * http://www.apache.org/licenses/LICENSE-2.0 *
+ * *
+ * Unless required by applicable law or agreed to in writing, *
+ * software distributed under the License is distributed on an *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
+ * KIND, either express or implied. See the License for the *
+ * specific language governing permissions and limitations *
+ * under the License. *
+ ****************************************************************/
+package org.apache.james.jmap.model;
+
+import java.util.Objects;
+
+import com.fasterxml.jackson.annotation.JsonValue;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Strings;
+
+public class BlobId {
+
+ public static BlobId of(String rawValue) {
+ Preconditions.checkArgument(!Strings.isNullOrEmpty(rawValue), "'rawValue' is mandatory");
+ return new BlobId(rawValue);
+ }
+
+ private final String rawValue;
+
+ private BlobId(String rawValue) {
+ this.rawValue = rawValue;
+ }
+
+ @JsonValue
+ public String getRawValue() {
+ return rawValue;
+ }
+
+ @Override
+ public final boolean equals(Object obj) {
+ if (obj instanceof BlobId) {
+ BlobId other = (BlobId) obj;
+ return Objects.equals(this.rawValue, other.rawValue);
+ }
+ return false;
+ }
+
+ @Override
+ public final int hashCode() {
+ return Objects.hashCode(this.rawValue);
+ }
+}
http://git-wip-us.apache.org/repos/asf/james-project/blob/7be2166e/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/Message.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/Message.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/Message.java
index 94b8517..2121843 100644
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/Message.java
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/Message.java
@@ -48,7 +48,7 @@ public class Message {
@JsonPOJOBuilder(withPrefix = "")
public static class Builder {
private MessageId id;
- private String blobId;
+ private BlobId blobId;
private String threadId;
private ImmutableList<String> mailboxIds;
private String inReplyToMessageId;
@@ -69,7 +69,7 @@ public class Message {
private String textBody;
private String htmlBody;
private final ImmutableList.Builder<Attachment> attachments;
- private final ImmutableMap.Builder<String, SubMessage> attachedMessages;
+ private final ImmutableMap.Builder<BlobId, SubMessage> attachedMessages;
private Builder() {
to = ImmutableList.builder();
@@ -85,7 +85,7 @@ public class Message {
return this;
}
- public Builder blobId(String blobId) {
+ public Builder blobId(BlobId blobId) {
this.blobId = blobId;
return this;
}
@@ -194,14 +194,14 @@ public class Message {
return this;
}
- public Builder attachedMessages(Map<String, SubMessage> attachedMessages) {
+ public Builder attachedMessages(Map<BlobId, SubMessage> attachedMessages) {
this.attachedMessages.putAll(attachedMessages);
return this;
}
public Message build() {
Preconditions.checkState(id != null, "'id' is mandatory");
- Preconditions.checkState(!Strings.isNullOrEmpty(blobId), "'blobId' is mandatory");
+ Preconditions.checkState(blobId != null, "'blobId' is mandatory");
Preconditions.checkState(!Strings.isNullOrEmpty(threadId), "'threadId' is mandatory");
Preconditions.checkState(mailboxIds != null, "'mailboxIds' is mandatory");
Preconditions.checkState(headers != null, "'headers' is mandatory");
@@ -210,7 +210,7 @@ public class Message {
Preconditions.checkState(date != null, "'date' is mandatory");
Preconditions.checkState(!Strings.isNullOrEmpty(preview), "'preview' is mandatory");
ImmutableList<Attachment> attachments = this.attachments.build();
- ImmutableMap<String, SubMessage> attachedMessages = this.attachedMessages.build();
+ ImmutableMap<BlobId, SubMessage> attachedMessages = this.attachedMessages.build();
Preconditions.checkState(areAttachedMessagesKeysInAttachments(attachments, attachedMessages), "'attachedMessages' keys must be in 'attachements'");
boolean hasAttachment = !attachments.isEmpty();
@@ -219,12 +219,12 @@ public class Message {
}
}
- protected static boolean areAttachedMessagesKeysInAttachments(ImmutableList<Attachment> attachments, ImmutableMap<String, SubMessage> attachedMessages) {
+ protected static boolean areAttachedMessagesKeysInAttachments(ImmutableList<Attachment> attachments, ImmutableMap<BlobId, SubMessage> attachedMessages) {
return attachedMessages.isEmpty() || attachedMessages.keySet().stream()
.anyMatch(inAttachments(attachments));
}
- private static Predicate<String> inAttachments(ImmutableList<Attachment> attachments) {
+ private static Predicate<BlobId> inAttachments(ImmutableList<Attachment> attachments) {
return (key) -> {
return attachments.stream()
.map(Attachment::getBlobId)
@@ -233,7 +233,7 @@ public class Message {
}
private final MessageId id;
- private final String blobId;
+ private final BlobId blobId;
private final String threadId;
private final ImmutableList<String> mailboxIds;
private final Optional<String> inReplyToMessageId;
@@ -256,11 +256,11 @@ public class Message {
private final Optional<String> textBody;
private final Optional<String> htmlBody;
private final ImmutableList<Attachment> attachments;
- private final ImmutableMap<String, SubMessage> attachedMessages;
+ private final ImmutableMap<BlobId, SubMessage> attachedMessages;
- @VisibleForTesting Message(MessageId id, String blobId, String threadId, ImmutableList<String> mailboxIds, Optional<String> inReplyToMessageId, boolean isUnread, boolean isFlagged, boolean isAnswered, boolean isDraft, boolean hasAttachment, ImmutableMap<String, String> headers, Optional<Emailer> from,
+ @VisibleForTesting Message(MessageId id, BlobId blobId, String threadId, ImmutableList<String> mailboxIds, Optional<String> inReplyToMessageId, boolean isUnread, boolean isFlagged, boolean isAnswered, boolean isDraft, boolean hasAttachment, ImmutableMap<String, String> headers, Optional<Emailer> from,
ImmutableList<Emailer> to, ImmutableList<Emailer> cc, ImmutableList<Emailer> bcc, ImmutableList<Emailer> replyTo, String subject, ZonedDateTime date, long size, String preview, Optional<String> textBody, Optional<String> htmlBody, ImmutableList<Attachment> attachments,
- ImmutableMap<String, SubMessage> attachedMessages) {
+ ImmutableMap<BlobId, SubMessage> attachedMessages) {
this.id = id;
this.blobId = blobId;
this.threadId = threadId;
@@ -291,7 +291,7 @@ public class Message {
return id;
}
- public String getBlobId() {
+ public BlobId getBlobId() {
return blobId;
}
@@ -379,7 +379,7 @@ public class Message {
return attachments;
}
- public ImmutableMap<String, SubMessage> getAttachedMessages() {
+ public ImmutableMap<BlobId, SubMessage> getAttachedMessages() {
return attachedMessages;
}
http://git-wip-us.apache.org/repos/asf/james-project/blob/7be2166e/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 a430627..d23215e 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
@@ -62,7 +62,7 @@ public class MessageFactory {
MessageId messageId = uidToMessageId.apply(im.getId());
return Message.builder()
.id(messageId)
- .blobId(String.valueOf(im.getId()))
+ .blobId(BlobId.of(String.valueOf(im.getId())))
.threadId(messageId.serialize())
.mailboxIds(ImmutableList.of(im.getMailboxId()))
.inReplyToMessageId(getHeaderAsSingleValue(im, "in-reply-to"))
@@ -159,7 +159,7 @@ public class MessageFactory {
private Attachment fromMailboxAttachment(MessageAttachment attachment) {
return Attachment.builder()
- .blobId(attachment.getAttachmentId().getId())
+ .blobId(BlobId.of(attachment.getAttachmentId().getId()))
.type(attachment.getAttachment().getType())
.size(attachment.getAttachment().getSize())
.name(attachment.getName().orNull())
http://git-wip-us.apache.org/repos/asf/james-project/blob/7be2166e/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SubMessage.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SubMessage.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SubMessage.java
index 38e68a9..cbaf1cd 100644
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SubMessage.java
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SubMessage.java
@@ -52,7 +52,7 @@ public class SubMessage {
private String textBody;
private String htmlBody;
private final ImmutableList.Builder<Attachment> attachments;
- private final ImmutableMap.Builder<String, SubMessage> attachedMessages;
+ private final ImmutableMap.Builder<BlobId, SubMessage> attachedMessages;
private Builder() {
to = ImmutableList.builder();
@@ -118,7 +118,7 @@ public class SubMessage {
return this;
}
- public Builder attachedMessages(Map<String, SubMessage> attachedMessages) {
+ public Builder attachedMessages(Map<BlobId, SubMessage> attachedMessages) {
this.attachedMessages.putAll(attachedMessages);
return this;
}
@@ -128,7 +128,7 @@ public class SubMessage {
Preconditions.checkState(!Strings.isNullOrEmpty(subject), "'subject' is mandatory");
Preconditions.checkState(date != null, "'date' is mandatory");
ImmutableList<Attachment> attachments = this.attachments.build();
- ImmutableMap<String, SubMessage> attachedMessages = this.attachedMessages.build();
+ ImmutableMap<BlobId, SubMessage> attachedMessages = this.attachedMessages.build();
Preconditions.checkState(Message.areAttachedMessagesKeysInAttachments(attachments, attachedMessages), "'attachedMessages' keys must be in 'attachements'");
return new SubMessage(headers, Optional.ofNullable(from), to.build(), cc.build(), bcc.build(),
replyTo.build(), subject, date, Optional.ofNullable(textBody), Optional.ofNullable(htmlBody),
@@ -148,10 +148,10 @@ public class SubMessage {
private final Optional<String> textBody;
private final Optional<String> htmlBody;
private final ImmutableList<Attachment> attachments;
- private final ImmutableMap<String, SubMessage> attachedMessages;
+ private final ImmutableMap<BlobId, SubMessage> attachedMessages;
@VisibleForTesting SubMessage(ImmutableMap<String, String> headers, Optional<Emailer> from, ImmutableList<Emailer> to, ImmutableList<Emailer> cc, ImmutableList<Emailer> bcc, ImmutableList<Emailer> replyTo, String subject, ZonedDateTime date, Optional<String> textBody,
- Optional<String> htmlBody, ImmutableList<Attachment> attachments, ImmutableMap<String, SubMessage> attachedMessages) {
+ Optional<String> htmlBody, ImmutableList<Attachment> attachments, ImmutableMap<BlobId, SubMessage> attachedMessages) {
super();
this.headers = headers;
this.from = from;
@@ -211,7 +211,7 @@ public class SubMessage {
return attachments;
}
- public ImmutableMap<String, SubMessage> getAttachedMessages() {
+ public ImmutableMap<BlobId, SubMessage> getAttachedMessages() {
return attachedMessages;
}
http://git-wip-us.apache.org/repos/asf/james-project/blob/7be2166e/server/protocols/jmap/src/test/java/org/apache/james/jmap/json/ParsingWritingObjects.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/json/ParsingWritingObjects.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/json/ParsingWritingObjects.java
index b0ea677..7723d8a 100644
--- a/server/protocols/jmap/src/test/java/org/apache/james/jmap/json/ParsingWritingObjects.java
+++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/json/ParsingWritingObjects.java
@@ -22,6 +22,7 @@ package org.apache.james.jmap.json;
import java.time.ZoneId;
import java.time.ZonedDateTime;
+import org.apache.james.jmap.model.BlobId;
import org.apache.james.jmap.model.Emailer;
import org.apache.james.jmap.model.Message;
import org.apache.james.jmap.model.MessageId;
@@ -34,7 +35,7 @@ public interface ParsingWritingObjects {
public interface Common {
MessageId MESSAGE_ID = MessageId.of("username|mailbox|1");
- String BLOB_ID = "myBlobId";
+ BlobId BLOB_ID = BlobId.of("myBlobId");
String THREAD_ID = "myThreadId";
ImmutableList<String> MAILBOX_IDS = ImmutableList.of("mailboxId1", "mailboxId2");
String IN_REPLY_TO_MESSAGE_ID = "myInReplyToMessageId";
http://git-wip-us.apache.org/repos/asf/james-project/blob/7be2166e/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 7f32174..12eba05 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
@@ -34,6 +34,7 @@ import java.util.function.Supplier;
import java.util.stream.Stream;
import org.apache.james.jmap.methods.ValueWithId.MessageWithId;
+import org.apache.james.jmap.model.BlobId;
import org.apache.james.jmap.model.CreationMessage;
import org.apache.james.jmap.model.CreationMessage.DraftEmailer;
import org.apache.james.jmap.model.CreationMessageId;
@@ -89,7 +90,7 @@ public class SetMessagesCreationProcessorTest {
private static final Message FAKE_OUTBOX_MESSAGE = Message.builder()
.id(MessageId.of(OUTBOX_MESSAGE_ID))
- .blobId("anything")
+ .blobId(BlobId.of("anything"))
.threadId("anything")
.mailboxId(OUTBOX_ID.serialize())
.headers(ImmutableMap.of())
http://git-wip-us.apache.org/repos/asf/james-project/blob/7be2166e/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/AttachmentTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/AttachmentTest.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/AttachmentTest.java
index 92b3194..c6a433a 100644
--- a/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/AttachmentTest.java
+++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/AttachmentTest.java
@@ -33,34 +33,29 @@ public class AttachmentTest {
@Test(expected=IllegalStateException.class)
public void buildShouldThrowWhenTypeIsNull() {
- Attachment.builder().blobId("blobId").build();
+ Attachment.builder().blobId(BlobId.of("blobId")).build();
}
@Test(expected=IllegalStateException.class)
public void buildShouldThrowWhenNameIsNull() {
- Attachment.builder().blobId("blobId").type("type").build();
+ Attachment.builder().blobId(BlobId.of("blobId")).type("type").build();
}
@Test(expected=IllegalStateException.class)
public void buildShouldThrowWhenSizeIsNull() {
- Attachment.builder().blobId("blobId").type("type").name("name").build();
- }
-
- @Test(expected=IllegalStateException.class)
- public void buildShouldThrowWhenBlobIdIsEmpty() {
- Attachment.builder().blobId("").type("type").name("name").size(123).build();
+ Attachment.builder().blobId(BlobId.of("blobId")).type("type").name("name").build();
}
@Test(expected=IllegalStateException.class)
public void buildShouldThrowWhenTypeIsEmpty() {
- Attachment.builder().blobId("blobId").type("").name("name").size(123).build();
+ Attachment.builder().blobId(BlobId.of("blobId")).type("").name("name").size(123).build();
}
@Test
public void buildShouldWorkWhenMandatoryFieldsArePresent() {
- Attachment expected = new Attachment("blobId", "type", Optional.empty(), 123, Optional.empty(), false, Optional.empty(), Optional.empty());
+ Attachment expected = new Attachment(BlobId.of("blobId"), "type", Optional.empty(), 123, Optional.empty(), false, Optional.empty(), Optional.empty());
Attachment tested = Attachment.builder()
- .blobId("blobId")
+ .blobId(BlobId.of("blobId"))
.type("type")
.size(123)
.build();
@@ -69,9 +64,9 @@ public class AttachmentTest {
@Test
public void buildShouldWorkWithAllFieldsSet() {
- Attachment expected = new Attachment("blobId", "type", Optional.of("name"), 123, Optional.of("cid"), true, Optional.of(456L), Optional.of(789L));
+ Attachment expected = new Attachment(BlobId.of("blobId"), "type", Optional.of("name"), 123, Optional.of("cid"), true, Optional.of(456L), Optional.of(789L));
Attachment tested = Attachment.builder()
- .blobId("blobId")
+ .blobId(BlobId.of("blobId"))
.type("type")
.name("name")
.size(123)
http://git-wip-us.apache.org/repos/asf/james-project/blob/7be2166e/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/BlobIdTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/BlobIdTest.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/BlobIdTest.java
new file mode 100644
index 0000000..bf04a1e
--- /dev/null
+++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/BlobIdTest.java
@@ -0,0 +1,49 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you under the Apache License, Version 2.0 (the *
+ * "License"); you may not use this file except in compliance *
+ * with the License. You may obtain a copy of the License at *
+ * *
+ * http://www.apache.org/licenses/LICENSE-2.0 *
+ * *
+ * Unless required by applicable law or agreed to in writing, *
+ * software distributed under the License is distributed on an *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
+ * KIND, either express or implied. See the License for the *
+ * specific language governing permissions and limitations *
+ * under the License. *
+ ****************************************************************/
+package org.apache.james.jmap.model;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+import org.junit.Test;
+
+import nl.jqno.equalsverifier.EqualsVerifier;
+
+public class BlobIdTest {
+
+ @Test
+ public void shouldNotAllowEmptyString() {
+ assertThatThrownBy(() -> BlobId.of("")).isInstanceOf(IllegalArgumentException.class);
+ }
+
+ @Test
+ public void shouldNotAllowNullInput() {
+ assertThatThrownBy(() -> BlobId.of(null)).isInstanceOf(IllegalArgumentException.class);
+ }
+
+ @Test
+ public void shouldCreateInstanceWhenSimpleString() {
+ assertThat(BlobId.of("simple string")).extracting(BlobId::getRawValue).containsExactly("simple string");
+ }
+
+ @Test
+ public void shouldRespectJavaBeanContract() {
+ EqualsVerifier.forClass(BlobId.class).verify();
+ }
+}
http://git-wip-us.apache.org/repos/asf/james-project/blob/7be2166e/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/MailboxMessageTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/MailboxMessageTest.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/MailboxMessageTest.java
index b11edcf..0293808 100644
--- a/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/MailboxMessageTest.java
+++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/MailboxMessageTest.java
@@ -73,73 +73,68 @@ public class MailboxMessageTest {
}
@Test(expected=IllegalStateException.class)
- public void buildShouldThrowWhenBlobIdIsEmpty() {
- Message.builder().id(MessageId.of("user|box|1")).blobId("").build();
- }
-
- @Test(expected=IllegalStateException.class)
public void buildShouldThrowWhenThreadIdIsNull() {
- Message.builder().id(MessageId.of("user|box|1")).blobId("blobId").build();
+ Message.builder().id(MessageId.of("user|box|1")).blobId(BlobId.of("blobId")).build();
}
@Test(expected=IllegalStateException.class)
public void buildShouldThrowWhenThreadIdIsEmpty() {
- Message.builder().id(MessageId.of("user|box|1")).blobId("blobId").threadId("").build();
+ Message.builder().id(MessageId.of("user|box|1")).blobId(BlobId.of("blobId")).threadId("").build();
}
@Test(expected=IllegalStateException.class)
public void buildShouldThrowWhenMailboxIdsIsNull() {
- Message.builder().id(MessageId.of("user|box|1")).blobId("blobId").threadId("threadId").build();
+ Message.builder().id(MessageId.of("user|box|1")).blobId(BlobId.of("blobId")).threadId("threadId").build();
}
@Test(expected=IllegalStateException.class)
public void buildShouldThrowWhenHeadersIsNull() {
- Message.builder().id(MessageId.of("user|box|1")).blobId("blobId").threadId("threadId").mailboxIds(ImmutableList.of()).build();
+ Message.builder().id(MessageId.of("user|box|1")).blobId(BlobId.of("blobId")).threadId("threadId").mailboxIds(ImmutableList.of()).build();
}
@Test(expected=IllegalStateException.class)
public void buildShouldThrowWhenSubjectIsNull() {
- Message.builder().id(MessageId.of("user|box|1")).blobId("blobId").threadId("threadId").mailboxIds(ImmutableList.of()).headers(ImmutableMap.of()).build();
+ Message.builder().id(MessageId.of("user|box|1")).blobId(BlobId.of("blobId")).threadId("threadId").mailboxIds(ImmutableList.of()).headers(ImmutableMap.of()).build();
}
@Test(expected=IllegalStateException.class)
public void buildShouldThrowWhenSubjectIsEmpty() {
- Message.builder().id(MessageId.of("user|box|1")).blobId("blobId").threadId("threadId").mailboxIds(ImmutableList.of()).headers(ImmutableMap.of())
+ Message.builder().id(MessageId.of("user|box|1")).blobId(BlobId.of("blobId")).threadId("threadId").mailboxIds(ImmutableList.of()).headers(ImmutableMap.of())
.subject("").build();
}
@Test(expected=IllegalStateException.class)
public void buildShouldThrowWhenSizeIsNull() {
- Message.builder().id(MessageId.of("user|box|1")).blobId("blobId").threadId("threadId").mailboxIds(ImmutableList.of()).headers(ImmutableMap.of())
+ Message.builder().id(MessageId.of("user|box|1")).blobId(BlobId.of("blobId")).threadId("threadId").mailboxIds(ImmutableList.of()).headers(ImmutableMap.of())
.subject("subject").build();
}
@Test(expected=IllegalStateException.class)
public void buildShouldThrowWhenDateIsNull() {
- Message.builder().id(MessageId.of("user|box|1")).blobId("blobId").threadId("threadId").mailboxIds(ImmutableList.of()).headers(ImmutableMap.of())
+ Message.builder().id(MessageId.of("user|box|1")).blobId(BlobId.of("blobId")).threadId("threadId").mailboxIds(ImmutableList.of()).headers(ImmutableMap.of())
.subject("subject").size(123).build();
}
@Test(expected=IllegalStateException.class)
public void buildShouldThrowWhenPreviewIsNull() {
- Message.builder().id(MessageId.of("user|box|1")).blobId("blobId").threadId("threadId").mailboxIds(ImmutableList.of()).headers(ImmutableMap.of())
+ Message.builder().id(MessageId.of("user|box|1")).blobId(BlobId.of("blobId")).threadId("threadId").mailboxIds(ImmutableList.of()).headers(ImmutableMap.of())
.subject("subject").size(123).date(ZonedDateTime.now()).build();
}
@Test(expected=IllegalStateException.class)
public void buildShouldThrowWhenPreviewIsEmpty() {
- Message.builder().id(MessageId.of("user|box|1")).blobId("blobId").threadId("threadId").mailboxIds(ImmutableList.of()).headers(ImmutableMap.of())
+ Message.builder().id(MessageId.of("user|box|1")).blobId(BlobId.of("blobId")).threadId("threadId").mailboxIds(ImmutableList.of()).headers(ImmutableMap.of())
.subject("subject").size(123).date(ZonedDateTime.now()).preview("").build();
}
@Test
public void buildShouldWorkWhenMandatoryFieldsArePresent() {
ZonedDateTime currentDate = ZonedDateTime.now();
- Message expected = new Message(MessageId.of("user|box|1"), "blobId", "threadId", ImmutableList.of("mailboxId"), Optional.empty(), false, false, false, false, false, ImmutableMap.of("key", "value"), Optional.empty(),
+ Message expected = new Message(MessageId.of("user|box|1"), BlobId.of("blobId"), "threadId", ImmutableList.of("mailboxId"), Optional.empty(), false, false, false, false, false, ImmutableMap.of("key", "value"), Optional.empty(),
ImmutableList.of(), ImmutableList.of(), ImmutableList.of(), ImmutableList.of(), "subject", currentDate, 123, "preview", Optional.empty(), Optional.empty(), ImmutableList.of(), ImmutableMap.of());
Message tested = Message.builder()
.id(MessageId.of("user|box|1"))
- .blobId("blobId")
+ .blobId(BlobId.of("blobId"))
.threadId("threadId")
.mailboxIds(ImmutableList.of("mailboxId"))
.headers(ImmutableMap.of("key", "value"))
@@ -153,17 +148,17 @@ public class MailboxMessageTest {
@Test(expected=IllegalStateException.class)
public void buildShouldThrowWhenAttachedMessageIsNotMatchingAttachments() {
- Attachment simpleAttachment = Attachment.builder().blobId("blobId").type("type").name("name").size(123).build();
+ Attachment simpleAttachment = Attachment.builder().blobId(BlobId.of("blobId")).type("type").name("name").size(123).build();
ImmutableList<Attachment> attachments = ImmutableList.of(simpleAttachment);
SubMessage simpleMessage = SubMessage.builder()
.headers(ImmutableMap.of("key", "value"))
.subject("subject")
.date(ZonedDateTime.now())
.build();
- ImmutableMap<String, SubMessage> attachedMessages = ImmutableMap.of("differentBlobId", simpleMessage);
+ ImmutableMap<BlobId, SubMessage> attachedMessages = ImmutableMap.of(BlobId.of("differentBlobId"), simpleMessage);
Message.builder()
.id(MessageId.of("user|box|1"))
- .blobId("blobId")
+ .blobId(BlobId.of("blobId"))
.threadId("threadId")
.mailboxIds(ImmutableList.of("mailboxId"))
.headers(ImmutableMap.of("key", "value"))
@@ -184,17 +179,17 @@ public class MailboxMessageTest {
ImmutableList<Emailer> bcc = ImmutableList.of(Emailer.builder().name("bcc").email("bcc@domain").build());
ImmutableList<Emailer> replyTo = ImmutableList.of(Emailer.builder().name("replyTo").email("replyTo@domain").build());
ZonedDateTime currentDate = ZonedDateTime.now();
- Attachment simpleAttachment = Attachment.builder().blobId("blobId").type("type").name("name").size(123).build();
+ Attachment simpleAttachment = Attachment.builder().blobId(BlobId.of("blobId")).type("type").name("name").size(123).build();
ImmutableList<Attachment> attachments = ImmutableList.of(simpleAttachment);
SubMessage simpleMessage = SubMessage.builder()
.headers(ImmutableMap.of("key", "value"))
.subject("subject")
.date(currentDate)
.build();
- ImmutableMap<String, SubMessage> attachedMessages = ImmutableMap.of("blobId", simpleMessage);
+ ImmutableMap<BlobId, SubMessage> attachedMessages = ImmutableMap.of(BlobId.of("blobId"), simpleMessage);
Message expected = new Message(
MessageId.of("user|box|1"),
- "blobId",
+ BlobId.of("blobId"),
"threadId",
ImmutableList.of("mailboxId"),
Optional.of("inReplyToMessageId"),
@@ -219,7 +214,7 @@ public class MailboxMessageTest {
attachedMessages);
Message tested = Message.builder()
.id(MessageId.of("user|box|1"))
- .blobId("blobId")
+ .blobId(BlobId.of("blobId"))
.threadId("threadId")
.mailboxIds(ImmutableList.of("mailboxId"))
.inReplyToMessageId("inReplyToMessageId")
@@ -322,7 +317,7 @@ public class MailboxMessageTest {
Message testee = messageFactory.fromMailboxMessage(testMail, ImmutableList.of(), x -> MessageId.of("user|box|" + x));
Message expected = Message.builder()
.id(MessageId.of("user|box|0"))
- .blobId("0")
+ .blobId(BlobId.of("0"))
.threadId("user|box|0")
.mailboxIds(ImmutableList.of(MAILBOX_ID.serialize()))
.inReplyToMessageId("<SN...@phx.gbl>")
@@ -411,7 +406,7 @@ public class MailboxMessageTest {
testMail.setModSeq(MOD_SEQ);
String payload = "payload";
- String blodId = "id1";
+ BlobId blodId = BlobId.of("id1");
String type = "content";
Attachment expectedAttachment = Attachment.builder()
.blobId(blodId)
@@ -423,7 +418,7 @@ public class MailboxMessageTest {
Message testee = messageFactory.fromMailboxMessage(testMail,
ImmutableList.of(MessageAttachment.builder()
.attachment(org.apache.james.mailbox.store.mail.model.Attachment.builder()
- .attachmentId(AttachmentId.from(blodId))
+ .attachmentId(AttachmentId.from(blodId.getRawValue()))
.bytes(payload.getBytes())
.type(type)
.build())
@@ -440,7 +435,7 @@ public class MailboxMessageTest {
public void buildShouldThrowWhenOneAttachedMessageIsNotInAttachments() throws Exception {
Message.builder()
.id(MessageId.of("user|box|1"))
- .blobId("blodId")
+ .blobId(BlobId.of("blobId"))
.threadId("threadId")
.mailboxIds(ImmutableList.of("mailboxId"))
.headers(ImmutableMap.of("key", "value"))
@@ -448,7 +443,7 @@ public class MailboxMessageTest {
.size(1)
.date(ZonedDateTime.now())
.preview("preview")
- .attachedMessages(ImmutableMap.of("key", SubMessage.builder()
+ .attachedMessages(ImmutableMap.of(BlobId.of("key"), SubMessage.builder()
.headers(ImmutableMap.of("key", "value"))
.subject("subject")
.date(ZonedDateTime.now())
@@ -460,7 +455,7 @@ public class MailboxMessageTest {
public void buildShouldNotThrowWhenOneAttachedMessageIsInAttachments() throws Exception {
Message.builder()
.id(MessageId.of("user|box|1"))
- .blobId("blodId")
+ .blobId(BlobId.of("blobId"))
.threadId("threadId")
.mailboxIds(ImmutableList.of("mailboxId"))
.headers(ImmutableMap.of("key", "value"))
@@ -469,11 +464,11 @@ public class MailboxMessageTest {
.date(ZonedDateTime.now())
.preview("preview")
.attachments(ImmutableList.of(Attachment.builder()
- .blobId("key")
+ .blobId(BlobId.of("key"))
.size(1)
.type("type")
.build()))
- .attachedMessages(ImmutableMap.of("key", SubMessage.builder()
+ .attachedMessages(ImmutableMap.of(BlobId.of("key"), SubMessage.builder()
.headers(ImmutableMap.of("key", "value"))
.subject("subject")
.date(ZonedDateTime.now())
http://git-wip-us.apache.org/repos/asf/james-project/blob/7be2166e/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/SetMessagesResponseTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/SetMessagesResponseTest.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/SetMessagesResponseTest.java
index 631fa96..24402a9 100644
--- a/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/SetMessagesResponseTest.java
+++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/SetMessagesResponseTest.java
@@ -56,7 +56,7 @@ public class SetMessagesResponseTest {
ImmutableMap<CreationMessageId, Message> created = ImmutableMap.of(CreationMessageId.of("user|created|1"),
Message.builder()
.id(MessageId.of("user|created|1"))
- .blobId("blobId")
+ .blobId(BlobId.of("blobId"))
.threadId("threadId")
.mailboxIds(ImmutableList.of("mailboxId"))
.headers(ImmutableMap.of("key", "value"))
@@ -106,7 +106,7 @@ public class SetMessagesResponseTest {
private ImmutableMap<CreationMessageId, Message> buildMessage(CreationMessageId messageId) {
return ImmutableMap.of(messageId, Message.builder()
.id(MessageId.of(messageId.getId()))
- .blobId("blobId")
+ .blobId(BlobId.of("blobId"))
.threadId("threadId")
.mailboxIds(ImmutableList.of())
.headers(ImmutableMap.of())
http://git-wip-us.apache.org/repos/asf/james-project/blob/7be2166e/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/SubMailboxMessageTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/SubMailboxMessageTest.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/SubMailboxMessageTest.java
index dc0ada9..daa2a8a 100644
--- a/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/SubMailboxMessageTest.java
+++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/SubMailboxMessageTest.java
@@ -64,14 +64,14 @@ public class SubMailboxMessageTest {
@Test(expected=IllegalStateException.class)
public void buildShouldThrowWhenAttachedMessageIsNotMatchingAttachments() {
- Attachment simpleAttachment = Attachment.builder().blobId("blobId").type("type").name("name").size(123).build();
+ Attachment simpleAttachment = Attachment.builder().blobId(BlobId.of("blobId")).type("type").name("name").size(123).build();
ImmutableList<Attachment> attachments = ImmutableList.of(simpleAttachment);
SubMessage simpleMessage = SubMessage.builder()
.headers(ImmutableMap.of("key", "value"))
.subject("subject")
.date(ZonedDateTime.now())
.build();
- ImmutableMap<String, SubMessage> attachedMessages = ImmutableMap.of("differentBlobId", simpleMessage);
+ ImmutableMap<BlobId, SubMessage> attachedMessages = ImmutableMap.of(BlobId.of("differentBlobId"), simpleMessage);
SubMessage.builder()
.headers(ImmutableMap.of("key", "value"))
.subject("subject")
@@ -89,14 +89,14 @@ public class SubMailboxMessageTest {
ImmutableList<Emailer> bcc = ImmutableList.of(Emailer.builder().name("bcc").email("bcc@domain").build());
ImmutableList<Emailer> replyTo = ImmutableList.of(Emailer.builder().name("replyTo").email("replyTo@domain").build());
ZonedDateTime currentDate = ZonedDateTime.now();
- Attachment simpleAttachment = Attachment.builder().blobId("blobId").type("type").name("name").size(123).build();
+ Attachment simpleAttachment = Attachment.builder().blobId(BlobId.of("blobId")).type("type").name("name").size(123).build();
ImmutableList<Attachment> attachments = ImmutableList.of(simpleAttachment);
SubMessage simpleMessage = SubMessage.builder()
.headers(ImmutableMap.of("key", "value"))
.subject("subject")
.date(currentDate)
.build();
- ImmutableMap<String, SubMessage> attachedMessages = ImmutableMap.of("blobId", simpleMessage);
+ ImmutableMap<BlobId, SubMessage> attachedMessages = ImmutableMap.of(BlobId.of("blobId"), simpleMessage);
SubMessage expected = new SubMessage(
ImmutableMap.of("key", "value"),
Optional.of(from),
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org
[5/5] james-project git commit: JAMES-1790 check that blobids exist
when attaching them
Posted by ad...@apache.org.
JAMES-1790 check that blobids exist when attaching them
Project: http://git-wip-us.apache.org/repos/asf/james-project/repo
Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/662fa4a9
Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/662fa4a9
Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/662fa4a9
Branch: refs/heads/master
Commit: 662fa4a954571ef6a0d7044873359211eeaae181
Parents: 7be2166
Author: Matthieu Baechler <ma...@linagora.com>
Authored: Tue Jul 5 17:09:13 2016 +0200
Committer: Antoine Duprat <ad...@linagora.com>
Committed: Fri Jul 8 16:45:00 2016 +0200
----------------------------------------------------------------------
.../integration/SetMessagesMethodTest.java | 619 +++++++++++++------
.../AttachmentsNotFoundException.java | 40 ++
.../jmap/methods/MIMEMessageConverter.java | 127 +++-
.../methods/SetMessagesCreationProcessor.java | 90 ++-
.../james/jmap/model/CreationMessage.java | 32 +-
.../org/apache/james/jmap/model/SetError.java | 9 +-
.../james/jmap/model/SetMessagesError.java | 92 +++
.../jmap/methods/MIMEMessageConverterTest.java | 73 ++-
.../SetMessagesCreationProcessorTest.java | 84 ++-
9 files changed, 887 insertions(+), 279 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/james-project/blob/662fa4a9/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 af96309..be3297b 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
@@ -33,10 +33,12 @@ import static org.hamcrest.Matchers.hasKey;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.isEmptyOrNullString;
import static org.hamcrest.Matchers.not;
+import static org.hamcrest.Matchers.nullValue;
import static org.hamcrest.collection.IsMapWithSize.aMapWithSize;
import static org.hamcrest.collection.IsMapWithSize.anEmptyMap;
import java.io.ByteArrayInputStream;
+import java.io.IOException;
import java.time.ZonedDateTime;
import java.util.Date;
import java.util.List;
@@ -52,6 +54,7 @@ import org.apache.james.jmap.model.mailbox.Role;
import org.apache.james.mailbox.exception.MailboxException;
import org.apache.james.mailbox.model.MailboxConstants;
import org.apache.james.mailbox.model.MailboxPath;
+import org.apache.james.mailbox.store.mail.model.Attachment;
import org.apache.james.mailbox.store.mail.model.Mailbox;
import org.hamcrest.Matchers;
import org.junit.After;
@@ -93,12 +96,12 @@ public abstract class SetMessagesMethodTest {
jmapServer = createJmapServer();
jmapServer.start();
RestAssured.requestSpecification = new RequestSpecBuilder()
- .setContentType(ContentType.JSON)
- .setAccept(ContentType.JSON)
- .setConfig(newConfig().encoderConfig(encoderConfig().defaultContentCharset(Charsets.UTF_8)))
- .setPort(jmapServer.getJmapPort())
- .build();
-
+ .setContentType(ContentType.JSON)
+ .setAccept(ContentType.JSON)
+ .setConfig(newConfig().encoderConfig(encoderConfig().defaultContentCharset(Charsets.UTF_8)))
+ .setPort(jmapServer.getJmapPort())
+ .build();
+
username = "username@" + USERS_DOMAIN;
String password = "password";
jmapServer.serverProbe().addDomain(USERS_DOMAIN);
@@ -148,6 +151,7 @@ public abstract class SetMessagesMethodTest {
.when()
.post("/jmap")
.then()
+ .log().ifValidationFails()
.statusCode(200)
.body(NAME, equalTo("error"))
.body(ARGUMENTS + ".type", equalTo("Not yet implemented"));
@@ -161,6 +165,7 @@ public abstract class SetMessagesMethodTest {
.when()
.post("/jmap")
.then()
+ .log().ifValidationFails()
.statusCode(200)
.body(NAME, equalTo("error"))
.body(ARGUMENTS + ".type", equalTo("Not yet implemented"));
@@ -215,7 +220,7 @@ public abstract class SetMessagesMethodTest {
jmapServer.serverProbe().createMailbox(MailboxConstants.USER_NAMESPACE, username, "mailbox");
jmapServer.serverProbe().appendMessage(username, new MailboxPath(MailboxConstants.USER_NAMESPACE, username, "mailbox"),
- new ByteArrayInputStream("Subject: test\r\n\r\ntestmail".getBytes()), new Date(), false, new Flags());
+ new ByteArrayInputStream("Subject: test\r\n\r\ntestmail".getBytes(Charsets.UTF_8)), new Date(), false, new Flags());
await();
given()
@@ -224,6 +229,7 @@ public abstract class SetMessagesMethodTest {
.when()
.post("/jmap")
.then()
+ .log().ifValidationFails()
.statusCode(200)
.body(NAME, equalTo("messagesSet"))
.body(ARGUMENTS + ".notDestroyed", anEmptyMap())
@@ -237,7 +243,7 @@ public abstract class SetMessagesMethodTest {
jmapServer.serverProbe().createMailbox(MailboxConstants.USER_NAMESPACE, username, "mailbox");
jmapServer.serverProbe().appendMessage(username, new MailboxPath(MailboxConstants.USER_NAMESPACE, username, "mailbox"),
- new ByteArrayInputStream("Subject: test\r\n\r\ntestmail".getBytes()), new Date(), false, new Flags());
+ new ByteArrayInputStream("Subject: test\r\n\r\ntestmail".getBytes(Charsets.UTF_8)), new Date(), false, new Flags());
await();
// When
@@ -247,6 +253,7 @@ public abstract class SetMessagesMethodTest {
.when()
.post("/jmap")
.then()
+ .log().ifValidationFails()
.statusCode(200);
// Then
@@ -256,6 +263,7 @@ public abstract class SetMessagesMethodTest {
.when()
.post("/jmap")
.then()
+ .log().ifValidationFails()
.statusCode(200)
.body(NAME, equalTo("messages"))
.body(ARGUMENTS + ".list", empty());
@@ -266,13 +274,13 @@ public abstract class SetMessagesMethodTest {
jmapServer.serverProbe().createMailbox(MailboxConstants.USER_NAMESPACE, username, "mailbox");
jmapServer.serverProbe().appendMessage(username, new MailboxPath(MailboxConstants.USER_NAMESPACE, username, "mailbox"),
- new ByteArrayInputStream("Subject: test\r\n\r\ntestmail".getBytes()), new Date(), false, new Flags());
+ new ByteArrayInputStream("Subject: test\r\n\r\ntestmail".getBytes(Charsets.UTF_8)), new Date(), false, new Flags());
jmapServer.serverProbe().appendMessage(username, new MailboxPath(MailboxConstants.USER_NAMESPACE, username, "mailbox"),
- new ByteArrayInputStream("Subject: test2\r\n\r\ntestmail".getBytes()), new Date(), false, new Flags());
+ new ByteArrayInputStream("Subject: test2\r\n\r\ntestmail".getBytes(Charsets.UTF_8)), new Date(), false, new Flags());
jmapServer.serverProbe().appendMessage(username, new MailboxPath(MailboxConstants.USER_NAMESPACE, username, "mailbox"),
- new ByteArrayInputStream("Subject: test3\r\n\r\ntestmail".getBytes()), new Date(), false, new Flags());
+ new ByteArrayInputStream("Subject: test3\r\n\r\ntestmail".getBytes(Charsets.UTF_8)), new Date(), false, new Flags());
await();
String missingMessageId = username + "|mailbox|4";
@@ -282,6 +290,7 @@ public abstract class SetMessagesMethodTest {
.when()
.post("/jmap")
.then()
+ .log().ifValidationFails()
.statusCode(200)
.body(NAME, equalTo("messagesSet"))
.body(ARGUMENTS + ".destroyed", hasSize(2))
@@ -299,13 +308,13 @@ public abstract class SetMessagesMethodTest {
jmapServer.serverProbe().createMailbox(MailboxConstants.USER_NAMESPACE, username, "mailbox");
jmapServer.serverProbe().appendMessage(username, new MailboxPath(MailboxConstants.USER_NAMESPACE, username, "mailbox"),
- new ByteArrayInputStream("Subject: test\r\n\r\ntestmail".getBytes()), new Date(), false, new Flags());
+ new ByteArrayInputStream("Subject: test\r\n\r\ntestmail".getBytes(Charsets.UTF_8)), new Date(), false, new Flags());
jmapServer.serverProbe().appendMessage(username, new MailboxPath(MailboxConstants.USER_NAMESPACE, username, "mailbox"),
- new ByteArrayInputStream("Subject: test2\r\n\r\ntestmail".getBytes()), new Date(), false, new Flags());
+ new ByteArrayInputStream("Subject: test2\r\n\r\ntestmail".getBytes(Charsets.UTF_8)), new Date(), false, new Flags());
jmapServer.serverProbe().appendMessage(username, new MailboxPath(MailboxConstants.USER_NAMESPACE, username, "mailbox"),
- new ByteArrayInputStream("Subject: test3\r\n\r\ntestmail".getBytes()), new Date(), false, new Flags());
+ new ByteArrayInputStream("Subject: test3\r\n\r\ntestmail".getBytes(Charsets.UTF_8)), new Date(), false, new Flags());
await();
// When
@@ -315,6 +324,7 @@ public abstract class SetMessagesMethodTest {
.when()
.post("/jmap")
.then()
+ .log().ifValidationFails()
.statusCode(200);
// Then
@@ -324,6 +334,7 @@ public abstract class SetMessagesMethodTest {
.when()
.post("/jmap")
.then()
+ .log().ifValidationFails()
.statusCode(200)
.body(NAME, equalTo("messages"))
.body(ARGUMENTS + ".list", hasSize(1));
@@ -335,7 +346,7 @@ public abstract class SetMessagesMethodTest {
jmapServer.serverProbe().createMailbox(MailboxConstants.USER_NAMESPACE, username, "mailbox");
jmapServer.serverProbe().appendMessage(username, new MailboxPath(MailboxConstants.USER_NAMESPACE, username, "mailbox"),
- new ByteArrayInputStream("Subject: test\r\n\r\ntestmail".getBytes()), new Date(), false, new Flags());
+ new ByteArrayInputStream("Subject: test\r\n\r\ntestmail".getBytes(Charsets.UTF_8)), new Date(), false, new Flags());
await();
String presumedMessageId = username + "|mailbox|1";
@@ -348,8 +359,8 @@ public abstract class SetMessagesMethodTest {
.post("/jmap")
// Then
.then()
- .spec(getSetMessagesUpdateOKResponseAssertions(presumedMessageId))
- .log().ifValidationFails();
+ .log().ifValidationFails()
+ .spec(getSetMessagesUpdateOKResponseAssertions(presumedMessageId));
}
private ResponseSpecification getSetMessagesUpdateOKResponseAssertions(String messageId) {
@@ -369,27 +380,27 @@ public abstract class SetMessagesMethodTest {
jmapServer.serverProbe().createMailbox(MailboxConstants.USER_NAMESPACE, username, "mailbox");
jmapServer.serverProbe().appendMessage(username, new MailboxPath(MailboxConstants.USER_NAMESPACE, username, "mailbox"),
- new ByteArrayInputStream("Subject: test\r\n\r\ntestmail".getBytes()), new Date(), false, new Flags());
+ new ByteArrayInputStream("Subject: test\r\n\r\ntestmail".getBytes(Charsets.UTF_8)), new Date(), false, new Flags());
await();
String presumedMessageId = username + "|mailbox|1";
given()
- .header("Authorization", accessToken.serialize())
- .body(String.format("[[\"setMessages\", {\"update\": {\"%s\" : { \"isUnread\" : false } } }, \"#0\"]]", presumedMessageId))
+ .header("Authorization", accessToken.serialize())
+ .body(String.format("[[\"setMessages\", {\"update\": {\"%s\" : { \"isUnread\" : false } } }, \"#0\"]]", presumedMessageId))
// When
.when()
- .post("/jmap");
+ .post("/jmap");
// Then
with()
- .header("Authorization", accessToken.serialize())
- .body("[[\"getMessages\", {\"ids\": [\"" + presumedMessageId + "\"]}, \"#0\"]]")
- .post("/jmap")
+ .header("Authorization", accessToken.serialize())
+ .body("[[\"getMessages\", {\"ids\": [\"" + presumedMessageId + "\"]}, \"#0\"]]")
+ .post("/jmap")
.then()
- .statusCode(200)
- .body(NAME, equalTo("messages"))
- .body(ARGUMENTS + ".list", hasSize(1))
- .body(ARGUMENTS + ".list[0].isUnread", equalTo(false))
- .log().ifValidationFails();
+ .log().ifValidationFails()
+ .statusCode(200)
+ .body(NAME, equalTo("messages"))
+ .body(ARGUMENTS + ".list", hasSize(1))
+ .body(ARGUMENTS + ".list[0].isUnread", equalTo(false));
}
@Test
@@ -398,20 +409,20 @@ public abstract class SetMessagesMethodTest {
jmapServer.serverProbe().createMailbox(MailboxConstants.USER_NAMESPACE, username, "mailbox");
jmapServer.serverProbe().appendMessage(username, new MailboxPath(MailboxConstants.USER_NAMESPACE, username, "mailbox"),
- new ByteArrayInputStream("Subject: test\r\n\r\ntestmail".getBytes()), new Date(), false, new Flags(Flags.Flag.SEEN));
+ new ByteArrayInputStream("Subject: test\r\n\r\ntestmail".getBytes(Charsets.UTF_8)), new Date(), false, new Flags(Flags.Flag.SEEN));
await();
String presumedMessageId = username + "|mailbox|1";
given()
- .header("Authorization", accessToken.serialize())
- .body(String.format("[[\"setMessages\", {\"update\": {\"%s\" : { \"isUnread\" : true } } }, \"#0\"]]", presumedMessageId))
+ .header("Authorization", accessToken.serialize())
+ .body(String.format("[[\"setMessages\", {\"update\": {\"%s\" : { \"isUnread\" : true } } }, \"#0\"]]", presumedMessageId))
// When
.when()
- .post("/jmap")
+ .post("/jmap")
// Then
.then()
- .spec(getSetMessagesUpdateOKResponseAssertions(presumedMessageId))
- .log().ifValidationFails();
+ .log().ifValidationFails()
+ .spec(getSetMessagesUpdateOKResponseAssertions(presumedMessageId));
}
@Test
@@ -420,26 +431,26 @@ public abstract class SetMessagesMethodTest {
jmapServer.serverProbe().createMailbox(MailboxConstants.USER_NAMESPACE, username, "mailbox");
jmapServer.serverProbe().appendMessage(username, new MailboxPath(MailboxConstants.USER_NAMESPACE, username, "mailbox"),
- new ByteArrayInputStream("Subject: test\r\n\r\ntestmail".getBytes()), new Date(), false, new Flags(Flags.Flag.SEEN));
+ new ByteArrayInputStream("Subject: test\r\n\r\ntestmail".getBytes(Charsets.UTF_8)), new Date(), false, new Flags(Flags.Flag.SEEN));
await();
String presumedMessageId = username + "|mailbox|1";
given()
- .header("Authorization", accessToken.serialize())
- .body(String.format("[[\"setMessages\", {\"update\": {\"%s\" : { \"isUnread\" : true } } }, \"#0\"]]", presumedMessageId))
+ .header("Authorization", accessToken.serialize())
+ .body(String.format("[[\"setMessages\", {\"update\": {\"%s\" : { \"isUnread\" : true } } }, \"#0\"]]", presumedMessageId))
// When
.when()
- .post("/jmap");
+ .post("/jmap");
// Then
with()
- .header("Authorization", accessToken.serialize())
- .body("[[\"getMessages\", {\"ids\": [\"" + presumedMessageId + "\"]}, \"#0\"]]")
- .post("/jmap")
+ .header("Authorization", accessToken.serialize())
+ .body("[[\"getMessages\", {\"ids\": [\"" + presumedMessageId + "\"]}, \"#0\"]]")
+ .post("/jmap")
.then()
- .body(NAME, equalTo("messages"))
- .body(ARGUMENTS + ".list", hasSize(1))
- .body(ARGUMENTS + ".list[0].isUnread", equalTo(true))
- .log().ifValidationFails();
+ .log().ifValidationFails()
+ .body(NAME, equalTo("messages"))
+ .body(ARGUMENTS + ".list", hasSize(1))
+ .body(ARGUMENTS + ".list[0].isUnread", equalTo(true));
}
@@ -449,20 +460,20 @@ public abstract class SetMessagesMethodTest {
jmapServer.serverProbe().createMailbox(MailboxConstants.USER_NAMESPACE, username, "mailbox");
jmapServer.serverProbe().appendMessage(username, new MailboxPath(MailboxConstants.USER_NAMESPACE, username, "mailbox"),
- new ByteArrayInputStream("Subject: test\r\n\r\ntestmail".getBytes()), new Date(), false, new Flags());
+ new ByteArrayInputStream("Subject: test\r\n\r\ntestmail".getBytes(Charsets.UTF_8)), new Date(), false, new Flags());
await();
String presumedMessageId = username + "|mailbox|1";
given()
- .header("Authorization", accessToken.serialize())
- .body(String.format("[[\"setMessages\", {\"update\": {\"%s\" : { \"isFlagged\" : true } } }, \"#0\"]]", presumedMessageId))
+ .header("Authorization", accessToken.serialize())
+ .body(String.format("[[\"setMessages\", {\"update\": {\"%s\" : { \"isFlagged\" : true } } }, \"#0\"]]", presumedMessageId))
// When
.when()
- .post("/jmap")
+ .post("/jmap")
// Then
.then()
- .spec(getSetMessagesUpdateOKResponseAssertions(presumedMessageId))
- .log().ifValidationFails();
+ .log().ifValidationFails()
+ .spec(getSetMessagesUpdateOKResponseAssertions(presumedMessageId));
}
@Test
@@ -471,53 +482,53 @@ public abstract class SetMessagesMethodTest {
jmapServer.serverProbe().createMailbox(MailboxConstants.USER_NAMESPACE, username, "mailbox");
jmapServer.serverProbe().appendMessage(username, new MailboxPath(MailboxConstants.USER_NAMESPACE, username, "mailbox"),
- new ByteArrayInputStream("Subject: test\r\n\r\ntestmail".getBytes()), new Date(), false, new Flags());
+ new ByteArrayInputStream("Subject: test\r\n\r\ntestmail".getBytes(Charsets.UTF_8)), new Date(), false, new Flags());
await();
String presumedMessageId = username + "|mailbox|1";
given()
- .header("Authorization", accessToken.serialize())
- .body(String.format("[[\"setMessages\", {\"update\": {\"%s\" : { \"isFlagged\" : true } } }, \"#0\"]]", presumedMessageId))
+ .header("Authorization", accessToken.serialize())
+ .body(String.format("[[\"setMessages\", {\"update\": {\"%s\" : { \"isFlagged\" : true } } }, \"#0\"]]", presumedMessageId))
// When
.when()
- .post("/jmap");
+ .post("/jmap");
// Then
with()
- .header("Authorization", accessToken.serialize())
- .body("[[\"getMessages\", {\"ids\": [\"" + presumedMessageId + "\"]}, \"#0\"]]")
- .post("/jmap")
+ .header("Authorization", accessToken.serialize())
+ .body("[[\"getMessages\", {\"ids\": [\"" + presumedMessageId + "\"]}, \"#0\"]]")
+ .post("/jmap")
.then()
- .body(NAME, equalTo("messages"))
- .body(ARGUMENTS + ".list", hasSize(1))
- .body(ARGUMENTS + ".list[0].isFlagged", equalTo(true))
- .log().ifValidationFails();
+ .log().ifValidationFails()
+ .body(NAME, equalTo("messages"))
+ .body(ARGUMENTS + ".list", hasSize(1))
+ .body(ARGUMENTS + ".list[0].isFlagged", equalTo(true));
}
@Test
public void setMessagesShouldRejectUpdateWhenPropertyHasWrongType() throws MailboxException {
jmapServer.serverProbe().createMailbox(MailboxConstants.USER_NAMESPACE, username, "mailbox");
jmapServer.serverProbe().appendMessage(username, new MailboxPath(MailboxConstants.USER_NAMESPACE, username, "mailbox"),
- new ByteArrayInputStream("Subject: test\r\n\r\ntestmail".getBytes()), new Date(), false, new Flags());
+ new ByteArrayInputStream("Subject: test\r\n\r\ntestmail".getBytes(Charsets.UTF_8)), new Date(), false, new Flags());
await();
String messageId = username + "|mailbox|1";
given()
- .header("Authorization", accessToken.serialize())
- .body(String.format("[[\"setMessages\", {\"update\": {\"%s\" : { \"isUnread\" : \"123\" } } }, \"#0\"]]", messageId))
+ .header("Authorization", accessToken.serialize())
+ .body(String.format("[[\"setMessages\", {\"update\": {\"%s\" : { \"isUnread\" : \"123\" } } }, \"#0\"]]", messageId))
.when()
- .post("/jmap")
+ .post("/jmap")
.then()
- .log().ifValidationFails()
- .statusCode(200)
- .body(NAME, equalTo("messagesSet"))
- .body(NOT_UPDATED, hasKey(messageId))
- .body(NOT_UPDATED + "[\""+messageId+"\"].type", equalTo("invalidProperties"))
- .body(NOT_UPDATED + "[\""+messageId+"\"].properties[0]", equalTo("isUnread"))
- .body(NOT_UPDATED + "[\""+messageId+"\"].description", equalTo("isUnread: Can not construct instance of java.lang.Boolean from String value '123': only \"true\" or \"false\" recognized\n" +
- " at [Source: {\"isUnread\":\"123\"}; line: 1, column: 2] (through reference chain: org.apache.james.jmap.model.Builder[\"isUnread\"])"))
- .body(ARGUMENTS + ".updated", hasSize(0));
+ .log().ifValidationFails()
+ .statusCode(200)
+ .body(NAME, equalTo("messagesSet"))
+ .body(NOT_UPDATED, hasKey(messageId))
+ .body(NOT_UPDATED + "[\""+messageId+"\"].type", equalTo("invalidProperties"))
+ .body(NOT_UPDATED + "[\""+messageId+"\"].properties[0]", equalTo("isUnread"))
+ .body(NOT_UPDATED + "[\""+messageId+"\"].description", equalTo("isUnread: Can not construct instance of java.lang.Boolean from String value '123': only \"true\" or \"false\" recognized\n" +
+ " at [Source: {\"isUnread\":\"123\"}; line: 1, column: 2] (through reference chain: org.apache.james.jmap.model.Builder[\"isUnread\"])"))
+ .body(ARGUMENTS + ".updated", hasSize(0));
}
@Test
@@ -525,27 +536,27 @@ public abstract class SetMessagesMethodTest {
public void setMessagesShouldRejectUpdateWhenPropertiesHaveWrongTypes() throws MailboxException {
jmapServer.serverProbe().createMailbox(MailboxConstants.USER_NAMESPACE, username, "mailbox");
jmapServer.serverProbe().appendMessage(username, new MailboxPath(MailboxConstants.USER_NAMESPACE, username, "mailbox"),
- new ByteArrayInputStream("Subject: test\r\n\r\ntestmail".getBytes()), new Date(), false, new Flags());
+ new ByteArrayInputStream("Subject: test\r\n\r\ntestmail".getBytes(Charsets.UTF_8)), new Date(), false, new Flags());
await();
String messageId = username + "|mailbox|1";
given()
- .header("Authorization", accessToken.serialize())
- .body(String.format("[[\"setMessages\", {\"update\": {\"%s\" : { \"isUnread\" : \"123\", \"isFlagged\" : 456 } } }, \"#0\"]]", messageId))
+ .header("Authorization", accessToken.serialize())
+ .body(String.format("[[\"setMessages\", {\"update\": {\"%s\" : { \"isUnread\" : \"123\", \"isFlagged\" : 456 } } }, \"#0\"]]", messageId))
.when()
- .post("/jmap")
+ .post("/jmap")
.then()
- .log().ifValidationFails()
- .statusCode(200)
- .body(NAME, equalTo("messagesSet"))
- .body(NOT_UPDATED, hasKey(messageId))
- .body(NOT_UPDATED + "[\""+messageId+"\"].type", equalTo("invalidProperties"))
- .body(NOT_UPDATED + "[\""+messageId+"\"].properties", hasSize(2))
- .body(NOT_UPDATED + "[\""+messageId+"\"].properties[0]", equalTo("isUnread"))
- .body(NOT_UPDATED + "[\""+messageId+"\"].properties[1]", equalTo("isFlagged"))
- .body(ARGUMENTS + ".updated", hasSize(0));
+ .log().ifValidationFails()
+ .statusCode(200)
+ .body(NAME, equalTo("messagesSet"))
+ .body(NOT_UPDATED, hasKey(messageId))
+ .body(NOT_UPDATED + "[\""+messageId+"\"].type", equalTo("invalidProperties"))
+ .body(NOT_UPDATED + "[\""+messageId+"\"].properties", hasSize(2))
+ .body(NOT_UPDATED + "[\""+messageId+"\"].properties[0]", equalTo("isUnread"))
+ .body(NOT_UPDATED + "[\""+messageId+"\"].properties[1]", equalTo("isFlagged"))
+ .body(ARGUMENTS + ".updated", hasSize(0));
}
@Test
@@ -554,20 +565,20 @@ public abstract class SetMessagesMethodTest {
jmapServer.serverProbe().createMailbox(MailboxConstants.USER_NAMESPACE, username, "mailbox");
jmapServer.serverProbe().appendMessage(username, new MailboxPath(MailboxConstants.USER_NAMESPACE, username, "mailbox"),
- new ByteArrayInputStream("Subject: test\r\n\r\ntestmail".getBytes()), new Date(), false, new Flags());
+ new ByteArrayInputStream("Subject: test\r\n\r\ntestmail".getBytes(Charsets.UTF_8)), new Date(), false, new Flags());
await();
String presumedMessageId = username + "|mailbox|1";
// When
given()
- .header("Authorization", accessToken.serialize())
- .body(String.format("[[\"setMessages\", {\"update\": {\"%s\" : { \"isAnswered\" : true } } }, \"#0\"]]", presumedMessageId))
+ .header("Authorization", accessToken.serialize())
+ .body(String.format("[[\"setMessages\", {\"update\": {\"%s\" : { \"isAnswered\" : true } } }, \"#0\"]]", presumedMessageId))
.when()
- .post("/jmap")
+ .post("/jmap")
// Then
.then()
- .spec(getSetMessagesUpdateOKResponseAssertions(presumedMessageId))
- .log().ifValidationFails();
+ .log().ifValidationFails()
+ .spec(getSetMessagesUpdateOKResponseAssertions(presumedMessageId));
}
@Test
@@ -576,26 +587,26 @@ public abstract class SetMessagesMethodTest {
jmapServer.serverProbe().createMailbox(MailboxConstants.USER_NAMESPACE, username, "mailbox");
jmapServer.serverProbe().appendMessage(username, new MailboxPath(MailboxConstants.USER_NAMESPACE, username, "mailbox"),
- new ByteArrayInputStream("Subject: test\r\n\r\ntestmail".getBytes()), new Date(), false, new Flags());
+ new ByteArrayInputStream("Subject: test\r\n\r\ntestmail".getBytes(Charsets.UTF_8)), new Date(), false, new Flags());
await();
String presumedMessageId = username + "|mailbox|1";
given()
- .header("Authorization", accessToken.serialize())
- .body(String.format("[[\"setMessages\", {\"update\": {\"%s\" : { \"isAnswered\" : true } } }, \"#0\"]]", presumedMessageId))
+ .header("Authorization", accessToken.serialize())
+ .body(String.format("[[\"setMessages\", {\"update\": {\"%s\" : { \"isAnswered\" : true } } }, \"#0\"]]", presumedMessageId))
// When
.when()
- .post("/jmap");
+ .post("/jmap");
// Then
with()
- .header("Authorization", accessToken.serialize())
- .body("[[\"getMessages\", {\"ids\": [\"" + presumedMessageId + "\"]}, \"#0\"]]")
- .post("/jmap")
+ .header("Authorization", accessToken.serialize())
+ .body("[[\"getMessages\", {\"ids\": [\"" + presumedMessageId + "\"]}, \"#0\"]]")
+ .post("/jmap")
.then()
- .body(NAME, equalTo("messages"))
- .body(ARGUMENTS + ".list", hasSize(1))
- .body(ARGUMENTS + ".list[0].isAnswered", equalTo(true))
- .log().ifValidationFails();
+ .log().ifValidationFails()
+ .body(NAME, equalTo("messages"))
+ .body(ARGUMENTS + ".list", hasSize(1))
+ .body(ARGUMENTS + ".list[0].isAnswered", equalTo(true));
}
@Test
@@ -640,34 +651,34 @@ public abstract class SetMessagesMethodTest {
"]";
given()
- .header("Authorization", accessToken.serialize())
- .body(requestBody)
+ .header("Authorization", accessToken.serialize())
+ .body(requestBody)
.when()
- .post("/jmap")
+ .post("/jmap")
.then()
- .log().ifValidationFails()
- .statusCode(200)
- .body(NAME, equalTo("messagesSet"))
- .body(ARGUMENTS + ".notCreated", aMapWithSize(0))
- // note that assertions on result message had to be split between
- // string-typed values and boolean-typed value assertions on the same .created entry
- // make sure only one creation has been processed
- .body(ARGUMENTS + ".created", aMapWithSize(1))
- // assert server-set attributes are returned
- .body(ARGUMENTS + ".created", hasEntry(equalTo(messageCreationId), Matchers.allOf(
- hasEntry(equalTo("id"), not(isEmptyOrNullString())),
- hasEntry(equalTo("blobId"), not(isEmptyOrNullString())),
- hasEntry(equalTo("threadId"), not(isEmptyOrNullString())),
- hasEntry(equalTo("size"), not(isEmptyOrNullString()))
- )))
- // assert that message flags are all unset
- .body(ARGUMENTS + ".created", hasEntry(equalTo(messageCreationId), Matchers.allOf(
- hasEntry(equalTo("isDraft"), equalTo(false)),
- hasEntry(equalTo("isUnread"), equalTo(false)),
- hasEntry(equalTo("isFlagged"), equalTo(false)),
- hasEntry(equalTo("isAnswered"), equalTo(false))
- )))
- ;
+ .log().ifValidationFails()
+ .statusCode(200)
+ .body(NAME, equalTo("messagesSet"))
+ .body(ARGUMENTS + ".notCreated", aMapWithSize(0))
+ // note that assertions on result message had to be split between
+ // string-typed values and boolean-typed value assertions on the same .created entry
+ // make sure only one creation has been processed
+ .body(ARGUMENTS + ".created", aMapWithSize(1))
+ // assert server-set attributes are returned
+ .body(ARGUMENTS + ".created", hasEntry(equalTo(messageCreationId), Matchers.allOf(
+ hasEntry(equalTo("id"), not(isEmptyOrNullString())),
+ hasEntry(equalTo("blobId"), not(isEmptyOrNullString())),
+ hasEntry(equalTo("threadId"), not(isEmptyOrNullString())),
+ hasEntry(equalTo("size"), not(isEmptyOrNullString()))
+ )))
+ // assert that message flags are all unset
+ .body(ARGUMENTS + ".created", hasEntry(equalTo(messageCreationId), Matchers.allOf(
+ hasEntry(equalTo("isDraft"), equalTo(false)),
+ hasEntry(equalTo("isUnread"), equalTo(false)),
+ hasEntry(equalTo("isFlagged"), equalTo(false)),
+ hasEntry(equalTo("isAnswered"), equalTo(false))
+ )))
+ ;
}
@Test
@@ -728,23 +739,24 @@ public abstract class SetMessagesMethodTest {
"]";
given()
- .header("Authorization", accessToken.serialize())
- .body(requestBody)
+ .header("Authorization", accessToken.serialize())
+ .body(requestBody)
// When
.when()
- .post("/jmap");
+ .post("/jmap");
// Then
with()
- .header("Authorization", accessToken.serialize())
- .body("[[\"getMessages\", {\"ids\": [\"" + presumedMessageId + "\"]}, \"#0\"]]")
+ .header("Authorization", accessToken.serialize())
+ .body("[[\"getMessages\", {\"ids\": [\"" + presumedMessageId + "\"]}, \"#0\"]]")
.post("/jmap")
.then()
- .body(NAME, equalTo("messages"))
- .body(ARGUMENTS + ".list", hasSize(1))
- .body(ARGUMENTS + ".list[0].subject", equalTo(messageSubject))
- .body(ARGUMENTS + ".list[0].mailboxIds", contains(outboxId))
- ;
+ .log().ifValidationFails()
+ .body(NAME, equalTo("messages"))
+ .body(ARGUMENTS + ".list", hasSize(1))
+ .body(ARGUMENTS + ".list[0].subject", equalTo(messageSubject))
+ .body(ARGUMENTS + ".list[0].mailboxIds", contains(outboxId))
+ ;
}
@Test
@@ -822,19 +834,19 @@ public abstract class SetMessagesMethodTest {
"]";
given()
- .header("Authorization", accessToken.serialize())
- .body(requestBody)
- .when()
- .post("/jmap")
- .then()
- .log().ifValidationFails()
- .statusCode(200)
- .body(NAME, equalTo("messagesSet"))
+ .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+"\"].description", endsWith("no recipient address set"))
- .body(ARGUMENTS + ".created", aMapWithSize(0));
+ .body(ARGUMENTS + ".notCreated", hasKey(messageCreationId))
+ .body(ARGUMENTS + ".notCreated[\""+messageCreationId+"\"].type", equalTo("invalidProperties"))
+ .body(ARGUMENTS + ".notCreated[\""+messageCreationId+"\"].description", endsWith("no recipient address set"))
+ .body(ARGUMENTS + ".created", aMapWithSize(0));
}
@Test
@@ -857,20 +869,20 @@ public abstract class SetMessagesMethodTest {
"]";
given()
- .header("Authorization", accessToken.serialize())
- .body(requestBody)
+ .header("Authorization", accessToken.serialize())
+ .body(requestBody)
.when()
- .post("/jmap")
+ .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+"\"].description", endsWith("'from' address is mandatory"))
- .body(ARGUMENTS + ".notCreated[\""+messageCreationId+"\"].properties", hasSize(1))
- .body(ARGUMENTS + ".notCreated[\""+messageCreationId+"\"].properties", contains("from"))
- .body(ARGUMENTS + ".created", aMapWithSize(0));
+ .log().ifValidationFails()
+ .statusCode(200)
+ .body(NAME, equalTo("messagesSet"))
+ .body(ARGUMENTS + ".notCreated", hasKey(messageCreationId))
+ .body(ARGUMENTS + ".notCreated[\""+messageCreationId+"\"].type", equalTo("invalidProperties"))
+ .body(ARGUMENTS + ".notCreated[\""+messageCreationId+"\"].description", endsWith("'from' address is mandatory"))
+ .body(ARGUMENTS + ".notCreated[\""+messageCreationId+"\"].properties", hasSize(1))
+ .body(ARGUMENTS + ".notCreated[\""+messageCreationId+"\"].properties", contains("from"))
+ .body(ARGUMENTS + ".created", aMapWithSize(0));
}
@Test
@@ -895,19 +907,19 @@ public abstract class SetMessagesMethodTest {
"]";
given()
- .header("Authorization", accessToken.serialize())
- .body(requestBody)
+ .header("Authorization", accessToken.serialize())
+ .body(requestBody)
.when()
- .post("/jmap")
+ .post("/jmap")
.then()
- .log().ifValidationFails()
- .statusCode(200)
- .body(NAME, equalTo("messagesSet"))
- .body(ARGUMENTS + ".created", aMapWithSize(1))
- .body(ARGUMENTS + ".created", hasKey(messageCreationId))
- .body(ARGUMENTS + ".created[\""+messageCreationId+"\"].headers.from", equalTo(fromAddress))
- .body(ARGUMENTS + ".created[\""+messageCreationId+"\"].from.name", equalTo(fromAddress))
- .body(ARGUMENTS + ".created[\""+messageCreationId+"\"].from.email", equalTo(fromAddress));
+ .log().ifValidationFails()
+ .statusCode(200)
+ .body(NAME, equalTo("messagesSet"))
+ .body(ARGUMENTS + ".created", aMapWithSize(1))
+ .body(ARGUMENTS + ".created", hasKey(messageCreationId))
+ .body(ARGUMENTS + ".created[\""+messageCreationId+"\"].headers.from", equalTo(fromAddress))
+ .body(ARGUMENTS + ".created[\""+messageCreationId+"\"].from.name", equalTo(fromAddress))
+ .body(ARGUMENTS + ".created[\""+messageCreationId+"\"].from.email", equalTo(fromAddress));
}
@Test
@@ -932,19 +944,19 @@ public abstract class SetMessagesMethodTest {
"]";
given()
- .header("Authorization", accessToken.serialize())
- .body(requestBody)
+ .header("Authorization", accessToken.serialize())
+ .body(requestBody)
.when()
- .post("/jmap")
+ .post("/jmap")
.then()
- .log().ifValidationFails()
- .statusCode(200)
- .body(NAME, equalTo("messagesSet"))
- .body(ARGUMENTS + ".created", aMapWithSize(1))
- .body(ARGUMENTS + ".created", hasKey(messageCreationId))
- .body(ARGUMENTS + ".created[\""+messageCreationId+"\"].headers.from", equalTo(fromAddress))
- .body(ARGUMENTS + ".created[\""+messageCreationId+"\"].from.name", equalTo(fromAddress))
- .body(ARGUMENTS + ".created[\""+messageCreationId+"\"].from.email", equalTo(fromAddress));
+ .log().ifValidationFails()
+ .statusCode(200)
+ .body(NAME, equalTo("messagesSet"))
+ .body(ARGUMENTS + ".created", aMapWithSize(1))
+ .body(ARGUMENTS + ".created", hasKey(messageCreationId))
+ .body(ARGUMENTS + ".created[\""+messageCreationId+"\"].headers.from", equalTo(fromAddress))
+ .body(ARGUMENTS + ".created[\""+messageCreationId+"\"].from.name", equalTo(fromAddress))
+ .body(ARGUMENTS + ".created[\""+messageCreationId+"\"].from.email", equalTo(fromAddress));
}
@Test
@@ -1004,20 +1016,20 @@ public abstract class SetMessagesMethodTest {
"]";
given()
- .header("Authorization", accessToken.serialize())
- .body(requestBody)
+ .header("Authorization", accessToken.serialize())
+ .body(requestBody)
.when()
- .post("/jmap")
+ .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("subject"))
- .body(ARGUMENTS + ".notCreated[\""+messageCreationId+"\"].description", endsWith("'subject' is missing"))
- .body(ARGUMENTS + ".created", aMapWithSize(0));
+ .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("subject"))
+ .body(ARGUMENTS + ".notCreated[\""+messageCreationId+"\"].description", endsWith("'subject' is missing"))
+ .body(ARGUMENTS + ".created", aMapWithSize(0));
}
@@ -1516,7 +1528,7 @@ public abstract class SetMessagesMethodTest {
ZonedDateTime dateTime = ZonedDateTime.parse("2014-10-30T14:12:00Z");
jmapServer.serverProbe().appendMessage(username, new MailboxPath("#private", username, "inbox"),
- new ByteArrayInputStream("Subject: my test subject\r\n\r\ntestmail".getBytes()), Date.from(dateTime.toInstant()), false, new Flags());
+ new ByteArrayInputStream("Subject: my test subject\r\n\r\ntestmail".getBytes(Charsets.UTF_8)), Date.from(dateTime.toInstant()), false, new Flags());
String messageToMoveId = "user|inbox|1";
@@ -1547,4 +1559,209 @@ public abstract class SetMessagesMethodTest {
+ "(through reference chain: org.apache.james.jmap.model.Builder[\"mailboxIds\"])"))
.body(ARGUMENTS + ".updated", hasSize(0));
}
+
+ @Test
+ public void setMessagesShouldReturnAttachmentsNotFoundWhenBlobIdDoesntExist() throws Exception {
+ jmapServer.serverProbe().createMailbox(MailboxConstants.USER_NAMESPACE, username, "sent");
+ await();
+ String messageCreationId = "creationId";
+ String fromAddress = username;
+ String outboxId = getOutboxId(accessToken);
+ String requestBody = "[" +
+ " [" +
+ " \"setMessages\","+
+ " {" +
+ " \"create\": { \"" + messageCreationId + "\" : {" +
+ " \"from\": { \"name\": \"Me\", \"email\": \"" + fromAddress + "\"}," +
+ " \"to\": [{ \"name\": \"BOB\", \"email\": \"someone@example.com\"}]," +
+ " \"subject\": \"Message with a broken blobId\"," +
+ " \"textBody\": \"Test body\"," +
+ " \"mailboxIds\": [\"" + outboxId + "\"], " +
+ " \"attachments\": [" +
+ " {\"blobId\" : \"brokenId1\", \"type\" : \"image/gif\", \"size\" : 1337}," +
+ " {\"blobId\" : \"brokenId2\", \"type\" : \"image/jpeg\", \"size\" : 1337}" +
+ " ]" +
+ " }}" +
+ " }," +
+ " \"#0\"" +
+ " ]" +
+ "]";
+
+ String notCreatedPath = ARGUMENTS + ".notCreated[\""+messageCreationId+"\"]";
+
+ given()
+ .header("Authorization", accessToken.serialize())
+ .body(requestBody)
+ .when()
+ .post("/jmap")
+ .then()
+ .statusCode(200)
+ .body(NAME, equalTo("messagesSet"))
+ .body(ARGUMENTS + ".notCreated", hasKey(messageCreationId))
+ .body(notCreatedPath + ".type", equalTo("invalidProperties"))
+ .body(notCreatedPath + ".attachmentsNotFound", contains("brokenId1", "brokenId2"))
+ .body(ARGUMENTS + ".created", aMapWithSize(0));
+ }
+
+ @Test
+ public void setMessagesShouldReturnAttachmentsWhenMessageHasAttachment() throws Exception {
+ jmapServer.serverProbe().createMailbox(MailboxConstants.USER_NAMESPACE, username, "sent");
+
+ Attachment attachment = Attachment.builder()
+ .bytes("attachment".getBytes(Charsets.UTF_8))
+ .type("application/octet-stream")
+ .build();
+ uploadAttachment(attachment);
+ Attachment attachment2 = Attachment.builder()
+ .bytes("attachment2".getBytes(Charsets.UTF_8))
+ .type("application/octet-stream")
+ .build();
+ uploadAttachment(attachment2);
+
+ String messageCreationId = "creationId";
+ String fromAddress = username;
+ String outboxId = getOutboxId(accessToken);
+ String requestBody = "[" +
+ " [" +
+ " \"setMessages\","+
+ " {" +
+ " \"create\": { \"" + messageCreationId + "\" : {" +
+ " \"from\": { \"name\": \"Me\", \"email\": \"" + fromAddress + "\"}," +
+ " \"to\": [{ \"name\": \"BOB\", \"email\": \"someone@example.com\"}]," +
+ " \"subject\": \"Message with two attachments\"," +
+ " \"textBody\": \"Test body\"," +
+ " \"mailboxIds\": [\"" + outboxId + "\"], " +
+ " \"attachments\": [" +
+ " {\"blobId\" : \"" + attachment.getAttachmentId().getId() + "\", " +
+ " \"type\" : \"" + attachment.getType() + "\", " +
+ " \"size\" : " + attachment.getSize() + "}," +
+ " {\"blobId\" : \"" + attachment2.getAttachmentId().getId() + "\", " +
+ " \"type\" : \"" + attachment2.getType() + "\", " +
+ " \"size\" : " + attachment2.getSize() + ", " +
+ " \"cid\" : \"123456789\", " +
+ " \"isInline\" : true }" +
+ " ]" +
+ " }}" +
+ " }," +
+ " \"#0\"" +
+ " ]" +
+ "]";
+
+ String createdPath = ARGUMENTS + ".created[\""+messageCreationId+"\"]";
+ String firstAttachment = createdPath + ".attachments[0]";
+ String secondAttachment = createdPath + ".attachments[1]";
+
+ given()
+ .header("Authorization", accessToken.serialize())
+ .body(requestBody)
+ .when()
+ .post("/jmap")
+ .then()
+ .statusCode(200)
+ .body(NAME, equalTo("messagesSet"))
+ .body(ARGUMENTS + ".notCreated", aMapWithSize(0))
+ .body(ARGUMENTS + ".created", aMapWithSize(1))
+ .body(createdPath + ".attachments", hasSize(2))
+ .body(firstAttachment + ".blobId", equalTo(attachment.getAttachmentId().getId()))
+ .body(firstAttachment + ".type", equalTo("application/octet-stream; charset=UTF-8"))
+ .body(firstAttachment + ".size", equalTo((int) attachment.getSize()))
+ .body(firstAttachment + ".cid", nullValue())
+ .body(firstAttachment + ".isInline", equalTo(false))
+ .body(secondAttachment + ".blobId", equalTo(attachment2.getAttachmentId().getId()))
+ .body(secondAttachment + ".type", equalTo("application/octet-stream; charset=UTF-8"))
+ .body(secondAttachment + ".size", equalTo((int) attachment2.getSize()))
+ .body(secondAttachment + ".cid", equalTo("123456789"))
+ .body(secondAttachment + ".isInline", equalTo(true));
+ }
+
+ private void uploadAttachment(Attachment attachment) throws IOException {
+ with()
+ .header("Authorization", accessToken.serialize())
+ .contentType(attachment.getType())
+ .content(attachment.getStream())
+ .post("/upload");
+ }
+
+ @Test
+ public void attachmentsShouldBeRetrievedWhenChainingSetMessagesAndGetMessages() throws Exception {
+ jmapServer.serverProbe().createMailbox(MailboxConstants.USER_NAMESPACE, username, "sent");
+
+ Attachment attachment = Attachment.builder()
+ .bytes("attachment".getBytes(Charsets.UTF_8))
+ .type("application/octet-stream")
+ .build();
+ uploadAttachment(attachment);
+
+ String messageCreationId = "creationId";
+ String fromAddress = username;
+ String outboxId = getOutboxId(accessToken);
+ String requestBody = "[" +
+ " [" +
+ " \"setMessages\","+
+ " {" +
+ " \"create\": { \"" + messageCreationId + "\" : {" +
+ " \"from\": { \"name\": \"Me\", \"email\": \"" + fromAddress + "\"}," +
+ " \"to\": [{ \"name\": \"Me\", \"email\": \"" + fromAddress + "\"}]," +
+ " \"subject\": \"Message with an attachment\"," +
+ " \"textBody\": \"Test body\"," +
+ " \"mailboxIds\": [\"" + outboxId + "\"], " +
+ " \"attachments\": [" +
+ " {\"blobId\" : \"" + attachment.getAttachmentId().getId() + "\", " +
+ " \"type\" : \"" + attachment.getType() + "\", " +
+ " \"size\" : " + attachment.getSize() + ", " +
+ " \"cid\" : \"123456789\", " +
+ " \"isInline\" : true }" +
+ " ]" +
+ " }}" +
+ " }," +
+ " \"#0\"" +
+ " ]" +
+ "]";
+
+ given()
+ .header("Authorization", accessToken.serialize())
+ .body(requestBody)
+ .when()
+ .post("/jmap");
+
+ calmlyAwait.atMost(30, TimeUnit.SECONDS).until( () -> isAnyMessageFoundInInbox(accessToken));
+
+ String firstMessage = ARGUMENTS + ".list[0]";
+ String firstAttachment = firstMessage + ".attachments[0]";
+ String presumedMessageId = "username@domain.tld|INBOX|1";
+ given()
+ .header("Authorization", accessToken.serialize())
+ .body("[[\"getMessages\", {\"ids\": [\"" + presumedMessageId + "\"]}, \"#0\"]]")
+ .when()
+ .post("/jmap")
+ .then()
+ .statusCode(200)
+ .body(NAME, equalTo("messages"))
+ .body(ARGUMENTS + ".list", hasSize(1))
+ .body(firstMessage + ".attachments", hasSize(1))
+ .body(firstAttachment + ".blobId", equalTo(attachment.getAttachmentId().getId()))
+ .body(firstAttachment + ".type", equalTo("application/octet-stream"))
+ .body(firstAttachment + ".size", equalTo((int) attachment.getSize()))
+ .body(firstAttachment + ".cid", equalTo("123456789"))
+ .body(firstAttachment + ".isInline", equalTo(true));
+ }
+
+ private boolean isAnyMessageFoundInInbox(AccessToken recipientToken) {
+ try {
+ String inboxId = getMailboxId(accessToken, Role.INBOX);
+ with()
+ .header("Authorization", recipientToken.serialize())
+ .body("[[\"getMessageList\", {\"filter\":{\"inMailboxes\":[\"" + inboxId + "\"]}}, \"#0\"]]")
+ .when()
+ .post("/jmap")
+ .then()
+ .statusCode(200)
+ .body(NAME, equalTo("messageList"))
+ .body(ARGUMENTS + ".messageIds", hasSize(1));
+ return true;
+
+ } catch (AssertionError e) {
+ return false;
+ }
+ }
}
http://git-wip-us.apache.org/repos/asf/james-project/blob/662fa4a9/server/protocols/jmap/src/main/java/org/apache/james/jmap/exceptions/AttachmentsNotFoundException.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/exceptions/AttachmentsNotFoundException.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/exceptions/AttachmentsNotFoundException.java
new file mode 100644
index 0000000..1c06cb4
--- /dev/null
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/exceptions/AttachmentsNotFoundException.java
@@ -0,0 +1,40 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you under the Apache License, Version 2.0 (the *
+ * "License"); you may not use this file except in compliance *
+ * with the License. You may obtain a copy of the License at *
+ * *
+ * http://www.apache.org/licenses/LICENSE-2.0 *
+ * *
+ * Unless required by applicable law or agreed to in writing, *
+ * software distributed under the License is distributed on an *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
+ * KIND, either express or implied. See the License for the *
+ * specific language governing permissions and limitations *
+ * under the License. *
+ ****************************************************************/
+
+package org.apache.james.jmap.exceptions;
+
+import java.util.List;
+
+import org.apache.james.jmap.model.BlobId;
+
+import com.google.common.collect.ImmutableList;
+
+public class AttachmentsNotFoundException extends Exception {
+
+ private List<BlobId> attachmentIds;
+
+
+ public AttachmentsNotFoundException(List<BlobId> attachmentIds) {
+ this.attachmentIds = ImmutableList.copyOf(attachmentIds);
+ }
+
+ public List<BlobId> getAttachmentIds() {
+ return attachmentIds;
+ }
+}
http://git-wip-us.apache.org/repos/asf/james-project/blob/662fa4a9/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 25ba906..2eb52e7 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
@@ -27,9 +27,11 @@ import java.util.TimeZone;
import java.util.function.Consumer;
import java.util.stream.Collectors;
+import org.apache.commons.io.IOUtils;
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.mailbox.store.mail.model.MessageAttachment;
import org.apache.james.mime4j.Charsets;
import org.apache.james.mime4j.codec.DecodeMonitor;
import org.apache.james.mime4j.dom.FieldParser;
@@ -37,9 +39,13 @@ import org.apache.james.mime4j.dom.Message;
import org.apache.james.mime4j.dom.Multipart;
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.UnstructuredField;
+import org.apache.james.mime4j.field.Fields;
import org.apache.james.mime4j.field.UnstructuredFieldImpl;
import org.apache.james.mime4j.message.BasicBodyFactory;
+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.MessageBuilder;
@@ -51,16 +57,23 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Splitter;
import com.google.common.base.Throwables;
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableMap.Builder;
import com.google.common.net.MediaType;
public class MIMEMessageConverter {
+
private static final Logger LOGGER = LoggerFactory.getLogger(MIMEMessageConverter.class);
private static final String PLAIN_TEXT_MEDIA_TYPE = MediaType.PLAIN_TEXT_UTF_8.withoutParameters().toString();
private static final String HTML_MEDIA_TYPE = MediaType.HTML_UTF_8.withoutParameters().toString();
private static final NameValuePair UTF_8_CHARSET = new NameValuePair("charset", Charsets.UTF_8.name());
private static final String MIXED_SUB_TYPE = "mixed";
+ private static final String FIELD_PARAMETERS_SEPARATOR = ";";
private final BasicBodyFactory bodyFactory;
@@ -68,34 +81,34 @@ public class MIMEMessageConverter {
this.bodyFactory = new BasicBodyFactory();
}
- public byte[] convert(ValueWithId.CreationMessageEntry creationMessageEntry) {
+ public byte[] convert(ValueWithId.CreationMessageEntry creationMessageEntry, ImmutableList<MessageAttachment> messageAttachments) {
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
DefaultMessageWriter writer = new DefaultMessageWriter();
try {
- writer.writeMessage(convertToMime(creationMessageEntry), buffer);
+ writer.writeMessage(convertToMime(creationMessageEntry, messageAttachments), buffer);
} catch (IOException e) {
throw Throwables.propagate(e);
}
return buffer.toByteArray();
}
- @VisibleForTesting Message convertToMime(ValueWithId.CreationMessageEntry creationMessageEntry) {
+ @VisibleForTesting Message convertToMime(ValueWithId.CreationMessageEntry creationMessageEntry, ImmutableList<MessageAttachment> messageAttachments) {
if (creationMessageEntry == null || creationMessageEntry.getValue() == null) {
throw new IllegalArgumentException("creationMessageEntry is either null or has null message");
}
MessageBuilder messageBuilder = MessageBuilder.create();
- if (mixedTextAndHtml(creationMessageEntry.getValue())) {
- messageBuilder.setBody(createMultipartBody(creationMessageEntry.getValue()));
+ if (isMultipart(creationMessageEntry.getValue(), messageAttachments)) {
+ messageBuilder.setBody(createMultipartBody(creationMessageEntry.getValue(), messageAttachments));
} else {
messageBuilder.setBody(createTextBody(creationMessageEntry.getValue()));
}
- buildMimeHeaders(messageBuilder, creationMessageEntry.getCreationId(), creationMessageEntry.getValue());
+ buildMimeHeaders(messageBuilder, creationMessageEntry.getCreationId(), creationMessageEntry.getValue(), messageAttachments);
return messageBuilder.build();
}
- private void buildMimeHeaders(MessageBuilder messageBuilder, CreationMessageId creationId, CreationMessage newMessage) {
+ private void buildMimeHeaders(MessageBuilder messageBuilder, CreationMessageId creationId, CreationMessage newMessage, ImmutableList<MessageAttachment> messageAttachments) {
Optional<Mailbox> fromAddress = newMessage.getFrom().filter(DraftEmailer::hasValidEmail).map(this::convertEmailToMimeHeader);
fromAddress.ifPresent(messageBuilder::setFrom);
fromAddress.ifPresent(messageBuilder::setSender);
@@ -121,7 +134,7 @@ 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));
- if (!mixedTextAndHtml(newMessage)) {
+ if (!isMultipart(newMessage, messageAttachments)) {
newMessage.getHtmlBody().ifPresent(x -> messageBuilder.setContentType(HTML_MEDIA_TYPE, UTF_8_CHARSET));
}
}
@@ -134,8 +147,9 @@ public class MIMEMessageConverter {
};
}
- private boolean mixedTextAndHtml(CreationMessage newMessage) {
- return newMessage.getTextBody().isPresent() && newMessage.getHtmlBody().isPresent();
+ private boolean isMultipart(CreationMessage newMessage, ImmutableList<MessageAttachment> messageAttachments) {
+ return (newMessage.getTextBody().isPresent() && newMessage.getHtmlBody().isPresent())
+ || !messageAttachments.isEmpty();
}
private TextBody createTextBody(CreationMessage newMessage) {
@@ -145,26 +159,93 @@ public class MIMEMessageConverter {
return bodyFactory.textBody(body, Charsets.UTF_8);
}
- private Multipart createMultipartBody(CreationMessage newMessage) {
+ private Multipart createMultipartBody(CreationMessage newMessage, ImmutableList<MessageAttachment> messageAttachments) {
try {
- return MultipartBuilder.create(MIXED_SUB_TYPE)
- .addBodyPart(BodyPartBuilder.create()
- .use(bodyFactory)
- .setBody(newMessage.getTextBody().get(), Charsets.UTF_8)
- .setContentType(PLAIN_TEXT_MEDIA_TYPE, UTF_8_CHARSET)
- .build())
- .addBodyPart(BodyPartBuilder.create()
- .use(bodyFactory)
- .setBody(newMessage.getHtmlBody().get(), Charsets.UTF_8)
- .setContentType(HTML_MEDIA_TYPE, UTF_8_CHARSET)
- .build())
- .build();
+ MultipartBuilder builder = MultipartBuilder.create(MIXED_SUB_TYPE);
+ addText(builder, newMessage.getTextBody());
+ addHtml(builder, newMessage.getHtmlBody());
+
+ Consumer<MessageAttachment> addAttachment = addAttachment(builder);
+ messageAttachments.stream()
+ .forEach(addAttachment);
+
+ return builder.build();
} catch (IOException e) {
LOGGER.error("Error while creating textBody \n"+ newMessage.getTextBody().get() +"\n or htmlBody \n" + newMessage.getHtmlBody().get(), e);
throw Throwables.propagate(e);
}
}
+ private void addText(MultipartBuilder builder, Optional<String> textBody) throws IOException {
+ if (textBody.isPresent()) {
+ builder.addBodyPart(BodyPartBuilder.create()
+ .use(bodyFactory)
+ .setBody(textBody.get(), Charsets.UTF_8)
+ .setContentType(PLAIN_TEXT_MEDIA_TYPE, UTF_8_CHARSET)
+ .build());
+ }
+ }
+
+ private void addHtml(MultipartBuilder builder, Optional<String> htmlBody) throws IOException {
+ if (htmlBody.isPresent()) {
+ builder.addBodyPart(BodyPartBuilder.create()
+ .use(bodyFactory)
+ .setBody(htmlBody.get(), Charsets.UTF_8)
+ .setContentType(HTML_MEDIA_TYPE, UTF_8_CHARSET)
+ .build());
+ }
+ }
+
+ private Consumer<MessageAttachment> addAttachment(MultipartBuilder builder) {
+ return att -> {
+ try {
+ builder.addBodyPart(attachmentBodyPart(att));
+ } catch (IOException e) {
+ LOGGER.error("Error while creating attachment", e);
+ throw Throwables.propagate(e);
+ }
+ };
+ }
+
+ private BodyPart attachmentBodyPart(MessageAttachment att) throws IOException {
+ BodyPartBuilder builder = BodyPartBuilder.create()
+ .use(bodyFactory)
+ .setBody(IOUtils.toString(att.getAttachment().getStream()), Charsets.UTF_8)
+ .setField(contentTypeField(att))
+ .setField(contentDispositionField(att.isInline()));
+ contentId(builder, att);
+ return builder.build();
+ }
+
+ private void contentId(BodyPartBuilder builder, MessageAttachment att) {
+ if (att.getCid().isPresent()) {
+ builder.setField(new RawField("Content-ID", att.getCid().get()));
+ }
+ }
+
+ private ContentTypeField contentTypeField(MessageAttachment att) {
+ Builder<String, String> parameters = ImmutableMap.<String, String> builder();
+ if (att.getName().isPresent()) {
+ parameters.put("name", att.getName().get());
+ }
+ String type = att.getAttachment().getType();
+ if (type.contains(FIELD_PARAMETERS_SEPARATOR)) {
+ return Fields.contentType(contentTypeWithoutParameters(type), parameters.build());
+ }
+ return Fields.contentType(type, parameters.build());
+ }
+
+ private String contentTypeWithoutParameters(String type) {
+ return FluentIterable.from(Splitter.on(FIELD_PARAMETERS_SEPARATOR).split(type)).get(0);
+ }
+
+ private ContentDispositionField contentDispositionField(boolean isInline) {
+ if (isInline) {
+ return Fields.contentDisposition("inline");
+ }
+ return Fields.contentDisposition("attachment");
+ }
+
private Mailbox convertEmailToMimeHeader(DraftEmailer address) {
if (!address.hasValidEmail()) {
throw new IllegalArgumentException("address");
http://git-wip-us.apache.org/repos/asf/james-project/blob/662fa4a9/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 3da428b..9d6210e 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
@@ -26,6 +26,7 @@ import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
+import java.util.stream.Stream;
import javax.inject.Inject;
import javax.mail.Flags;
@@ -33,8 +34,11 @@ import javax.mail.MessagingException;
import javax.mail.internet.SharedInputStream;
import javax.mail.util.SharedByteArrayInputStream;
+import org.apache.james.jmap.exceptions.AttachmentsNotFoundException;
import org.apache.james.jmap.methods.ValueWithId.CreationMessageEntry;
import org.apache.james.jmap.methods.ValueWithId.MessageWithId;
+import org.apache.james.jmap.model.Attachment;
+import org.apache.james.jmap.model.BlobId;
import org.apache.james.jmap.model.CreationMessage;
import org.apache.james.jmap.model.CreationMessageId;
import org.apache.james.jmap.model.Message;
@@ -43,6 +47,7 @@ import org.apache.james.jmap.model.MessageId;
import org.apache.james.jmap.model.MessageProperties;
import org.apache.james.jmap.model.MessageProperties.MessageProperty;
import org.apache.james.jmap.model.SetError;
+import org.apache.james.jmap.model.SetMessagesError;
import org.apache.james.jmap.model.SetMessagesRequest;
import org.apache.james.jmap.model.SetMessagesResponse;
import org.apache.james.jmap.model.SetMessagesResponse.Builder;
@@ -52,16 +57,22 @@ import org.apache.james.jmap.send.MailMetadata;
import org.apache.james.jmap.send.MailSpool;
import org.apache.james.jmap.utils.SystemMailboxesProvider;
import org.apache.james.mailbox.MailboxSession;
+import org.apache.james.mailbox.exception.AttachmentNotFoundException;
import org.apache.james.mailbox.exception.MailboxException;
import org.apache.james.mailbox.exception.MailboxNotFoundException;
import org.apache.james.mailbox.model.MailboxPath;
import org.apache.james.mailbox.store.MailboxSessionMapperFactory;
+import org.apache.james.mailbox.store.mail.AttachmentMapper;
+import org.apache.james.mailbox.store.mail.AttachmentMapperFactory;
import org.apache.james.mailbox.store.mail.MessageMapper;
+import org.apache.james.mailbox.store.mail.model.AttachmentId;
import org.apache.james.mailbox.store.mail.model.Mailbox;
import org.apache.james.mailbox.store.mail.model.MailboxId;
import org.apache.james.mailbox.store.mail.model.MailboxMessage;
+import org.apache.james.mailbox.store.mail.model.MessageAttachment;
import org.apache.james.mailbox.store.mail.model.impl.PropertyBuilder;
import org.apache.james.mailbox.store.mail.model.impl.SimpleMailboxMessage;
+import org.apache.james.util.streams.ImmutableCollectors;
import org.apache.mailet.Mail;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -80,6 +91,7 @@ public class SetMessagesCreationProcessor implements SetMessagesProcessor {
private final MailFactory mailFactory;
private final MessageFactory messageFactory;
private final SystemMailboxesProvider systemMailboxesProvider;
+ private AttachmentMapperFactory attachmentMapperFactory;
@VisibleForTesting @Inject
@@ -88,13 +100,15 @@ public class SetMessagesCreationProcessor implements SetMessagesProcessor {
MailSpool mailSpool,
MailFactory mailFactory,
MessageFactory messageFactory,
- SystemMailboxesProvider systemMailboxesProvider) {
+ SystemMailboxesProvider systemMailboxesProvider,
+ AttachmentMapperFactory attachmentMapperFactory) {
this.mailboxSessionMapperFactory = mailboxSessionMapperFactory;
this.mimeMessageConverter = mimeMessageConverter;
this.mailSpool = mailSpool;
this.mailFactory = mailFactory;
this.messageFactory = messageFactory;
this.systemMailboxesProvider = systemMailboxesProvider;
+ this.attachmentMapperFactory = attachmentMapperFactory;
}
@Override
@@ -109,7 +123,7 @@ public class SetMessagesCreationProcessor implements SetMessagesProcessor {
private void handleCreate(CreationMessageEntry create, Builder responseBuilder, MailboxSession mailboxSession) {
try {
validateImplementedFeature(create, mailboxSession);
- validateArguments(create);
+ validateArguments(create, mailboxSession);
validateRights(create, mailboxSession);
MessageWithId created = handleOutboxMessages(create, mailboxSession);
responseBuilder.created(created.getCreationId(), created.getValue());
@@ -123,6 +137,15 @@ public class SetMessagesCreationProcessor implements SetMessagesProcessor {
Joiner.on(", ").join(e.getAllowedFroms()))
.build());
+ } catch (AttachmentsNotFoundException e) {
+ responseBuilder.notCreated(create.getCreationId(),
+ SetMessagesError.builder()
+ .type("invalidProperties")
+ .properties(MessageProperty.mailboxIds)
+ .attachmentsNotFound(e.getAttachmentIds())
+ .description("Attachment not found")
+ .build());
+
} catch (MailboxNotImplementedException e) {
responseBuilder.notCreated(create.getCreationId(),
SetError.builder()
@@ -161,13 +184,41 @@ public class SetMessagesCreationProcessor implements SetMessagesProcessor {
}
}
- private void validateArguments(CreationMessageEntry entry) throws MailboxInvalidMessageCreationException {
+ private void validateArguments(CreationMessageEntry entry, MailboxSession session) throws MailboxInvalidMessageCreationException, AttachmentsNotFoundException, MailboxException {
CreationMessage message = entry.getValue();
if (!message.isValid()) {
throw new MailboxInvalidMessageCreationException();
}
+ assertAttachmentsExist(entry, session);
}
+ @VisibleForTesting void assertAttachmentsExist(CreationMessageEntry entry, MailboxSession session) throws AttachmentsNotFoundException, MailboxException {
+ List<Attachment> attachments = entry.getValue().getAttachments();
+ if (!attachments.isEmpty()) {
+ AttachmentMapper attachmentMapper = attachmentMapperFactory.getAttachmentMapper(session);
+ List<BlobId> notFounds = listAttachmentsNotFound(attachments, attachmentMapper);
+ if (!notFounds.isEmpty()) {
+ throw new AttachmentsNotFoundException(notFounds);
+ }
+ }
+ }
+
+ private List<BlobId> listAttachmentsNotFound(List<Attachment> attachments, AttachmentMapper attachmentMapper) {
+ return attachments.stream()
+ .flatMap(attachment -> {
+ try {
+ attachmentMapper.getAttachment(getAttachmentId(attachment));
+ return Stream.of();
+ } catch (AttachmentNotFoundException e) {
+ return Stream.of(attachment.getBlobId());
+ }
+ }).collect(ImmutableCollectors.toImmutableList());
+ }
+
+ private AttachmentId getAttachmentId(Attachment attachment) {
+ return AttachmentId.from(attachment.getBlobId().getRawValue());
+ }
+
private void validateRights(CreationMessageEntry entry, MailboxSession session) throws MailboxSendingNotAllowedException {
List<String> allowedSenders = ImmutableList.of(session.getUser().getUserName());
if (!isAllowedFromAddress(entry.getValue(), allowedSenders)) {
@@ -200,9 +251,9 @@ public class SetMessagesCreationProcessor implements SetMessagesProcessor {
CreationMessageId creationId = createdEntry.getCreationId();
MessageMapper messageMapper = mailboxSessionMapperFactory.createMessageMapper(session);
- MailboxMessage newMailboxMessage = buildMailboxMessage(createdEntry, outbox);
+ MailboxMessage newMailboxMessage = buildMailboxMessage(session, createdEntry, outbox);
messageMapper.add(outbox, newMailboxMessage);
- Message jmapMessage = messageFactory.fromMailboxMessage(newMailboxMessage, ImmutableList.of(), buildMessageIdFromUid);
+ Message jmapMessage = messageFactory.fromMailboxMessage(newMailboxMessage, newMailboxMessage.getAttachments(), buildMessageIdFromUid);
sendMessage(newMailboxMessage, jmapMessage, session);
return new MessageWithId(creationId, jmapMessage);
}
@@ -248,8 +299,9 @@ public class SetMessagesCreationProcessor implements SetMessagesProcessor {
return new MessageId(session.getUser(), outboxPath, uid);
}
- private MailboxMessage buildMailboxMessage(MessageWithId.CreationMessageEntry createdEntry, Mailbox outbox) {
- byte[] messageContent = mimeMessageConverter.convert(createdEntry);
+ private MailboxMessage buildMailboxMessage(MailboxSession session, MessageWithId.CreationMessageEntry createdEntry, Mailbox outbox) throws MailboxException {
+ ImmutableList<MessageAttachment> messageAttachments = getMessageAttachments(session, createdEntry.getValue().getAttachments());
+ byte[] messageContent = mimeMessageConverter.convert(createdEntry, messageAttachments);
SharedInputStream content = new SharedByteArrayInputStream(messageContent);
long size = messageContent.length;
int bodyStartOctet = 0;
@@ -260,7 +312,29 @@ public class SetMessagesCreationProcessor implements SetMessagesProcessor {
Date internalDate = Date.from(createdEntry.getValue().getDate().toInstant());
return new SimpleMailboxMessage(internalDate, size,
- bodyStartOctet, content, flags, propertyBuilder, mailboxId);
+ bodyStartOctet, content, flags, propertyBuilder, mailboxId, messageAttachments);
+ }
+
+ private ImmutableList<MessageAttachment> getMessageAttachments(MailboxSession session, ImmutableList<Attachment> attachments) throws MailboxException {
+ AttachmentMapper attachmentMapper = attachmentMapperFactory.getAttachmentMapper(session);
+ return attachments.stream()
+ .map(att -> messageAttachment(attachmentMapper, att))
+ .collect(ImmutableCollectors.toImmutableList());
+ }
+
+ private MessageAttachment messageAttachment(AttachmentMapper attachmentMapper, Attachment attachment) {
+ try {
+ return MessageAttachment.builder()
+ .attachment(attachmentMapper.getAttachment(AttachmentId.from(attachment.getBlobId().getRawValue())))
+ .name(attachment.getName().orElse(null))
+ .cid(attachment.getCid().orElse(null))
+ .isInline(attachment.isIsInline())
+ .build();
+ } catch (AttachmentNotFoundException e) {
+ // should not happen (checked before)
+ LOG.error(String.format("Attachment %s not found", attachment.getBlobId()), e);
+ return null;
+ }
}
private PropertyBuilder buildPropertyBuilder() {
http://git-wip-us.apache.org/repos/asf/james-project/blob/662fa4a9/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/CreationMessage.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/CreationMessage.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/CreationMessage.java
index 60f7b91..5202a15 100644
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/CreationMessage.java
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/CreationMessage.java
@@ -25,6 +25,7 @@ import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
+import java.util.function.Predicate;
import java.util.stream.Collectors;
import javax.mail.internet.AddressException;
@@ -73,7 +74,7 @@ public class CreationMessage {
private String textBody;
private String htmlBody;
private final ImmutableList.Builder<Attachment> attachments;
- private final ImmutableMap.Builder<String, SubMessage> attachedMessages;
+ private final ImmutableMap.Builder<BlobId, SubMessage> attachedMessages;
private Builder() {
to = ImmutableList.builder();
@@ -89,6 +90,7 @@ public class CreationMessage {
return mailboxIds(Arrays.asList(mailboxIds));
}
+ @JsonDeserialize
public Builder mailboxIds(List<String> mailboxIds) {
this.mailboxIds = ImmutableList.copyOf(mailboxIds);
return this;
@@ -169,27 +171,39 @@ public class CreationMessage {
return this;
}
+ public Builder attachments(Attachment... attachments) {
+ return attachments(Arrays.asList(attachments));
+ }
+
+ @JsonDeserialize
public Builder attachments(List<Attachment> attachments) {
this.attachments.addAll(attachments);
return this;
}
- public Builder attachedMessages(Map<String, SubMessage> attachedMessages) {
+ public Builder attachedMessages(Map<BlobId, SubMessage> attachedMessages) {
this.attachedMessages.putAll(attachedMessages);
return this;
}
- private static boolean areAttachedMessagesKeysInAttachments(ImmutableList<Attachment> attachments, ImmutableMap<String, SubMessage> attachedMessages) {
- return attachments.stream()
+ private static boolean areAttachedMessagesKeysInAttachments(ImmutableList<Attachment> attachments, ImmutableMap<BlobId, SubMessage> attachedMessages) {
+ return attachedMessages.isEmpty() || attachedMessages.keySet().stream()
+ .anyMatch(inAttachments(attachments));
+ }
+
+ private static Predicate<BlobId> inAttachments(ImmutableList<Attachment> attachments) {
+ return (key) -> {
+ return attachments.stream()
.map(Attachment::getBlobId)
- .allMatch(attachedMessages::containsKey);
+ .anyMatch(blobId -> blobId.equals(key));
+ };
}
public CreationMessage build() {
Preconditions.checkState(mailboxIds != null, "'mailboxIds' is mandatory");
Preconditions.checkState(headers != null, "'headers' is mandatory");
ImmutableList<Attachment> attachments = this.attachments.build();
- ImmutableMap<String, SubMessage> attachedMessages = this.attachedMessages.build();
+ ImmutableMap<BlobId, SubMessage> attachedMessages = this.attachedMessages.build();
Preconditions.checkState(areAttachedMessagesKeysInAttachments(attachments, attachedMessages), "'attachedMessages' keys must be in 'attachments'");
if (date == null) {
@@ -218,12 +232,12 @@ public class CreationMessage {
private final Optional<String> textBody;
private final Optional<String> htmlBody;
private final ImmutableList<Attachment> attachments;
- private final ImmutableMap<String, SubMessage> attachedMessages;
+ private final ImmutableMap<BlobId, SubMessage> attachedMessages;
@VisibleForTesting
CreationMessage(ImmutableList<String> mailboxIds, Optional<String> inReplyToMessageId, boolean isUnread, boolean isFlagged, boolean isAnswered, boolean isDraft, ImmutableMap<String, String> headers, Optional<DraftEmailer> from,
ImmutableList<DraftEmailer> to, ImmutableList<DraftEmailer> cc, ImmutableList<DraftEmailer> bcc, ImmutableList<DraftEmailer> replyTo, String subject, ZonedDateTime date, Optional<String> textBody, Optional<String> htmlBody, ImmutableList<Attachment> attachments,
- ImmutableMap<String, SubMessage> attachedMessages) {
+ ImmutableMap<BlobId, SubMessage> attachedMessages) {
this.mailboxIds = mailboxIds;
this.inReplyToMessageId = inReplyToMessageId;
this.isUnread = isUnread;
@@ -312,7 +326,7 @@ public class CreationMessage {
return attachments;
}
- public ImmutableMap<String, SubMessage> getAttachedMessages() {
+ public ImmutableMap<BlobId, SubMessage> getAttachedMessages() {
return attachedMessages;
}
http://git-wip-us.apache.org/repos/asf/james-project/blob/662fa4a9/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetError.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetError.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetError.java
index 658491c..cda1aef 100644
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetError.java
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetError.java
@@ -49,7 +49,7 @@ public class SetError {
private String description;
private Optional<ImmutableSet<MessageProperty>> properties = Optional.empty();
- private Builder() {
+ protected Builder() {
}
public Builder type(String type) {
@@ -91,6 +91,13 @@ public class SetError {
this.properties = properties;
}
+ protected SetError(SetError setError) {
+ this.type = setError.type;
+ this.description = setError.description;
+ this.properties = setError.properties;
+ }
+
+
@JsonSerialize
public String getType() {
return type;
http://git-wip-us.apache.org/repos/asf/james-project/blob/662fa4a9/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetMessagesError.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetMessagesError.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetMessagesError.java
new file mode 100644
index 0000000..2cf19e0
--- /dev/null
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetMessagesError.java
@@ -0,0 +1,92 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you under the Apache License, Version 2.0 (the *
+ * "License"); you may not use this file except in compliance *
+ * with the License. You may obtain a copy of the License at *
+ * *
+ * http://www.apache.org/licenses/LICENSE-2.0 *
+ * *
+ * Unless required by applicable law or agreed to in writing, *
+ * software distributed under the License is distributed on an *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
+ * KIND, either express or implied. See the License for the *
+ * specific language governing permissions and limitations *
+ * under the License. *
+ ****************************************************************/
+package org.apache.james.jmap.model;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.james.jmap.model.MessageProperties.MessageProperty;
+
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.google.common.collect.ImmutableList;
+
+public class SetMessagesError extends SetError {
+
+ public static SetMessagesError.Builder builder() {
+ return new Builder();
+ }
+
+ public static class Builder extends SetError.Builder {
+
+ private List<BlobId> attachmentsNotFound;
+
+ private Builder() {
+ super();
+ attachmentsNotFound = new ArrayList<>();
+ }
+
+ @Override
+ public Builder description(String description) {
+ return (Builder) super.description(description);
+ }
+
+ @Override
+ public Builder properties(MessageProperty... properties) {
+ return (Builder) super.properties(properties);
+ }
+
+ @Override
+ public Builder properties(Set<MessageProperty> properties) {
+ return (Builder) super.properties(properties);
+ }
+
+ @Override
+ public Builder type(String type) {
+ return (Builder) super.type(type);
+ }
+
+ public Builder attachmentsNotFound(BlobId... attachmentIds) {
+ return attachmentsNotFound(Arrays.asList(attachmentIds));
+ }
+
+ public Builder attachmentsNotFound(List<BlobId> attachmentIds) {
+ this.attachmentsNotFound.addAll(attachmentIds);
+ return this;
+ }
+
+ @Override
+ public SetError build() {
+ return new SetMessagesError(super.build(), ImmutableList.copyOf(attachmentsNotFound));
+ }
+ }
+
+ private ImmutableList<BlobId> attachmentsNotFound;
+
+ public SetMessagesError(SetError setError, ImmutableList<BlobId> attachmentsNotFound) {
+ super(setError);
+ this.attachmentsNotFound = attachmentsNotFound;
+ }
+
+ @JsonSerialize
+ public List<BlobId> getAttachmentsNotFound() {
+ return attachmentsNotFound;
+ }
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org
[3/5] james-project git commit: JAMES-1790 stop logging errors when
stopping MailQueue
Posted by ad...@apache.org.
JAMES-1790 stop logging errors when stopping MailQueue
Project: http://git-wip-us.apache.org/repos/asf/james-project/repo
Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/2a7c50f5
Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/2a7c50f5
Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/2a7c50f5
Branch: refs/heads/master
Commit: 2a7c50f5f40ed43ff0e6fcef5faa1fcf097e3ca6
Parents: 1c294dd
Author: Matthieu Baechler <ma...@linagora.com>
Authored: Mon Jul 4 11:34:23 2016 +0200
Committer: Antoine Duprat <ad...@linagora.com>
Committed: Fri Jul 8 14:24:55 2016 +0200
----------------------------------------------------------------------
.../modules/server/MemoryMailQueueFactory.java | 11 +++-------
.../mailetcontainer/impl/JamesMailSpooler.java | 21 ++++++++++----------
.../org/apache/james/queue/api/MailQueue.java | 4 +---
3 files changed, 15 insertions(+), 21 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/james-project/blob/2a7c50f5/server/container/guice/memory-guice/src/main/java/org/apache/james/modules/server/MemoryMailQueueFactory.java
----------------------------------------------------------------------
diff --git a/server/container/guice/memory-guice/src/main/java/org/apache/james/modules/server/MemoryMailQueueFactory.java b/server/container/guice/memory-guice/src/main/java/org/apache/james/modules/server/MemoryMailQueueFactory.java
index 75466e4..c1f92b1 100644
--- a/server/container/guice/memory-guice/src/main/java/org/apache/james/modules/server/MemoryMailQueueFactory.java
+++ b/server/container/guice/memory-guice/src/main/java/org/apache/james/modules/server/MemoryMailQueueFactory.java
@@ -33,7 +33,6 @@ import org.apache.james.queue.api.MailQueueItemDecoratorFactory;
import org.apache.mailet.Mail;
import com.google.common.base.Objects;
-import com.google.common.base.Throwables;
import com.google.inject.Inject;
public class MemoryMailQueueFactory implements MailQueueFactory {
@@ -86,14 +85,10 @@ public class MemoryMailQueueFactory implements MailQueueFactory {
}
@Override
- public MailQueueItem deQueue() throws MailQueueException {
+ public MailQueueItem deQueue() throws MailQueueException, InterruptedException {
while (true) {
- try {
- MemoryMailQueueItem item = mailItems.take();
- return mailQueueItemDecoratorFactory.decorate(item);
- } catch (InterruptedException e) {
- Throwables.propagate(e);
- }
+ MemoryMailQueueItem item = mailItems.take();
+ return mailQueueItemDecoratorFactory.decorate(item);
}
}
http://git-wip-us.apache.org/repos/asf/james-project/blob/2a7c50f5/server/mailet/mailetcontainer-camel/src/main/java/org/apache/james/mailetcontainer/impl/JamesMailSpooler.java
----------------------------------------------------------------------
diff --git a/server/mailet/mailetcontainer-camel/src/main/java/org/apache/james/mailetcontainer/impl/JamesMailSpooler.java b/server/mailet/mailetcontainer-camel/src/main/java/org/apache/james/mailetcontainer/impl/JamesMailSpooler.java
index ccfed91..f2c3e47 100644
--- a/server/mailet/mailetcontainer-camel/src/main/java/org/apache/james/mailetcontainer/impl/JamesMailSpooler.java
+++ b/server/mailet/mailetcontainer-camel/src/main/java/org/apache/james/mailetcontainer/impl/JamesMailSpooler.java
@@ -19,6 +19,14 @@
package org.apache.james.mailetcontainer.impl;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+import javax.inject.Inject;
+
import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.HierarchicalConfiguration;
import org.apache.james.lifecycle.api.Configurable;
@@ -35,13 +43,6 @@ import org.apache.james.util.concurrent.JMXEnabledThreadPoolExecutor;
import org.apache.mailet.Mail;
import org.slf4j.Logger;
-import javax.annotation.PostConstruct;
-import javax.annotation.PreDestroy;
-import javax.inject.Inject;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicInteger;
-
/**
* Manages the mail spool. This class is responsible for retrieving messages
* from the spool, directing messages to the appropriate processor, and removing
@@ -192,11 +193,11 @@ public class JamesMailSpooler implements Runnable, Disposable, Configurable, Log
logger.error("Exception dequeue mail", e1);
}
+ } catch (InterruptedException interrupted) {
+ //MailSpooler is stopping
}
}
- if (logger.isInfoEnabled()) {
- logger.info("Stop " + getClass().getName() + ": " + Thread.currentThread().getName());
- }
+ logger.info("Stop {} : {}", getClass().getName(), Thread.currentThread().getName());
}
/**
http://git-wip-us.apache.org/repos/asf/james-project/blob/2a7c50f5/server/queue/queue-api/src/main/java/org/apache/james/queue/api/MailQueue.java
----------------------------------------------------------------------
diff --git a/server/queue/queue-api/src/main/java/org/apache/james/queue/api/MailQueue.java b/server/queue/queue-api/src/main/java/org/apache/james/queue/api/MailQueue.java
index ca82525..67c9282 100644
--- a/server/queue/queue-api/src/main/java/org/apache/james/queue/api/MailQueue.java
+++ b/server/queue/queue-api/src/main/java/org/apache/james/queue/api/MailQueue.java
@@ -86,10 +86,8 @@ public interface MailQueue {
* block until a Mail is ready and then process the operation.
* Implementations should take care todo some kind of transactions to not
* loose any mail on error
- *
- * @throws MailQueueException
*/
- MailQueueItem deQueue() throws MailQueueException;
+ MailQueueItem deQueue() throws MailQueueException, InterruptedException;
/**
* Exception which will get thrown if any problems occur while working the
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org
[4/5] james-project git commit: JAMES-1790 check that blobids exist
when attaching them
Posted by ad...@apache.org.
http://git-wip-us.apache.org/repos/asf/james-project/blob/662fa4a9/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 e64d6a9..6f9b3d3 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
@@ -30,7 +30,10 @@ import org.apache.james.jmap.methods.ValueWithId.MessageWithId;
import org.apache.james.jmap.model.CreationMessage;
import org.apache.james.jmap.model.CreationMessage.DraftEmailer;
import org.apache.james.jmap.model.CreationMessageId;
+import org.apache.james.mailbox.store.mail.model.AttachmentId;
+import org.apache.james.mailbox.store.mail.model.MessageAttachment;
import org.apache.james.mime4j.Charsets;
+import org.apache.james.mime4j.dom.Entity;
import org.apache.james.mime4j.dom.Message;
import org.apache.james.mime4j.dom.Multipart;
import org.apache.james.mime4j.dom.TextBody;
@@ -57,7 +60,7 @@ public class MIMEMessageConverterTest {
// When
Message result = sut.convertToMime(new ValueWithId.CreationMessageEntry(
- CreationMessageId.of("user|mailbox|1"), messageHavingInReplyTo));
+ CreationMessageId.of("user|mailbox|1"), messageHavingInReplyTo), ImmutableList.of());
// Then
assertThat(result.getHeader().getFields("In-Reply-To")).extracting(Field::getBody)
@@ -68,7 +71,7 @@ public class MIMEMessageConverterTest {
public void convertToMimeShouldThrowWhenMessageIsNull() {
MIMEMessageConverter sut = new MIMEMessageConverter();
- sut.convertToMime(new ValueWithId.CreationMessageEntry(CreationMessageId.of("any"), null));
+ sut.convertToMime(new ValueWithId.CreationMessageEntry(CreationMessageId.of("any"), null), ImmutableList.of());
}
@Test
@@ -85,7 +88,7 @@ public class MIMEMessageConverterTest {
// When
Message result = sut.convertToMime(new ValueWithId.CreationMessageEntry(
- CreationMessageId.of("user|mailbox|1"), testMessage));
+ CreationMessageId.of("user|mailbox|1"), testMessage), ImmutableList.of());
// Then
assertThat(result.getFrom()).extracting(Mailbox::getAddress).allMatch(f -> f.equals(joesEmail));
@@ -109,7 +112,7 @@ public class MIMEMessageConverterTest {
// When
Message result = sut.convertToMime(new ValueWithId.CreationMessageEntry(
- CreationMessageId.of("user|mailbox|1"), testMessage));
+ CreationMessageId.of("user|mailbox|1"), testMessage), ImmutableList.of());
// Then
assertThat(result.getDate()).isEqualToIgnoringMillis(Date.from(now));
@@ -130,7 +133,7 @@ public class MIMEMessageConverterTest {
// When
Message result = sut.convertToMime(new ValueWithId.CreationMessageEntry(
- CreationMessageId.of("user|mailbox|1"), testMessage));
+ CreationMessageId.of("user|mailbox|1"), testMessage), ImmutableList.of());
// Then
assertThat(result.getBody()).isEqualToComparingOnlyGivenFields(expected, "content", "charset");
@@ -150,7 +153,7 @@ public class MIMEMessageConverterTest {
// When
Message result = sut.convertToMime(new ValueWithId.CreationMessageEntry(
- CreationMessageId.of("user|mailbox|1"), testMessage));
+ CreationMessageId.of("user|mailbox|1"), testMessage), ImmutableList.of());
// Then
assertThat(result.getBody()).isEqualToComparingOnlyGivenFields(expected, "content", "charset");
@@ -171,7 +174,7 @@ public class MIMEMessageConverterTest {
// When
Message result = sut.convertToMime(new ValueWithId.CreationMessageEntry(
- CreationMessageId.of("user|mailbox|1"), testMessage));
+ CreationMessageId.of("user|mailbox|1"), testMessage), ImmutableList.of());
// Then
assertThat(result.getBody()).isEqualToComparingOnlyGivenFields(expected, "content", "charset");
@@ -192,7 +195,7 @@ public class MIMEMessageConverterTest {
// When
Message result = sut.convertToMime(new ValueWithId.CreationMessageEntry(
- CreationMessageId.of("user|mailbox|1"), testMessage));
+ CreationMessageId.of("user|mailbox|1"), testMessage), ImmutableList.of());
// Then
assertThat(result.getBody()).isInstanceOf(Multipart.class);
@@ -216,7 +219,7 @@ public class MIMEMessageConverterTest {
String expectedHeaders = "MIME-Version: 1.0\r\n" +
"Content-Type: multipart/mixed;\r\n" +
- " boundary=\"-=Part.0.";
+ " boundary=\"-=Part.1.";
String expectedPart1 = "Content-Type: text/plain; charset=UTF-8\r\n" +
"\r\n" +
"Hello all!\r\n";
@@ -226,7 +229,7 @@ public class MIMEMessageConverterTest {
// When
byte[] convert = sut.convert(new MessageWithId.CreationMessageEntry(
- CreationMessageId.of("user|mailbox|1"), testMessage));
+ CreationMessageId.of("user|mailbox|1"), testMessage), ImmutableList.of());
// Then
String actual = new String(convert, Charsets.UTF_8);
@@ -249,7 +252,7 @@ public class MIMEMessageConverterTest {
// When
Message result = sut.convertToMime(new ValueWithId.CreationMessageEntry(
- CreationMessageId.of("user|mailbox|1"), testMessage));
+ CreationMessageId.of("user|mailbox|1"), testMessage), ImmutableList.of());
// Then
assertThat(result.getMimeType()).isEqualTo("text/plain");
@@ -269,7 +272,7 @@ public class MIMEMessageConverterTest {
// When
Message result = sut.convertToMime(new ValueWithId.CreationMessageEntry(
- CreationMessageId.of("user|mailbox|1"), testMessage));
+ CreationMessageId.of("user|mailbox|1"), testMessage), ImmutableList.of());
// Then
assertThat(result.getMimeType()).isEqualTo("text/html");
@@ -290,7 +293,7 @@ public class MIMEMessageConverterTest {
// When
Message result = sut.convertToMime(new ValueWithId.CreationMessageEntry(
- CreationMessageId.of("user|mailbox|1"), testMessage));
+ CreationMessageId.of("user|mailbox|1"), testMessage), ImmutableList.of());
// Then
assertThat(result.getBody()).isEqualToComparingOnlyGivenFields(expected, "content", "charset");
@@ -312,10 +315,52 @@ public class MIMEMessageConverterTest {
// When
Message result = sut.convertToMime(new ValueWithId.CreationMessageEntry(
- CreationMessageId.of("user|mailbox|1"), testMessage));
+ CreationMessageId.of("user|mailbox|1"), testMessage), ImmutableList.of());
// Then
assertThat(result.getBody()).isEqualToComparingOnlyGivenFields(expected, "content", "charset");
assertThat(result.getMimeType()).isEqualTo("text/plain");
}
+
+ @Test
+ public void convertToMimeShouldAddAttachmentWhenOne() {
+ // Given
+ MIMEMessageConverter sut = new MIMEMessageConverter();
+
+ CreationMessage testMessage = CreationMessage.builder()
+ .mailboxIds(ImmutableList.of("dead-bada55"))
+ .subject("subject")
+ .from(DraftEmailer.builder().name("sender").build())
+ .htmlBody("Hello <b>all<b>!")
+ .build();
+
+ String expectedCID = "<cid>";
+ String expectedMimeType = "image/png";
+ String text = "123456";
+ TextBody expectedBody = new BasicBodyFactory().textBody(text, Charsets.UTF_8);
+ MessageAttachment attachment = MessageAttachment.builder()
+ .attachment(org.apache.james.mailbox.store.mail.model.Attachment.builder()
+ .attachmentId(AttachmentId.from("blodId"))
+ .bytes(text.getBytes())
+ .type(expectedMimeType)
+ .build())
+ .cid(expectedCID)
+ .isInline(true)
+ .build();
+
+ // When
+ Message result = sut.convertToMime(new ValueWithId.CreationMessageEntry(
+ CreationMessageId.of("user|mailbox|1"), testMessage), ImmutableList.of(attachment));
+
+ // Then
+ assertThat(result.getBody()).isInstanceOf(Multipart.class);
+ assertThat(result.isMultipart()).isTrue();
+ Multipart typedResult = (Multipart)result.getBody();
+ assertThat(typedResult.getBodyParts()).hasSize(2);
+ Entity attachmentPart = typedResult.getBodyParts().get(1);
+ assertThat(result.getBody()).isEqualToComparingOnlyGivenFields(expectedBody);
+ assertThat(attachmentPart.getDispositionType()).isEqualTo("inline");
+ assertThat(attachmentPart.getMimeType()).isEqualTo(expectedMimeType);
+ assertThat(attachmentPart.getHeader().getField("Content-ID").getBody()).isEqualTo(expectedCID);
+ }
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/james-project/blob/662fa4a9/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 12eba05..178c554 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
@@ -20,6 +20,7 @@
package org.apache.james.jmap.methods;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
@@ -33,7 +34,10 @@ import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Stream;
+import org.apache.james.jmap.exceptions.AttachmentsNotFoundException;
+import org.apache.james.jmap.methods.ValueWithId.CreationMessageEntry;
import org.apache.james.jmap.methods.ValueWithId.MessageWithId;
+import org.apache.james.jmap.model.Attachment;
import org.apache.james.jmap.model.BlobId;
import org.apache.james.jmap.model.CreationMessage;
import org.apache.james.jmap.model.CreationMessage.DraftEmailer;
@@ -54,13 +58,17 @@ import org.apache.james.jmap.utils.HtmlTextExtractor;
import org.apache.james.jmap.utils.MailboxBasedHtmlTextExtractor;
import org.apache.james.jmap.utils.SystemMailboxesProvider;
import org.apache.james.mailbox.MailboxSession;
+import org.apache.james.mailbox.exception.AttachmentNotFoundException;
import org.apache.james.mailbox.exception.MailboxException;
import org.apache.james.mailbox.mock.MockMailboxSession;
import org.apache.james.mailbox.model.MailboxPath;
import org.apache.james.mailbox.store.MailboxSessionMapperFactory;
import org.apache.james.mailbox.store.TestId;
import org.apache.james.mailbox.store.extractor.DefaultTextExtractor;
+import org.apache.james.mailbox.store.mail.AttachmentMapper;
+import org.apache.james.mailbox.store.mail.AttachmentMapperFactory;
import org.apache.james.mailbox.store.mail.MessageMapper;
+import org.apache.james.mailbox.store.mail.model.AttachmentId;
import org.apache.james.mailbox.store.mail.model.Mailbox;
import org.apache.james.mailbox.store.mail.model.MailboxMessage;
import org.apache.james.mailbox.store.mail.model.impl.SimpleMailbox;
@@ -72,6 +80,7 @@ import org.junit.Test;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
public class SetMessagesCreationProcessorTest {
@@ -133,6 +142,9 @@ public class SetMessagesCreationProcessorTest {
private SystemMailboxesProvider fakeSystemMailboxesProvider;
private MockMailboxSession session;
private MIMEMessageConverter mimeMessageConverter;
+ private AttachmentMapper mockedAttachmentMapper;
+ private AttachmentMapperFactory mockedAttachmentMapperFactory;
+ private SetMessagesCreationProcessor sut;
@Before
public void setUp() throws MailboxException {
@@ -142,17 +154,19 @@ public class SetMessagesCreationProcessorTest {
.thenReturn(mockMapper);
mockedMailSpool = mock(MailSpool.class);
mockedMailFactory = mock(MailFactory.class);
-
+ mockedAttachmentMapperFactory = mock(AttachmentMapperFactory.class);
+ mockedAttachmentMapper = mock(AttachmentMapper.class);
+ when(mockedAttachmentMapperFactory.getAttachmentMapper(any(MailboxSession.class))).thenReturn(mockedAttachmentMapper);
+
fakeSystemMailboxesProvider = new TestSystemMailboxesProvider(() -> optionalOutbox, () -> optionalDrafts);
session = new MockMailboxSession(USER);
mimeMessageConverter = new MIMEMessageConverter();
+ sut = new SetMessagesCreationProcessor(
+ stubSessionMapperFactory, mimeMessageConverter, mockedMailSpool, mockedMailFactory, messageFactory, fakeSystemMailboxesProvider, mockedAttachmentMapperFactory);
}
@Test
public void processShouldReturnEmptyCreatedWhenRequestHasEmptyCreate() {
- SetMessagesCreationProcessor sut = new SetMessagesCreationProcessor(
- stubSessionMapperFactory, mimeMessageConverter, mockedMailSpool, mockedMailFactory, messageFactory, fakeSystemMailboxesProvider);
-
SetMessagesRequest requestWithEmptyCreate = SetMessagesRequest.builder().build();
SetMessagesResponse result = sut.process(requestWithEmptyCreate, session);
@@ -169,8 +183,8 @@ public class SetMessagesCreationProcessorTest {
when(mockSessionMapperFactory.createMessageMapper(any(MailboxSession.class)))
.thenReturn(stubMapper);
- SetMessagesCreationProcessor sut = new SetMessagesCreationProcessor(
- mockSessionMapperFactory, mimeMessageConverter, mockedMailSpool, mockedMailFactory, messageFactory, fakeSystemMailboxesProvider) {
+ sut = new SetMessagesCreationProcessor(
+ mockSessionMapperFactory, mimeMessageConverter, mockedMailSpool, mockedMailFactory, messageFactory, fakeSystemMailboxesProvider, mockedAttachmentMapperFactory) {
@Override
protected MessageWithId createMessageInOutboxAndSend(ValueWithId.CreationMessageEntry createdEntry, MailboxSession session, Mailbox outbox, Function<Long, MessageId> buildMessageIdFromUid) {
return new MessageWithId(createdEntry.getCreationId(), FAKE_OUTBOX_MESSAGE);
@@ -190,7 +204,7 @@ public class SetMessagesCreationProcessorTest {
// Given
TestSystemMailboxesProvider doNotProvideOutbox = new TestSystemMailboxesProvider(Optional::empty, () -> optionalDrafts);
SetMessagesCreationProcessor sut = new SetMessagesCreationProcessor(
- stubSessionMapperFactory, mimeMessageConverter, mockedMailSpool, mockedMailFactory, messageFactory, doNotProvideOutbox);
+ stubSessionMapperFactory, mimeMessageConverter, mockedMailSpool, mockedMailFactory, messageFactory, doNotProvideOutbox, mockedAttachmentMapperFactory);
// When
SetMessagesResponse actual = sut.process(createMessageInOutbox, session);
@@ -201,9 +215,6 @@ public class SetMessagesCreationProcessorTest {
@Test
public void processShouldCallMessageMapperWhenRequestHasNonEmptyCreate() throws MailboxException {
- // Given
- SetMessagesCreationProcessor sut = new SetMessagesCreationProcessor(
- stubSessionMapperFactory, mimeMessageConverter, mockedMailSpool, mockedMailFactory, messageFactory, fakeSystemMailboxesProvider);
// When
sut.process(createMessageInOutbox, session);
@@ -213,9 +224,6 @@ public class SetMessagesCreationProcessorTest {
@Test
public void processShouldSendMailWhenRequestHasNonEmptyCreate() throws Exception {
- // Given
- SetMessagesCreationProcessor sut = new SetMessagesCreationProcessor(
- stubSessionMapperFactory, mimeMessageConverter, mockedMailSpool, mockedMailFactory, messageFactory, fakeSystemMailboxesProvider);
// When
sut.process(createMessageInOutbox, session);
@@ -225,9 +233,6 @@ public class SetMessagesCreationProcessorTest {
@Test
public void processShouldNotSpoolMailWhenNotSavingToOutbox() throws Exception {
- // Given
- SetMessagesCreationProcessor sut = new SetMessagesCreationProcessor(
- stubSessionMapperFactory, mimeMessageConverter, mockedMailSpool, mockedMailFactory, messageFactory, fakeSystemMailboxesProvider);
// When
SetMessagesRequest notInOutboxCreationRequest =
SetMessagesRequest.builder()
@@ -244,10 +249,6 @@ public class SetMessagesCreationProcessorTest {
@Test
public void processShouldReturnNotImplementedErrorWhenSavingToDrafts() {
- // Given
- SetMessagesCreationProcessor sut = new SetMessagesCreationProcessor(
- stubSessionMapperFactory, mimeMessageConverter, mockedMailSpool, mockedMailFactory, messageFactory, fakeSystemMailboxesProvider);
-
CreationMessageId creationMessageId = CreationMessageId.of("anything-really");
SetMessagesRequest createMessageInDrafts = SetMessagesRequest.builder()
.create(
@@ -267,9 +268,6 @@ public class SetMessagesCreationProcessorTest {
@Test
public void processShouldNotSendWhenSavingToDrafts() throws Exception {
- // Given
- SetMessagesCreationProcessor sut = new SetMessagesCreationProcessor(
- stubSessionMapperFactory, mimeMessageConverter, mockedMailSpool, mockedMailFactory, messageFactory, fakeSystemMailboxesProvider);
// When
CreationMessageId creationMessageId = CreationMessageId.of("anything-really");
SetMessagesRequest createMessageInDrafts = SetMessagesRequest.builder()
@@ -283,6 +281,46 @@ public class SetMessagesCreationProcessorTest {
}
+ @Test
+ public void assertAttachmentsExistShouldThrowWhenUnknownBlobId() throws AttachmentNotFoundException {
+ BlobId unknownBlobId = BlobId.of("unknownBlobId");
+ AttachmentId unknownAttachmentId = AttachmentId.from(unknownBlobId.getRawValue());
+ when(mockedAttachmentMapper.getAttachment(unknownAttachmentId)).thenThrow(new AttachmentNotFoundException(unknownBlobId.getRawValue()));
+
+ assertThatThrownBy(() -> sut.assertAttachmentsExist(
+ new CreationMessageEntry(
+ creationMessageId,
+ creationMessageBuilder.attachments(
+ Attachment.builder().size(12l).type("image/jpeg").blobId(unknownBlobId).build())
+ .build()
+ ),
+ session))
+ .isInstanceOf(AttachmentsNotFoundException.class);
+ }
+
+ @Test
+ public void assertAttachmentsExistShouldThrowWhenUnknownBlobIds() throws AttachmentNotFoundException {
+ BlobId unknownBlobId1 = BlobId.of("unknownBlobId1");
+ BlobId unknownBlobId2 = BlobId.of("unknownBlobId2");
+ AttachmentId unknownAttachmentId1 = AttachmentId.from(unknownBlobId1.getRawValue());
+ AttachmentId unknownAttachmentId2 = AttachmentId.from(unknownBlobId2.getRawValue());
+
+ when(mockedAttachmentMapper.getAttachment(unknownAttachmentId1)).thenThrow(new AttachmentNotFoundException(unknownBlobId1.getRawValue()));
+ when(mockedAttachmentMapper.getAttachment(unknownAttachmentId2)).thenThrow(new AttachmentNotFoundException(unknownBlobId2.getRawValue()));
+
+ assertThatThrownBy(() -> sut.assertAttachmentsExist(
+ new CreationMessageEntry(
+ creationMessageId,
+ creationMessageBuilder.attachments(
+ Attachment.builder().size(12l).type("image/jpeg").blobId(unknownBlobId1).build(),
+ Attachment.builder().size(23l).type("image/git").blobId(unknownBlobId2).build())
+ .build()
+ ),
+ session))
+ .isInstanceOf(AttachmentsNotFoundException.class)
+ .matches(e -> ((AttachmentsNotFoundException)e).getAttachmentIds().containsAll(ImmutableSet.of(unknownBlobId1, unknownBlobId2)));
+ }
+
public static class TestSystemMailboxesProvider implements SystemMailboxesProvider {
private final Supplier<Optional<Mailbox>> outboxSupplier;
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org
[2/5] james-project git commit: JAMES-1790 don't detect mailing lists
on sender when none
Posted by ad...@apache.org.
JAMES-1790 don't detect mailing lists on sender when none
Project: http://git-wip-us.apache.org/repos/asf/james-project/repo
Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/a8d2de92
Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/a8d2de92
Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/a8d2de92
Branch: refs/heads/master
Commit: a8d2de92a8a3e7a09ddd08b8dd10f418183729e5
Parents: 2a7c50f
Author: Matthieu Baechler <ma...@linagora.com>
Authored: Mon Jul 4 12:08:44 2016 +0200
Committer: Antoine Duprat <ad...@linagora.com>
Committed: Fri Jul 8 14:24:55 2016 +0200
----------------------------------------------------------------------
.../base/AutomaticallySentMailDetectorImpl.java | 37 ++++++++++++++------
1 file changed, 27 insertions(+), 10 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/james-project/blob/a8d2de92/mailet/base/src/main/java/org/apache/mailet/base/AutomaticallySentMailDetectorImpl.java
----------------------------------------------------------------------
diff --git a/mailet/base/src/main/java/org/apache/mailet/base/AutomaticallySentMailDetectorImpl.java b/mailet/base/src/main/java/org/apache/mailet/base/AutomaticallySentMailDetectorImpl.java
index 72fad65..b6360fb 100644
--- a/mailet/base/src/main/java/org/apache/mailet/base/AutomaticallySentMailDetectorImpl.java
+++ b/mailet/base/src/main/java/org/apache/mailet/base/AutomaticallySentMailDetectorImpl.java
@@ -32,9 +32,19 @@ import org.apache.james.mime4j.parser.MimeStreamParser;
import org.apache.james.mime4j.stream.BodyDescriptor;
import org.apache.james.mime4j.stream.MimeConfig;
import org.apache.mailet.Mail;
+import org.apache.mailet.MailAddress;
public class AutomaticallySentMailDetectorImpl implements AutomaticallySentMailDetector {
+ private static final String[] MAILING_LIST_HEADERS = new String[] {
+ "List-Help",
+ "List-Subscribe",
+ "List-Unsubscribe",
+ "List-Owner",
+ "List-Post",
+ "List-Id",
+ "List-Archive" };
+
public boolean isAutomaticallySent(Mail mail) throws MessagingException {
return isMailingList(mail) ||
isAutoSubmitted(mail) ||
@@ -42,20 +52,27 @@ public class AutomaticallySentMailDetectorImpl implements AutomaticallySentMailD
}
public boolean isMailingList(Mail mail) throws MessagingException {
- String localPart = mail.getSender().getLocalPart();
+ return senderIsMailingList(mail)
+ || headerIsMailingList(mail);
+ }
+
+ private boolean senderIsMailingList(Mail mail) {
+ MailAddress sender = mail.getSender();
+ if (sender == null) {
+ return false;
+ }
+
+ String localPart = sender.getLocalPart();
return localPart.startsWith("owner-")
|| localPart.endsWith("-request")
|| localPart.equalsIgnoreCase("MAILER-DAEMON")
|| localPart.equalsIgnoreCase("LISTSERV")
- || localPart.equalsIgnoreCase("majordomo")
- || mail.getMessage()
- .getMatchingHeaders(new String[]{"List-Help",
- "List-Subscribe",
- "List-Unsubscribe",
- "List-Owner",
- "List-Post",
- "List-Id",
- "List-Archive"})
+ || localPart.equalsIgnoreCase("majordomo");
+ }
+
+ private boolean headerIsMailingList(Mail mail) throws MessagingException {
+ return mail.getMessage()
+ .getMatchingHeaders(MAILING_LIST_HEADERS)
.hasMoreElements();
}
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org