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/03/01 16:00:33 UTC
[1/9] james-project git commit: JAMES-1692 add unit tests for
SetMessagesMethod's delegates
Repository: james-project
Updated Branches:
refs/heads/master 00678d881 -> 3b09ad753
JAMES-1692 add unit tests for SetMessagesMethod's delegates
... that were recently added or extracted
Project: http://git-wip-us.apache.org/repos/asf/james-project/repo
Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/9388764f
Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/9388764f
Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/9388764f
Branch: refs/heads/master
Commit: 9388764f9196879ef8befc047b28e4f17acde9a4
Parents: b21eae3
Author: Fabien Vignon <fv...@linagora.com>
Authored: Wed Feb 17 19:36:15 2016 +0100
Committer: Raphael Ouazana <ra...@linagora.com>
Committed: Tue Mar 1 15:42:53 2016 +0100
----------------------------------------------------------------------
.../jmap/methods/MIMEMessageConverterTest.java | 109 ++++++++++++++++++
.../SetMessagesCreationProcessorTest.java | 113 +++++++++++++------
.../methods/SetMessagesUpdateProcessorTest.java | 85 ++++++++++++++
.../UpdateMessagePatchConverterTest.java | 73 ++++++++++++
4 files changed, 346 insertions(+), 34 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/james-project/blob/9388764f/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
new file mode 100644
index 0000000..af7d17a
--- /dev/null
+++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/methods/MIMEMessageConverterTest.java
@@ -0,0 +1,109 @@
+/****************************************************************
+ * 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.methods;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.sql.Date;
+import java.time.Instant;
+import java.time.ZoneId;
+import java.time.ZonedDateTime;
+
+import org.apache.james.jmap.model.CreationMessage;
+import org.apache.james.jmap.model.Emailer;
+import org.apache.james.mime4j.dom.Message;
+import org.apache.james.mime4j.dom.address.Mailbox;
+import org.apache.james.mime4j.stream.Field;
+import org.junit.Test;
+
+import com.google.common.collect.ImmutableList;
+
+public class MIMEMessageConverterTest {
+ @Test
+ public void convertToMimeShouldAddInReplyToHeaderWhenProvided() {
+ // Given
+ MIMEMessageConverter sut = new MIMEMessageConverter();
+
+ String matchingMessageId = "unique-message-id";
+ CreationMessage messageHavingInReplyTo = CreationMessage.builder()
+ .inReplyToMessageId(matchingMessageId)
+ .mailboxIds(ImmutableList.of("Hey!"))
+ .subject("subject")
+ .build();
+
+ // When
+ Message result = sut.convertToMime(new MessageWithId.CreationMessageEntry(
+ "user|mailbox|1", messageHavingInReplyTo));
+
+ // Then
+ assertThat(result.getHeader().getFields("In-Reply-To")).extracting(Field::getBody)
+ .containsOnly(matchingMessageId);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void convertToMimeShouldThrowWhenMessageIsNull() {
+ MIMEMessageConverter sut = new MIMEMessageConverter();
+
+ sut.convertToMime(new MessageWithId.CreationMessageEntry("any", null));
+ }
+
+ @Test
+ public void convertToMimeShouldSetBothFromAndSenderHeaders() {
+ // Given
+ MIMEMessageConverter sut = new MIMEMessageConverter();
+
+ String joesEmail = "joe@example.com";
+ CreationMessage testMessage = CreationMessage.builder()
+ .mailboxIds(ImmutableList.of("deadbeef-dead-beef-dead-beef"))
+ .subject("subject")
+ .from(Emailer.builder().email(joesEmail).name("joe").build())
+ .build();
+
+ // When
+ Message result = sut.convertToMime(new MessageWithId.CreationMessageEntry(
+ "user|mailbox|1", testMessage));
+
+ // Then
+ assertThat(result.getFrom()).extracting(Mailbox::getAddress).allMatch(f -> f.toString().equals(joesEmail));
+ assertThat(result.getSender().getAddress()).isEqualTo(joesEmail);
+ }
+
+ @Test
+ public void convertToMimeShouldSetCorrectLocalDate() {
+ // Given
+ MIMEMessageConverter sut = new MIMEMessageConverter();
+
+ Instant now = Instant.now();
+ ZonedDateTime messageDate = ZonedDateTime.ofInstant(now, ZoneId.systemDefault());
+
+ CreationMessage testMessage = CreationMessage.builder()
+ .mailboxIds(ImmutableList.of("dead-bada55"))
+ .subject("subject")
+ .date(messageDate)
+ .build();
+
+ // When
+ Message result = sut.convertToMime(new MessageWithId.CreationMessageEntry(
+ "user|mailbox|1", testMessage));
+
+ // Then
+ assertThat(result.getDate()).isEqualToIgnoringMillis(Date.from(now));
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/james-project/blob/9388764f/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 0b73ee2..06dc7c4 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
@@ -21,13 +21,16 @@ package org.apache.james.jmap.methods;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.time.ZonedDateTime;
import java.util.Optional;
import java.util.function.Function;
+import org.apache.james.jmap.exceptions.MailboxRoleNotFoundException;
import org.apache.james.jmap.model.CreationMessage;
import org.apache.james.jmap.model.Emailer;
import org.apache.james.jmap.model.Message;
@@ -37,9 +40,10 @@ import org.apache.james.jmap.model.SetMessagesResponse;
import org.apache.james.mailbox.MailboxSession;
import org.apache.james.mailbox.exception.MailboxException;
import org.apache.james.mailbox.store.MailboxSessionMapperFactory;
+import org.apache.james.mailbox.store.TestId;
import org.apache.james.mailbox.store.mail.MessageMapper;
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.junit.Test;
import com.google.common.collect.ImmutableList;
@@ -47,13 +51,25 @@ import com.google.common.collect.ImmutableMap;
public class SetMessagesCreationProcessorTest {
+ private static final Message FAKE_MESSAGE = Message.builder()
+ .id(MessageId.of("user|outbox|1"))
+ .blobId("anything")
+ .threadId("anything")
+ .mailboxIds(ImmutableList.of("mailboxId"))
+ .headers(ImmutableMap.of())
+ .subject("anything")
+ .size(0)
+ .date(ZonedDateTime.now())
+ .preview("anything")
+ .build();
+
@Test
- @SuppressWarnings("unchecked")
public void processShouldReturnEmptyCreatedWhenRequestHasEmptyCreate() {
- SetMessagesCreationProcessor<MailboxId> sut = new SetMessagesCreationProcessor<MailboxId>(null, null, null, null) {
+ SetMessagesCreationProcessor<TestId> sut = new SetMessagesCreationProcessor<TestId>(null, null, null, null) {
@Override
- protected Optional<Mailbox<MailboxId>> getOutbox(MailboxSession session) throws MailboxException {
- Mailbox<MailboxId> fakeOutbox = mock(Mailbox.class);
+ protected Optional<Mailbox<TestId>> getOutbox(MailboxSession session) throws MailboxException {
+ @SuppressWarnings("unchecked")
+ Mailbox<TestId> fakeOutbox = (Mailbox<TestId>) mock(Mailbox.class);
when(fakeOutbox.getName()).thenReturn("outbox");
return Optional.of(fakeOutbox);
}
@@ -79,26 +95,75 @@ public class SetMessagesCreationProcessorTest {
@Test
@SuppressWarnings("unchecked")
public void processShouldReturnNonEmptyCreatedWhenRequestHasNonEmptyCreate() throws MailboxException {
-
- MessageMapper<MailboxId> stubMapper = mock(MessageMapper.class);
- MailboxSessionMapperFactory<MailboxId> mockSessionMapperFactory = mock(MailboxSessionMapperFactory.class);
+ // Given
+ MessageMapper<TestId> stubMapper = mock(MessageMapper.class);
+ MailboxSessionMapperFactory<TestId> mockSessionMapperFactory = mock(MailboxSessionMapperFactory.class);
when(mockSessionMapperFactory.createMessageMapper(any(MailboxSession.class)))
.thenReturn(stubMapper);
- SetMessagesCreationProcessor<MailboxId> sut = new SetMessagesCreationProcessor<MailboxId>(null, null, mockSessionMapperFactory, null) {
+ SetMessagesCreationProcessor<TestId> sut = new SetMessagesCreationProcessor<TestId>(null, null, mockSessionMapperFactory, null) {
+ @Override
+ protected MessageWithId<Message> createMessageInOutbox(MessageWithId.CreationMessageEntry createdEntry, MailboxSession session, Mailbox<TestId> outbox, Function<Long, MessageId> buildMessageIdFromUid) {
+ return new MessageWithId<>(createdEntry.getCreationId(), FAKE_MESSAGE);
+ }
+ @Override
+ protected Optional<Mailbox<TestId>> getOutbox(MailboxSession session) throws MailboxException {
+ Mailbox<TestId> fakeOutbox = mock(Mailbox.class);
+ when(fakeOutbox.getName()).thenReturn("outbox");
+ return Optional.of(fakeOutbox);
+ }
+ };
+ // When
+ SetMessagesResponse result = sut.process(buildFakeCreationRequest(), buildStubbedSession());
+
+ // Then
+ assertThat(result.getCreated()).isNotEmpty();
+ assertThat(result.getNotCreated()).isEmpty();
+ }
+
+ @Test(expected = MailboxRoleNotFoundException.class)
+ public void processShouldThrowWhenOutboxNotFound() {
+ // Given
+ SetMessagesCreationProcessor<TestId> sut = new SetMessagesCreationProcessor<TestId>(null, null, null, null) {
@Override
- protected MessageWithId<Message> createMessageInOutbox(MessageWithId.CreationMessageEntry createdEntry, MailboxSession session, Mailbox<MailboxId> outbox, Function<Long, MessageId> buildMessageIdFromUid) {
- return new MessageWithId<>(createdEntry.creationId, getFakeMessage());
+ protected Optional<Mailbox<TestId>> getOutbox(MailboxSession session) throws MailboxException {
+ return Optional.empty();
}
+ };
+ // When
+ sut.process(buildFakeCreationRequest(), null);
+ }
+
+ @Test
+ @SuppressWarnings("unchecked")
+ public void processShouldCallMessageMapperWhenRequestHasNonEmptyCreate() throws MailboxException {
+ // Given
+ Mailbox<TestId> fakeOutbox = mock(Mailbox.class);
+ MessageMapper<TestId> mockMapper = mock(MessageMapper.class);
+ MailboxSessionMapperFactory<TestId> stubSessionMapperFactory = mock(MailboxSessionMapperFactory.class);
+ when(stubSessionMapperFactory.createMessageMapper(any(MailboxSession.class)))
+ .thenReturn(mockMapper);
+
+ SetMessagesCreationProcessor<TestId> sut = new SetMessagesCreationProcessor<TestId>(null, null,
+ stubSessionMapperFactory, new MIMEMessageConverter()) {
@Override
- protected Optional<Mailbox<MailboxId>> getOutbox(MailboxSession session) throws MailboxException {
- Mailbox<MailboxId> fakeOutbox = mock(Mailbox.class);
+ protected Optional<Mailbox<TestId>> getOutbox(MailboxSession session) throws MailboxException {
+ TestId stubMailboxId = mock(TestId.class);
+ when(stubMailboxId.serialize()).thenReturn("user|outbox|12345");
+ when(fakeOutbox.getMailboxId()).thenReturn(stubMailboxId);
when(fakeOutbox.getName()).thenReturn("outbox");
return Optional.of(fakeOutbox);
}
};
+ // When
+ sut.process(buildFakeCreationRequest(), buildStubbedSession());
+
+ // Then
+ verify(mockMapper).add(eq(fakeOutbox), any(MailboxMessage.class));
+ }
- SetMessagesRequest creationRequest = SetMessagesRequest.builder()
+ private SetMessagesRequest buildFakeCreationRequest() {
+ return SetMessagesRequest.builder()
.create(ImmutableMap.of("anything-really", CreationMessage.builder()
.from(Emailer.builder().name("alice").email("alice@example.com").build())
.to(ImmutableList.of(Emailer.builder().name("bob").email("bob@example.com").build()))
@@ -106,26 +171,6 @@ public class SetMessagesCreationProcessorTest {
.mailboxIds(ImmutableList.of("mailboxId"))
.build()
))
- .build()
- ;
-
- SetMessagesResponse result = sut.process(creationRequest, buildStubbedSession());
-
- assertThat(result.getCreated()).isNotEmpty();
- assertThat(result.getNotCreated()).isEmpty();
- }
-
- private Message getFakeMessage() {
- return Message.builder()
- .id(org.apache.james.jmap.model.MessageId.of("user|outbox|1"))
- .blobId("anything")
- .threadId("anything")
- .mailboxIds(ImmutableList.of("mailboxId"))
- .headers(ImmutableMap.of())
- .subject("anything")
- .size(0)
- .date(ZonedDateTime.now())
- .preview("anything")
.build();
}
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/james-project/blob/9388764f/server/protocols/jmap/src/test/java/org/apache/james/jmap/methods/SetMessagesUpdateProcessorTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/methods/SetMessagesUpdateProcessorTest.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/methods/SetMessagesUpdateProcessorTest.java
new file mode 100644
index 0000000..9a625c3
--- /dev/null
+++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/methods/SetMessagesUpdateProcessorTest.java
@@ -0,0 +1,85 @@
+/****************************************************************
+ * 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.methods;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import org.apache.james.jmap.model.MessageId;
+import org.apache.james.jmap.model.MessageProperties;
+import org.apache.james.jmap.model.SetMessagesRequest;
+import org.apache.james.jmap.model.SetMessagesResponse;
+import org.apache.james.jmap.model.UpdateMessagePatch;
+import org.apache.james.mailbox.store.TestId;
+import org.junit.Test;
+
+import com.fasterxml.jackson.databind.node.JsonNodeFactory;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+
+public class SetMessagesUpdateProcessorTest {
+
+ @Test
+ public void processShouldReturnEmptyUpdatedWhenRequestHasEmptyUpdate() {
+ SetMessagesUpdateProcessor<TestId> sut = new SetMessagesUpdateProcessor<>(null, null, null);
+ SetMessagesRequest requestWithEmptyUpdate = SetMessagesRequest.builder().build();
+
+ SetMessagesResponse result = sut.process(requestWithEmptyUpdate, null);
+
+ assertThat(result.getUpdated()).isEmpty();
+ assertThat(result.getNotUpdated()).isEmpty();
+ }
+
+ @Test
+ public void processShouldReturnNonEmptyNotUpdatedWhenRequestHasInvalidUpdate() {
+ // Given
+ UpdateMessagePatchConverter mockConverter = mock(UpdateMessagePatchConverter.class);
+ UpdateMessagePatch mockInvalidPatch = mock(UpdateMessagePatch.class);
+ when(mockInvalidPatch.isValid()).thenReturn(false);
+
+ MessageProperties.MessageProperty invalidProperty = MessageProperties.MessageProperty.from;
+ ImmutableList<ValidationResult> nonEmptyValidationResult = ImmutableList.of(ValidationResult.builder()
+ .property(invalidProperty.toString()).build());
+ when(mockInvalidPatch.getValidationErrors())
+ .thenReturn(nonEmptyValidationResult);
+ when(mockConverter.fromJsonNode(any(ObjectNode.class)))
+ .thenReturn(mockInvalidPatch);
+
+ SetMessagesUpdateProcessor<TestId> sut = new SetMessagesUpdateProcessor<>(mockConverter, null, null);
+ MessageId requestMessageId = MessageId.of("user|inbox|1");
+ SetMessagesRequest requestWithInvalidUpdate = SetMessagesRequest.builder()
+ .update(ImmutableMap.of(requestMessageId, JsonNodeFactory.instance.objectNode()))
+ .build();
+
+ // When
+ SetMessagesResponse result = sut.process(requestWithInvalidUpdate, null);
+
+ // Then
+ assertThat(result.getNotUpdated()).isNotEmpty().describedAs("NotUpdated should not be empty");
+ assertThat(result.getNotUpdated()).containsKey(requestMessageId);
+ assertThat(result.getNotUpdated().get(requestMessageId).getProperties()).isPresent();
+ assertThat(result.getNotUpdated().get(requestMessageId).getProperties().get()).contains(invalidProperty);
+ assertThat(result.getUpdated()).isEmpty();
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/james-project/blob/9388764f/server/protocols/jmap/src/test/java/org/apache/james/jmap/methods/UpdateMessagePatchConverterTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/methods/UpdateMessagePatchConverterTest.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/methods/UpdateMessagePatchConverterTest.java
new file mode 100644
index 0000000..f67c92a
--- /dev/null
+++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/methods/UpdateMessagePatchConverterTest.java
@@ -0,0 +1,73 @@
+/****************************************************************
+ * 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.methods;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.verify;
+
+import org.apache.james.jmap.model.UpdateMessagePatch;
+import org.junit.Test;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.JsonNodeFactory;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.google.common.collect.ImmutableSet;
+
+public class UpdateMessagePatchConverterTest {
+
+ @Test
+ public void fromJsonNodeShouldSetValidationResultWhenPatchIsInvalid() {
+
+ UpdateMessagePatchValidator stubValidator = mock(UpdateMessagePatchValidator.class);
+ when(stubValidator.isValid(any(ObjectNode.class))).thenReturn(false);
+ ImmutableSet<ValidationResult> nonEmptyValidationResult = ImmutableSet.of(ValidationResult.builder().build());
+ when(stubValidator.validate(any(ObjectNode.class))).thenReturn(nonEmptyValidationResult);
+
+ UpdateMessagePatchConverter sut = new UpdateMessagePatchConverter(null, stubValidator);
+
+ ObjectNode dummynode = JsonNodeFactory.instance.objectNode();
+ UpdateMessagePatch result = sut.fromJsonNode(dummynode);
+
+ assertThat(result).extracting(UpdateMessagePatch::getValidationErrors)
+ .isNotEmpty();
+ }
+
+ @Test
+ public void fromJsonNodeShouldReturnNoErrorWhenPatchIsValid() {
+
+ UpdateMessagePatchValidator mockValidator = mock(UpdateMessagePatchValidator.class);
+ when(mockValidator.isValid(any(ObjectNode.class))).thenReturn(true);
+ when(mockValidator.validate(any(ObjectNode.class))).thenReturn(ImmutableSet.of());
+ verify(mockValidator, never()).validate(any(ObjectNode.class));
+ ObjectMapper jsonParser = new ObjectMapper();
+
+ UpdateMessagePatchConverter sut = new UpdateMessagePatchConverter(jsonParser, mockValidator);
+
+ ObjectNode dummynode = JsonNodeFactory.instance.objectNode();
+ UpdateMessagePatch result = sut.fromJsonNode(dummynode);
+
+ assertThat(result.getValidationErrors().isEmpty()).isTrue();
+ }
+
+}
\ No newline at end of file
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org
[8/9] james-project git commit: JAMES-1692 Strong typing creationId
in SetMessages requests/responses
Posted by ad...@apache.org.
JAMES-1692 Strong typing creationId in SetMessages requests/responses
Project: http://git-wip-us.apache.org/repos/asf/james-project/repo
Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/8174cb77
Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/8174cb77
Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/8174cb77
Branch: refs/heads/master
Commit: 8174cb776ed611fc3208ae650fb604b2a5a945d0
Parents: 078ba1a
Author: Fabien Vignon <fv...@linagora.com>
Authored: Thu Feb 25 16:01:05 2016 +0100
Committer: Raphael Ouazana <ra...@linagora.com>
Committed: Tue Mar 1 15:46:15 2016 +0100
----------------------------------------------------------------------
.../jmap/methods/MIMEMessageConverter.java | 5 +-
.../james/jmap/methods/MessageWithId.java | 9 +--
.../methods/SetMessagesCreationProcessor.java | 3 +-
.../james/jmap/model/CreationMessageId.java | 59 ++++++++++++++++++++
.../james/jmap/model/SetMessagesRequest.java | 10 ++--
.../james/jmap/model/SetMessagesResponse.java | 20 +++----
.../jmap/methods/MIMEMessageConverterTest.java | 9 +--
.../SetMessagesCreationProcessorTest.java | 3 +-
.../jmap/model/SetMessagesResponseTest.java | 16 +++---
9 files changed, 99 insertions(+), 35 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/james-project/blob/8174cb77/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 783ced0..207a36d 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
@@ -30,6 +30,7 @@ import java.util.function.Consumer;
import java.util.stream.Collectors;
import org.apache.james.jmap.model.CreationMessage;
+import org.apache.james.jmap.model.CreationMessageId;
import org.apache.james.mime4j.Charsets;
import org.apache.james.mime4j.codec.DecodeMonitor;
import org.apache.james.mime4j.dom.FieldParser;
@@ -86,7 +87,7 @@ public class MIMEMessageConverter {
return message;
}
- private Header buildMimeHeaders(String creationId, CreationMessage newMessage) {
+ private Header buildMimeHeaders(CreationMessageId creationId, CreationMessage newMessage) {
Header messageHeaders = new HeaderImpl();
// add From: and Sender: headers
@@ -116,7 +117,7 @@ public class MIMEMessageConverter {
// add Subject: header
messageHeaders.addField(Fields.subject(newMessage.getSubject()));
// set creation Id as MessageId: header
- messageHeaders.addField(Fields.messageId(creationId));
+ messageHeaders.addField(Fields.messageId(creationId.getId()));
// date(String fieldName, Date date, TimeZone zone)
// note that date conversion probably lose milliseconds !
http://git-wip-us.apache.org/repos/asf/james-project/blob/8174cb77/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/MessageWithId.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/MessageWithId.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/MessageWithId.java
index fbc7105..0e4e172 100644
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/MessageWithId.java
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/MessageWithId.java
@@ -20,18 +20,19 @@
package org.apache.james.jmap.methods;
import org.apache.james.jmap.model.CreationMessage;
+import org.apache.james.jmap.model.CreationMessageId;
public class MessageWithId<T> {
- private String creationId;
+ private CreationMessageId creationId;
private T message;
- public MessageWithId(String creationId, T message) {
+ public MessageWithId(CreationMessageId creationId, T message) {
this.creationId = creationId;
this.message = message;
}
- public String getCreationId() {
+ public CreationMessageId getCreationId() {
return creationId;
}
@@ -40,7 +41,7 @@ public class MessageWithId<T> {
}
public static class CreationMessageEntry extends MessageWithId<CreationMessage> {
- public CreationMessageEntry(String creationId, CreationMessage message) {
+ public CreationMessageEntry(CreationMessageId creationId, CreationMessage message) {
super(creationId, message);
}
}
http://git-wip-us.apache.org/repos/asf/james-project/blob/8174cb77/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 1177e54..718734d 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
@@ -38,6 +38,7 @@ import javax.mail.util.SharedByteArrayInputStream;
import org.apache.james.jmap.exceptions.MailboxRoleNotFoundException;
import org.apache.james.jmap.model.CreationMessage;
+import org.apache.james.jmap.model.CreationMessageId;
import org.apache.james.jmap.model.Message;
import org.apache.james.jmap.model.MessageId;
import org.apache.james.jmap.model.MessageProperties;
@@ -114,7 +115,7 @@ public class SetMessagesCreationProcessor<Id extends MailboxId> implements SetMe
.build();
}
- private Map<String, SetError> handleCreationErrors(Predicate<CreationMessage> invalidMessagesTester,
+ private Map<CreationMessageId, SetError> handleCreationErrors(Predicate<CreationMessage> invalidMessagesTester,
SetMessagesRequest request) {
return request.getCreate().entrySet().stream()
.filter(e -> invalidMessagesTester.test(e.getValue()))
http://git-wip-us.apache.org/repos/asf/james-project/blob/8174cb77/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/CreationMessageId.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/CreationMessageId.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/CreationMessageId.java
new file mode 100644
index 0000000..e23dd6a
--- /dev/null
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/CreationMessageId.java
@@ -0,0 +1,59 @@
+/****************************************************************
+ * 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;
+
+public class CreationMessageId {
+
+ public static CreationMessageId of(String creationMessageId) {
+ return new CreationMessageId(creationMessageId);
+ }
+
+ private final String id;
+
+ private CreationMessageId(String id) {
+ Preconditions.checkNotNull(id);
+ Preconditions.checkArgument(!id.isEmpty());
+ this.id = id;
+ }
+
+ @JsonValue
+ public String getId() {
+ return id;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof CreationMessageId) {
+ CreationMessageId other = (CreationMessageId) obj;
+ return Objects.equals(this.id, other.id);
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(id);
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/james-project/blob/8174cb77/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetMessagesRequest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetMessagesRequest.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetMessagesRequest.java
index 8e25ac5..096e9c6 100644
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetMessagesRequest.java
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetMessagesRequest.java
@@ -48,7 +48,7 @@ public class SetMessagesRequest implements JmapRequest {
private String accountId;
private String ifInState;
- private ImmutableMap.Builder<String, CreationMessage> create;
+ private ImmutableMap.Builder<CreationMessageId, CreationMessage> create;
private ImmutableMap.Builder<MessageId, Function<UpdateMessagePatchConverter, UpdateMessagePatch>> updatesProvider;
private ImmutableList.Builder<MessageId> destroy;
@@ -73,7 +73,7 @@ public class SetMessagesRequest implements JmapRequest {
return this;
}
- public Builder create(Map<String, CreationMessage> creations) {
+ public Builder create(Map<CreationMessageId, CreationMessage> creations) {
this.create.putAll(creations);
return this;
}
@@ -95,11 +95,11 @@ public class SetMessagesRequest implements JmapRequest {
private final Optional<String> accountId;
private final Optional<String> ifInState;
- private final Map<String, CreationMessage> create;
+ private final Map<CreationMessageId, CreationMessage> create;
private final Map<MessageId, Function<UpdateMessagePatchConverter, UpdateMessagePatch>> update;
private final List<MessageId> destroy;
- @VisibleForTesting SetMessagesRequest(Optional<String> accountId, Optional<String> ifInState, Map<String, CreationMessage> create, Map<MessageId, Function<UpdateMessagePatchConverter, UpdateMessagePatch>> update, List<MessageId> destroy) {
+ @VisibleForTesting SetMessagesRequest(Optional<String> accountId, Optional<String> ifInState, Map<CreationMessageId, CreationMessage> create, Map<MessageId, Function<UpdateMessagePatchConverter, UpdateMessagePatch>> update, List<MessageId> destroy) {
this.accountId = accountId;
this.ifInState = ifInState;
this.create = create;
@@ -115,7 +115,7 @@ public class SetMessagesRequest implements JmapRequest {
return ifInState;
}
- public Map<String, CreationMessage> getCreate() {
+ public Map<CreationMessageId, CreationMessage> getCreate() {
return create;
}
http://git-wip-us.apache.org/repos/asf/james-project/blob/8174cb77/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetMessagesResponse.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetMessagesResponse.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetMessagesResponse.java
index 004b11b..a536ba4 100644
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetMessagesResponse.java
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetMessagesResponse.java
@@ -53,10 +53,10 @@ public class SetMessagesResponse implements Method.Response {
private String accountId;
private String oldState;
private String newState;
- private final ImmutableMap.Builder<String, Message> created;
+ private final ImmutableMap.Builder<CreationMessageId, Message> created;
private final ImmutableList.Builder<MessageId> updated;
private final ImmutableList.Builder<MessageId> destroyed;
- private final ImmutableMap.Builder<String, SetError> notCreated;
+ private final ImmutableMap.Builder<CreationMessageId, SetError> notCreated;
private final ImmutableMap.Builder<MessageId, SetError> notUpdated;
private final ImmutableMap.Builder<MessageId, SetError> notDestroyed;
@@ -81,7 +81,7 @@ public class SetMessagesResponse implements Method.Response {
throw new NotImplementedException();
}
- public Builder created(Map<String, Message> created) {
+ public Builder created(Map<CreationMessageId, Message> created) {
this.created.putAll(created);
return this;
}
@@ -101,7 +101,7 @@ public class SetMessagesResponse implements Method.Response {
return this;
}
- public Builder notCreated(Map<String, SetError> notCreated) {
+ public Builder notCreated(Map<CreationMessageId, SetError> notCreated) {
this.notCreated.putAll(notCreated);
return this;
}
@@ -130,15 +130,15 @@ public class SetMessagesResponse implements Method.Response {
private final String accountId;
private final String oldState;
private final String newState;
- private final Map<String, Message> created;
+ private final Map<CreationMessageId, Message> created;
private final List<MessageId> updated;
private final List<MessageId> destroyed;
- private final Map<String, SetError> notCreated;
+ private final Map<CreationMessageId, SetError> notCreated;
private final Map<MessageId, SetError> notUpdated;
private final Map<MessageId, SetError> notDestroyed;
- @VisibleForTesting SetMessagesResponse(String accountId, String oldState, String newState, Map<String, Message> created, List<MessageId> updated, List<MessageId> destroyed,
- Map<String, SetError> notCreated, Map<MessageId, SetError> notUpdated, Map<MessageId, SetError> notDestroyed) {
+ @VisibleForTesting SetMessagesResponse(String accountId, String oldState, String newState, Map<CreationMessageId, Message> created, List<MessageId> updated, List<MessageId> destroyed,
+ Map<CreationMessageId, SetError> notCreated, Map<MessageId, SetError> notUpdated, Map<MessageId, SetError> notDestroyed) {
this.accountId = accountId;
this.oldState = oldState;
this.newState = newState;
@@ -166,7 +166,7 @@ public class SetMessagesResponse implements Method.Response {
}
@JsonSerialize
- public Map<String, Message> getCreated() {
+ public Map<CreationMessageId, Message> getCreated() {
return created;
}
@@ -181,7 +181,7 @@ public class SetMessagesResponse implements Method.Response {
}
@JsonSerialize
- public Map<String, SetError> getNotCreated() {
+ public Map<CreationMessageId, SetError> getNotCreated() {
return notCreated;
}
http://git-wip-us.apache.org/repos/asf/james-project/blob/8174cb77/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 0224f49..b238dbf 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
@@ -28,6 +28,7 @@ import java.time.ZoneId;
import java.time.ZonedDateTime;
import org.apache.james.jmap.model.CreationMessage;
+import org.apache.james.jmap.model.CreationMessageId;
import org.apache.james.mime4j.dom.Message;
import org.apache.james.mime4j.dom.address.Mailbox;
import org.apache.james.mime4j.stream.Field;
@@ -51,7 +52,7 @@ public class MIMEMessageConverterTest {
// When
Message result = sut.convertToMime(new MessageWithId.CreationMessageEntry(
- "user|mailbox|1", messageHavingInReplyTo));
+ CreationMessageId.of("user|mailbox|1"), messageHavingInReplyTo));
// Then
assertThat(result.getHeader().getFields("In-Reply-To")).extracting(Field::getBody)
@@ -62,7 +63,7 @@ public class MIMEMessageConverterTest {
public void convertToMimeShouldThrowWhenMessageIsNull() {
MIMEMessageConverter sut = new MIMEMessageConverter();
- sut.convertToMime(new MessageWithId.CreationMessageEntry("any", null));
+ sut.convertToMime(new MessageWithId.CreationMessageEntry(CreationMessageId.of("any"), null));
}
@Test
@@ -79,7 +80,7 @@ public class MIMEMessageConverterTest {
// When
Message result = sut.convertToMime(new MessageWithId.CreationMessageEntry(
- "user|mailbox|1", testMessage));
+ CreationMessageId.of("user|mailbox|1"), testMessage));
// Then
assertThat(result.getFrom()).extracting(Mailbox::getAddress).allMatch(f -> f.equals(joesEmail));
@@ -103,7 +104,7 @@ public class MIMEMessageConverterTest {
// When
Message result = sut.convertToMime(new MessageWithId.CreationMessageEntry(
- "user|mailbox|1", testMessage));
+ CreationMessageId.of("user|mailbox|1"), testMessage));
// Then
assertThat(result.getDate()).isEqualToIgnoringMillis(Date.from(now));
http://git-wip-us.apache.org/repos/asf/james-project/blob/8174cb77/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 c5c8db6..5978f0e 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
@@ -33,6 +33,7 @@ import java.util.function.Function;
import org.apache.james.jmap.exceptions.MailboxRoleNotFoundException;
import org.apache.james.jmap.model.CreationMessage;
+import org.apache.james.jmap.model.CreationMessageId;
import org.apache.james.jmap.model.Message;
import org.apache.james.jmap.model.MessageId;
import org.apache.james.jmap.model.SetMessagesRequest;
@@ -164,7 +165,7 @@ public class SetMessagesCreationProcessorTest {
private SetMessagesRequest buildFakeCreationRequest() {
return SetMessagesRequest.builder()
- .create(ImmutableMap.of("anything-really", CreationMessage.builder()
+ .create(ImmutableMap.of(CreationMessageId.of("anything-really"), CreationMessage.builder()
.from(DraftEmailer.builder().name("alice").email("alice@example.com").build())
.to(ImmutableList.of(DraftEmailer.builder().name("bob").email("bob@example.com").build()))
.subject("Hey! ")
http://git-wip-us.apache.org/repos/asf/james-project/blob/8174cb77/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 373f1b3..631fa96 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
@@ -53,7 +53,7 @@ public class SetMessagesResponseTest {
@Test
public void builderShouldWork() {
ZonedDateTime currentDate = ZonedDateTime.now();
- ImmutableMap<String, Message> created = ImmutableMap.of("user|created|1",
+ ImmutableMap<CreationMessageId, Message> created = ImmutableMap.of(CreationMessageId.of("user|created|1"),
Message.builder()
.id(MessageId.of("user|created|1"))
.blobId("blobId")
@@ -67,7 +67,7 @@ public class SetMessagesResponseTest {
.build());
ImmutableList<MessageId> updated = ImmutableList.of(MessageId.of("user|updated|1"));
ImmutableList<MessageId> destroyed = ImmutableList.of(MessageId.of("user|destroyed|1"));
- ImmutableMap<String, SetError> notCreated = ImmutableMap.of("dead-beef-defec8", SetError.builder().type("created").build());
+ ImmutableMap<CreationMessageId, SetError> notCreated = ImmutableMap.of(CreationMessageId.of("dead-beef-defec8"), SetError.builder().type("created").build());
ImmutableMap<MessageId, SetError> notUpdated = ImmutableMap.of(MessageId.of("user|update|2"), SetError.builder().type("updated").build());
ImmutableMap<MessageId, SetError> notDestroyed = ImmutableMap.of(MessageId.of("user|destroyed|3"), SetError.builder().type("destroyed").build());
SetMessagesResponse expected = new SetMessagesResponse(null, null, null, created, updated, destroyed, notCreated, notUpdated, notDestroyed);
@@ -89,10 +89,10 @@ public class SetMessagesResponseTest {
// Given
SetMessagesResponse.Builder emptyBuilder = SetMessagesResponse.builder();
SetMessagesResponse testee = SetMessagesResponse.builder()
- .created(buildMessage("user|inbox|1"))
+ .created(buildMessage(CreationMessageId.of("user|inbox|1")))
.updated(ImmutableList.of(MessageId.of("user|inbox|2")))
.destroyed(ImmutableList.of(MessageId.of("user|inbox|3")))
- .notCreated(ImmutableMap.of( "dead-beef-defec8", SetError.builder().type("type").build()))
+ .notCreated(ImmutableMap.of(CreationMessageId.of("dead-beef-defec8"), SetError.builder().type("type").build()))
.notUpdated(ImmutableMap.of(MessageId.of("user|inbox|5"), SetError.builder().type("type").build()))
.notDestroyed(ImmutableMap.of(MessageId.of("user|inbox|6"), SetError.builder().type("type").build()))
.build();
@@ -103,9 +103,9 @@ public class SetMessagesResponseTest {
assertThat(emptyBuilder.build()).isEqualToComparingFieldByField(testee);
}
- private ImmutableMap<String, Message> buildMessage(String messageId) {
+ private ImmutableMap<CreationMessageId, Message> buildMessage(CreationMessageId messageId) {
return ImmutableMap.of(messageId, Message.builder()
- .id(MessageId.of(messageId))
+ .id(MessageId.of(messageId.getId()))
.blobId("blobId")
.threadId("threadId")
.mailboxIds(ImmutableList.of())
@@ -138,10 +138,10 @@ public class SetMessagesResponseTest {
@Test
public void mergeIntoShouldMergeCreatedLists() {
// Given
- String buildersCreatedMessageId = "user|inbox|1";
+ CreationMessageId buildersCreatedMessageId = CreationMessageId.of("user|inbox|1");
SetMessagesResponse.Builder nonEmptyBuilder = SetMessagesResponse.builder()
.created(buildMessage(buildersCreatedMessageId));
- String createdMessageId = "user|inbox|2";
+ CreationMessageId createdMessageId = CreationMessageId.of("user|inbox|2");
SetMessagesResponse testee = SetMessagesResponse.builder()
.created(buildMessage(createdMessageId))
.build();
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org
[7/9] james-project git commit: JAMES-1692 send messages requests
validation is deferred
Posted by ad...@apache.org.
JAMES-1692 send messages requests validation is deferred
... to method handler processing
setMessages response property notCreated is a map of creationId (not MessageId)
Project: http://git-wip-us.apache.org/repos/asf/james-project/repo
Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/078ba1a6
Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/078ba1a6
Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/078ba1a6
Branch: refs/heads/master
Commit: 078ba1a6caae80a425778b3eb305f24f0df7568d
Parents: 8983dbb
Author: Fabien Vignon <fv...@linagora.com>
Authored: Wed Feb 24 17:43:24 2016 +0100
Committer: Raphael Ouazana <ra...@linagora.com>
Committed: Tue Mar 1 15:46:13 2016 +0100
----------------------------------------------------------------------
.../jmap/methods/SetMessagesMethodTest.java | 162 +++++++++++++-
.../jmap/methods/MIMEMessageConverter.java | 27 ++-
.../methods/SetMessagesCreationProcessor.java | 48 ++++-
.../james/jmap/methods/ValidationResult.java | 24 +++
.../james/jmap/model/CreationMessage.java | 213 ++++++++++++++++---
.../james/jmap/model/SetMessagesResponse.java | 24 +--
.../jmap/methods/MIMEMessageConverterTest.java | 10 +-
.../SetMessagesCreationProcessorTest.java | 6 +-
.../james/jmap/model/CreationMessageTest.java | 87 ++++++++
.../jmap/model/SetMessagesResponseTest.java | 6 +-
10 files changed, 538 insertions(+), 69 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/james-project/blob/078ba1a6/server/protocols/jmap-integration-testing/src/test/java/org/apache/james/jmap/methods/SetMessagesMethodTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap-integration-testing/src/test/java/org/apache/james/jmap/methods/SetMessagesMethodTest.java b/server/protocols/jmap-integration-testing/src/test/java/org/apache/james/jmap/methods/SetMessagesMethodTest.java
index 3acaf8c..70dcd8f 100644
--- a/server/protocols/jmap-integration-testing/src/test/java/org/apache/james/jmap/methods/SetMessagesMethodTest.java
+++ b/server/protocols/jmap-integration-testing/src/test/java/org/apache/james/jmap/methods/SetMessagesMethodTest.java
@@ -25,6 +25,7 @@ import static com.jayway.restassured.config.EncoderConfig.encoderConfig;
import static com.jayway.restassured.config.RestAssuredConfig.newConfig;
import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.empty;
+import static org.hamcrest.Matchers.endsWith;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasEntry;
import static org.hamcrest.Matchers.hasKey;
@@ -68,10 +69,10 @@ public abstract class SetMessagesMethodTest {
private static final String NAME = "[0][0]";
private static final String ARGUMENTS = "[0][1]";
- private TemporaryFolder temporaryFolder = new TemporaryFolder();
- private EmbeddedElasticSearch embeddedElasticSearch = new EmbeddedElasticSearch();
- private EmbeddedCassandra cassandra = EmbeddedCassandra.createStartServer();
- private JmapServer jmapServer = jmapServer(temporaryFolder, embeddedElasticSearch, cassandra);
+ private final TemporaryFolder temporaryFolder = new TemporaryFolder();
+ private final EmbeddedElasticSearch embeddedElasticSearch = new EmbeddedElasticSearch();
+ private final EmbeddedCassandra cassandra = EmbeddedCassandra.createStartServer();
+ private final JmapServer jmapServer = jmapServer(temporaryFolder, embeddedElasticSearch, cassandra);
private String outboxId;
protected abstract JmapServer jmapServer(TemporaryFolder temporaryFolder, EmbeddedElasticSearch embeddedElasticSearch, EmbeddedCassandra cassandra);
@@ -743,4 +744,157 @@ public abstract class SetMessagesMethodTest {
.body(ARGUMENTS + ".list[0].subject", equalTo(messageSubject))
.log().ifValidationFails();
}
+
+ @Test
+ public void setMessagesShouldRejectWhenSendingMessageHasNoValidAddress() {
+ String messageCreationId = "user|inbox|1";
+ String requestBody = "[" +
+ " [" +
+ " \"setMessages\","+
+ " {" +
+ " \"create\": { \"" + messageCreationId + "\" : {" +
+ " \"from\": { \"name\": \"MAILER-DEAMON\", \"email\": \"postmaster@example.com\"}," +
+ " \"to\": [{ \"name\": \"BOB\", \"email\": \"someone@example.com@example.com\"}]," +
+ " \"cc\": [{ \"name\": \"ALICE\"}]," +
+ " \"subject\": \"Thank you for joining example.com!\"," +
+ " \"textBody\": \"Hello someone, and thank you for joining example.com!\"," +
+ " \"mailboxIds\": [\"" + outboxId + "\"]" +
+ " }}" +
+ " }," +
+ " \"#0\"" +
+ " ]" +
+ "]";
+
+ given()
+ .accept(ContentType.JSON)
+ .contentType(ContentType.JSON)
+ .header("Authorization", accessToken.serialize())
+ .body(requestBody)
+ .when()
+ .post("/jmap")
+ .then()
+ .log().ifValidationFails()
+ .statusCode(200)
+ .body(NAME, equalTo("messagesSet"))
+
+ .body(ARGUMENTS + ".notCreated", hasKey(messageCreationId))
+ .body(ARGUMENTS + ".notCreated[\""+messageCreationId+"\"].type", equalTo("invalidProperties"))
+ .body(ARGUMENTS + ".notCreated[\""+messageCreationId+"\"].description", endsWith("no recipient address set"))
+ .body(ARGUMENTS + ".created", aMapWithSize(0));
+ }
+
+ @Test
+ public void setMessagesShouldRejectWhenSendingMessageHasMissingFrom() {
+ String messageCreationId = "user|inbox|1";
+ String requestBody = "[" +
+ " [" +
+ " \"setMessages\","+
+ " {" +
+ " \"create\": { \"" + messageCreationId + "\" : {" +
+ " \"to\": [{ \"name\": \"BOB\", \"email\": \"someone@example.com\"}]," +
+ " \"cc\": [{ \"name\": \"ALICE\"}]," +
+ " \"subject\": \"Thank you for joining example.com!\"," +
+ " \"textBody\": \"Hello someone, and thank you for joining example.com!\"," +
+ " \"mailboxIds\": [\"" + outboxId + "\"]" +
+ " }}" +
+ " }," +
+ " \"#0\"" +
+ " ]" +
+ "]";
+
+ given()
+ .accept(ContentType.JSON)
+ .contentType(ContentType.JSON)
+ .header("Authorization", accessToken.serialize())
+ .body(requestBody)
+ .when()
+ .post("/jmap")
+ .then()
+ .log().ifValidationFails()
+ .statusCode(200)
+ .body(NAME, equalTo("messagesSet"))
+ .body(ARGUMENTS + ".notCreated", hasKey(messageCreationId))
+ .body(ARGUMENTS + ".notCreated[\""+messageCreationId+"\"].type", equalTo("invalidProperties"))
+ .body(ARGUMENTS + ".notCreated[\""+messageCreationId+"\"].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
+ public void setMessagesShouldSucceedWhenSendingMessageWithOnlyFromAddress() {
+ String messageCreationId = "user|inbox|1";
+ String fromAddress = "postmaster@example.com";
+ String requestBody = "[" +
+ " [" +
+ " \"setMessages\","+
+ " {" +
+ " \"create\": { \"" + messageCreationId + "\" : {" +
+ " \"from\": { \"email\": \"" + fromAddress + "\"}," +
+ " \"to\": [{ \"name\": \"BOB\", \"email\": \"someone@example.com\"}]," +
+ " \"cc\": [{ \"name\": \"ALICE\"}]," +
+ " \"subject\": \"Thank you for joining example.com!\"," +
+ " \"textBody\": \"Hello someone, and thank you for joining example.com!\"," +
+ " \"mailboxIds\": [\"" + outboxId + "\"]" +
+ " }}" +
+ " }," +
+ " \"#0\"" +
+ " ]" +
+ "]";
+
+ given()
+ .accept(ContentType.JSON)
+ .contentType(ContentType.JSON)
+ .header("Authorization", accessToken.serialize())
+ .body(requestBody)
+ .when()
+ .post("/jmap")
+ .then()
+ .log().ifValidationFails()
+ .statusCode(200)
+ .body(NAME, equalTo("messagesSet"))
+ .body(ARGUMENTS + ".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
+ public void setMessagesShouldRejectWhenSendingMessageHasMissingSubject() {
+ String messageCreationId = "user|inbox|1";
+ String requestBody = "[" +
+ " [" +
+ " \"setMessages\","+
+ " {" +
+ " \"create\": { \"" + messageCreationId + "\" : {" +
+ " \"from\": { \"name\": \"MAILER-DEAMON\", \"email\": \"postmaster@example.com\"}," +
+ " \"to\": [{ \"name\": \"BOB\", \"email\": \"someone@example.com\"}]," +
+ " \"cc\": [{ \"name\": \"ALICE\"}]," +
+ " \"textBody\": \"Hello someone, and thank you for joining example.com!\"," +
+ " \"mailboxIds\": [\"" + outboxId + "\"]" +
+ " }}" +
+ " }," +
+ " \"#0\"" +
+ " ]" +
+ "]";
+
+ given()
+ .accept(ContentType.JSON)
+ .contentType(ContentType.JSON)
+ .header("Authorization", accessToken.serialize())
+ .body(requestBody)
+ .when()
+ .post("/jmap")
+ .then()
+ .log().ifValidationFails()
+ .statusCode(200)
+ .body(NAME, equalTo("messagesSet"))
+ .body(ARGUMENTS + ".notCreated", hasKey(messageCreationId))
+ .body(ARGUMENTS + ".notCreated[\""+messageCreationId+"\"].type", equalTo("invalidProperties"))
+ .body(ARGUMENTS + ".notCreated[\""+messageCreationId+"\"].properties", hasSize(1))
+ .body(ARGUMENTS + ".notCreated[\""+messageCreationId+"\"].properties", contains("subject"))
+ .body(ARGUMENTS + ".notCreated[\""+messageCreationId+"\"].description", endsWith("'subject' is missing"))
+ .body(ARGUMENTS + ".created", aMapWithSize(0));
+ }
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/james-project/blob/078ba1a6/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 05d0229..783ced0 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
@@ -19,15 +19,17 @@
package org.apache.james.jmap.methods;
+import static org.apache.james.jmap.model.CreationMessage.DraftEmailer;
+
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Date;
+import java.util.Optional;
import java.util.TimeZone;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import org.apache.james.jmap.model.CreationMessage;
-import org.apache.james.jmap.model.Emailer;
import org.apache.james.mime4j.Charsets;
import org.apache.james.mime4j.codec.DecodeMonitor;
import org.apache.james.mime4j.dom.FieldParser;
@@ -88,27 +90,27 @@ public class MIMEMessageConverter {
Header messageHeaders = new HeaderImpl();
// add From: and Sender: headers
- newMessage.getFrom().map(this::convertEmailToMimeHeader)
- .map(Fields::from)
- .ifPresent(f -> messageHeaders.addField(f));
- newMessage.getFrom().map(this::convertEmailToMimeHeader)
- .map(Fields::sender)
- .ifPresent(f -> messageHeaders.addField(f));
+ Optional<Mailbox> fromAddress = newMessage.getFrom().filter(DraftEmailer::hasValidEmail).map(this::convertEmailToMimeHeader);
+ fromAddress.map(Fields::from).ifPresent(messageHeaders::addField);
+ fromAddress.map(Fields::sender).ifPresent(messageHeaders::addField);
// add Reply-To:
messageHeaders.addField(Fields.replyTo(newMessage.getReplyTo().stream()
- .map(rt -> convertEmailToMimeHeader(rt))
+ .map(this::convertEmailToMimeHeader)
.collect(Collectors.toList())));
// add To: headers
messageHeaders.addField(Fields.to(newMessage.getTo().stream()
+ .filter(DraftEmailer::hasValidEmail)
.map(this::convertEmailToMimeHeader)
.collect(Collectors.toList())));
// add Cc: headers
messageHeaders.addField(Fields.cc(newMessage.getCc().stream()
+ .filter(DraftEmailer::hasValidEmail)
.map(this::convertEmailToMimeHeader)
.collect(Collectors.toList())));
// add Bcc: headers
messageHeaders.addField(Fields.bcc(newMessage.getBcc().stream()
+ .filter(DraftEmailer::hasValidEmail)
.map(this::convertEmailToMimeHeader)
.collect(Collectors.toList())));
// add Subject: header
@@ -143,8 +145,11 @@ public class MIMEMessageConverter {
}
}
- private Mailbox convertEmailToMimeHeader(Emailer address) {
- String[] splitAddress = address.getEmail().split("@", 2);
- return new Mailbox(address.getName(), null, splitAddress[0], splitAddress[1]);
+ private Mailbox convertEmailToMimeHeader(DraftEmailer address) {
+ if (!address.hasValidEmail()) {
+ throw new IllegalArgumentException("address");
+ }
+ CreationMessage.EmailUserAndDomain emailUserAndDomain = address.getEmailUserAndDomain();
+ return new Mailbox(address.getName().orElse(null), null, emailUserAndDomain.getUser().orElse(null), emailUserAndDomain.getDomain().orElse(null));
}
}
http://git-wip-us.apache.org/repos/asf/james-project/blob/078ba1a6/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 3cb11db..1177e54 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
@@ -19,9 +19,17 @@
package org.apache.james.jmap.methods;
+import static org.apache.james.jmap.model.MessageProperties.MessageProperty;
+
+import java.util.AbstractMap;
import java.util.Date;
+import java.util.List;
+import java.util.Map;
import java.util.Optional;
+import java.util.Set;
import java.util.function.Function;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
import javax.inject.Inject;
import javax.mail.Flags;
@@ -32,6 +40,8 @@ import org.apache.james.jmap.exceptions.MailboxRoleNotFoundException;
import org.apache.james.jmap.model.CreationMessage;
import org.apache.james.jmap.model.Message;
import org.apache.james.jmap.model.MessageId;
+import org.apache.james.jmap.model.MessageProperties;
+import org.apache.james.jmap.model.SetError;
import org.apache.james.jmap.model.SetMessagesRequest;
import org.apache.james.jmap.model.SetMessagesResponse;
import org.apache.james.jmap.model.mailbox.Role;
@@ -54,6 +64,7 @@ import org.slf4j.LoggerFactory;
import com.github.fge.lambdas.functions.ThrowingFunction;
import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Splitter;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableMap;
@@ -70,7 +81,8 @@ public class SetMessagesCreationProcessor<Id extends MailboxId> implements SetMe
@VisibleForTesting
SetMessagesCreationProcessor(MailboxMapperFactory<Id> mailboxMapperFactory,
MailboxManager mailboxManager,
- MailboxSessionMapperFactory<Id> mailboxSessionMapperFactory, MIMEMessageConverter mimeMessageConverter) {
+ MailboxSessionMapperFactory<Id> mailboxSessionMapperFactory,
+ MIMEMessageConverter mimeMessageConverter) {
this.mailboxMapperFactory = mailboxMapperFactory;
this.mailboxManager = mailboxManager;
this.mailboxSessionMapperFactory = mailboxSessionMapperFactory;
@@ -86,11 +98,43 @@ public class SetMessagesCreationProcessor<Id extends MailboxId> implements SetMe
LOGGER.error("Unable to find a mailbox with role 'outbox'!");
throw Throwables.propagate(e);
}
+
+ // handle errors
+ Predicate<CreationMessage> validMessagesTester = CreationMessage::isValid;
+ Predicate<CreationMessage> invalidMessagesTester = validMessagesTester.negate();
+ SetMessagesResponse.Builder responseBuilder = SetMessagesResponse.builder()
+ .notCreated(handleCreationErrors(invalidMessagesTester, request));
+
return request.getCreate().entrySet().stream()
+ .filter(e -> validMessagesTester.test(e.getValue()))
.map(e -> new MessageWithId.CreationMessageEntry(e.getKey(), e.getValue()))
.map(nuMsg -> createMessageInOutbox(nuMsg, mailboxSession, outbox, buildMessageIdFunc(mailboxSession, outbox)))
.map(msg -> SetMessagesResponse.builder().created(ImmutableMap.of(msg.getCreationId(), msg.getMessage())).build())
- .reduce(SetMessagesResponse.builder(), SetMessagesResponse.Builder::accumulator, SetMessagesResponse.Builder::combiner)
+ .reduce(responseBuilder, SetMessagesResponse.Builder::accumulator, SetMessagesResponse.Builder::combiner)
+ .build();
+ }
+
+ private Map<String, SetError> handleCreationErrors(Predicate<CreationMessage> invalidMessagesTester,
+ SetMessagesRequest request) {
+ return request.getCreate().entrySet().stream()
+ .filter(e -> invalidMessagesTester.test(e.getValue()))
+ .map(e -> new AbstractMap.SimpleEntry<>(e.getKey(), buildSetErrorFromValidationResult(e.getValue().validate())))
+ .collect(Collectors.toMap(AbstractMap.SimpleEntry::getKey, AbstractMap.SimpleEntry::getValue));
+ }
+
+ private SetError buildSetErrorFromValidationResult(List<ValidationResult> validationErrors) {
+ String formattedValidationErrorMessage = validationErrors.stream()
+ .map(err -> err.getProperty() + ": " + err.getErrorMessage())
+ .collect(Collectors.joining("\\n"));
+ Splitter propertiesSplitter = Splitter.on(',').trimResults().omitEmptyStrings();
+ Set<MessageProperties.MessageProperty> properties = validationErrors.stream()
+ .flatMap(err -> propertiesSplitter.splitToList(err.getProperty()).stream())
+ .flatMap(MessageProperty::find)
+ .collect(Collectors.toSet());
+ return SetError.builder()
+ .type("invalidProperties")
+ .properties(properties)
+ .description(formattedValidationErrorMessage)
.build();
}
http://git-wip-us.apache.org/repos/asf/james-project/blob/078ba1a6/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/ValidationResult.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/ValidationResult.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/ValidationResult.java
index b48c88f..9540ce6 100644
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/ValidationResult.java
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/ValidationResult.java
@@ -19,6 +19,8 @@
package org.apache.james.jmap.methods;
+import java.util.Objects;
+
import com.google.common.annotations.VisibleForTesting;
public class ValidationResult {
@@ -66,4 +68,26 @@ public class ValidationResult {
return errorMessage;
}
+ @Override
+ public boolean equals(Object o) {
+ if (o instanceof ValidationResult) {
+ ValidationResult otherEMailer = (ValidationResult) o;
+ return Objects.equals(property, otherEMailer.property)
+ && Objects.equals(errorMessage, otherEMailer.errorMessage);
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(property, errorMessage);
+ }
+
+ @Override
+ public String toString() {
+ return com.google.common.base.Objects.toStringHelper(getClass())
+ .add("property", property)
+ .add("errorMessage", errorMessage)
+ .toString();
+ }
}
http://git-wip-us.apache.org/repos/asf/james-project/blob/078ba1a6/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 697c9c7..4fac7e8 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
@@ -19,15 +19,20 @@
package org.apache.james.jmap.model;
+import static org.apache.james.jmap.model.MessageProperties.MessageProperty;
+
import java.time.ZonedDateTime;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
import java.util.Optional;
+import java.util.stream.Collectors;
+
+import javax.mail.internet.AddressException;
+import javax.mail.internet.InternetAddress;
-import org.apache.james.jmap.methods.GetMessagesMethod;
-import org.apache.james.jmap.methods.JmapResponseWriterImpl;
+import org.apache.james.jmap.methods.ValidationResult;
-import com.fasterxml.jackson.annotation.JsonFilter;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
import com.google.common.annotations.VisibleForTesting;
@@ -39,6 +44,10 @@ import com.google.common.collect.ImmutableMap;
@JsonDeserialize(builder = CreationMessage.Builder.class)
public class CreationMessage {
+ private static final String RECIPIENT_PROPERTY_NAMES = ImmutableList.of(MessageProperty.to, MessageProperty.cc, MessageProperty.bcc).stream()
+ .map(MessageProperty::asFieldName)
+ .collect(Collectors.joining(", "));
+
public static Builder builder() {
return new Builder();
}
@@ -52,11 +61,11 @@ public class CreationMessage {
private boolean isAnswered;
private boolean isDraft;
private final ImmutableMap.Builder<String, String> headers;
- private Emailer from;
- private final ImmutableList.Builder<Emailer> to;
- private final ImmutableList.Builder<Emailer> cc;
- private final ImmutableList.Builder<Emailer> bcc;
- private final ImmutableList.Builder<Emailer> replyTo;
+ private Optional<DraftEmailer> from = Optional.empty();
+ private final ImmutableList.Builder<DraftEmailer> to;
+ private final ImmutableList.Builder<DraftEmailer> cc;
+ private final ImmutableList.Builder<DraftEmailer> bcc;
+ private final ImmutableList.Builder<DraftEmailer> replyTo;
private String subject;
private ZonedDateTime date;
private String textBody;
@@ -109,27 +118,27 @@ public class CreationMessage {
return this;
}
- public Builder from(Emailer from) {
- this.from = from;
+ public Builder from(DraftEmailer from) {
+ this.from = Optional.ofNullable(from);
return this;
}
- public Builder to(List<Emailer> to) {
+ public Builder to(List<DraftEmailer> to) {
this.to.addAll(to);
return this;
}
- public Builder cc(List<Emailer> cc) {
+ public Builder cc(List<DraftEmailer> cc) {
this.cc.addAll(cc);
return this;
}
- public Builder bcc(List<Emailer> bcc) {
+ public Builder bcc(List<DraftEmailer> bcc) {
this.bcc.addAll(bcc);
return this;
}
- public Builder replyTo(List<Emailer> replyTo) {
+ public Builder replyTo(List<DraftEmailer> replyTo) {
this.replyTo.addAll(replyTo);
return this;
}
@@ -173,7 +182,6 @@ public class CreationMessage {
public CreationMessage build() {
Preconditions.checkState(mailboxIds != null, "'mailboxIds' is mandatory");
Preconditions.checkState(headers != null, "'headers' is mandatory");
- Preconditions.checkState(!Strings.isNullOrEmpty(subject), "'subject' is mandatory");
ImmutableList<Attachment> attachments = this.attachments.build();
ImmutableMap<String, SubMessage> attachedMessages = this.attachedMessages.build();
Preconditions.checkState(areAttachedMessagesKeysInAttachments(attachments, attachedMessages), "'attachedMessages' keys must be in 'attachments'");
@@ -182,7 +190,7 @@ public class CreationMessage {
date = ZonedDateTime.now();
}
- return new CreationMessage(mailboxIds, Optional.ofNullable(inReplyToMessageId), isUnread, isFlagged, isAnswered, isDraft, headers.build(), Optional.ofNullable(from),
+ return new CreationMessage(mailboxIds, Optional.ofNullable(inReplyToMessageId), isUnread, isFlagged, isAnswered, isDraft, headers.build(), from,
to.build(), cc.build(), bcc.build(), replyTo.build(), subject, date, Optional.ofNullable(textBody), Optional.ofNullable(htmlBody), attachments, attachedMessages);
}
}
@@ -194,11 +202,11 @@ public class CreationMessage {
private final boolean isAnswered;
private final boolean isDraft;
private final ImmutableMap<String, String> headers;
- private final Optional<Emailer> from;
- private final ImmutableList<Emailer> to;
- private final ImmutableList<Emailer> cc;
- private final ImmutableList<Emailer> bcc;
- private final ImmutableList<Emailer> replyTo;
+ private final Optional<DraftEmailer> from;
+ private final ImmutableList<DraftEmailer> to;
+ private final ImmutableList<DraftEmailer> cc;
+ private final ImmutableList<DraftEmailer> bcc;
+ private final ImmutableList<DraftEmailer> replyTo;
private final String subject;
private final ZonedDateTime date;
private final Optional<String> textBody;
@@ -207,8 +215,8 @@ public class CreationMessage {
private final ImmutableMap<String, SubMessage> attachedMessages;
@VisibleForTesting
- CreationMessage(ImmutableList<String> mailboxIds, Optional<String> inReplyToMessageId, boolean isUnread, boolean isFlagged, boolean isAnswered, boolean isDraft, 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,
+ 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) {
this.mailboxIds = mailboxIds;
this.inReplyToMessageId = inReplyToMessageId;
@@ -258,23 +266,23 @@ public class CreationMessage {
return headers;
}
- public Optional<Emailer> getFrom() {
+ public Optional<DraftEmailer> getFrom() {
return from;
}
- public ImmutableList<Emailer> getTo() {
+ public ImmutableList<DraftEmailer> getTo() {
return to;
}
- public ImmutableList<Emailer> getCc() {
+ public ImmutableList<DraftEmailer> getCc() {
return cc;
}
- public ImmutableList<Emailer> getBcc() {
+ public ImmutableList<DraftEmailer> getBcc() {
return bcc;
}
- public ImmutableList<Emailer> getReplyTo() {
+ public ImmutableList<DraftEmailer> getReplyTo() {
return replyTo;
}
@@ -302,4 +310,153 @@ public class CreationMessage {
return attachedMessages;
}
+ public boolean isValid() {
+ return validate().isEmpty();
+ }
+
+ public List<ValidationResult> validate() {
+ ImmutableList.Builder<ValidationResult> errors = ImmutableList.builder();
+ assertValidFromProvided(errors);
+ assertAtLeastOneValidRecipient(errors);
+ assertSubjectProvided(errors);
+ return errors.build();
+ }
+
+ private void assertSubjectProvided(ImmutableList.Builder<ValidationResult> errors) {
+ if (Strings.isNullOrEmpty(subject)) {
+ errors.add(ValidationResult.builder().message("'subject' is missing").property(MessageProperty.subject.asFieldName()).build());
+ }
+ }
+
+ private void assertAtLeastOneValidRecipient(ImmutableList.Builder<ValidationResult> errors) {
+ ImmutableList<DraftEmailer> recipients = ImmutableList.<DraftEmailer>builder().addAll(to).addAll(cc).addAll(bcc).build();
+ boolean hasAtLeastOneAddressToSendTo = recipients.stream().anyMatch(DraftEmailer::hasValidEmail);
+ boolean recipientsHaveValidAddresses = recipients.stream().allMatch(e1 -> e1.getEmail() != null);
+ if (!(recipientsHaveValidAddresses && hasAtLeastOneAddressToSendTo)) {
+ errors.add(ValidationResult.builder().message("no recipient address set").property(RECIPIENT_PROPERTY_NAMES).build());
+ }
+ }
+
+ private void assertValidFromProvided(ImmutableList.Builder<ValidationResult> errors) {
+ ValidationResult invalidPropertyFrom = ValidationResult.builder()
+ .property(MessageProperty.from.asFieldName())
+ .message("'from' address is mandatory")
+ .build();
+ if (!from.isPresent()) {
+ errors.add(invalidPropertyFrom);
+ }
+ from.filter(f -> !f.hasValidEmail()).ifPresent(f -> errors.add(invalidPropertyFrom));
+ }
+
+ @JsonDeserialize(builder = DraftEmailer.Builder.class)
+ public static class DraftEmailer {
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ @JsonPOJOBuilder(withPrefix = "")
+ public static class Builder {
+ private Optional<String> name = Optional.empty();
+ private Optional<String> email = Optional.empty();
+
+ public Builder name(String name) {
+ this.name = Optional.ofNullable(name);
+ return this;
+ }
+
+ public Builder email(String email) {
+ this.email = Optional.ofNullable(email);
+ return this;
+ }
+
+ public DraftEmailer build() {
+ return new DraftEmailer(name, email);
+ }
+ }
+
+ private final Optional<String> name;
+ private final Optional<String> email;
+ private final EmailValidator emailValidator;
+
+ @VisibleForTesting
+ DraftEmailer(Optional<String> name, Optional<String> email) {
+ this.name = name;
+ this.email = email;
+ this.emailValidator = new EmailValidator();
+ }
+
+ public Optional<String> getName() {
+ return name;
+ }
+
+ public Optional<String> getEmail() {
+ return email;
+ }
+
+ public boolean hasValidEmail() {
+ return getEmail().isPresent() && emailValidator.isValid(getEmail().get());
+ }
+
+ public EmailUserAndDomain getEmailUserAndDomain() {
+ String[] splitAddress = email.get().split("@", 2);
+ return new EmailUserAndDomain(Optional.ofNullable(splitAddress[0]), Optional.ofNullable(splitAddress[1]));
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o instanceof DraftEmailer) {
+ DraftEmailer otherEMailer = (DraftEmailer) o;
+ return Objects.equals(name, otherEMailer.name)
+ && Objects.equals(email.orElse("<unset>"), otherEMailer.email.orElse("<unset>") );
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(name, email);
+ }
+
+ @Override
+ public String toString() {
+ return com.google.common.base.Objects.toStringHelper(this)
+ .add("name", name)
+ .add("email", email.orElse("<unset>"))
+ .toString();
+ }
+ }
+
+ public static class EmailUserAndDomain {
+ private final Optional<String> user;
+ private final Optional<String> domain;
+
+ public EmailUserAndDomain(Optional<String> user, Optional<String> domain) {
+ this.user = user;
+ this.domain = domain;
+ }
+
+ public Optional<String> getUser() {
+ return user;
+ }
+
+ public Optional<String> getDomain() {
+ return domain;
+ }
+ }
+
+ public static class EmailValidator {
+
+ public boolean isValid(String email) {
+ boolean result = true;
+ try {
+ InternetAddress emailAddress = new InternetAddress(email);
+ // verrrry permissive validator !
+ emailAddress.validate();
+ } catch (AddressException ex) {
+ result = false;
+ }
+ return result;
+ }
+ }
}
http://git-wip-us.apache.org/repos/asf/james-project/blob/078ba1a6/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetMessagesResponse.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetMessagesResponse.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetMessagesResponse.java
index c096c8a..004b11b 100644
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetMessagesResponse.java
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetMessagesResponse.java
@@ -20,17 +20,15 @@ package org.apache.james.jmap.model;
import java.util.List;
import java.util.Map;
-import java.util.function.BiFunction;
-import com.google.common.base.Strings;
import org.apache.commons.lang.NotImplementedException;
-import org.apache.james.jmap.methods.MessageWithId;
import org.apache.james.jmap.methods.Method;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
@@ -55,12 +53,12 @@ public class SetMessagesResponse implements Method.Response {
private String accountId;
private String oldState;
private String newState;
- private ImmutableMap.Builder<String, Message> created;
- private ImmutableList.Builder<MessageId> updated;
- private ImmutableList.Builder<MessageId> destroyed;
- private ImmutableMap.Builder<MessageId, SetError> notCreated;
- private ImmutableMap.Builder<MessageId, SetError> notUpdated;
- private ImmutableMap.Builder<MessageId, SetError> notDestroyed;
+ private final ImmutableMap.Builder<String, Message> created;
+ private final ImmutableList.Builder<MessageId> updated;
+ private final ImmutableList.Builder<MessageId> destroyed;
+ private final ImmutableMap.Builder<String, SetError> notCreated;
+ private final ImmutableMap.Builder<MessageId, SetError> notUpdated;
+ private final ImmutableMap.Builder<MessageId, SetError> notDestroyed;
private Builder() {
created = ImmutableMap.builder();
@@ -103,7 +101,7 @@ public class SetMessagesResponse implements Method.Response {
return this;
}
- public Builder notCreated(Map<MessageId, SetError> notCreated) {
+ public Builder notCreated(Map<String, SetError> notCreated) {
this.notCreated.putAll(notCreated);
return this;
}
@@ -135,12 +133,12 @@ public class SetMessagesResponse implements Method.Response {
private final Map<String, Message> created;
private final List<MessageId> updated;
private final List<MessageId> destroyed;
- private final Map<MessageId, SetError> notCreated;
+ private final Map<String, SetError> notCreated;
private final Map<MessageId, SetError> notUpdated;
private final Map<MessageId, SetError> notDestroyed;
@VisibleForTesting SetMessagesResponse(String accountId, String oldState, String newState, Map<String, Message> created, List<MessageId> updated, List<MessageId> destroyed,
- Map<MessageId, SetError> notCreated, Map<MessageId, SetError> notUpdated, Map<MessageId, SetError> notDestroyed) {
+ Map<String, SetError> notCreated, Map<MessageId, SetError> notUpdated, Map<MessageId, SetError> notDestroyed) {
this.accountId = accountId;
this.oldState = oldState;
this.newState = newState;
@@ -183,7 +181,7 @@ public class SetMessagesResponse implements Method.Response {
}
@JsonSerialize
- public Map<MessageId, SetError> getNotCreated() {
+ public Map<String, SetError> getNotCreated() {
return notCreated;
}
http://git-wip-us.apache.org/repos/asf/james-project/blob/078ba1a6/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 af7d17a..0224f49 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
@@ -19,6 +19,7 @@
package org.apache.james.jmap.methods;
+import static org.apache.james.jmap.model.CreationMessage.DraftEmailer;
import static org.assertj.core.api.Assertions.assertThat;
import java.sql.Date;
@@ -27,7 +28,6 @@ import java.time.ZoneId;
import java.time.ZonedDateTime;
import org.apache.james.jmap.model.CreationMessage;
-import org.apache.james.jmap.model.Emailer;
import org.apache.james.mime4j.dom.Message;
import org.apache.james.mime4j.dom.address.Mailbox;
import org.apache.james.mime4j.stream.Field;
@@ -43,8 +43,9 @@ public class MIMEMessageConverterTest {
String matchingMessageId = "unique-message-id";
CreationMessage messageHavingInReplyTo = CreationMessage.builder()
+ .from(DraftEmailer.builder().name("sender").build())
.inReplyToMessageId(matchingMessageId)
- .mailboxIds(ImmutableList.of("Hey!"))
+ .mailboxIds(ImmutableList.of("dead-beef-1337"))
.subject("subject")
.build();
@@ -73,7 +74,7 @@ public class MIMEMessageConverterTest {
CreationMessage testMessage = CreationMessage.builder()
.mailboxIds(ImmutableList.of("deadbeef-dead-beef-dead-beef"))
.subject("subject")
- .from(Emailer.builder().email(joesEmail).name("joe").build())
+ .from(DraftEmailer.builder().email(joesEmail).name("joe").build())
.build();
// When
@@ -81,7 +82,7 @@ public class MIMEMessageConverterTest {
"user|mailbox|1", testMessage));
// Then
- assertThat(result.getFrom()).extracting(Mailbox::getAddress).allMatch(f -> f.toString().equals(joesEmail));
+ assertThat(result.getFrom()).extracting(Mailbox::getAddress).allMatch(f -> f.equals(joesEmail));
assertThat(result.getSender().getAddress()).isEqualTo(joesEmail);
}
@@ -96,6 +97,7 @@ public class MIMEMessageConverterTest {
CreationMessage testMessage = CreationMessage.builder()
.mailboxIds(ImmutableList.of("dead-bada55"))
.subject("subject")
+ .from(DraftEmailer.builder().name("sender").build())
.date(messageDate)
.build();
http://git-wip-us.apache.org/repos/asf/james-project/blob/078ba1a6/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 06dc7c4..c5c8db6 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
@@ -19,6 +19,7 @@
package org.apache.james.jmap.methods;
+import static org.apache.james.jmap.model.CreationMessage.DraftEmailer;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
@@ -32,7 +33,6 @@ import java.util.function.Function;
import org.apache.james.jmap.exceptions.MailboxRoleNotFoundException;
import org.apache.james.jmap.model.CreationMessage;
-import org.apache.james.jmap.model.Emailer;
import org.apache.james.jmap.model.Message;
import org.apache.james.jmap.model.MessageId;
import org.apache.james.jmap.model.SetMessagesRequest;
@@ -165,8 +165,8 @@ public class SetMessagesCreationProcessorTest {
private SetMessagesRequest buildFakeCreationRequest() {
return SetMessagesRequest.builder()
.create(ImmutableMap.of("anything-really", CreationMessage.builder()
- .from(Emailer.builder().name("alice").email("alice@example.com").build())
- .to(ImmutableList.of(Emailer.builder().name("bob").email("bob@example.com").build()))
+ .from(DraftEmailer.builder().name("alice").email("alice@example.com").build())
+ .to(ImmutableList.of(DraftEmailer.builder().name("bob").email("bob@example.com").build()))
.subject("Hey! ")
.mailboxIds(ImmutableList.of("mailboxId"))
.build()
http://git-wip-us.apache.org/repos/asf/james-project/blob/078ba1a6/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/CreationMessageTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/CreationMessageTest.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/CreationMessageTest.java
new file mode 100644
index 0000000..48fca1c
--- /dev/null
+++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/CreationMessageTest.java
@@ -0,0 +1,87 @@
+/****************************************************************
+ * 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.apache.james.jmap.model.CreationMessage.DraftEmailer;
+import static org.apache.james.jmap.model.MessageProperties.MessageProperty;
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.apache.james.jmap.methods.ValidationResult;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+
+public class CreationMessageTest {
+
+ private CreationMessage.Builder testedBuilder;
+
+ @Before
+ public void setUp() {
+ testedBuilder = CreationMessage.builder()
+ .mailboxIds(ImmutableList.of("ba9-0f-dead-beef"))
+ .headers(ImmutableMap.of())
+ .subject("anything");
+ }
+
+ @Test
+ public void validateShouldReturnErrorWhenFromIsMissing() {
+ CreationMessage sut = testedBuilder.build();
+
+ assertThat(sut.validate()).contains(ValidationResult.builder()
+ .message("'from' address is mandatory")
+ .property(MessageProperty.from.asFieldName())
+ .build()
+ );
+ }
+
+ @Test
+ public void validateShouldReturnErrorWhenFromIsInvalid() {
+ CreationMessage sut = testedBuilder.from(DraftEmailer.builder().name("bob").email("bob@domain.com@example.com").build()).build();
+
+ assertThat(sut.validate()).contains(ValidationResult.builder()
+ .message("'from' address is mandatory")
+ .property(MessageProperty.from.asFieldName())
+ .build()
+ );
+ }
+
+ @Test
+ public void validateShouldReturnErrorWhenNoRecipientSet () {
+ CreationMessage sut = testedBuilder
+ .from(DraftEmailer.builder().name("bob").email("bob@example.com").build()).build();
+
+ assertThat(sut.validate()).extracting(ValidationResult::getErrorMessage).contains("no recipient address set");
+ }
+
+ @Test
+ public void validateShouldReturnErrorWhenNoValidRecipientSet () {
+ CreationMessage sut = testedBuilder
+ .from(DraftEmailer.builder().name("bob").email("bob@example.com").build())
+ .to(ImmutableList.of(DraftEmailer.builder().name("riri").email("riri@acme.com@example.com").build()))
+ .cc(ImmutableList.of(DraftEmailer.builder().name("fifi").email("fifi@acme.com@example.com").build()))
+ .bcc(ImmutableList.of(DraftEmailer.builder().name("loulou").email("loulou@acme.com@example.com").build()))
+ .build();
+
+ assertThat(sut.validate()).extracting(ValidationResult::getErrorMessage).contains("no recipient address set");
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/james-project/blob/078ba1a6/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 9877651..373f1b3 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
@@ -23,8 +23,6 @@ import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import java.time.ZonedDateTime;
-import java.util.List;
-import java.util.stream.Collectors;
import org.apache.commons.lang.NotImplementedException;
import org.junit.Test;
@@ -69,7 +67,7 @@ public class SetMessagesResponseTest {
.build());
ImmutableList<MessageId> updated = ImmutableList.of(MessageId.of("user|updated|1"));
ImmutableList<MessageId> destroyed = ImmutableList.of(MessageId.of("user|destroyed|1"));
- ImmutableMap<MessageId, SetError> notCreated = ImmutableMap.of(MessageId.of("user|created|2"), SetError.builder().type("created").build());
+ ImmutableMap<String, SetError> notCreated = ImmutableMap.of("dead-beef-defec8", SetError.builder().type("created").build());
ImmutableMap<MessageId, SetError> notUpdated = ImmutableMap.of(MessageId.of("user|update|2"), SetError.builder().type("updated").build());
ImmutableMap<MessageId, SetError> notDestroyed = ImmutableMap.of(MessageId.of("user|destroyed|3"), SetError.builder().type("destroyed").build());
SetMessagesResponse expected = new SetMessagesResponse(null, null, null, created, updated, destroyed, notCreated, notUpdated, notDestroyed);
@@ -94,7 +92,7 @@ public class SetMessagesResponseTest {
.created(buildMessage("user|inbox|1"))
.updated(ImmutableList.of(MessageId.of("user|inbox|2")))
.destroyed(ImmutableList.of(MessageId.of("user|inbox|3")))
- .notCreated(ImmutableMap.of( MessageId.of("user|inbox|4"), SetError.builder().type("type").build()))
+ .notCreated(ImmutableMap.of( "dead-beef-defec8", SetError.builder().type("type").build()))
.notUpdated(ImmutableMap.of(MessageId.of("user|inbox|5"), SetError.builder().type("type").build()))
.notDestroyed(ImmutableMap.of(MessageId.of("user|inbox|6"), SetError.builder().type("type").build()))
.build();
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org
[3/9] james-project git commit: JAMES-1692 add
SetMessagesCreationProcessor impl. for sending message
Posted by ad...@apache.org.
JAMES-1692 add SetMessagesCreationProcessor impl. for sending message
add CreationMessage to hold new messages.
build up MIME Messages for james to append to OUTBOX
extract SetMessagesProcessor<Id> interface
Project: http://git-wip-us.apache.org/repos/asf/james-project/repo
Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/99ac325d
Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/99ac325d
Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/99ac325d
Branch: refs/heads/master
Commit: 99ac325d5f9bab58363a62b50a1ff7965611473b
Parents: 0625fb5
Author: Fabien Vignon <fv...@linagora.com>
Authored: Fri Feb 12 19:40:12 2016 +0100
Committer: Raphael Ouazana <ra...@linagora.com>
Committed: Tue Mar 1 15:42:53 2016 +0100
----------------------------------------------------------------------
.../org/apache/james/jmap/MethodsModule.java | 2 +
.../jmap/methods/SetMessagesMethodTest.java | 2 -
.../MailboxRoleNotFoundException.java | 36 +++
.../jmap/methods/MIMEMessageConverter.java | 150 +++++++++
.../james/jmap/methods/MessageWithId.java | 48 +++
.../methods/SetMessagesCreationProcessor.java | 174 +++++++++++
.../james/jmap/methods/SetMessagesMethod.java | 9 +-
.../jmap/methods/SetMessagesProcessor.java | 29 ++
.../methods/SetMessagesUpdateProcessor.java | 4 +-
.../james/jmap/model/CreationMessage.java | 305 +++++++++++++++++++
.../james/jmap/model/SetMessagesRequest.java | 12 +-
.../james/jmap/model/SetMessagesResponse.java | 27 +-
.../SetMessagesCreationProcessorTest.java | 131 ++++++++
.../jmap/model/SetMessagesResponseTest.java | 11 +-
14 files changed, 913 insertions(+), 27 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/james-project/blob/99ac325d/server/container/cassandra-guice/src/main/java/org/apache/james/jmap/MethodsModule.java
----------------------------------------------------------------------
diff --git a/server/container/cassandra-guice/src/main/java/org/apache/james/jmap/MethodsModule.java b/server/container/cassandra-guice/src/main/java/org/apache/james/jmap/MethodsModule.java
index 27faf5a..4e57d20 100644
--- a/server/container/cassandra-guice/src/main/java/org/apache/james/jmap/MethodsModule.java
+++ b/server/container/cassandra-guice/src/main/java/org/apache/james/jmap/MethodsModule.java
@@ -28,6 +28,7 @@ import org.apache.james.jmap.methods.JmapRequestParserImpl;
import org.apache.james.jmap.methods.JmapResponseWriter;
import org.apache.james.jmap.methods.JmapResponseWriterImpl;
import org.apache.james.jmap.methods.Method;
+import org.apache.james.jmap.methods.SetMessagesCreationProcessor;
import org.apache.james.jmap.methods.SetMessagesMethod;
import org.apache.james.jmap.methods.SetMessagesUpdateProcessor;
import org.apache.james.mailbox.cassandra.CassandraId;
@@ -54,6 +55,7 @@ public class MethodsModule extends AbstractModule {
methods.addBinding().to(new TypeLiteral<GetMessagesMethod<CassandraId>>(){});
methods.addBinding().to(new TypeLiteral<SetMessagesMethod<CassandraId>>(){});
bind(SetMessagesUpdateProcessor.class).to(new TypeLiteral<SetMessagesUpdateProcessor<CassandraId>>(){});
+ bind(SetMessagesCreationProcessor.class).to(new TypeLiteral<SetMessagesCreationProcessor<CassandraId>>(){});
}
}
http://git-wip-us.apache.org/repos/asf/james-project/blob/99ac325d/server/protocols/jmap-integration-testing/src/test/java/org/apache/james/jmap/methods/SetMessagesMethodTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap-integration-testing/src/test/java/org/apache/james/jmap/methods/SetMessagesMethodTest.java b/server/protocols/jmap-integration-testing/src/test/java/org/apache/james/jmap/methods/SetMessagesMethodTest.java
index fcc3101..3acaf8c 100644
--- a/server/protocols/jmap-integration-testing/src/test/java/org/apache/james/jmap/methods/SetMessagesMethodTest.java
+++ b/server/protocols/jmap-integration-testing/src/test/java/org/apache/james/jmap/methods/SetMessagesMethodTest.java
@@ -648,7 +648,6 @@ public abstract class SetMessagesMethodTest {
}
@Test
- @Ignore("pending SetMessages's send messages feature implementation")
public void setMessageShouldReturnCreatedMessageWhenSendingMessage() {
String messageCreationId = "user|inbox|1";
String requestBody = "[" +
@@ -701,7 +700,6 @@ public abstract class SetMessagesMethodTest {
}
@Test
- @Ignore("pending SetMessages's send messages feature implementation")
public void setMessagesShouldCreateMessageInOutboxWhenSendingMessage() throws MailboxException {
// Given
String messageCreationId = "user|inbox|1";
http://git-wip-us.apache.org/repos/asf/james-project/blob/99ac325d/server/protocols/jmap/src/main/java/org/apache/james/jmap/exceptions/MailboxRoleNotFoundException.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/exceptions/MailboxRoleNotFoundException.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/exceptions/MailboxRoleNotFoundException.java
new file mode 100644
index 0000000..88692c8
--- /dev/null
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/exceptions/MailboxRoleNotFoundException.java
@@ -0,0 +1,36 @@
+/****************************************************************
+ * 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 org.apache.james.jmap.model.mailbox.Role;
+
+public class MailboxRoleNotFoundException extends RuntimeException {
+
+ private final Role role;
+
+ public MailboxRoleNotFoundException(Role role) {
+ super(String.format("Could not find any mailbox with role '%s'", role.serialize()));
+ this.role = role;
+ }
+
+ public Role getRole() {
+ return role;
+ }
+}
http://git-wip-us.apache.org/repos/asf/james-project/blob/99ac325d/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
new file mode 100644
index 0000000..05d0229
--- /dev/null
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/MIMEMessageConverter.java
@@ -0,0 +1,150 @@
+/****************************************************************
+ * 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.methods;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.Date;
+import java.util.TimeZone;
+import java.util.function.Consumer;
+import java.util.stream.Collectors;
+
+import org.apache.james.jmap.model.CreationMessage;
+import org.apache.james.jmap.model.Emailer;
+import org.apache.james.mime4j.Charsets;
+import org.apache.james.mime4j.codec.DecodeMonitor;
+import org.apache.james.mime4j.dom.FieldParser;
+import org.apache.james.mime4j.dom.Header;
+import org.apache.james.mime4j.dom.Message;
+import org.apache.james.mime4j.dom.MessageBuilder;
+import org.apache.james.mime4j.dom.TextBody;
+import org.apache.james.mime4j.dom.address.Mailbox;
+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.io.InputStreams;
+import org.apache.james.mime4j.message.BasicBodyFactory;
+import org.apache.james.mime4j.message.BodyFactory;
+import org.apache.james.mime4j.message.DefaultMessageBuilder;
+import org.apache.james.mime4j.message.DefaultMessageWriter;
+import org.apache.james.mime4j.message.HeaderImpl;
+import org.apache.james.mime4j.stream.Field;
+import org.apache.james.mime4j.stream.RawField;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Throwables;
+
+public class MIMEMessageConverter {
+
+ private final MessageBuilder messageBuilder;
+ private final BodyFactory bodyFactory;
+
+ public MIMEMessageConverter() {
+ this.messageBuilder = new DefaultMessageBuilder();
+ this.bodyFactory = new BasicBodyFactory();
+ }
+
+ public byte[] convert(MessageWithId.CreationMessageEntry creationMessageEntry) {
+
+ ByteArrayOutputStream buffer = new ByteArrayOutputStream();
+ DefaultMessageWriter writer = new DefaultMessageWriter();
+ try {
+ writer.writeMessage(convertToMime(creationMessageEntry), buffer);
+ } catch (IOException e) {
+ throw Throwables.propagate(e);
+ }
+ return buffer.toByteArray();
+ }
+
+ @VisibleForTesting Message convertToMime(MessageWithId.CreationMessageEntry creationMessageEntry) {
+ if (creationMessageEntry == null || creationMessageEntry.getMessage() == null) {
+ throw new IllegalArgumentException("creationMessageEntry is either null or has null message");
+ }
+
+ Message message = messageBuilder.newMessage();
+ message.setBody(createTextBody(creationMessageEntry.getMessage()));
+ message.setHeader(buildMimeHeaders(creationMessageEntry.getCreationId(), creationMessageEntry.getMessage()));
+ return message;
+ }
+
+ private Header buildMimeHeaders(String creationId, CreationMessage newMessage) {
+ Header messageHeaders = new HeaderImpl();
+
+ // add From: and Sender: headers
+ newMessage.getFrom().map(this::convertEmailToMimeHeader)
+ .map(Fields::from)
+ .ifPresent(f -> messageHeaders.addField(f));
+ newMessage.getFrom().map(this::convertEmailToMimeHeader)
+ .map(Fields::sender)
+ .ifPresent(f -> messageHeaders.addField(f));
+
+ // add Reply-To:
+ messageHeaders.addField(Fields.replyTo(newMessage.getReplyTo().stream()
+ .map(rt -> convertEmailToMimeHeader(rt))
+ .collect(Collectors.toList())));
+ // add To: headers
+ messageHeaders.addField(Fields.to(newMessage.getTo().stream()
+ .map(this::convertEmailToMimeHeader)
+ .collect(Collectors.toList())));
+ // add Cc: headers
+ messageHeaders.addField(Fields.cc(newMessage.getCc().stream()
+ .map(this::convertEmailToMimeHeader)
+ .collect(Collectors.toList())));
+ // add Bcc: headers
+ messageHeaders.addField(Fields.bcc(newMessage.getBcc().stream()
+ .map(this::convertEmailToMimeHeader)
+ .collect(Collectors.toList())));
+ // add Subject: header
+ messageHeaders.addField(Fields.subject(newMessage.getSubject()));
+ // set creation Id as MessageId: header
+ messageHeaders.addField(Fields.messageId(creationId));
+
+ // date(String fieldName, Date date, TimeZone zone)
+ // note that date conversion probably lose milliseconds !
+ messageHeaders.addField(Fields.date("Date",
+ Date.from(newMessage.getDate().toInstant()), TimeZone.getTimeZone(newMessage.getDate().getZone())
+ ));
+ newMessage.getInReplyToMessageId().ifPresent(addInReplyToHeader(messageHeaders::addField));
+ return messageHeaders;
+ }
+
+ private Consumer<String> addInReplyToHeader(Consumer<Field> headerAppender) {
+ return msgId -> {
+ FieldParser<UnstructuredField> parser = UnstructuredFieldImpl.PARSER;
+ RawField rawField = new RawField("In-Reply-To", msgId);
+ headerAppender.accept(parser.parse(rawField, DecodeMonitor.SILENT));
+ };
+ }
+
+ private TextBody createTextBody(CreationMessage newMessage) {
+ try {
+ return bodyFactory.textBody(
+ InputStreams.create(newMessage.getTextBody().orElse(""), Charsets.UTF_8),
+ Charsets.UTF_8.name());
+ } catch (IOException e) {
+ throw Throwables.propagate(e);
+ }
+ }
+
+ private Mailbox convertEmailToMimeHeader(Emailer address) {
+ String[] splitAddress = address.getEmail().split("@", 2);
+ return new Mailbox(address.getName(), null, splitAddress[0], splitAddress[1]);
+ }
+}
http://git-wip-us.apache.org/repos/asf/james-project/blob/99ac325d/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/MessageWithId.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/MessageWithId.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/MessageWithId.java
new file mode 100644
index 0000000..fbc7105
--- /dev/null
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/MessageWithId.java
@@ -0,0 +1,48 @@
+/****************************************************************
+ * 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.methods;
+
+import org.apache.james.jmap.model.CreationMessage;
+
+public class MessageWithId<T> {
+
+ private String creationId;
+ private T message;
+
+ public MessageWithId(String creationId, T message) {
+ this.creationId = creationId;
+ this.message = message;
+ }
+
+ public String getCreationId() {
+ return creationId;
+ }
+
+ public T getMessage() {
+ return message;
+ }
+
+ public static class CreationMessageEntry extends MessageWithId<CreationMessage> {
+ public CreationMessageEntry(String creationId, CreationMessage message) {
+ super(creationId, message);
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/james-project/blob/99ac325d/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
new file mode 100644
index 0000000..3cb11db
--- /dev/null
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/SetMessagesCreationProcessor.java
@@ -0,0 +1,174 @@
+/****************************************************************
+ * 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.methods;
+
+import java.util.Date;
+import java.util.Optional;
+import java.util.function.Function;
+
+import javax.inject.Inject;
+import javax.mail.Flags;
+import javax.mail.internet.SharedInputStream;
+import javax.mail.util.SharedByteArrayInputStream;
+
+import org.apache.james.jmap.exceptions.MailboxRoleNotFoundException;
+import org.apache.james.jmap.model.CreationMessage;
+import org.apache.james.jmap.model.Message;
+import org.apache.james.jmap.model.MessageId;
+import org.apache.james.jmap.model.SetMessagesRequest;
+import org.apache.james.jmap.model.SetMessagesResponse;
+import org.apache.james.jmap.model.mailbox.Role;
+import org.apache.james.mailbox.MailboxManager;
+import org.apache.james.mailbox.MailboxSession;
+import org.apache.james.mailbox.exception.MailboxException;
+import org.apache.james.mailbox.model.MailboxMetaData;
+import org.apache.james.mailbox.model.MailboxPath;
+import org.apache.james.mailbox.model.MailboxQuery;
+import org.apache.james.mailbox.store.MailboxSessionMapperFactory;
+import org.apache.james.mailbox.store.mail.MailboxMapperFactory;
+import org.apache.james.mailbox.store.mail.MessageMapper;
+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.impl.PropertyBuilder;
+import org.apache.james.mailbox.store.mail.model.impl.SimpleMailboxMessage;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.github.fge.lambdas.functions.ThrowingFunction;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Throwables;
+import com.google.common.collect.ImmutableMap;
+
+public class SetMessagesCreationProcessor<Id extends MailboxId> implements SetMessagesProcessor<Id> {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(SetMessagesCreationProcessor.class);
+
+ private final MailboxMapperFactory<Id> mailboxMapperFactory;
+ private final MailboxManager mailboxManager;
+ private final MailboxSessionMapperFactory<Id> mailboxSessionMapperFactory;
+ private final MIMEMessageConverter mimeMessageConverter;
+
+ @Inject
+ @VisibleForTesting
+ SetMessagesCreationProcessor(MailboxMapperFactory<Id> mailboxMapperFactory,
+ MailboxManager mailboxManager,
+ MailboxSessionMapperFactory<Id> mailboxSessionMapperFactory, MIMEMessageConverter mimeMessageConverter) {
+ this.mailboxMapperFactory = mailboxMapperFactory;
+ this.mailboxManager = mailboxManager;
+ this.mailboxSessionMapperFactory = mailboxSessionMapperFactory;
+ this.mimeMessageConverter = mimeMessageConverter;
+ }
+
+ @Override
+ public SetMessagesResponse process(SetMessagesRequest request, MailboxSession mailboxSession) {
+ Mailbox<Id> outbox;
+ try {
+ outbox = getOutbox(mailboxSession).orElseThrow(() -> new MailboxRoleNotFoundException(Role.OUTBOX));
+ } catch (MailboxException | MailboxRoleNotFoundException e) {
+ LOGGER.error("Unable to find a mailbox with role 'outbox'!");
+ throw Throwables.propagate(e);
+ }
+ return request.getCreate().entrySet().stream()
+ .map(e -> new MessageWithId.CreationMessageEntry(e.getKey(), e.getValue()))
+ .map(nuMsg -> createMessageInOutbox(nuMsg, mailboxSession, outbox, buildMessageIdFunc(mailboxSession, outbox)))
+ .map(msg -> SetMessagesResponse.builder().created(ImmutableMap.of(msg.getCreationId(), msg.getMessage())).build())
+ .reduce(SetMessagesResponse.builder(), SetMessagesResponse.Builder::accumulator, SetMessagesResponse.Builder::combiner)
+ .build();
+ }
+
+ @VisibleForTesting
+ protected MessageWithId<Message> createMessageInOutbox(MessageWithId.CreationMessageEntry createdEntry,
+ MailboxSession session,
+ Mailbox<Id> outbox, Function<Long, MessageId> buildMessageIdFromUid) {
+ try {
+ MessageMapper<Id> messageMapper = mailboxSessionMapperFactory.createMessageMapper(session);
+ MailboxMessage<Id> newMailboxMessage = buildMailboxMessage(createdEntry, outbox);
+ messageMapper.add(outbox, newMailboxMessage);
+ return new MessageWithId<>(createdEntry.getCreationId(), Message.fromMailboxMessage(newMailboxMessage, buildMessageIdFromUid));
+ } catch (MailboxException e) {
+ throw Throwables.propagate(e);
+ } catch (MailboxRoleNotFoundException e) {
+ LOGGER.error("Could not find mailbox '%s' while trying to save message.", e.getRole().serialize());
+ throw Throwables.propagate(e);
+ }
+ }
+
+ private Function<Long, MessageId> buildMessageIdFunc(MailboxSession session, Mailbox<Id> outbox) {
+ MailboxPath outboxPath = new MailboxPath(session.getPersonalSpace(), session.getUser().getUserName(), outbox.getName());
+ return uid -> new MessageId(session.getUser(), outboxPath, uid);
+ }
+
+ private MailboxMessage<Id> buildMailboxMessage(MessageWithId.CreationMessageEntry createdEntry, Mailbox<Id> outbox) {
+ byte[] messageContent = mimeMessageConverter.convert(createdEntry);
+ SharedInputStream content = new SharedByteArrayInputStream(messageContent);
+ long size = messageContent.length;
+ int bodyStartOctet = 0;
+
+ Flags flags = getMessageFlags(createdEntry.getMessage());
+ PropertyBuilder propertyBuilder = buildPropertyBuilder();
+ Id mailboxId = outbox.getMailboxId();
+ Date internalDate = Date.from(createdEntry.getMessage().getDate().toInstant());
+
+ return new SimpleMailboxMessage<>(internalDate, size,
+ bodyStartOctet, content, flags, propertyBuilder, mailboxId);
+ }
+
+ @VisibleForTesting
+ protected Optional<Mailbox<Id>> getOutbox(MailboxSession session) throws MailboxException {
+ return mailboxManager.search(MailboxQuery.builder(session)
+ .privateUserMailboxes().build(), session).stream()
+ .map(MailboxMetaData::getPath)
+ .filter(this::hasRoleOutbox)
+ .map(loadMailbox(session))
+ .findFirst();
+ }
+
+ private boolean hasRoleOutbox(MailboxPath mailBoxPath) {
+ return Role.from(mailBoxPath.getName())
+ .map(Role.OUTBOX::equals)
+ .orElse(false);
+ }
+
+ private ThrowingFunction<MailboxPath, Mailbox<Id>> loadMailbox(MailboxSession session) {
+ return path -> mailboxMapperFactory.getMailboxMapper(session).findMailboxByPath(path);
+ }
+
+ private PropertyBuilder buildPropertyBuilder() {
+ return new PropertyBuilder();
+ }
+
+ private Flags getMessageFlags(CreationMessage message) {
+ Flags result = new Flags();
+ if (!message.isIsUnread()) {
+ result.add(Flags.Flag.SEEN);
+ }
+ if (message.isIsFlagged()) {
+ result.add(Flags.Flag.FLAGGED);
+ }
+ if (message.isIsAnswered() || message.getInReplyToMessageId().isPresent()) {
+ result.add(Flags.Flag.ANSWERED);
+ }
+ if (message.isIsDraft()) {
+ result.add(Flags.Flag.DRAFT);
+ }
+ return result;
+ }
+}
http://git-wip-us.apache.org/repos/asf/james-project/blob/99ac325d/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/SetMessagesMethod.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/SetMessagesMethod.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/SetMessagesMethod.java
index f14cdba..5202026 100644
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/SetMessagesMethod.java
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/SetMessagesMethod.java
@@ -56,13 +56,17 @@ public class SetMessagesMethod<Id extends MailboxId> implements Method {
private final MailboxMapperFactory<Id> mailboxMapperFactory;
private final MailboxSessionMapperFactory<Id> mailboxSessionMapperFactory;
private final SetMessagesUpdateProcessor<Id> messageUpdater;
+ private final SetMessagesCreationProcessor messageCreator;
@Inject
@VisibleForTesting SetMessagesMethod(MailboxMapperFactory<Id> mailboxMapperFactory,
- MailboxSessionMapperFactory<Id> mailboxSessionMapperFactory, SetMessagesUpdateProcessor<Id> messageUpdater) {
+ MailboxSessionMapperFactory<Id> mailboxSessionMapperFactory,
+ SetMessagesUpdateProcessor<Id> messageUpdater,
+ SetMessagesCreationProcessor messageCreator) {
this.mailboxMapperFactory = mailboxMapperFactory;
this.mailboxSessionMapperFactory = mailboxSessionMapperFactory;
this.messageUpdater = messageUpdater;
+ this.messageCreator = messageCreator;
}
@Override
@@ -95,7 +99,8 @@ public class SetMessagesMethod<Id extends MailboxId> implements Method {
private SetMessagesResponse setMessagesResponse(SetMessagesRequest request, MailboxSession mailboxSession) throws MailboxException {
SetMessagesResponse.Builder responseBuilder = SetMessagesResponse.builder();
processDestroy(request.getDestroy(), mailboxSession, responseBuilder);
- messageUpdater.processUpdates(request, mailboxSession).mergeInto(responseBuilder);
+ messageUpdater.process(request, mailboxSession).mergeInto(responseBuilder);
+ messageCreator.process(request, mailboxSession).mergeInto(responseBuilder);
return responseBuilder.build();
}
http://git-wip-us.apache.org/repos/asf/james-project/blob/99ac325d/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/SetMessagesProcessor.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/SetMessagesProcessor.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/SetMessagesProcessor.java
new file mode 100644
index 0000000..4c7e00d
--- /dev/null
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/SetMessagesProcessor.java
@@ -0,0 +1,29 @@
+/****************************************************************
+ * 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.methods;
+
+import org.apache.james.jmap.model.SetMessagesRequest;
+import org.apache.james.jmap.model.SetMessagesResponse;
+import org.apache.james.mailbox.MailboxSession;
+import org.apache.james.mailbox.store.mail.model.MailboxId;
+
+public interface SetMessagesProcessor<Id extends MailboxId> {
+ SetMessagesResponse process(SetMessagesRequest request, MailboxSession mailboxSession);
+}
http://git-wip-us.apache.org/repos/asf/james-project/blob/99ac325d/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/SetMessagesUpdateProcessor.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/SetMessagesUpdateProcessor.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/SetMessagesUpdateProcessor.java
index f62e390..ed7e219 100644
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/SetMessagesUpdateProcessor.java
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/SetMessagesUpdateProcessor.java
@@ -52,7 +52,7 @@ import com.google.common.collect.ImmutableSet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-public class SetMessagesUpdateProcessor<Id extends MailboxId> {
+public class SetMessagesUpdateProcessor<Id extends MailboxId> implements SetMessagesProcessor<Id> {
private static final int LIMIT_BY_ONE = 1;
private static final Logger LOGGER = LoggerFactory.getLogger(SetMessagesUpdateProcessor.class);
@@ -71,7 +71,7 @@ public class SetMessagesUpdateProcessor<Id extends MailboxId> {
this.mailboxSessionMapperFactory = mailboxSessionMapperFactory;
}
- public SetMessagesResponse processUpdates(SetMessagesRequest request, MailboxSession mailboxSession) {
+ public SetMessagesResponse process(SetMessagesRequest request, MailboxSession mailboxSession) {
SetMessagesResponse.Builder responseBuilder = SetMessagesResponse.builder();
request.buildUpdatePatches(updatePatchConverter).forEach( (id, patch) -> {
if (patch.isValid()) {
http://git-wip-us.apache.org/repos/asf/james-project/blob/99ac325d/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
new file mode 100644
index 0000000..697c9c7
--- /dev/null
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/CreationMessage.java
@@ -0,0 +1,305 @@
+/****************************************************************
+ * 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.time.ZonedDateTime;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+import org.apache.james.jmap.methods.GetMessagesMethod;
+import org.apache.james.jmap.methods.JmapResponseWriterImpl;
+
+import com.fasterxml.jackson.annotation.JsonFilter;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Strings;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+
+@JsonDeserialize(builder = CreationMessage.Builder.class)
+public class CreationMessage {
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ @JsonPOJOBuilder(withPrefix = "")
+ public static class Builder {
+ private ImmutableList<String> mailboxIds;
+ private String inReplyToMessageId;
+ private boolean isUnread;
+ private boolean isFlagged;
+ private boolean isAnswered;
+ private boolean isDraft;
+ private final ImmutableMap.Builder<String, String> headers;
+ private Emailer from;
+ private final ImmutableList.Builder<Emailer> to;
+ private final ImmutableList.Builder<Emailer> cc;
+ private final ImmutableList.Builder<Emailer> bcc;
+ private final ImmutableList.Builder<Emailer> replyTo;
+ private String subject;
+ private ZonedDateTime date;
+ private String textBody;
+ private String htmlBody;
+ private final ImmutableList.Builder<Attachment> attachments;
+ private final ImmutableMap.Builder<String, SubMessage> attachedMessages;
+
+ private Builder() {
+ to = ImmutableList.builder();
+ cc = ImmutableList.builder();
+ bcc = ImmutableList.builder();
+ replyTo = ImmutableList.builder();
+ attachments = ImmutableList.builder();
+ attachedMessages = ImmutableMap.builder();
+ headers = ImmutableMap.builder();
+ }
+
+ public Builder mailboxIds(ImmutableList<String> mailboxIds) {
+ this.mailboxIds = mailboxIds;
+ return this;
+ }
+
+ public Builder inReplyToMessageId(String inReplyToMessageId) {
+ this.inReplyToMessageId = inReplyToMessageId;
+ return this;
+ }
+
+ public Builder isUnread(boolean isUnread) {
+ this.isUnread = isUnread;
+ return this;
+ }
+
+ public Builder isFlagged(boolean isFlagged) {
+ this.isFlagged = isFlagged;
+ return this;
+ }
+
+ public Builder isAnswered(boolean isAnswered) {
+ this.isAnswered = isAnswered;
+ return this;
+ }
+
+ public Builder isDraft(boolean isDraft) {
+ this.isDraft = isDraft;
+ return this;
+ }
+
+ public Builder headers(ImmutableMap<String, String> headers) {
+ this.headers.putAll(headers);
+ return this;
+ }
+
+ public Builder from(Emailer from) {
+ this.from = from;
+ return this;
+ }
+
+ public Builder to(List<Emailer> to) {
+ this.to.addAll(to);
+ return this;
+ }
+
+ public Builder cc(List<Emailer> cc) {
+ this.cc.addAll(cc);
+ return this;
+ }
+
+ public Builder bcc(List<Emailer> bcc) {
+ this.bcc.addAll(bcc);
+ return this;
+ }
+
+ public Builder replyTo(List<Emailer> replyTo) {
+ this.replyTo.addAll(replyTo);
+ return this;
+ }
+
+ public Builder subject(String subject) {
+ this.subject = subject;
+ return this;
+ }
+
+ public Builder date(ZonedDateTime date) {
+ this.date = date;
+ return this;
+ }
+
+ public Builder textBody(String textBody) {
+ this.textBody = textBody;
+ return this;
+ }
+
+ public Builder htmlBody(String htmlBody) {
+ this.htmlBody = htmlBody;
+ return this;
+ }
+
+ public Builder attachments(List<Attachment> attachments) {
+ this.attachments.addAll(attachments);
+ return this;
+ }
+
+ public Builder attachedMessages(Map<String, SubMessage> attachedMessages) {
+ this.attachedMessages.putAll(attachedMessages);
+ return this;
+ }
+
+ private static boolean areAttachedMessagesKeysInAttachments(ImmutableList<Attachment> attachments, ImmutableMap<String, SubMessage> attachedMessages) {
+ return attachments.stream()
+ .map(Attachment::getBlobId)
+ .allMatch(attachedMessages::containsKey);
+ }
+
+ public CreationMessage build() {
+ Preconditions.checkState(mailboxIds != null, "'mailboxIds' is mandatory");
+ Preconditions.checkState(headers != null, "'headers' is mandatory");
+ Preconditions.checkState(!Strings.isNullOrEmpty(subject), "'subject' is mandatory");
+ ImmutableList<Attachment> attachments = this.attachments.build();
+ ImmutableMap<String, SubMessage> attachedMessages = this.attachedMessages.build();
+ Preconditions.checkState(areAttachedMessagesKeysInAttachments(attachments, attachedMessages), "'attachedMessages' keys must be in 'attachments'");
+
+ if (date == null) {
+ date = ZonedDateTime.now();
+ }
+
+ return new CreationMessage(mailboxIds, Optional.ofNullable(inReplyToMessageId), isUnread, isFlagged, isAnswered, isDraft, headers.build(), Optional.ofNullable(from),
+ to.build(), cc.build(), bcc.build(), replyTo.build(), subject, date, Optional.ofNullable(textBody), Optional.ofNullable(htmlBody), attachments, attachedMessages);
+ }
+ }
+
+ private final ImmutableList<String> mailboxIds;
+ private final Optional<String> inReplyToMessageId;
+ private final boolean isUnread;
+ private final boolean isFlagged;
+ private final boolean isAnswered;
+ private final boolean isDraft;
+ private final ImmutableMap<String, String> headers;
+ private final Optional<Emailer> from;
+ private final ImmutableList<Emailer> to;
+ private final ImmutableList<Emailer> cc;
+ private final ImmutableList<Emailer> bcc;
+ private final ImmutableList<Emailer> replyTo;
+ private final String subject;
+ private final ZonedDateTime date;
+ private final Optional<String> textBody;
+ private final Optional<String> htmlBody;
+ private final ImmutableList<Attachment> attachments;
+ private final ImmutableMap<String, SubMessage> attachedMessages;
+
+ @VisibleForTesting
+ CreationMessage(ImmutableList<String> mailboxIds, Optional<String> inReplyToMessageId, boolean isUnread, boolean isFlagged, boolean isAnswered, boolean isDraft, 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) {
+ this.mailboxIds = mailboxIds;
+ this.inReplyToMessageId = inReplyToMessageId;
+ this.isUnread = isUnread;
+ this.isFlagged = isFlagged;
+ this.isAnswered = isAnswered;
+ this.isDraft = isDraft;
+ this.headers = headers;
+ this.from = from;
+ this.to = to;
+ this.cc = cc;
+ this.bcc = bcc;
+ this.replyTo = replyTo;
+ this.subject = subject;
+ this.date = date;
+ this.textBody = textBody;
+ this.htmlBody = htmlBody;
+ this.attachments = attachments;
+ this.attachedMessages = attachedMessages;
+ }
+
+ public ImmutableList<String> getMailboxIds() {
+ return mailboxIds;
+ }
+
+ public Optional<String> getInReplyToMessageId() {
+ return inReplyToMessageId;
+ }
+
+ public boolean isIsUnread() {
+ return isUnread;
+ }
+
+ public boolean isIsFlagged() {
+ return isFlagged;
+ }
+
+ public boolean isIsAnswered() {
+ return isAnswered;
+ }
+
+ public boolean isIsDraft() {
+ return isDraft;
+ }
+
+ public ImmutableMap<String, String> getHeaders() {
+ return headers;
+ }
+
+ public Optional<Emailer> getFrom() {
+ return from;
+ }
+
+ public ImmutableList<Emailer> getTo() {
+ return to;
+ }
+
+ public ImmutableList<Emailer> getCc() {
+ return cc;
+ }
+
+ public ImmutableList<Emailer> getBcc() {
+ return bcc;
+ }
+
+ public ImmutableList<Emailer> getReplyTo() {
+ return replyTo;
+ }
+
+ public String getSubject() {
+ return subject;
+ }
+
+ public ZonedDateTime getDate() {
+ return date;
+ }
+
+ public Optional<String> getTextBody() {
+ return textBody;
+ }
+
+ public Optional<String> getHtmlBody() {
+ return htmlBody;
+ }
+
+ public ImmutableList<Attachment> getAttachments() {
+ return attachments;
+ }
+
+ public ImmutableMap<String, SubMessage> getAttachedMessages() {
+ return attachedMessages;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/james-project/blob/99ac325d/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetMessagesRequest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetMessagesRequest.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetMessagesRequest.java
index aadb886..8e25ac5 100644
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetMessagesRequest.java
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetMessagesRequest.java
@@ -48,7 +48,7 @@ public class SetMessagesRequest implements JmapRequest {
private String accountId;
private String ifInState;
- private ImmutableMap.Builder<MessageId, Message> create;
+ private ImmutableMap.Builder<String, CreationMessage> create;
private ImmutableMap.Builder<MessageId, Function<UpdateMessagePatchConverter, UpdateMessagePatch>> updatesProvider;
private ImmutableList.Builder<MessageId> destroy;
@@ -73,8 +73,8 @@ public class SetMessagesRequest implements JmapRequest {
return this;
}
- public Builder create(Map<MessageId, Message> creates) {
- this.create.putAll(creates);
+ public Builder create(Map<String, CreationMessage> creations) {
+ this.create.putAll(creations);
return this;
}
@@ -95,11 +95,11 @@ public class SetMessagesRequest implements JmapRequest {
private final Optional<String> accountId;
private final Optional<String> ifInState;
- private final Map<MessageId, Message> create;
+ private final Map<String, CreationMessage> create;
private final Map<MessageId, Function<UpdateMessagePatchConverter, UpdateMessagePatch>> update;
private final List<MessageId> destroy;
- @VisibleForTesting SetMessagesRequest(Optional<String> accountId, Optional<String> ifInState, Map<MessageId, Message> create, Map<MessageId, Function<UpdateMessagePatchConverter, UpdateMessagePatch>> update, List<MessageId> destroy) {
+ @VisibleForTesting SetMessagesRequest(Optional<String> accountId, Optional<String> ifInState, Map<String, CreationMessage> create, Map<MessageId, Function<UpdateMessagePatchConverter, UpdateMessagePatch>> update, List<MessageId> destroy) {
this.accountId = accountId;
this.ifInState = ifInState;
this.create = create;
@@ -115,7 +115,7 @@ public class SetMessagesRequest implements JmapRequest {
return ifInState;
}
- public Map<MessageId, Message> getCreate() {
+ public Map<String, CreationMessage> getCreate() {
return create;
}
http://git-wip-us.apache.org/repos/asf/james-project/blob/99ac325d/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetMessagesResponse.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetMessagesResponse.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetMessagesResponse.java
index 304f8c3..c096c8a 100644
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetMessagesResponse.java
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetMessagesResponse.java
@@ -20,9 +20,11 @@ package org.apache.james.jmap.model;
import java.util.List;
import java.util.Map;
+import java.util.function.BiFunction;
import com.google.common.base.Strings;
import org.apache.commons.lang.NotImplementedException;
+import org.apache.james.jmap.methods.MessageWithId;
import org.apache.james.jmap.methods.Method;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
@@ -42,10 +44,18 @@ public class SetMessagesResponse implements Method.Response {
@JsonPOJOBuilder(withPrefix = "")
public static class Builder {
+ public static Builder accumulator(Builder accumulator, SetMessagesResponse response) {
+ return response.mergeInto(accumulator);
+ }
+
+ public static Builder combiner(Builder firstBuilder, Builder secondBuilder) {
+ return secondBuilder.build().mergeInto(firstBuilder);
+ }
+
private String accountId;
private String oldState;
private String newState;
- private ImmutableList.Builder<Message> created;
+ private ImmutableMap.Builder<String, Message> created;
private ImmutableList.Builder<MessageId> updated;
private ImmutableList.Builder<MessageId> destroyed;
private ImmutableMap.Builder<MessageId, SetError> notCreated;
@@ -53,7 +63,7 @@ public class SetMessagesResponse implements Method.Response {
private ImmutableMap.Builder<MessageId, SetError> notDestroyed;
private Builder() {
- created = ImmutableList.builder();
+ created = ImmutableMap.builder();
updated = ImmutableList.builder();
destroyed = ImmutableList.builder();
notCreated = ImmutableMap.builder();
@@ -73,8 +83,8 @@ public class SetMessagesResponse implements Method.Response {
throw new NotImplementedException();
}
- public Builder created(List<Message> created) {
- this.created.addAll(created);
+ public Builder created(Map<String, Message> created) {
+ this.created.putAll(created);
return this;
}
@@ -122,14 +132,14 @@ public class SetMessagesResponse implements Method.Response {
private final String accountId;
private final String oldState;
private final String newState;
- private final List<Message> created;
+ private final Map<String, Message> created;
private final List<MessageId> updated;
private final List<MessageId> destroyed;
private final Map<MessageId, SetError> notCreated;
private final Map<MessageId, SetError> notUpdated;
private final Map<MessageId, SetError> notDestroyed;
- @VisibleForTesting SetMessagesResponse(String accountId, String oldState, String newState, List<Message> created, List<MessageId> updated, List<MessageId> destroyed,
+ @VisibleForTesting SetMessagesResponse(String accountId, String oldState, String newState, Map<String, Message> created, List<MessageId> updated, List<MessageId> destroyed,
Map<MessageId, SetError> notCreated, Map<MessageId, SetError> notUpdated, Map<MessageId, SetError> notDestroyed) {
this.accountId = accountId;
this.oldState = oldState;
@@ -158,7 +168,7 @@ public class SetMessagesResponse implements Method.Response {
}
@JsonSerialize
- public List<Message> getCreated() {
+ public Map<String, Message> getCreated() {
return created;
}
@@ -187,7 +197,7 @@ public class SetMessagesResponse implements Method.Response {
return notDestroyed;
}
- public void mergeInto(SetMessagesResponse.Builder responseBuilder) {
+ public SetMessagesResponse.Builder mergeInto(SetMessagesResponse.Builder responseBuilder) {
responseBuilder.created(getCreated());
responseBuilder.updated(getUpdated());
responseBuilder.destroyed(getDestroyed());
@@ -203,5 +213,6 @@ public class SetMessagesResponse implements Method.Response {
if(! Strings.isNullOrEmpty(getNewState())) {
responseBuilder.accountId(getAccountId());
}
+ return responseBuilder;
}
}
http://git-wip-us.apache.org/repos/asf/james-project/blob/99ac325d/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
new file mode 100644
index 0000000..0b73ee2
--- /dev/null
+++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/methods/SetMessagesCreationProcessorTest.java
@@ -0,0 +1,131 @@
+/****************************************************************
+ * 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.methods;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.time.ZonedDateTime;
+import java.util.Optional;
+import java.util.function.Function;
+
+import org.apache.james.jmap.model.CreationMessage;
+import org.apache.james.jmap.model.Emailer;
+import org.apache.james.jmap.model.Message;
+import org.apache.james.jmap.model.MessageId;
+import org.apache.james.jmap.model.SetMessagesRequest;
+import org.apache.james.jmap.model.SetMessagesResponse;
+import org.apache.james.mailbox.MailboxSession;
+import org.apache.james.mailbox.exception.MailboxException;
+import org.apache.james.mailbox.store.MailboxSessionMapperFactory;
+import org.apache.james.mailbox.store.mail.MessageMapper;
+import org.apache.james.mailbox.store.mail.model.Mailbox;
+import org.apache.james.mailbox.store.mail.model.MailboxId;
+import org.junit.Test;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+
+public class SetMessagesCreationProcessorTest {
+
+ @Test
+ @SuppressWarnings("unchecked")
+ public void processShouldReturnEmptyCreatedWhenRequestHasEmptyCreate() {
+ SetMessagesCreationProcessor<MailboxId> sut = new SetMessagesCreationProcessor<MailboxId>(null, null, null, null) {
+ @Override
+ protected Optional<Mailbox<MailboxId>> getOutbox(MailboxSession session) throws MailboxException {
+ Mailbox<MailboxId> fakeOutbox = mock(Mailbox.class);
+ when(fakeOutbox.getName()).thenReturn("outbox");
+ return Optional.of(fakeOutbox);
+ }
+ };
+ SetMessagesRequest requestWithEmptyCreate = SetMessagesRequest.builder().build();
+
+ SetMessagesResponse result = sut.process(requestWithEmptyCreate, buildStubbedSession());
+
+ assertThat(result.getCreated()).isEmpty();
+ assertThat(result.getNotCreated()).isEmpty();
+ }
+
+ private MailboxSession buildStubbedSession() {
+ MailboxSession.User stubUser = mock(MailboxSession.User.class);
+ when(stubUser.getUserName()).thenReturn("user");
+ MailboxSession stubSession = mock(MailboxSession.class);
+ when(stubSession.getPathDelimiter()).thenReturn('.');
+ when(stubSession.getUser()).thenReturn(stubUser);
+ when(stubSession.getPersonalSpace()).thenReturn("#private");
+ return stubSession;
+ }
+
+ @Test
+ @SuppressWarnings("unchecked")
+ public void processShouldReturnNonEmptyCreatedWhenRequestHasNonEmptyCreate() throws MailboxException {
+
+ MessageMapper<MailboxId> stubMapper = mock(MessageMapper.class);
+ MailboxSessionMapperFactory<MailboxId> mockSessionMapperFactory = mock(MailboxSessionMapperFactory.class);
+ when(mockSessionMapperFactory.createMessageMapper(any(MailboxSession.class)))
+ .thenReturn(stubMapper);
+
+ SetMessagesCreationProcessor<MailboxId> sut = new SetMessagesCreationProcessor<MailboxId>(null, null, mockSessionMapperFactory, null) {
+ @Override
+ protected MessageWithId<Message> createMessageInOutbox(MessageWithId.CreationMessageEntry createdEntry, MailboxSession session, Mailbox<MailboxId> outbox, Function<Long, MessageId> buildMessageIdFromUid) {
+ return new MessageWithId<>(createdEntry.creationId, getFakeMessage());
+ }
+ @Override
+ protected Optional<Mailbox<MailboxId>> getOutbox(MailboxSession session) throws MailboxException {
+ Mailbox<MailboxId> fakeOutbox = mock(Mailbox.class);
+ when(fakeOutbox.getName()).thenReturn("outbox");
+ return Optional.of(fakeOutbox);
+ }
+ };
+
+ SetMessagesRequest creationRequest = SetMessagesRequest.builder()
+ .create(ImmutableMap.of("anything-really", CreationMessage.builder()
+ .from(Emailer.builder().name("alice").email("alice@example.com").build())
+ .to(ImmutableList.of(Emailer.builder().name("bob").email("bob@example.com").build()))
+ .subject("Hey! ")
+ .mailboxIds(ImmutableList.of("mailboxId"))
+ .build()
+ ))
+ .build()
+ ;
+
+ SetMessagesResponse result = sut.process(creationRequest, buildStubbedSession());
+
+ assertThat(result.getCreated()).isNotEmpty();
+ assertThat(result.getNotCreated()).isEmpty();
+ }
+
+ private Message getFakeMessage() {
+ return Message.builder()
+ .id(org.apache.james.jmap.model.MessageId.of("user|outbox|1"))
+ .blobId("anything")
+ .threadId("anything")
+ .mailboxIds(ImmutableList.of("mailboxId"))
+ .headers(ImmutableMap.of())
+ .subject("anything")
+ .size(0)
+ .date(ZonedDateTime.now())
+ .preview("anything")
+ .build();
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/james-project/blob/99ac325d/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 e2bc7c7..9877651 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
@@ -55,7 +55,7 @@ public class SetMessagesResponseTest {
@Test
public void builderShouldWork() {
ZonedDateTime currentDate = ZonedDateTime.now();
- ImmutableList<Message> created = ImmutableList.of(
+ ImmutableMap<String, Message> created = ImmutableMap.of("user|created|1",
Message.builder()
.id(MessageId.of("user|created|1"))
.blobId("blobId")
@@ -105,8 +105,8 @@ public class SetMessagesResponseTest {
assertThat(emptyBuilder.build()).isEqualToComparingFieldByField(testee);
}
- private ImmutableList<Message> buildMessage(String messageId) {
- return ImmutableList.of(Message.builder()
+ private ImmutableMap<String, Message> buildMessage(String messageId) {
+ return ImmutableMap.of(messageId, Message.builder()
.id(MessageId.of(messageId))
.blobId("blobId")
.threadId("threadId")
@@ -152,10 +152,7 @@ public class SetMessagesResponseTest {
SetMessagesResponse mergedResponse = nonEmptyBuilder.build();
// Then
- List<String> createdMessageIds = mergedResponse.getCreated().stream()
- .map(m -> m.getId().serialize())
- .collect(Collectors.toList());
- assertThat(createdMessageIds).containsExactly(buildersCreatedMessageId, createdMessageId);
+ assertThat(mergedResponse.getCreated().keySet()).containsExactly(buildersCreatedMessageId, createdMessageId);
}
@Test
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org
[9/9] james-project git commit: JAMES-1692 Send the message throw the
MailSpool
Posted by ad...@apache.org.
JAMES-1692 Send the message throw the MailSpool
Project: http://git-wip-us.apache.org/repos/asf/james-project/repo
Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/3b09ad75
Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/3b09ad75
Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/3b09ad75
Branch: refs/heads/master
Commit: 3b09ad7534457312572a65d1bd6e61956d8b85ec
Parents: 8174cb7
Author: Raphael Ouazana <ra...@linagora.com>
Authored: Fri Feb 26 09:28:44 2016 +0100
Committer: Raphael Ouazana <ra...@linagora.com>
Committed: Tue Mar 1 15:46:32 2016 +0100
----------------------------------------------------------------------
.../org/apache/james/jmap/JMAPCommonModule.java | 2 +
.../methods/SetMessagesCreationProcessor.java | 33 ++++--
.../org/apache/james/jmap/send/MailFactory.java | 78 +++++++++++++++
.../SetMessagesCreationProcessorTest.java | 48 +++++++--
.../apache/james/jmap/send/MailFactoryTest.java | 100 +++++++++++++++++++
5 files changed, 248 insertions(+), 13 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/james-project/blob/3b09ad75/server/container/cassandra-guice/src/main/java/org/apache/james/jmap/JMAPCommonModule.java
----------------------------------------------------------------------
diff --git a/server/container/cassandra-guice/src/main/java/org/apache/james/jmap/JMAPCommonModule.java b/server/container/cassandra-guice/src/main/java/org/apache/james/jmap/JMAPCommonModule.java
index 14c2d9f..d2ad4b0 100644
--- a/server/container/cassandra-guice/src/main/java/org/apache/james/jmap/JMAPCommonModule.java
+++ b/server/container/cassandra-guice/src/main/java/org/apache/james/jmap/JMAPCommonModule.java
@@ -29,6 +29,7 @@ import org.apache.james.jmap.crypto.JamesSignatureHandler;
import org.apache.james.jmap.crypto.SignatureHandler;
import org.apache.james.jmap.crypto.SignedContinuationTokenManager;
import org.apache.james.jmap.memory.access.MemoryAccessTokenRepository;
+import org.apache.james.jmap.send.MailFactory;
import org.apache.james.jmap.send.MailSpool;
import org.apache.james.jmap.utils.DefaultZonedDateTimeProvider;
import org.apache.james.jmap.utils.ZonedDateTimeProvider;
@@ -54,6 +55,7 @@ public class JMAPCommonModule extends AbstractModule {
bind(AccessTokenManager.class).to(AccessTokenManagerImpl.class);
bind(MailSpool.class).in(Singleton.class);
+ bind(MailFactory.class).in(Singleton.class);
}
@Provides
http://git-wip-us.apache.org/repos/asf/james-project/blob/3b09ad75/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 718734d..da871a2 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
@@ -19,8 +19,7 @@
package org.apache.james.jmap.methods;
-import static org.apache.james.jmap.model.MessageProperties.MessageProperty;
-
+import java.io.IOException;
import java.util.AbstractMap;
import java.util.Date;
import java.util.List;
@@ -33,6 +32,7 @@ import java.util.stream.Collectors;
import javax.inject.Inject;
import javax.mail.Flags;
+import javax.mail.MessagingException;
import javax.mail.internet.SharedInputStream;
import javax.mail.util.SharedByteArrayInputStream;
@@ -42,10 +42,14 @@ import org.apache.james.jmap.model.CreationMessageId;
import org.apache.james.jmap.model.Message;
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.SetMessagesRequest;
import org.apache.james.jmap.model.SetMessagesResponse;
import org.apache.james.jmap.model.mailbox.Role;
+import org.apache.james.jmap.send.MailFactory;
+import org.apache.james.jmap.send.MailMetadata;
+import org.apache.james.jmap.send.MailSpool;
import org.apache.james.mailbox.MailboxManager;
import org.apache.james.mailbox.MailboxSession;
import org.apache.james.mailbox.exception.MailboxException;
@@ -60,6 +64,7 @@ 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.impl.PropertyBuilder;
import org.apache.james.mailbox.store.mail.model.impl.SimpleMailboxMessage;
+import org.apache.mailet.Mail;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -77,17 +82,23 @@ public class SetMessagesCreationProcessor<Id extends MailboxId> implements SetMe
private final MailboxManager mailboxManager;
private final MailboxSessionMapperFactory<Id> mailboxSessionMapperFactory;
private final MIMEMessageConverter mimeMessageConverter;
+ private final MailSpool mailSpool;
+ private final MailFactory<Id> mailFactory;
@Inject
@VisibleForTesting
SetMessagesCreationProcessor(MailboxMapperFactory<Id> mailboxMapperFactory,
MailboxManager mailboxManager,
MailboxSessionMapperFactory<Id> mailboxSessionMapperFactory,
- MIMEMessageConverter mimeMessageConverter) {
+ MIMEMessageConverter mimeMessageConverter,
+ MailSpool mailSpool,
+ MailFactory<Id> mailFactory) {
this.mailboxMapperFactory = mailboxMapperFactory;
this.mailboxManager = mailboxManager;
this.mailboxSessionMapperFactory = mailboxSessionMapperFactory;
this.mimeMessageConverter = mimeMessageConverter;
+ this.mailSpool = mailSpool;
+ this.mailFactory = mailFactory;
}
@Override
@@ -109,7 +120,7 @@ public class SetMessagesCreationProcessor<Id extends MailboxId> implements SetMe
return request.getCreate().entrySet().stream()
.filter(e -> validMessagesTester.test(e.getValue()))
.map(e -> new MessageWithId.CreationMessageEntry(e.getKey(), e.getValue()))
- .map(nuMsg -> createMessageInOutbox(nuMsg, mailboxSession, outbox, buildMessageIdFunc(mailboxSession, outbox)))
+ .map(nuMsg -> createMessageInOutboxAndSend(nuMsg, mailboxSession, outbox, buildMessageIdFunc(mailboxSession, outbox)))
.map(msg -> SetMessagesResponse.builder().created(ImmutableMap.of(msg.getCreationId(), msg.getMessage())).build())
.reduce(responseBuilder, SetMessagesResponse.Builder::accumulator, SetMessagesResponse.Builder::combiner)
.build();
@@ -140,15 +151,17 @@ public class SetMessagesCreationProcessor<Id extends MailboxId> implements SetMe
}
@VisibleForTesting
- protected MessageWithId<Message> createMessageInOutbox(MessageWithId.CreationMessageEntry createdEntry,
+ protected MessageWithId<Message> createMessageInOutboxAndSend(MessageWithId.CreationMessageEntry createdEntry,
MailboxSession session,
Mailbox<Id> outbox, Function<Long, MessageId> buildMessageIdFromUid) {
try {
MessageMapper<Id> messageMapper = mailboxSessionMapperFactory.createMessageMapper(session);
MailboxMessage<Id> newMailboxMessage = buildMailboxMessage(createdEntry, outbox);
messageMapper.add(outbox, newMailboxMessage);
- return new MessageWithId<>(createdEntry.getCreationId(), Message.fromMailboxMessage(newMailboxMessage, buildMessageIdFromUid));
- } catch (MailboxException e) {
+ Message jmapMessage = Message.fromMailboxMessage(newMailboxMessage, buildMessageIdFromUid);
+ sendMessage(newMailboxMessage, jmapMessage, session);
+ return new MessageWithId<>(createdEntry.getCreationId(), jmapMessage);
+ } catch (MailboxException | MessagingException | IOException e) {
throw Throwables.propagate(e);
} catch (MailboxRoleNotFoundException e) {
LOGGER.error("Could not find mailbox '%s' while trying to save message.", e.getRole().serialize());
@@ -216,4 +229,10 @@ public class SetMessagesCreationProcessor<Id extends MailboxId> implements SetMe
}
return result;
}
+
+ private void sendMessage(MailboxMessage<Id> mailboxMessage, Message jmapMessage, MailboxSession session) throws MessagingException, IOException {
+ Mail mail = mailFactory.build(mailboxMessage, jmapMessage);
+ MailMetadata metadata = new MailMetadata(jmapMessage.getId(), session.getUser().getUserName());
+ mailSpool.send(mail, metadata);
+ }
}
http://git-wip-us.apache.org/repos/asf/james-project/blob/3b09ad75/server/protocols/jmap/src/main/java/org/apache/james/jmap/send/MailFactory.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/send/MailFactory.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/send/MailFactory.java
new file mode 100644
index 0000000..4de9c1c
--- /dev/null
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/send/MailFactory.java
@@ -0,0 +1,78 @@
+/****************************************************************
+ * 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.send;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import javax.mail.MessagingException;
+import javax.mail.internet.AddressException;
+
+import org.apache.james.core.MailImpl;
+import org.apache.james.jmap.model.Emailer;
+import org.apache.james.jmap.model.Message;
+import org.apache.james.mailbox.store.mail.model.MailboxId;
+import org.apache.james.mailbox.store.mail.model.MailboxMessage;
+import org.apache.mailet.Mail;
+import org.apache.mailet.MailAddress;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Throwables;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Sets;
+
+public class MailFactory<Id extends MailboxId> {
+ private static final Logger LOGGER = LoggerFactory.getLogger(MailFactory.class);
+
+ @VisibleForTesting MailFactory() {
+ }
+
+ public Mail build(MailboxMessage<Id> mailboxMessage, Message jmapMessage) throws MessagingException, IOException {
+ MailAddress sender = jmapMessage.getFrom()
+ .map(this::emailerToMailAddress)
+ .orElseThrow(() -> new RuntimeException("Sender is mandatory"));
+ Set<MailAddress> to = emailersToMailAddressSet(jmapMessage.getTo());
+ Set<MailAddress> cc = emailersToMailAddressSet(jmapMessage.getCc());
+ Set<MailAddress> bcc = emailersToMailAddressSet(jmapMessage.getBcc());
+ ImmutableSet<MailAddress> recipients = Sets.union(
+ Sets.union(to, cc),
+ bcc).immutableCopy();
+ return new MailImpl(jmapMessage.getId().serialize(), sender, recipients, mailboxMessage.getBodyContent());
+ }
+
+ private MailAddress emailerToMailAddress(Emailer emailer) {
+ try {
+ return new MailAddress(emailer.getEmail());
+ } catch (AddressException e) {
+ LOGGER.error("Invalid mail address", emailer.getEmail());
+ throw Throwables.propagate(e);
+ }
+ }
+
+ private Set<MailAddress> emailersToMailAddressSet(List<Emailer> emailers) {
+ return emailers.stream()
+ .map(this::emailerToMailAddress)
+ .collect(Collectors.toSet());
+ }
+}
http://git-wip-us.apache.org/repos/asf/james-project/blob/3b09ad75/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 5978f0e..4c73ca8 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
@@ -19,7 +19,6 @@
package org.apache.james.jmap.methods;
-import static org.apache.james.jmap.model.CreationMessage.DraftEmailer;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
@@ -33,11 +32,15 @@ import java.util.function.Function;
import org.apache.james.jmap.exceptions.MailboxRoleNotFoundException;
import org.apache.james.jmap.model.CreationMessage;
+import org.apache.james.jmap.model.CreationMessage.DraftEmailer;
import org.apache.james.jmap.model.CreationMessageId;
import org.apache.james.jmap.model.Message;
import org.apache.james.jmap.model.MessageId;
import org.apache.james.jmap.model.SetMessagesRequest;
import org.apache.james.jmap.model.SetMessagesResponse;
+import org.apache.james.jmap.send.MailFactory;
+import org.apache.james.jmap.send.MailMetadata;
+import org.apache.james.jmap.send.MailSpool;
import org.apache.james.mailbox.MailboxSession;
import org.apache.james.mailbox.exception.MailboxException;
import org.apache.james.mailbox.store.MailboxSessionMapperFactory;
@@ -45,6 +48,7 @@ import org.apache.james.mailbox.store.TestId;
import org.apache.james.mailbox.store.mail.MessageMapper;
import org.apache.james.mailbox.store.mail.model.Mailbox;
import org.apache.james.mailbox.store.mail.model.MailboxMessage;
+import org.apache.mailet.Mail;
import org.junit.Test;
import com.google.common.collect.ImmutableList;
@@ -66,7 +70,7 @@ public class SetMessagesCreationProcessorTest {
@Test
public void processShouldReturnEmptyCreatedWhenRequestHasEmptyCreate() {
- SetMessagesCreationProcessor<TestId> sut = new SetMessagesCreationProcessor<TestId>(null, null, null, null) {
+ SetMessagesCreationProcessor<TestId> sut = new SetMessagesCreationProcessor<TestId>(null, null, null, null, null, null) {
@Override
protected Optional<Mailbox<TestId>> getOutbox(MailboxSession session) throws MailboxException {
@SuppressWarnings("unchecked")
@@ -102,9 +106,9 @@ public class SetMessagesCreationProcessorTest {
when(mockSessionMapperFactory.createMessageMapper(any(MailboxSession.class)))
.thenReturn(stubMapper);
- SetMessagesCreationProcessor<TestId> sut = new SetMessagesCreationProcessor<TestId>(null, null, mockSessionMapperFactory, null) {
+ SetMessagesCreationProcessor<TestId> sut = new SetMessagesCreationProcessor<TestId>(null, null, mockSessionMapperFactory, null, null, null) {
@Override
- protected MessageWithId<Message> createMessageInOutbox(MessageWithId.CreationMessageEntry createdEntry, MailboxSession session, Mailbox<TestId> outbox, Function<Long, MessageId> buildMessageIdFromUid) {
+ protected MessageWithId<Message> createMessageInOutboxAndSend(MessageWithId.CreationMessageEntry createdEntry, MailboxSession session, Mailbox<TestId> outbox, Function<Long, MessageId> buildMessageIdFromUid) {
return new MessageWithId<>(createdEntry.getCreationId(), FAKE_MESSAGE);
}
@Override
@@ -125,7 +129,7 @@ public class SetMessagesCreationProcessorTest {
@Test(expected = MailboxRoleNotFoundException.class)
public void processShouldThrowWhenOutboxNotFound() {
// Given
- SetMessagesCreationProcessor<TestId> sut = new SetMessagesCreationProcessor<TestId>(null, null, null, null) {
+ SetMessagesCreationProcessor<TestId> sut = new SetMessagesCreationProcessor<TestId>(null, null, null, null, null, null) {
@Override
protected Optional<Mailbox<TestId>> getOutbox(MailboxSession session) throws MailboxException {
return Optional.empty();
@@ -144,9 +148,11 @@ public class SetMessagesCreationProcessorTest {
MailboxSessionMapperFactory<TestId> stubSessionMapperFactory = mock(MailboxSessionMapperFactory.class);
when(stubSessionMapperFactory.createMessageMapper(any(MailboxSession.class)))
.thenReturn(mockMapper);
+ MailSpool mockedMailSpool = mock(MailSpool.class);
+ MailFactory<TestId> mockedMailFactory = mock(MailFactory.class);
SetMessagesCreationProcessor<TestId> sut = new SetMessagesCreationProcessor<TestId>(null, null,
- stubSessionMapperFactory, new MIMEMessageConverter()) {
+ stubSessionMapperFactory, new MIMEMessageConverter(), mockedMailSpool, mockedMailFactory) {
@Override
protected Optional<Mailbox<TestId>> getOutbox(MailboxSession session) throws MailboxException {
TestId stubMailboxId = mock(TestId.class);
@@ -163,6 +169,36 @@ public class SetMessagesCreationProcessorTest {
verify(mockMapper).add(eq(fakeOutbox), any(MailboxMessage.class));
}
+ @Test
+ @SuppressWarnings("unchecked")
+ public void processShouldSendMailWhenRequestHasNonEmptyCreate() throws Exception {
+ // Given
+ Mailbox<TestId> fakeOutbox = mock(Mailbox.class);
+ MessageMapper<TestId> mockMapper = mock(MessageMapper.class);
+ MailboxSessionMapperFactory<TestId> stubSessionMapperFactory = mock(MailboxSessionMapperFactory.class);
+ when(stubSessionMapperFactory.createMessageMapper(any(MailboxSession.class)))
+ .thenReturn(mockMapper);
+ MailSpool mockedMailSpool = mock(MailSpool.class);
+ MailFactory<TestId> mockedMailFactory = mock(MailFactory.class);
+
+ SetMessagesCreationProcessor<TestId> sut = new SetMessagesCreationProcessor<TestId>(null, null,
+ stubSessionMapperFactory, new MIMEMessageConverter(), mockedMailSpool, mockedMailFactory) {
+ @Override
+ protected Optional<Mailbox<TestId>> getOutbox(MailboxSession session) throws MailboxException {
+ TestId stubMailboxId = mock(TestId.class);
+ when(stubMailboxId.serialize()).thenReturn("user|outbox|12345");
+ when(fakeOutbox.getMailboxId()).thenReturn(stubMailboxId);
+ when(fakeOutbox.getName()).thenReturn("outbox");
+ return Optional.of(fakeOutbox);
+ }
+ };
+ // When
+ sut.process(buildFakeCreationRequest(), buildStubbedSession());
+
+ // Then
+ verify(mockedMailSpool).send(any(Mail.class), any(MailMetadata.class));
+ }
+
private SetMessagesRequest buildFakeCreationRequest() {
return SetMessagesRequest.builder()
.create(ImmutableMap.of(CreationMessageId.of("anything-really"), CreationMessage.builder()
http://git-wip-us.apache.org/repos/asf/james-project/blob/3b09ad75/server/protocols/jmap/src/test/java/org/apache/james/jmap/send/MailFactoryTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/send/MailFactoryTest.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/send/MailFactoryTest.java
new file mode 100644
index 0000000..59f09e2
--- /dev/null
+++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/send/MailFactoryTest.java
@@ -0,0 +1,100 @@
+/****************************************************************
+ * 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.send;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.util.Collection;
+import java.util.Date;
+
+import javax.mail.Flags;
+import javax.mail.util.SharedByteArrayInputStream;
+
+import org.apache.james.jmap.model.Message;
+import org.apache.james.jmap.model.MessageId;
+import org.apache.james.mailbox.FlagsBuilder;
+import org.apache.james.mailbox.store.TestId;
+import org.apache.james.mailbox.store.mail.model.MailboxMessage;
+import org.apache.james.mailbox.store.mail.model.impl.PropertyBuilder;
+import org.apache.james.mailbox.store.mail.model.impl.SimpleMailboxMessage;
+import org.apache.mailet.Mail;
+import org.apache.mailet.MailAddress;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.google.common.collect.ImmutableSet;
+
+public class MailFactoryTest {
+
+ private MailFactory<TestId> testee;
+ private MailboxMessage<TestId> mailboxMessage;
+ private Message jmapMessage;
+
+ @Before
+ public void init() {
+ testee = new MailFactory<TestId>();
+ String headers = "From: me@example.com\n"
+ + "To: 1@example.com\n"
+ + "Cc: 2@example.com, 3@example.com\n"
+ + "Bcc: 4@example.com\n"
+ + "Subject: news\n";
+ String content = headers
+ + "Hello! How are you?";
+ PropertyBuilder propertyBuilder = new PropertyBuilder();
+ propertyBuilder.setMediaType("plain");
+ propertyBuilder.setSubType("text");
+ propertyBuilder.setTextualLineCount(18L);
+ mailboxMessage = new SimpleMailboxMessage<>(
+ new Date(),
+ content.length(),
+ headers.length(),
+ new SharedByteArrayInputStream(content.getBytes()),
+ new FlagsBuilder().add(Flags.Flag.SEEN).build(),
+ propertyBuilder,
+ TestId.of(2));
+ jmapMessage = Message.fromMailboxMessage(mailboxMessage, x -> MessageId.of("test|test|" + x));
+ }
+
+ @Test(expected=NullPointerException.class)
+ public void buildMailShouldThrowWhenNullMailboxMessage() throws Exception {
+ testee.build(null, jmapMessage);
+ }
+
+ @Test(expected=NullPointerException.class)
+ public void buildMailShouldThrowWhenNullJmapMessage() throws Exception {
+ testee.build(mailboxMessage, null);
+ }
+
+ @Test
+ public void buildMailShouldWork() throws Exception {
+ String expectedName = jmapMessage.getId().serialize();
+ MailAddress expectedSender = new MailAddress("me@example.com");
+ Collection<MailAddress> expectedRecipients = ImmutableSet.of(
+ new MailAddress("1@example.com"),
+ new MailAddress("3@example.com"),
+ new MailAddress("2@example.com"),
+ new MailAddress("4@example.com"));
+
+ Mail actual = testee.build(mailboxMessage, jmapMessage);
+
+ assertThat(actual.getName()).isEqualTo(expectedName);
+ assertThat(actual.getSender()).isEqualTo(expectedSender);
+ assertThat(actual.getRecipients()).containsAll(expectedRecipients);
+ }
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org
[5/9] james-project git commit: JAMES-1692 add a failing test for
sending a message
Posted by ad...@apache.org.
JAMES-1692 add a failing test for sending a message
Project: http://git-wip-us.apache.org/repos/asf/james-project/repo
Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/7c7f3773
Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/7c7f3773
Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/7c7f3773
Branch: refs/heads/master
Commit: 7c7f377362e6d06f2084e4535af7e2651f252afb
Parents: 00678d8
Author: Fabien Vignon <fv...@linagora.com>
Authored: Fri Feb 12 17:52:43 2016 +0100
Committer: Raphael Ouazana <ra...@linagora.com>
Committed: Tue Mar 1 15:42:53 2016 +0100
----------------------------------------------------------------------
.../jmap/methods/SetMessagesMethodTest.java | 135 ++++++++++++++++++-
1 file changed, 128 insertions(+), 7 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/james-project/blob/7c7f3773/server/protocols/jmap-integration-testing/src/test/java/org/apache/james/jmap/methods/SetMessagesMethodTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap-integration-testing/src/test/java/org/apache/james/jmap/methods/SetMessagesMethodTest.java b/server/protocols/jmap-integration-testing/src/test/java/org/apache/james/jmap/methods/SetMessagesMethodTest.java
index c2b4b04..fcc3101 100644
--- a/server/protocols/jmap-integration-testing/src/test/java/org/apache/james/jmap/methods/SetMessagesMethodTest.java
+++ b/server/protocols/jmap-integration-testing/src/test/java/org/apache/james/jmap/methods/SetMessagesMethodTest.java
@@ -36,6 +36,9 @@ import static org.hamcrest.collection.IsMapWithSize.anEmptyMap;
import java.io.ByteArrayInputStream;
import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
import javax.mail.Flags;
import org.apache.james.backends.cassandra.EmbeddedCassandra;
@@ -46,20 +49,19 @@ import org.apache.james.mailbox.elasticsearch.EmbeddedElasticSearch;
import org.apache.james.mailbox.exception.MailboxException;
import org.apache.james.mailbox.model.MailboxConstants;
import org.apache.james.mailbox.model.MailboxPath;
-
+import org.hamcrest.Matchers;
+import org.junit.Before;
import org.junit.Ignore;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.RuleChain;
+import org.junit.rules.TemporaryFolder;
import com.google.common.base.Charsets;
import com.jayway.restassured.RestAssured;
import com.jayway.restassured.builder.ResponseSpecBuilder;
import com.jayway.restassured.http.ContentType;
import com.jayway.restassured.specification.ResponseSpecification;
-import org.hamcrest.Matchers;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.RuleChain;
-import org.junit.rules.TemporaryFolder;
public abstract class SetMessagesMethodTest {
@@ -70,6 +72,7 @@ public abstract class SetMessagesMethodTest {
private EmbeddedElasticSearch embeddedElasticSearch = new EmbeddedElasticSearch();
private EmbeddedCassandra cassandra = EmbeddedCassandra.createStartServer();
private JmapServer jmapServer = jmapServer(temporaryFolder, embeddedElasticSearch, cassandra);
+ private String outboxId;
protected abstract JmapServer jmapServer(TemporaryFolder temporaryFolder, EmbeddedElasticSearch embeddedElasticSearch, EmbeddedCassandra cassandra);
@@ -94,6 +97,25 @@ public abstract class SetMessagesMethodTest {
jmapServer.serverProbe().addUser(username, password);
jmapServer.serverProbe().createMailbox("#private", "username", "inbox");
accessToken = JmapAuthentication.authenticateJamesUser(username, password);
+
+ jmapServer.serverProbe().createMailbox(MailboxConstants.USER_NAMESPACE, username, "outbox");
+ embeddedElasticSearch.awaitForElasticSearch();
+ // Find the newly created outbox mailbox (using getMailboxes command on /jmap endpoint)
+ List<Map<String, String>> mailboxes = with()
+ .accept(ContentType.JSON)
+ .contentType(ContentType.JSON)
+ .header("Authorization", accessToken.serialize())
+ .body("[[\"getMailboxes\", {\"properties\": [\"role\", \"id\"]}, \"#0\"]]")
+ .post("/jmap")
+ .andReturn()
+ .body()
+ .jsonPath()
+ .getList(ARGUMENTS + ".list");
+
+ outboxId = mailboxes.stream()
+ .filter(x -> x.get("role").equals("outbox"))
+ .map(x -> x.get("id"))
+ .findFirst().get();
}
@Test
@@ -624,4 +646,103 @@ public abstract class SetMessagesMethodTest {
.body(ARGUMENTS + ".notUpdated[\""+nonExistingMessageId+"\"].description", equalTo("message not found"))
.body(ARGUMENTS + ".updated", hasSize(0));
}
+
+ @Test
+ @Ignore("pending SetMessages's send messages feature implementation")
+ public void setMessageShouldReturnCreatedMessageWhenSendingMessage() {
+ String messageCreationId = "user|inbox|1";
+ String requestBody = "[" +
+ " [" +
+ " \"setMessages\","+
+ " {" +
+ " \"create\": { \"" + messageCreationId + "\" : {" +
+ " \"from\": { \"name\": \"MAILER-DEAMON\", \"email\": \"postmaster@example.com\"}," +
+ " \"to\": [{ \"name\": \"BOB\", \"email\": \"someone@example.com\"}]," +
+ " \"subject\": \"Thank you for joining example.com!\"," +
+ " \"textBody\": \"Hello someone, and thank you for joining example.com!\"," +
+ " \"mailboxIds\": [\"" + outboxId + "\"]" +
+ " }}" +
+ " }," +
+ " \"#0\"" +
+ " ]" +
+ "]";
+
+ given()
+ .accept(ContentType.JSON)
+ .contentType(ContentType.JSON)
+ .header("Authorization", accessToken.serialize())
+ .body(requestBody)
+ .when()
+ .post("/jmap")
+ .then()
+ .log().ifValidationFails()
+ .statusCode(200)
+ .body(NAME, equalTo("messagesSet"))
+ .body(ARGUMENTS + ".notCreated", 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
+ @Ignore("pending SetMessages's send messages feature implementation")
+ public void setMessagesShouldCreateMessageInOutboxWhenSendingMessage() throws MailboxException {
+ // Given
+ String messageCreationId = "user|inbox|1";
+ String presumedMessageId = "username@domain.tld|outbox|1";
+ String messageSubject = "Thank you for joining example.com!";
+ String requestBody = "[" +
+ " [" +
+ " \"setMessages\","+
+ " {" +
+ " \"create\": { \"" + messageCreationId + "\" : {" +
+ " \"from\": { \"name\": \"MAILER-DAEMON\", \"email\": \"postmaster@example.com\"}," +
+ " \"to\": [{ \"name\": \"BOB\", \"email\": \"someone@example.com\"}]," +
+ " \"subject\": \"" + messageSubject + "\"," +
+ " \"textBody\": \"Hello someone, and thank you for joining example.com!\"," +
+ " \"mailboxIds\": [\"" + outboxId + "\"]" +
+ " }}" +
+ " }," +
+ " \"#0\"" +
+ " ]" +
+ "]";
+
+ given()
+ .accept(ContentType.JSON)
+ .contentType(ContentType.JSON)
+ .header("Authorization", accessToken.serialize())
+ .body(requestBody)
+ // When
+ .when()
+ .post("/jmap");
+
+ // Then
+ with()
+ .accept(ContentType.JSON)
+ .contentType(ContentType.JSON)
+ .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))
+ .log().ifValidationFails();
+ }
}
\ No newline at end of file
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org
[2/9] james-project git commit: JAMES-1692 message processors are
injected
Posted by ad...@apache.org.
JAMES-1692 message processors are injected
... through SetMessagesMethod's ctor
Project: http://git-wip-us.apache.org/repos/asf/james-project/repo
Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/b21eae3f
Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/b21eae3f
Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/b21eae3f
Branch: refs/heads/master
Commit: b21eae3f04c024cb80436702e799bd1af60952b9
Parents: 99ac325
Author: Fabien Vignon <fv...@linagora.com>
Authored: Wed Feb 17 11:40:18 2016 +0100
Committer: Raphael Ouazana <ra...@linagora.com>
Committed: Tue Mar 1 15:42:53 2016 +0100
----------------------------------------------------------------------
.../org/apache/james/jmap/MethodsModule.java | 13 +++++++++++++
.../james/jmap/methods/SetMessagesMethod.java | 20 +++++++++++---------
2 files changed, 24 insertions(+), 9 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/james-project/blob/b21eae3f/server/container/cassandra-guice/src/main/java/org/apache/james/jmap/MethodsModule.java
----------------------------------------------------------------------
diff --git a/server/container/cassandra-guice/src/main/java/org/apache/james/jmap/MethodsModule.java b/server/container/cassandra-guice/src/main/java/org/apache/james/jmap/MethodsModule.java
index 4e57d20..01257da 100644
--- a/server/container/cassandra-guice/src/main/java/org/apache/james/jmap/MethodsModule.java
+++ b/server/container/cassandra-guice/src/main/java/org/apache/james/jmap/MethodsModule.java
@@ -19,6 +19,8 @@
package org.apache.james.jmap;
+import java.util.List;
+
import org.apache.james.jmap.json.ObjectMapperFactory;
import org.apache.james.jmap.methods.GetMailboxesMethod;
import org.apache.james.jmap.methods.GetMessageListMethod;
@@ -30,10 +32,13 @@ import org.apache.james.jmap.methods.JmapResponseWriterImpl;
import org.apache.james.jmap.methods.Method;
import org.apache.james.jmap.methods.SetMessagesCreationProcessor;
import org.apache.james.jmap.methods.SetMessagesMethod;
+import org.apache.james.jmap.methods.SetMessagesProcessor;
import org.apache.james.jmap.methods.SetMessagesUpdateProcessor;
import org.apache.james.mailbox.cassandra.CassandraId;
+import com.google.common.collect.ImmutableList;
import com.google.inject.AbstractModule;
+import com.google.inject.Provides;
import com.google.inject.Singleton;
import com.google.inject.TypeLiteral;
import com.google.inject.multibindings.Multibinder;
@@ -58,4 +63,12 @@ public class MethodsModule extends AbstractModule {
bind(SetMessagesCreationProcessor.class).to(new TypeLiteral<SetMessagesCreationProcessor<CassandraId>>(){});
}
+ @Provides
+ public List<SetMessagesProcessor<CassandraId>> setMessagesProcessors(
+ SetMessagesUpdateProcessor<CassandraId> messageUpdater,
+ SetMessagesCreationProcessor<CassandraId> messageCreator) {
+
+ return ImmutableList.of( messageUpdater, messageCreator);
+ }
+
}
http://git-wip-us.apache.org/repos/asf/james-project/blob/b21eae3f/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/SetMessagesMethod.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/SetMessagesMethod.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/SetMessagesMethod.java
index 5202026..7bb606b 100644
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/SetMessagesMethod.java
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/SetMessagesMethod.java
@@ -43,6 +43,7 @@ import org.apache.james.mailbox.store.mail.model.MailboxMessage;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
+
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -55,18 +56,15 @@ public class SetMessagesMethod<Id extends MailboxId> implements Method {
private final MailboxMapperFactory<Id> mailboxMapperFactory;
private final MailboxSessionMapperFactory<Id> mailboxSessionMapperFactory;
- private final SetMessagesUpdateProcessor<Id> messageUpdater;
- private final SetMessagesCreationProcessor messageCreator;
+ private final List<SetMessagesProcessor<Id>> messagesProcessors;
@Inject
@VisibleForTesting SetMessagesMethod(MailboxMapperFactory<Id> mailboxMapperFactory,
MailboxSessionMapperFactory<Id> mailboxSessionMapperFactory,
- SetMessagesUpdateProcessor<Id> messageUpdater,
- SetMessagesCreationProcessor messageCreator) {
+ List<SetMessagesProcessor<Id>> messagesProcessors) {
this.mailboxMapperFactory = mailboxMapperFactory;
this.mailboxSessionMapperFactory = mailboxSessionMapperFactory;
- this.messageUpdater = messageUpdater;
- this.messageCreator = messageCreator;
+ this.messagesProcessors = messagesProcessors;
}
@Override
@@ -99,9 +97,13 @@ public class SetMessagesMethod<Id extends MailboxId> implements Method {
private SetMessagesResponse setMessagesResponse(SetMessagesRequest request, MailboxSession mailboxSession) throws MailboxException {
SetMessagesResponse.Builder responseBuilder = SetMessagesResponse.builder();
processDestroy(request.getDestroy(), mailboxSession, responseBuilder);
- messageUpdater.process(request, mailboxSession).mergeInto(responseBuilder);
- messageCreator.process(request, mailboxSession).mergeInto(responseBuilder);
- return responseBuilder.build();
+ return messagesProcessors.stream()
+ .map(processor -> processor.process(request, mailboxSession))
+ .reduce(responseBuilder,
+ (builder, resp) -> resp.mergeInto(builder) ,
+ (builder1, builder2) -> builder2.build().mergeInto(builder1)
+ )
+ .build();
}
private void processDestroy(List<MessageId> messageIds, MailboxSession mailboxSession, SetMessagesResponse.Builder responseBuilder) throws MailboxException {
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org
[6/9] james-project git commit: JAMES-1692 extract
SetMessagesMethod.processDestroy to a class
Posted by ad...@apache.org.
JAMES-1692 extract SetMessagesMethod.processDestroy to a class
Project: http://git-wip-us.apache.org/repos/asf/james-project/repo
Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/8983dbbe
Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/8983dbbe
Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/8983dbbe
Branch: refs/heads/master
Commit: 8983dbbe0512b394d1063f5c5ee585e5873fc30d
Parents: 9388764
Author: Fabien Vignon <fv...@linagora.com>
Authored: Fri Feb 19 18:25:57 2016 +0100
Committer: Raphael Ouazana <ra...@linagora.com>
Committed: Tue Mar 1 15:44:51 2016 +0100
----------------------------------------------------------------------
.../org/apache/james/jmap/MethodsModule.java | 19 +--
.../SetMessagesDestructionProcessor.java | 116 +++++++++++++++++++
.../james/jmap/methods/SetMessagesMethod.java | 79 +------------
3 files changed, 126 insertions(+), 88 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/james-project/blob/8983dbbe/server/container/cassandra-guice/src/main/java/org/apache/james/jmap/MethodsModule.java
----------------------------------------------------------------------
diff --git a/server/container/cassandra-guice/src/main/java/org/apache/james/jmap/MethodsModule.java b/server/container/cassandra-guice/src/main/java/org/apache/james/jmap/MethodsModule.java
index 01257da..b5d254a 100644
--- a/server/container/cassandra-guice/src/main/java/org/apache/james/jmap/MethodsModule.java
+++ b/server/container/cassandra-guice/src/main/java/org/apache/james/jmap/MethodsModule.java
@@ -19,8 +19,6 @@
package org.apache.james.jmap;
-import java.util.List;
-
import org.apache.james.jmap.json.ObjectMapperFactory;
import org.apache.james.jmap.methods.GetMailboxesMethod;
import org.apache.james.jmap.methods.GetMessageListMethod;
@@ -31,14 +29,13 @@ import org.apache.james.jmap.methods.JmapResponseWriter;
import org.apache.james.jmap.methods.JmapResponseWriterImpl;
import org.apache.james.jmap.methods.Method;
import org.apache.james.jmap.methods.SetMessagesCreationProcessor;
+import org.apache.james.jmap.methods.SetMessagesDestructionProcessor;
import org.apache.james.jmap.methods.SetMessagesMethod;
import org.apache.james.jmap.methods.SetMessagesProcessor;
import org.apache.james.jmap.methods.SetMessagesUpdateProcessor;
import org.apache.james.mailbox.cassandra.CassandraId;
-import com.google.common.collect.ImmutableList;
import com.google.inject.AbstractModule;
-import com.google.inject.Provides;
import com.google.inject.Singleton;
import com.google.inject.TypeLiteral;
import com.google.inject.multibindings.Multibinder;
@@ -59,16 +56,10 @@ public class MethodsModule extends AbstractModule {
methods.addBinding().to(new TypeLiteral<GetMessageListMethod<CassandraId>>(){});
methods.addBinding().to(new TypeLiteral<GetMessagesMethod<CassandraId>>(){});
methods.addBinding().to(new TypeLiteral<SetMessagesMethod<CassandraId>>(){});
- bind(SetMessagesUpdateProcessor.class).to(new TypeLiteral<SetMessagesUpdateProcessor<CassandraId>>(){});
- bind(SetMessagesCreationProcessor.class).to(new TypeLiteral<SetMessagesCreationProcessor<CassandraId>>(){});
- }
- @Provides
- public List<SetMessagesProcessor<CassandraId>> setMessagesProcessors(
- SetMessagesUpdateProcessor<CassandraId> messageUpdater,
- SetMessagesCreationProcessor<CassandraId> messageCreator) {
-
- return ImmutableList.of( messageUpdater, messageCreator);
+ Multibinder<SetMessagesProcessor<CassandraId>> setMessagesProcessors = Multibinder.newSetBinder(binder(), new TypeLiteral<SetMessagesProcessor<CassandraId>>(){});
+ setMessagesProcessors.addBinding().to(new TypeLiteral<SetMessagesUpdateProcessor<CassandraId>>(){});
+ setMessagesProcessors.addBinding().to(new TypeLiteral<SetMessagesCreationProcessor<CassandraId>>(){});
+ setMessagesProcessors.addBinding().to(new TypeLiteral<SetMessagesDestructionProcessor<CassandraId>>(){});
}
-
}
http://git-wip-us.apache.org/repos/asf/james-project/blob/8983dbbe/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/SetMessagesDestructionProcessor.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/SetMessagesDestructionProcessor.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/SetMessagesDestructionProcessor.java
new file mode 100644
index 0000000..9424fff
--- /dev/null
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/SetMessagesDestructionProcessor.java
@@ -0,0 +1,116 @@
+/****************************************************************
+ * 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.methods;
+
+import java.util.Iterator;
+import java.util.function.Function;
+
+import javax.inject.Inject;
+
+import org.apache.james.jmap.exceptions.MessageNotFoundException;
+import org.apache.james.jmap.model.MessageId;
+import org.apache.james.jmap.model.SetError;
+import org.apache.james.jmap.model.SetMessagesRequest;
+import org.apache.james.jmap.model.SetMessagesResponse;
+import org.apache.james.mailbox.MailboxSession;
+import org.apache.james.mailbox.exception.MailboxException;
+import org.apache.james.mailbox.model.MessageRange;
+import org.apache.james.mailbox.store.MailboxSessionMapperFactory;
+import org.apache.james.mailbox.store.mail.MailboxMapperFactory;
+import org.apache.james.mailbox.store.mail.MessageMapper;
+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.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Throwables;
+
+public class SetMessagesDestructionProcessor<Id extends MailboxId> implements SetMessagesProcessor<Id> {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(SetMessagesCreationProcessor.class);
+ private static final int LIMIT_BY_ONE = 1;
+
+ private final MailboxMapperFactory<Id> mailboxMapperFactory;
+ private final MailboxSessionMapperFactory<Id> mailboxSessionMapperFactory;
+
+ @Inject
+ @VisibleForTesting
+ SetMessagesDestructionProcessor(MailboxMapperFactory<Id> mailboxMapperFactory,
+ MailboxSessionMapperFactory<Id> mailboxSessionMapperFactory) {
+ this.mailboxMapperFactory = mailboxMapperFactory;
+ this.mailboxSessionMapperFactory = mailboxSessionMapperFactory;
+ }
+
+ @Override
+ public SetMessagesResponse process(SetMessagesRequest request, MailboxSession mailboxSession) {
+ MessageMapper<Id> messageMapper;
+ try {
+ messageMapper = mailboxSessionMapperFactory.createMessageMapper(mailboxSession);
+ } catch (MailboxException e) {
+ throw Throwables.propagate(e);
+ }
+ return request.getDestroy().stream()
+ .map(delete(messageMapper, mailboxSession))
+ .reduce(SetMessagesResponse.builder(), SetMessagesResponse.Builder::accumulator, SetMessagesResponse.Builder::combiner)
+ .build();
+ }
+
+ private Function<? super MessageId, SetMessagesResponse> delete(MessageMapper<Id> messageMapper, MailboxSession mailboxSession) {
+ return (messageId) -> {
+ try {
+ Mailbox<Id> mailbox = mailboxMapperFactory
+ .getMailboxMapper(mailboxSession)
+ .findMailboxByPath(messageId.getMailboxPath());
+
+ MailboxMessage<Id> mailboxMessage = getMailboxMessage(messageMapper, messageId, mailbox);
+
+ messageMapper.delete(mailbox, mailboxMessage);
+ return SetMessagesResponse.builder().destroyed(messageId).build();
+ } catch (MessageNotFoundException e) {
+ return SetMessagesResponse.builder().notDestroyed(messageId,
+ SetError.builder()
+ .type("notFound")
+ .description("The message " + messageId.serialize() + " can't be found")
+ .build())
+ .build();
+ } catch (MailboxException e) {
+ LOGGER.error("An error occurred when deleting a message", e);
+ return SetMessagesResponse.builder().notDestroyed(messageId,
+ SetError.builder()
+ .type("anErrorOccurred")
+ .description("An error occurred while deleting message " + messageId.serialize())
+ .build())
+ .build();
+ }
+ };
+ }
+
+ private MailboxMessage<Id> getMailboxMessage(MessageMapper<Id> messageMapper, MessageId messageId, Mailbox<Id> mailbox)
+ throws MailboxException, MessageNotFoundException {
+
+ Iterator<MailboxMessage<Id>> mailboxMessage = messageMapper.findInMailbox(mailbox, MessageRange.one(messageId.getUid()), MessageMapper.FetchType.Metadata, LIMIT_BY_ONE);
+ if (!mailboxMessage.hasNext()) {
+ throw new MessageNotFoundException();
+ }
+ return mailboxMessage.next();
+ }
+}
http://git-wip-us.apache.org/repos/asf/james-project/blob/8983dbbe/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/SetMessagesMethod.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/SetMessagesMethod.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/SetMessagesMethod.java
index 7bb606b..76c97ee 100644
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/SetMessagesMethod.java
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/SetMessagesMethod.java
@@ -19,51 +19,30 @@
package org.apache.james.jmap.methods;
-import java.util.*;
-import java.util.function.Consumer;
+import java.util.Set;
import java.util.stream.Stream;
+
import javax.inject.Inject;
-import org.apache.james.jmap.exceptions.MessageNotFoundException;
import org.apache.james.jmap.model.ClientId;
-import org.apache.james.jmap.model.MessageId;
-import org.apache.james.jmap.model.SetError;
import org.apache.james.jmap.model.SetMessagesRequest;
import org.apache.james.jmap.model.SetMessagesResponse;
import org.apache.james.mailbox.MailboxSession;
import org.apache.james.mailbox.exception.MailboxException;
-import org.apache.james.mailbox.model.MessageRange;
-import org.apache.james.mailbox.store.MailboxSessionMapperFactory;
-import org.apache.james.mailbox.store.mail.MailboxMapperFactory;
-import org.apache.james.mailbox.store.mail.MessageMapper;
-import org.apache.james.mailbox.store.mail.MessageMapper.FetchType;
-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 com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
public class SetMessagesMethod<Id extends MailboxId> implements Method {
- private static final int LIMIT_BY_ONE = 1;
- private static final Logger LOGGER = LoggerFactory.getLogger(SetMessagesMethod.class);
private static final Method.Request.Name METHOD_NAME = Method.Request.name("setMessages");
private static final Method.Response.Name RESPONSE_NAME = Method.Response.name("messagesSet");
- private final MailboxMapperFactory<Id> mailboxMapperFactory;
- private final MailboxSessionMapperFactory<Id> mailboxSessionMapperFactory;
- private final List<SetMessagesProcessor<Id>> messagesProcessors;
+ private final Set<SetMessagesProcessor<Id>> messagesProcessors;
@Inject
- @VisibleForTesting SetMessagesMethod(MailboxMapperFactory<Id> mailboxMapperFactory,
- MailboxSessionMapperFactory<Id> mailboxSessionMapperFactory,
- List<SetMessagesProcessor<Id>> messagesProcessors) {
- this.mailboxMapperFactory = mailboxMapperFactory;
- this.mailboxSessionMapperFactory = mailboxSessionMapperFactory;
+ @VisibleForTesting SetMessagesMethod(Set<SetMessagesProcessor<Id>> messagesProcessors) {
this.messagesProcessors = messagesProcessors;
}
@@ -95,60 +74,12 @@ public class SetMessagesMethod<Id extends MailboxId> implements Method {
}
private SetMessagesResponse setMessagesResponse(SetMessagesRequest request, MailboxSession mailboxSession) throws MailboxException {
- SetMessagesResponse.Builder responseBuilder = SetMessagesResponse.builder();
- processDestroy(request.getDestroy(), mailboxSession, responseBuilder);
return messagesProcessors.stream()
.map(processor -> processor.process(request, mailboxSession))
- .reduce(responseBuilder,
+ .reduce(SetMessagesResponse.builder(),
(builder, resp) -> resp.mergeInto(builder) ,
(builder1, builder2) -> builder2.build().mergeInto(builder1)
)
.build();
}
-
- private void processDestroy(List<MessageId> messageIds, MailboxSession mailboxSession, SetMessagesResponse.Builder responseBuilder) throws MailboxException {
- MessageMapper<Id> messageMapper = mailboxSessionMapperFactory.createMessageMapper(mailboxSession);
- Consumer<? super MessageId> delete = delete(messageMapper, mailboxSession, responseBuilder);
-
- messageIds.stream()
- .forEach(delete);
- }
-
- private Consumer<? super MessageId> delete(MessageMapper<Id> messageMapper, MailboxSession mailboxSession, SetMessagesResponse.Builder responseBuilder) {
- return (messageId) -> {
- try {
- Mailbox<Id> mailbox = mailboxMapperFactory
- .getMailboxMapper(mailboxSession)
- .findMailboxByPath(messageId.getMailboxPath());
-
- MailboxMessage<Id> mailboxMessage = getMailboxMessage(messageMapper, messageId, mailbox);
-
- messageMapper.delete(mailbox, mailboxMessage);
- responseBuilder.destroyed(messageId);
- } catch (MessageNotFoundException e) {
- responseBuilder.notDestroyed(messageId,
- SetError.builder()
- .type("notFound")
- .description("The message " + messageId.serialize() + " can't be found")
- .build());
- } catch (MailboxException e) {
- LOGGER.error("An error occurred when deleting a message", e);
- responseBuilder.notDestroyed(messageId,
- SetError.builder()
- .type("anErrorOccurred")
- .description("An error occurred while deleting message " + messageId.serialize())
- .build());
- }
- };
- }
-
- private MailboxMessage<Id> getMailboxMessage(MessageMapper<Id> messageMapper, MessageId messageId, Mailbox<Id> mailbox)
- throws MailboxException, MessageNotFoundException {
-
- Iterator<MailboxMessage<Id>> mailboxMessage = messageMapper.findInMailbox(mailbox, MessageRange.one(messageId.getUid()), FetchType.Metadata, LIMIT_BY_ONE);
- if (!mailboxMessage.hasNext()) {
- throw new MessageNotFoundException();
- }
- return mailboxMessage.next();
- }
}
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org
[4/9] james-project git commit: JAMES-1692 setMessages.create is
actually a map of ids and messages
Posted by ad...@apache.org.
JAMES-1692 setMessages.create is actually a map of ids and messages
... not just a list of message
Project: http://git-wip-us.apache.org/repos/asf/james-project/repo
Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/0625fb5d
Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/0625fb5d
Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/0625fb5d
Branch: refs/heads/master
Commit: 0625fb5dc4bb384c58c748c58ebb9f760718e469
Parents: 7c7f377
Author: Fabien Vignon <fv...@linagora.com>
Authored: Fri Feb 12 18:43:49 2016 +0100
Committer: Raphael Ouazana <ra...@linagora.com>
Committed: Tue Mar 1 15:42:53 2016 +0100
----------------------------------------------------------------------
.../james/jmap/model/SetMessagesRequest.java | 16 +++++++--------
.../jmap/model/SetMessagesRequestTest.java | 21 ++------------------
2 files changed, 9 insertions(+), 28 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/james-project/blob/0625fb5d/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetMessagesRequest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetMessagesRequest.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetMessagesRequest.java
index ba81c35..aadb886 100644
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetMessagesRequest.java
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetMessagesRequest.java
@@ -48,13 +48,13 @@ public class SetMessagesRequest implements JmapRequest {
private String accountId;
private String ifInState;
- private ImmutableList.Builder<Message> create;
+ private ImmutableMap.Builder<MessageId, Message> create;
private ImmutableMap.Builder<MessageId, Function<UpdateMessagePatchConverter, UpdateMessagePatch>> updatesProvider;
private ImmutableList.Builder<MessageId> destroy;
private Builder() {
- create = ImmutableList.builder();
+ create = ImmutableMap.builder();
updatesProvider = ImmutableMap.builder();
destroy = ImmutableList.builder();
}
@@ -73,10 +73,8 @@ public class SetMessagesRequest implements JmapRequest {
return this;
}
- public Builder create(List<Message> create) {
- if (create != null && !create.isEmpty()) {
- throw new NotImplementedException();
- }
+ public Builder create(Map<MessageId, Message> creates) {
+ this.create.putAll(creates);
return this;
}
@@ -97,11 +95,11 @@ public class SetMessagesRequest implements JmapRequest {
private final Optional<String> accountId;
private final Optional<String> ifInState;
- private final List<Message> create;
+ private final Map<MessageId, Message> create;
private final Map<MessageId, Function<UpdateMessagePatchConverter, UpdateMessagePatch>> update;
private final List<MessageId> destroy;
- @VisibleForTesting SetMessagesRequest(Optional<String> accountId, Optional<String> ifInState, List<Message> create, Map<MessageId, Function<UpdateMessagePatchConverter, UpdateMessagePatch>> update, List<MessageId> destroy) {
+ @VisibleForTesting SetMessagesRequest(Optional<String> accountId, Optional<String> ifInState, Map<MessageId, Message> create, Map<MessageId, Function<UpdateMessagePatchConverter, UpdateMessagePatch>> update, List<MessageId> destroy) {
this.accountId = accountId;
this.ifInState = ifInState;
this.create = create;
@@ -117,7 +115,7 @@ public class SetMessagesRequest implements JmapRequest {
return ifInState;
}
- public List<Message> getCreate() {
+ public Map<MessageId, Message> getCreate() {
return create;
}
http://git-wip-us.apache.org/repos/asf/james-project/blob/0625fb5d/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/SetMessagesRequestTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/SetMessagesRequestTest.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/SetMessagesRequestTest.java
index 0a079b6..7be03e1 100644
--- a/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/SetMessagesRequestTest.java
+++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/SetMessagesRequestTest.java
@@ -22,7 +22,6 @@ package org.apache.james.jmap.model;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
-import java.time.ZonedDateTime;
import java.util.Optional;
import org.apache.commons.lang.NotImplementedException;
@@ -46,31 +45,15 @@ public class SetMessagesRequestTest {
}
@Test
- public void builderShouldThrowWhenCreateIsNotEmpty() {
- assertThatThrownBy(() -> SetMessagesRequest.builder().create(ImmutableList.of(Message.builder()
- .id(MessageId.of("user|create|1"))
- .blobId("blobId")
- .threadId("threadId")
- .mailboxIds(ImmutableList.of("mailboxId"))
- .headers(ImmutableMap.of("key", "value"))
- .subject("subject")
- .size(123)
- .date(ZonedDateTime.now())
- .preview("preview")
- .build())))
- .isInstanceOf(NotImplementedException.class);
- }
-
- @Test
public void builderShouldWork() {
ImmutableList<MessageId> destroy = ImmutableList.of(MessageId.of("user|destroy|1"));
- SetMessagesRequest expected = new SetMessagesRequest(Optional.empty(), Optional.empty(), ImmutableList.of(), ImmutableMap.of(), destroy);
+ SetMessagesRequest expected = new SetMessagesRequest(Optional.empty(), Optional.empty(), ImmutableMap.of(), ImmutableMap.of(), destroy);
SetMessagesRequest setMessagesRequest = SetMessagesRequest.builder()
.accountId(null)
.ifInState(null)
- .create(ImmutableList.of())
+ .create(ImmutableMap.of())
.update(ImmutableMap.of())
.destroy(destroy)
.build();
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org