JAMES-1745 Handle attachments in GetMessages
Project: http://git-wip-us.apache.org/repos/asf/james-project/repo Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/4e13597b Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/4e13597b Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/4e13597b Branch: refs/heads/master Commit: 4e13597bb71d35cec228a0d7a744c174c0728a7c Parents: 7367a6f Author: Antoine Duprat <[email protected]> Authored: Wed Jun 1 09:19:24 2016 +0200 Committer: Antoine Duprat <[email protected]> Committed: Fri Jun 3 13:10:59 2016 +0200 ---------------------------------------------------------------------- .../integration/GetMessagesMethodTest.java | 39 ++++++- .../src/test/resources/twoAttachments.eml | 73 ++++++++++++ .../protocols/jmap/doc/specs/spec/message.mdwn | 6 - .../james/jmap/methods/GetMessagesMethod.java | 115 ++++++++++++++++--- .../methods/SetMessagesCreationProcessor.java | 2 +- .../org/apache/james/jmap/model/Attachment.java | 47 +++++++- .../org/apache/james/jmap/model/Message.java | 39 +++++-- .../james/jmap/json/ParsingWritingObjects.java | 1 - .../jmap/methods/GetMessagesMethodTest.java | 24 ++-- .../apache/james/jmap/model/AttachmentTest.java | 10 +- .../james/jmap/model/MailboxMessageTest.java | 99 ++++++++++++++-- .../apache/james/jmap/send/MailFactoryTest.java | 3 +- .../jmap/src/test/resources/json/message.json | 2 +- 13 files changed, 384 insertions(+), 76 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/james-project/blob/4e13597b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/GetMessagesMethodTest.java ---------------------------------------------------------------------- diff --git a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/GetMessagesMethodTest.java b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/GetMessagesMethodTest.java index b013c3e..90776d8 100644 --- a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/GetMessagesMethodTest.java +++ b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/GetMessagesMethodTest.java @@ -51,6 +51,9 @@ import com.jayway.restassured.http.ContentType; public abstract class GetMessagesMethodTest { private static final String NAME = "[0][0]"; private static final String ARGUMENTS = "[0][1]"; + private static final String ATTACHMENTS = ARGUMENTS + ".list[0].attachments"; + private static final String FIRST_ATTACHMENT = ATTACHMENTS + "[0]"; + private static final String SECOND_ATTACHMENT = ATTACHMENTS + "[1]"; protected abstract GuiceJamesServer createJmapServer(); @@ -66,6 +69,7 @@ public abstract class GetMessagesMethodTest { jmapServer.start(); RestAssured.port = jmapServer.getJmapPort(); RestAssured.config = newConfig().encoderConfig(encoderConfig().defaultContentCharset(Charsets.UTF_8)); + RestAssured.enableLoggingOfRequestAndResponseIfValidationFails(); String domain = "domain.tld"; username = "username@" + domain; @@ -185,7 +189,9 @@ public abstract class GetMessagesMethodTest { .body(ARGUMENTS + ".list[0].isUnread", equalTo(true)) .body(ARGUMENTS + ".list[0].preview", equalTo("testmail")) .body(ARGUMENTS + ".list[0].headers", equalTo(ImmutableMap.of("subject", "my test subject"))) - .body(ARGUMENTS + ".list[0].date", equalTo("2014-10-30T14:12:00Z")); + .body(ARGUMENTS + ".list[0].date", equalTo("2014-10-30T14:12:00Z")) + .body(ARGUMENTS + ".list[0].hasAttachment", equalTo(false)) + .body(ATTACHMENTS, empty()); } @Test @@ -331,4 +337,35 @@ public abstract class GetMessagesMethodTest { .body(ARGUMENTS + ".list[0].id", equalTo("[email protected]|mailbox|1")) .body(ARGUMENTS + ".list[0].subject", equalTo("my test subject")); } + + @Test + public void getMessagesShouldReturnAttachmentsWhenSome() throws Exception { + jmapServer.serverProbe().createMailbox(MailboxConstants.USER_NAMESPACE, username, "inbox"); + + ZonedDateTime dateTime = ZonedDateTime.parse("2014-10-30T14:12:00Z"); + jmapServer.serverProbe().appendMessage(username, new MailboxPath(MailboxConstants.USER_NAMESPACE, username, "inbox"), + ClassLoader.getSystemResourceAsStream("twoAttachments.eml"), Date.from(dateTime.toInstant()), false, new Flags()); + + await(); + + given() + .accept(ContentType.JSON) + .contentType(ContentType.JSON) + .header("Authorization", accessToken.serialize()) + .body("[[\"getMessages\", {\"ids\": [\"" + username + "|inbox|1\"]}, \"#0\"]]") + .when() + .post("/jmap") + .then() + .statusCode(200) + .body(NAME, equalTo("messages")) + .body(ARGUMENTS + ".list", hasSize(1)) + .body(ARGUMENTS + ".list[0].hasAttachment", equalTo(true)) + .body(ATTACHMENTS, hasSize(2)) + .body(FIRST_ATTACHMENT + ".blobId", equalTo("223a76c0e8c1b1762487d8e0598bd88497d73ef2")) + .body(FIRST_ATTACHMENT + ".type", equalTo("image/jpeg")) + .body(FIRST_ATTACHMENT + ".size", equalTo(846)) + .body(SECOND_ATTACHMENT + ".blobId", equalTo("58aa22c2ec5770fb9e574ba19008dbfc647eba43")) + .body(SECOND_ATTACHMENT + ".type", equalTo("image/jpeg")) + .body(SECOND_ATTACHMENT + ".size", equalTo(597)); + } } http://git-wip-us.apache.org/repos/asf/james-project/blob/4e13597b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/resources/twoAttachments.eml ---------------------------------------------------------------------- diff --git a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/resources/twoAttachments.eml b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/resources/twoAttachments.eml new file mode 100644 index 0000000..85f0e3b --- /dev/null +++ b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/resources/twoAttachments.eml @@ -0,0 +1,73 @@ +Return-Path: <[email protected]> +Received: from alderaan.linagora.com (smtp.linagora.dc1 [172.16.18.53]) + by imap (Cyrus v2.2.13-Debian-2.2.13-19+squeeze3) with LMTPA; + Fri, 27 Feb 2015 20:32:14 +0100 +X-Sieve: CMU Sieve 2.2 +Received: from canondir.par.lng (unknown [92.103.166.6]) + (using TLSv1 with cipher AES256-SHA (256/256 bits)) + (No client certificate requested) + by alderaan.linagora.com (Postfix) with ESMTPSA id BAB0D728 + for <[email protected]>; Fri, 27 Feb 2015 20:31:38 +0100 (CET) +X-Priority: 3 (Normal) +From: "From" + <[email protected]> +To: "To" + <[email protected]> +Subject: [8/10]Attached Image light with text +Date: Fri, 27 Mar 2015 21:48:38 +0100 +Message-Id: <[email protected]> +Mime-Version: 1.0 +Content-Type: multipart/mixed; + boundary="AHNPACBLDCDIDAGGGDDFAABECGCA" + +--AHNPACBLDCDIDAGGGDDFAABECGCA +Content-Type: text/html; charset=utf-8; format=flowed +Content-Transfer-Encoding: 8bit + +<b>html</b> + +--AHNPACBLDCDIDAGGGDDFAABECGCA +Content-Type: image/jpeg; + name="4037_014.jpg" +Content-Transfer-Encoding: base64 +Content-Disposition: attachment; + filename="4037_014.jpg" + +/9j/4X2cRXhpZgAASUkqAAgAAAANAA8BAgAKAAAAqgAAABABAgAJAAAAtAAAABIBAwABAAAA +AQAAABoBBQABAAAAvgAAABsBBQABAAAAxgAAACgBAwABAAAAAgAAADEBAgAKAAAAzgAAADIB +AgAUAAAA2AAAABMCAwABAAAAAgAAAGmHBAABAAAAfAIAAKXEBwDQAAAA7AAAANLGBwBAAAAA +vAEAANPGBwCAAAAA/AEAAEwqAABQYW5hc29uaWMARE1DLUZaNDUAALQAAAABAAAAtAAAAAEA +AABWZXIuMS4wICAAMjAxNDowMjoyNSAxMDozMjowOQBQcmludElNADAyNTAAAA4AAQAWABYA +AgAAAAAAAwBkAAAABwAAAAAACAAAAAAACQAAAAAACgAAAAAACwCsAAAADAAAAAAADQAAAAAA +DgDEAAAAAAEFAAAAAQEBAAAAEAGAAAAACREAABAnAAALDwAAECcAAJcFAAAQJwAAsAgAABAn +AAABHAAAECcAAF4CAAAQJwAAiwAAABAnAADLAwAAECcAAOUbAAAQJwAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + +--AHNPACBLDCDIDAGGGDDFAABECGCA +Content-Type: image/jpeg; + name="4037_015.jpg" +Content-Transfer-Encoding: base64 +Content-Disposition: attachment; + filename="4037_015.jpg" + +iVBORw0KGgoAAAANSUhEUgAABYUAAAL4CAIAAACrzA8fAAAACXBIWXMAAAsTAAALEwEAmpwY +AAAAB3RJTUUH3wMNDiUMca0XkQAAIABJREFUeNq8vWm0bdlVHja/tc+99zX13qv2VSeVmlIv +FSqEOhA2AoEhxMRBg8QOyEkG6WMDSZzhMQTGDDcwiJPhBBMby4SMDJthgmOMAYvGMcF0QgIU +WRKobymp+qpX9fp779nry4+9mjnnWuuc80qMvCpdvXrv3nP22Xutueb85je/D1/3+q+ipF9z +nGfGdZznGCMjKaSIkJQwBYSAEMI0Tatptdrb21utVqvVtJKAAAABEAAiUP+IiECYfsfyJf1B +10+cOHH48OGVlZVSypaWlv379zc2Nr722msNDQ2u+y9zaYQeAQAAAACCHgEAAAB0y969e+ON +KnpOe3v7JZdccj6fwPXr10+aNKnAB956663Zs2fjTgMAAADOKzhOAQAAAFCYs+yO0XfNNQAA +AAAA/nNBfgQAAADQDVddddW6detSqdQZ7JvL5W655RZIEgAAAAAAEayKigqcBQAAAKAAhw8f +3rZt25AhQwYNGpTJZHq4V2tr6/bt25csWbJjxw6cQwAAAACACMiPAAAAAAAAAAAAQH8D/wgA +AAAAAAAAAAD0N9AjAAAAAAAAAAAA0N9AjwAAAAAAAAAAAEB/Az0CAAAAAAAAAAAA/Q30CAAA +AAAAAAAAAPQ30CMAAAAAAAAAAADQ30CPAAAAAAAAAAAAQH/z/0IKJwmNQbpqAAAAAElFTkSu +QmCC + +--AHNPACBLDCDIDAGGGDDFAABECGCA-- http://git-wip-us.apache.org/repos/asf/james-project/blob/4e13597b/server/protocols/jmap/doc/specs/spec/message.mdwn ---------------------------------------------------------------------- diff --git a/server/protocols/jmap/doc/specs/spec/message.mdwn b/server/protocols/jmap/doc/specs/spec/message.mdwn index 2c65069..ab144cb 100644 --- a/server/protocols/jmap/doc/specs/spec/message.mdwn +++ b/server/protocols/jmap/doc/specs/spec/message.mdwn @@ -35,9 +35,6 @@ A **Message** object has the following properties: - **isDraft**: `Boolean` (Mutable by the server only) Is the message a draft? This corresponds to the `\Draft` system flag in IMAP. - **hasAttachment**: `Boolean` - <aside class="warning"> - Not implemented - </aside> Does the message have any attachments? - **headers**: `String[String]` A map of header name to (decoded) header value for all headers in the message. For headers that occur multiple times (e.g. `Received`), the values are concatenated with a single new line (`\n`) character in between each one. @@ -67,9 +64,6 @@ A **Message** object has the following properties: </aside> The HTML body part for the message if present. If there is only a plain text version of the body, an HTML version will be generated from this. Any scripting content, or references to external plugins, MUST be stripped from the HTML by the server. - **attachments**: `Attachment[]|null` - <aside class="warning"> - Not implemented - </aside> An array of attachment objects (see below) detailing all the attachments to the message. - **attachedMessages**: `String[Message]|null` <aside class="warning"> http://git-wip-us.apache.org/repos/asf/james-project/blob/4e13597b/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/GetMessagesMethod.java ---------------------------------------------------------------------- diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/GetMessagesMethod.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/GetMessagesMethod.java index b490ad7..2993ff3 100644 --- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/GetMessagesMethod.java +++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/GetMessagesMethod.java @@ -38,11 +38,16 @@ import org.apache.james.jmap.model.MessageId; import org.apache.james.jmap.model.MessageProperties; import org.apache.james.jmap.model.MessageProperties.HeaderProperty; import org.apache.james.mailbox.MailboxSession; +import org.apache.james.mailbox.exception.MailboxException; import org.apache.james.mailbox.model.MailboxPath; import org.apache.james.mailbox.model.MessageRange; +import org.apache.james.mailbox.store.mail.AttachmentMapper; +import org.apache.james.mailbox.store.mail.AttachmentMapperFactory; import org.apache.james.mailbox.store.mail.MailboxMapperFactory; import org.apache.james.mailbox.store.mail.MessageMapper; import org.apache.james.mailbox.store.mail.MessageMapperFactory; +import org.apache.james.mailbox.store.mail.model.Attachment; +import org.apache.james.mailbox.store.mail.model.AttachmentId; import org.apache.james.mailbox.store.mail.model.Mailbox; import org.apache.james.mailbox.store.mail.model.MailboxMessage; import org.apache.james.util.streams.Collectors; @@ -62,13 +67,16 @@ public class GetMessagesMethod implements Method { private static final Method.Response.Name RESPONSE_NAME = Method.Response.name("messages"); private final MessageMapperFactory messageMapperFactory; private final MailboxMapperFactory mailboxMapperFactory; + private final AttachmentMapperFactory attachmentMapperFactory; @Inject @VisibleForTesting GetMessagesMethod( - MessageMapperFactory messageMapperFactory, - MailboxMapperFactory mailboxMapperFactory) { + MessageMapperFactory messageMapperFactory, + MailboxMapperFactory mailboxMapperFactory, + AttachmentMapperFactory attachmentMapperFactory) { this.messageMapperFactory = messageMapperFactory; this.mailboxMapperFactory = mailboxMapperFactory; + this.attachmentMapperFactory = attachmentMapperFactory; } @Override @@ -110,8 +118,8 @@ public class GetMessagesMethod implements Method { private GetMessagesResponse getMessagesResponse(MailboxSession mailboxSession, GetMessagesRequest getMessagesRequest) { getMessagesRequest.getAccountId().ifPresent(GetMessagesMethod::notImplemented); - Function<MessageId, Stream<Pair<MailboxMessage, MailboxPath>>> loadMessages = loadMessage(mailboxSession); - Function<Pair<MailboxMessage, MailboxPath>, Message> convertToJmapMessage = toJmapMessage(mailboxSession); + Function<MessageId, Stream<CompletedMailboxMessage>> loadMessages = loadMessage(mailboxSession); + Function<CompletedMailboxMessage, Message> convertToJmapMessage = toJmapMessage(mailboxSession); List<Message> result = getMessagesRequest.getIds().stream() .flatMap(loadMessages) @@ -126,17 +134,14 @@ public class GetMessagesMethod implements Method { } - private Function<Pair<MailboxMessage, MailboxPath>, Message> toJmapMessage(MailboxSession mailboxSession) { - return (value) -> { - MailboxMessage messageResult = value.getValue0(); - MailboxPath mailboxPath = value.getValue1(); - return Message.fromMailboxMessage(messageResult, uid -> new MessageId(mailboxSession.getUser(), mailboxPath , uid)); - }; + private Function<CompletedMailboxMessage, Message> toJmapMessage(MailboxSession mailboxSession) { + return (completedMailboxMessage) -> Message.fromMailboxMessage( + completedMailboxMessage.mailboxMessage, + completedMailboxMessage.attachments, + uid -> new MessageId(mailboxSession.getUser(), completedMailboxMessage.mailboxPath , uid)); } - private Function<MessageId, Stream< - Pair<MailboxMessage, - MailboxPath>>> + private Function<MessageId, Stream<CompletedMailboxMessage>> loadMessage(MailboxSession mailboxSession) { return Throwing @@ -148,15 +153,89 @@ public class GetMessagesMethod implements Method { messageMapper.findInMailbox(mailbox, MessageRange.one(messageId.getUid()), MessageMapper.FetchType.Full, 1), mailboxPath ); - }) - .andThen(this::iteratorToStream); + }) + .andThen(Throwing.function((pair) -> retrieveCompleteMailboxMessages(pair, mailboxSession))); } - private Stream<Pair<MailboxMessage, MailboxPath>> iteratorToStream(Pair<Iterator<MailboxMessage>, MailboxPath> value) { + private Stream<CompletedMailboxMessage> retrieveCompleteMailboxMessages(Pair<Iterator<MailboxMessage>, MailboxPath> value, MailboxSession mailboxSession) throws MailboxException { Iterable<MailboxMessage> iterable = () -> value.getValue0(); Stream<MailboxMessage> targetStream = StreamSupport.stream(iterable.spliterator(), false); - + + Function<List<AttachmentId>, List<Attachment>> retrieveAttachments = retrieveAttachments(attachmentMapperFactory.getAttachmentMapper(mailboxSession)); + MailboxPath mailboxPath = value.getValue1(); - return targetStream.map(x -> Pair.with(x, mailboxPath)); + return targetStream + .map(message -> CompletedMailboxMessage.builder().mailboxMessage(message).attachmentIds(message.getAttachmentsIds())) + .map(builder -> builder.mailboxPath(mailboxPath)) + .map(builder -> builder.retrieveAttachments(retrieveAttachments)) + .map(builder -> builder.build()); + } + + private static class CompletedMailboxMessage { + + public static Builder builder() { + return new Builder(); + } + + public static class Builder { + + private MailboxMessage mailboxMessage; + private List<AttachmentId> attachmentIds; + private MailboxPath mailboxPath; + private Function<List<AttachmentId>, List<Attachment>> retrieveAttachments; + + private Builder() { + } + + public Builder mailboxMessage(MailboxMessage mailboxMessage) { + Preconditions.checkArgument(mailboxMessage != null); + this.mailboxMessage = mailboxMessage; + return this; + } + + public Builder attachmentIds(List<AttachmentId> attachmentIds) { + Preconditions.checkArgument(attachmentIds != null); + this.attachmentIds = attachmentIds; + return this; + } + + public Builder mailboxPath(MailboxPath mailboxPath) { + Preconditions.checkArgument(mailboxPath != null); + this.mailboxPath = mailboxPath; + return this; + } + + public Builder retrieveAttachments(Function<List<AttachmentId>, List<Attachment>> retrieveAttachments) { + Preconditions.checkArgument(retrieveAttachments != null); + this.retrieveAttachments = retrieveAttachments; + return this; + } + + public CompletedMailboxMessage build() { + Preconditions.checkState(mailboxMessage != null); + Preconditions.checkState(attachmentIds != null); + Preconditions.checkState(mailboxPath != null); + Preconditions.checkState(retrieveAttachments != null); + return new CompletedMailboxMessage(mailboxMessage, retrieveAttachments.apply(attachmentIds), mailboxPath); + } + } + + private final MailboxMessage mailboxMessage; + private final List<Attachment> attachments; + private final MailboxPath mailboxPath; + + public CompletedMailboxMessage(MailboxMessage mailboxMessage, List<Attachment> attachments, MailboxPath mailboxPath) { + this.mailboxMessage = mailboxMessage; + this.attachments = attachments; + this.mailboxPath = mailboxPath; + } + } + + private Function<List<AttachmentId>, List<Attachment>> retrieveAttachments(AttachmentMapper attachmentMapper) { + return (attachmentsIds) -> { + return attachmentsIds.stream() + .map(Throwing.function(id -> attachmentMapper.getAttachment(id))) + .collect(Collectors.toImmutableList()); + }; } } http://git-wip-us.apache.org/repos/asf/james-project/blob/4e13597b/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 c7bacc5..a5097d7 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 @@ -195,7 +195,7 @@ public class SetMessagesCreationProcessor implements SetMessagesProcessor { MessageMapper messageMapper = mailboxSessionMapperFactory.createMessageMapper(session); MailboxMessage newMailboxMessage = buildMailboxMessage(createdEntry, outbox); messageMapper.add(outbox, newMailboxMessage); - Message jmapMessage = Message.fromMailboxMessage(newMailboxMessage, buildMessageIdFromUid); + Message jmapMessage = Message.fromMailboxMessage(newMailboxMessage, ImmutableList.of(), buildMessageIdFromUid); sendMessage(newMailboxMessage, jmapMessage, session); return new MessageWithId<>(createdEntry.getCreationId(), jmapMessage); } catch (MailboxException | MessagingException | IOException e) { http://git-wip-us.apache.org/repos/asf/james-project/blob/4e13597b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/Attachment.java ---------------------------------------------------------------------- diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/Attachment.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/Attachment.java index d0550a2..8aa0927 100644 --- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/Attachment.java +++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/Attachment.java @@ -24,6 +24,8 @@ import java.util.Optional; 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.MoreObjects; +import com.google.common.base.Objects; import com.google.common.base.Preconditions; import com.google.common.base.Strings; @@ -88,22 +90,21 @@ public class Attachment { public Attachment build() { Preconditions.checkState(!Strings.isNullOrEmpty(blobId), "'blobId' is mandatory"); Preconditions.checkState(!Strings.isNullOrEmpty(type), "'type' is mandatory"); - Preconditions.checkState(!Strings.isNullOrEmpty(name), "'name' is mandatory"); Preconditions.checkState(size != null, "'size' is mandatory"); - return new Attachment(blobId, type, name, size, Optional.ofNullable(cid), isInline, Optional.ofNullable(width), Optional.ofNullable(height)); + return new Attachment(blobId, type, Optional.ofNullable(name), size, Optional.ofNullable(cid), isInline, Optional.ofNullable(width), Optional.ofNullable(height)); } } private final String blobId; private final String type; - private final String name; + private final Optional<String> name; private final long size; private final Optional<String> cid; private final boolean isInline; private final Optional<Long> width; private final Optional<Long> height; - @VisibleForTesting Attachment(String blobId, String type, String name, long size, Optional<String> cid, boolean isInline, Optional<Long> width, Optional<Long> height) { + @VisibleForTesting Attachment(String blobId, String type, Optional<String> name, long size, Optional<String> cid, boolean isInline, Optional<Long> width, Optional<Long> height) { this.blobId = blobId; this.type = type; this.name = name; @@ -122,7 +123,7 @@ public class Attachment { return type; } - public String getName() { + public Optional<String> getName() { return name; } @@ -145,4 +146,40 @@ public class Attachment { public Optional<Long> getHeight() { return height; } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Attachment) { + Attachment other = (Attachment) obj; + return Objects.equal(blobId, other.blobId) + && Objects.equal(type, other.type) + && Objects.equal(name, other.name) + && Objects.equal(size, other.size) + && Objects.equal(cid, other.cid) + && Objects.equal(isInline, other.isInline) + && Objects.equal(width, other.width) + && Objects.equal(height, other.height); + } + return false; + } + + @Override + public int hashCode() { + return Objects.hashCode(blobId, type, name, size, cid, isInline, width, height); + } + + @Override + public String toString() { + return MoreObjects + .toStringHelper(this) + .add("blobId", blobId) + .add("type", type) + .add("name", name) + .add("size", size) + .add("cid", cid) + .add("isInline", isInline) + .add("width", width) + .add("height", height) + .toString(); + } } http://git-wip-us.apache.org/repos/asf/james-project/blob/4e13597b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/Message.java ---------------------------------------------------------------------- diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/Message.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/Message.java index d299489..721c0f7 100644 --- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/Message.java +++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/Message.java @@ -26,9 +26,9 @@ 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 org.apache.commons.lang.NotImplementedException; import org.apache.james.jmap.methods.GetMessagesMethod; import org.apache.james.jmap.methods.JmapResponseWriterImpl; import org.apache.james.jmap.model.message.EMailer; @@ -60,11 +60,9 @@ public class Message { } public static Message fromMailboxMessage(MailboxMessage mailboxMessage, + List<org.apache.james.mailbox.store.mail.model.Attachment> attachments, Function<Long, MessageId> uidToMessageId) { IndexableMessage im = IndexableMessage.from(mailboxMessage, new DefaultTextExtractor(), UTC_ZONE_ID); - if (im.getHasAttachment()) { - throw new NotImplementedException(); - } MessageId messageId = uidToMessageId.apply(im.getId()); return builder() .id(messageId) @@ -88,6 +86,7 @@ public class Message { .preview(getPreview(im)) .textBody(getTextBody(im)) .htmlBody(getHtmlBody(im)) + .attachments(getAttachments(attachments)) .build(); } @@ -181,6 +180,20 @@ public class Message { && im.getSubType().equals(MediaType.HTML_UTF_8.subtype()); } + private static List<Attachment> getAttachments(List<org.apache.james.mailbox.store.mail.model.Attachment> attachments) { + return attachments.stream() + .map(Message::fromMailboxAttachment) + .collect(org.apache.james.util.streams.Collectors.toImmutableList()); + } + + private static Attachment fromMailboxAttachment(org.apache.james.mailbox.store.mail.model.Attachment attachment) { + return Attachment.builder() + .blobId(attachment.getAttachmentId().getId()) + .type(attachment.getType()) + .size(attachment.getSize()) + .build(); + } + @JsonPOJOBuilder(withPrefix = "") public static class Builder { private MessageId id; @@ -192,7 +205,6 @@ public class Message { private boolean isFlagged; private boolean isAnswered; private boolean isDraft; - private boolean hasAttachment; private ImmutableMap<String, String> headers; private Emailer from; private final ImmutableList.Builder<Emailer> to; @@ -262,11 +274,6 @@ public class Message { return this; } - public Builder hasAttachment(boolean hasAttachment) { - this.hasAttachment = hasAttachment; - return this; - } - public Builder headers(ImmutableMap<String, String> headers) { this.headers = headers; return this; @@ -350,6 +357,7 @@ public class Message { ImmutableList<Attachment> attachments = this.attachments.build(); ImmutableMap<String, SubMessage> attachedMessages = this.attachedMessages.build(); Preconditions.checkState(areAttachedMessagesKeysInAttachments(attachments, attachedMessages), "'attachedMessages' keys must be in 'attachements'"); + boolean hasAttachment = !attachments.isEmpty(); return new Message(id, blobId, threadId, mailboxIds, Optional.ofNullable(inReplyToMessageId), isUnread, isFlagged, isAnswered, isDraft, hasAttachment, headers, Optional.ofNullable(from), to.build(), cc.build(), bcc.build(), replyTo.build(), subject, date, size, preview, Optional.ofNullable(textBody), Optional.ofNullable(htmlBody), attachments, attachedMessages); @@ -357,9 +365,16 @@ public class Message { } protected static boolean areAttachedMessagesKeysInAttachments(ImmutableList<Attachment> attachments, ImmutableMap<String, SubMessage> attachedMessages) { - return attachments.stream() + return attachedMessages.isEmpty() || attachedMessages.keySet().stream() + .anyMatch(inAttachments(attachments)); + } + + private static Predicate<String> inAttachments(ImmutableList<Attachment> attachments) { + return (key) -> { + return attachments.stream() .map(Attachment::getBlobId) - .allMatch(attachedMessages::containsKey); + .anyMatch(blobId -> blobId.equals(key)); + }; } private final MessageId id; http://git-wip-us.apache.org/repos/asf/james-project/blob/4e13597b/server/protocols/jmap/src/test/java/org/apache/james/jmap/json/ParsingWritingObjects.java ---------------------------------------------------------------------- diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/json/ParsingWritingObjects.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/json/ParsingWritingObjects.java index 866d1f8..b0ea677 100644 --- a/server/protocols/jmap/src/test/java/org/apache/james/jmap/json/ParsingWritingObjects.java +++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/json/ParsingWritingObjects.java @@ -71,7 +71,6 @@ public interface ParsingWritingObjects { .isFlagged(Common.IS_FLAGGED) .isAnswered(Common.IS_ANSWERED) .isDraft(Common.IS_DRAFT) - .hasAttachment(Common.HAS_ATTACHMENT) .headers(Common.HEADERS) .from(Common.FROM) .to(Common.TO) http://git-wip-us.apache.org/repos/asf/james-project/blob/4e13597b/server/protocols/jmap/src/test/java/org/apache/james/jmap/methods/GetMessagesMethodTest.java ---------------------------------------------------------------------- diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/methods/GetMessagesMethodTest.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/methods/GetMessagesMethodTest.java index 4632c1a..ce86d03 100644 --- a/server/protocols/jmap/src/test/java/org/apache/james/jmap/methods/GetMessagesMethodTest.java +++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/methods/GetMessagesMethodTest.java @@ -123,28 +123,28 @@ public class GetMessagesMethodTest { @Test public void processShouldThrowWhenNullRequest() { - GetMessagesMethod testee = new GetMessagesMethod(mailboxSessionMapperFactory, mailboxSessionMapperFactory); + GetMessagesMethod testee = new GetMessagesMethod(mailboxSessionMapperFactory, mailboxSessionMapperFactory, mailboxSessionMapperFactory); GetMessagesRequest request = null; assertThatThrownBy(() -> testee.process(request, mock(ClientId.class), mock(MailboxSession.class))).isInstanceOf(NullPointerException.class); } @Test public void processShouldThrowWhenNullSession() { - GetMessagesMethod testee = new GetMessagesMethod(mailboxSessionMapperFactory, mailboxSessionMapperFactory); + GetMessagesMethod testee = new GetMessagesMethod(mailboxSessionMapperFactory, mailboxSessionMapperFactory, mailboxSessionMapperFactory); MailboxSession mailboxSession = null; assertThatThrownBy(() -> testee.process(mock(GetMessagesRequest.class), mock(ClientId.class), mailboxSession)).isInstanceOf(NullPointerException.class); } @Test public void processShouldThrowWhenNullClientId() { - GetMessagesMethod testee = new GetMessagesMethod(mailboxSessionMapperFactory, mailboxSessionMapperFactory); + GetMessagesMethod testee = new GetMessagesMethod(mailboxSessionMapperFactory, mailboxSessionMapperFactory, mailboxSessionMapperFactory); ClientId clientId = null; assertThatThrownBy(() -> testee.process(mock(GetMessagesRequest.class), clientId, mock(MailboxSession.class))).isInstanceOf(NullPointerException.class); } @Test public void processShouldThrowWhenRequestHasAccountId() { - GetMessagesMethod testee = new GetMessagesMethod(mailboxSessionMapperFactory, mailboxSessionMapperFactory); + GetMessagesMethod testee = new GetMessagesMethod(mailboxSessionMapperFactory, mailboxSessionMapperFactory, mailboxSessionMapperFactory); assertThatThrownBy(() -> testee.process( GetMessagesRequest.builder().accountId("abc").build(), mock(ClientId.class), mock(MailboxSession.class))).isInstanceOf(NotImplementedException.class); } @@ -166,7 +166,7 @@ public class GetMessagesMethodTest { new MessageId(ROBERT, inboxPath, message3Uid))) .build(); - GetMessagesMethod testee = new GetMessagesMethod(mailboxSessionMapperFactory, mailboxSessionMapperFactory); + GetMessagesMethod testee = new GetMessagesMethod(mailboxSessionMapperFactory, mailboxSessionMapperFactory, mailboxSessionMapperFactory); List<JmapResponse> result = testee.process(request, clientId, session).collect(Collectors.toList()); assertThat(result).hasSize(1) @@ -195,7 +195,7 @@ public class GetMessagesMethodTest { .ids(ImmutableList.of(new MessageId(ROBERT, inboxPath, messageUid))) .build(); - GetMessagesMethod testee = new GetMessagesMethod(mailboxSessionMapperFactory, mailboxSessionMapperFactory); + GetMessagesMethod testee = new GetMessagesMethod(mailboxSessionMapperFactory, mailboxSessionMapperFactory, mailboxSessionMapperFactory); List<JmapResponse> result = testee.process(request, clientId, session).collect(Collectors.toList()); assertThat(result).hasSize(1) @@ -219,7 +219,7 @@ public class GetMessagesMethodTest { .properties(ImmutableList.of()) .build(); - GetMessagesMethod testee = new GetMessagesMethod(mailboxSessionMapperFactory, mailboxSessionMapperFactory); + GetMessagesMethod testee = new GetMessagesMethod(mailboxSessionMapperFactory, mailboxSessionMapperFactory, mailboxSessionMapperFactory); List<JmapResponse> result = testee.process(request, clientId, session).collect(Collectors.toList()); assertThat(result).hasSize(1) @@ -240,7 +240,7 @@ public class GetMessagesMethodTest { .ids(ImmutableList.of(new MessageId(ROBERT, inboxPath, message1Uid))) .build(); - GetMessagesMethod testee = new GetMessagesMethod(mailboxSessionMapperFactory, mailboxSessionMapperFactory); + GetMessagesMethod testee = new GetMessagesMethod(mailboxSessionMapperFactory, mailboxSessionMapperFactory, mailboxSessionMapperFactory); Stream<JmapResponse> result = testee.process(request, clientId, session); assertThat(result).hasSize(1) @@ -264,7 +264,7 @@ public class GetMessagesMethodTest { Set<MessageProperty> expected = Sets.newHashSet(MessageProperty.id, MessageProperty.subject); - GetMessagesMethod testee = new GetMessagesMethod(mailboxSessionMapperFactory, mailboxSessionMapperFactory); + GetMessagesMethod testee = new GetMessagesMethod(mailboxSessionMapperFactory, mailboxSessionMapperFactory, mailboxSessionMapperFactory); List<JmapResponse> result = testee.process(request, clientId, session).collect(Collectors.toList()); assertThat(result).hasSize(1) @@ -288,7 +288,7 @@ public class GetMessagesMethodTest { Set<MessageProperty> expected = Sets.newHashSet(MessageProperty.id, MessageProperty.textBody); - GetMessagesMethod testee = new GetMessagesMethod(mailboxSessionMapperFactory, mailboxSessionMapperFactory); + GetMessagesMethod testee = new GetMessagesMethod(mailboxSessionMapperFactory, mailboxSessionMapperFactory, mailboxSessionMapperFactory); List<JmapResponse> result = testee.process(request, clientId, session).collect(Collectors.toList()); assertThat(result).hasSize(1) @@ -315,7 +315,7 @@ public class GetMessagesMethodTest { Set<MessageProperty> expected = Sets.newHashSet(MessageProperty.id, MessageProperty.headers); - GetMessagesMethod testee = new GetMessagesMethod(mailboxSessionMapperFactory, mailboxSessionMapperFactory); + GetMessagesMethod testee = new GetMessagesMethod(mailboxSessionMapperFactory, mailboxSessionMapperFactory, mailboxSessionMapperFactory); List<JmapResponse> result = testee.process(request, clientId, session).collect(Collectors.toList()); assertThat(result) @@ -341,7 +341,7 @@ public class GetMessagesMethodTest { .properties(ImmutableList.of("headers.from", "headers.heADER2")) .build(); - GetMessagesMethod testee = new GetMessagesMethod(mailboxSessionMapperFactory, mailboxSessionMapperFactory); + GetMessagesMethod testee = new GetMessagesMethod(mailboxSessionMapperFactory, mailboxSessionMapperFactory, mailboxSessionMapperFactory); List<JmapResponse> result = testee.process(request, clientId, session).collect(Collectors.toList()); assertThat(result) http://git-wip-us.apache.org/repos/asf/james-project/blob/4e13597b/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/AttachmentTest.java ---------------------------------------------------------------------- diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/AttachmentTest.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/AttachmentTest.java index e7d9add..92b3194 100644 --- a/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/AttachmentTest.java +++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/AttachmentTest.java @@ -56,18 +56,12 @@ public class AttachmentTest { Attachment.builder().blobId("blobId").type("").name("name").size(123).build(); } - @Test(expected=IllegalStateException.class) - public void buildShouldThrowWhenNameIsEmpty() { - Attachment.builder().blobId("blobId").type("type").name("").size(123).build(); - } - @Test public void buildShouldWorkWhenMandatoryFieldsArePresent() { - Attachment expected = new Attachment("blobId", "type", "name", 123, Optional.empty(), false, Optional.empty(), Optional.empty()); + Attachment expected = new Attachment("blobId", "type", Optional.empty(), 123, Optional.empty(), false, Optional.empty(), Optional.empty()); Attachment tested = Attachment.builder() .blobId("blobId") .type("type") - .name("name") .size(123) .build(); assertThat(tested).isEqualToComparingFieldByField(expected); @@ -75,7 +69,7 @@ public class AttachmentTest { @Test public void buildShouldWorkWithAllFieldsSet() { - Attachment expected = new Attachment("blobId", "type", "name", 123, Optional.of("cid"), true, Optional.of(456L), Optional.of(789L)); + Attachment expected = new Attachment("blobId", "type", Optional.of("name"), 123, Optional.of("cid"), true, Optional.of(456L), Optional.of(789L)); Attachment tested = Attachment.builder() .blobId("blobId") .type("type") http://git-wip-us.apache.org/repos/asf/james-project/blob/4e13597b/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/MailboxMessageTest.java ---------------------------------------------------------------------- diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/MailboxMessageTest.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/MailboxMessageTest.java index 5bad5c5..d34d7a9 100644 --- a/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/MailboxMessageTest.java +++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/MailboxMessageTest.java @@ -30,8 +30,8 @@ import javax.mail.Flags.Flag; import javax.mail.util.SharedByteArrayInputStream; import org.apache.commons.io.IOUtils; -import org.apache.commons.lang.NotImplementedException; import org.apache.james.mailbox.store.TestId; +import org.apache.james.mailbox.store.mail.model.AttachmentId; 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; @@ -212,7 +212,6 @@ public class MailboxMessageTest { .isFlagged(true) .isAnswered(true) .isDraft(true) - .hasAttachment(true) .headers(ImmutableMap.of("key", "value")) .from(from) .to(to) @@ -243,7 +242,7 @@ public class MailboxMessageTest { MAILBOX_ID); testMail.setModSeq(MOD_SEQ); - Message testee = Message.fromMailboxMessage(testMail, x -> MessageId.of("user|box|" + x)); + Message testee = Message.fromMailboxMessage(testMail, ImmutableList.of(), x -> MessageId.of("user|box|" + x)); assertThat(testee) .extracting(Message::getPreview, Message::getSize, Message::getSubject, Message::getHeaders, Message::getDate) .containsExactly("(Empty)", 0L, "(No subject)", ImmutableMap.of(), ZONED_DATE); @@ -265,7 +264,7 @@ public class MailboxMessageTest { MAILBOX_ID); testMail.setModSeq(MOD_SEQ); - Message testee = Message.fromMailboxMessage(testMail, x -> MessageId.of("user|box|" + x)); + Message testee = Message.fromMailboxMessage(testMail, ImmutableList.of(), x -> MessageId.of("user|box|" + x)); assertThat(testee) .extracting(Message::isIsUnread, Message::isIsFlagged, Message::isIsAnswered, Message::isIsDraft) .containsExactly(true, true, true, true); @@ -307,7 +306,7 @@ public class MailboxMessageTest { .put("in-reply-to", "<[email protected]>") .put("other-header", "other header value") .build(); - Message testee = Message.fromMailboxMessage(testMail, x -> MessageId.of("user|box|" + x)); + Message testee = Message.fromMailboxMessage(testMail, ImmutableList.of(), x -> MessageId.of("user|box|" + x)); Message expected = Message.builder() .id(MessageId.of("user|box|0")) .blobId("0") @@ -343,7 +342,7 @@ public class MailboxMessageTest { MAILBOX_ID); testMail.setModSeq(MOD_SEQ); - Message testee = Message.fromMailboxMessage(testMail, x -> MessageId.of("user|box|" + x)); + Message testee = Message.fromMailboxMessage(testMail, ImmutableList.of(), x -> MessageId.of("user|box|" + x)); assertThat(testee.getTextBody()).hasValue("Mail body"); } @@ -391,12 +390,28 @@ public class MailboxMessageTest { MAILBOX_ID); testMail.setModSeq(MOD_SEQ); - Message testee = Message.fromMailboxMessage(testMail, x -> MessageId.of("user|box|" + x)); + Message testee = Message.fromMailboxMessage(testMail, ImmutableList.of(), x -> MessageId.of("user|box|" + x)); assertThat(testee.getPreview()).isEqualTo(expectedPreview); } - @Test(expected=NotImplementedException.class) - public void attachmentsShouldNotBeHandledForNow() throws Exception { + @Test + public void attachmentsShouldBeEmptyWhenNone() throws Exception { + MailboxMessage testMail = new SimpleMailboxMessage( + INTERNAL_DATE, + 0, + 0, + new SharedByteArrayInputStream(IOUtils.toByteArray(ClassLoader.getSystemResourceAsStream("spamMail.eml"))), + new Flags(Flag.SEEN), + new PropertyBuilder(), + MAILBOX_ID); + testMail.setModSeq(MOD_SEQ); + + Message testee = Message.fromMailboxMessage(testMail, ImmutableList.of(), x -> MessageId.of("user|box|" + x)); + assertThat(testee.getAttachments()).isEmpty(); + } + + @Test + public void attachmentsShouldBeRetrievedWhenSome() throws Exception { MailboxMessage testMail = new SimpleMailboxMessage( INTERNAL_DATE, 0, @@ -407,6 +422,70 @@ public class MailboxMessageTest { MAILBOX_ID); testMail.setModSeq(MOD_SEQ); - Message.fromMailboxMessage(testMail, x -> MessageId.of("user|box|" + x)); + String payload = "payload"; + String blodId = "id1"; + String type = "content"; + Attachment expectedAttachment = Attachment.builder() + .blobId(blodId) + .size(payload.length()) + .type(type) + .build(); + + Message testee = Message.fromMailboxMessage(testMail, + ImmutableList.of(org.apache.james.mailbox.store.mail.model.Attachment.builder() + .attachmentId(AttachmentId.from(blodId)) + .bytes(payload.getBytes()) + .type(type) + .size(payload.length()) + .build()), + x -> MessageId.of("user|box|" + x)); + + assertThat(testee.getAttachments()).hasSize(1); + assertThat(testee.getAttachments().get(0)).isEqualToComparingFieldByField(expectedAttachment); + } + + @Test(expected = IllegalStateException.class) + public void buildShouldThrowWhenOneAttachedMessageIsNotInAttachments() throws Exception { + Message.builder() + .id(MessageId.of("user|box|1")) + .blobId("blodId") + .threadId("threadId") + .mailboxIds(ImmutableList.of("mailboxId")) + .headers(ImmutableMap.of("key", "value")) + .subject("subject") + .size(1) + .date(ZonedDateTime.now()) + .preview("preview") + .attachedMessages(ImmutableMap.of("key", SubMessage.builder() + .headers(ImmutableMap.of("key", "value")) + .subject("subject") + .date(ZonedDateTime.now()) + .build())) + .build(); + } + + @Test + public void buildShouldNotThrowWhenOneAttachedMessageIsInAttachments() throws Exception { + Message.builder() + .id(MessageId.of("user|box|1")) + .blobId("blodId") + .threadId("threadId") + .mailboxIds(ImmutableList.of("mailboxId")) + .headers(ImmutableMap.of("key", "value")) + .subject("subject") + .size(1) + .date(ZonedDateTime.now()) + .preview("preview") + .attachments(ImmutableList.of(Attachment.builder() + .blobId("key") + .size(1) + .type("type") + .build())) + .attachedMessages(ImmutableMap.of("key", SubMessage.builder() + .headers(ImmutableMap.of("key", "value")) + .subject("subject") + .date(ZonedDateTime.now()) + .build())) + .build(); } } http://git-wip-us.apache.org/repos/asf/james-project/blob/4e13597b/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 index 84d00a6..98cd1d0 100644 --- 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 @@ -38,6 +38,7 @@ import org.apache.mailet.MailAddress; import org.junit.Before; import org.junit.Test; +import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; public class MailFactoryTest { @@ -68,7 +69,7 @@ public class MailFactoryTest { new FlagsBuilder().add(Flags.Flag.SEEN).build(), propertyBuilder, TestId.of(2)); - jmapMessage = Message.fromMailboxMessage(mailboxMessage, x -> MessageId.of("test|test|" + x)); + jmapMessage = Message.fromMailboxMessage(mailboxMessage, ImmutableList.of(), x -> MessageId.of("test|test|" + x)); } @Test(expected=NullPointerException.class) http://git-wip-us.apache.org/repos/asf/james-project/blob/4e13597b/server/protocols/jmap/src/test/resources/json/message.json ---------------------------------------------------------------------- diff --git a/server/protocols/jmap/src/test/resources/json/message.json b/server/protocols/jmap/src/test/resources/json/message.json index 28eecae..72d37bd 100644 --- a/server/protocols/jmap/src/test/resources/json/message.json +++ b/server/protocols/jmap/src/test/resources/json/message.json @@ -8,7 +8,7 @@ "isFlagged": true, "isAnswered": true, "isDraft": true, - "hasAttachment": true, + "hasAttachment": false, "headers": { "h1": "h1Value", "h2": "h2Value" }, "from": { "name": "myName", "email": "[email protected]"}, "to": [ { "name": "to1", "email": "[email protected]"}, { "name": "to2", "email": "[email protected]"} ], --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
