JAMES-1818 Simplify loadMessage by introducing MetaDataWithContent
Project: http://git-wip-us.apache.org/repos/asf/james-project/repo Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/7bfb0cd8 Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/7bfb0cd8 Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/7bfb0cd8 Branch: refs/heads/master Commit: 7bfb0cd84ceb8cf8a0093de9e1b83862dae820df Parents: 844a740 Author: Raphael Ouazana <[email protected]> Authored: Wed Aug 24 12:01:17 2016 +0200 Committer: Raphael Ouazana <[email protected]> Committed: Mon Aug 29 15:16:28 2016 +0200 ---------------------------------------------------------------------- .../cucumber/GetMessagesMethodStepdefs.java | 2 +- .../james/jmap/methods/GetMessagesMethod.java | 131 +---- .../apache/james/jmap/model/MessageFactory.java | 246 ++++++++-- .../james/jmap/model/MailboxMessageTest.java | 480 ------------------- .../james/jmap/model/MessageFactoryTest.java | 262 ++++++++++ .../apache/james/jmap/model/MessageTest.java | 256 ++++++++++ 6 files changed, 743 insertions(+), 634 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/james-project/blob/7bfb0cd8/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/cucumber/GetMessagesMethodStepdefs.java ---------------------------------------------------------------------- diff --git a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/cucumber/GetMessagesMethodStepdefs.java b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/cucumber/GetMessagesMethodStepdefs.java index e12a0f4..437078d 100644 --- a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/cucumber/GetMessagesMethodStepdefs.java +++ b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/cucumber/GetMessagesMethodStepdefs.java @@ -281,7 +281,7 @@ public class GetMessagesMethodStepdefs { @Then("^the headers of the message contains:$") public void assertHeadersOfTheFirstMessage(DataTable headers) throws Throwable { - assertThat(jsonPath.<Map<String, String>>read(FIRST_MESSAGE + ".headers")).isEqualTo(headers.asMap(String.class, String.class)); + assertThat(jsonPath.<Map<String, String>>read(FIRST_MESSAGE + ".headers")).containsAllEntriesOf(headers.asMap(String.class, String.class)); } @Then("^the date of the message is \"([^\"]*)\"$") http://git-wip-us.apache.org/repos/asf/james-project/blob/7bfb0cd8/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 1ae5a60..d2789b6 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 @@ -23,7 +23,6 @@ import java.util.List; import java.util.Optional; import java.util.function.Function; import java.util.stream.Stream; -import java.util.stream.StreamSupport; import javax.inject.Inject; @@ -34,20 +33,17 @@ import org.apache.james.jmap.model.GetMessagesRequest; import org.apache.james.jmap.model.GetMessagesResponse; import org.apache.james.jmap.model.Message; import org.apache.james.jmap.model.MessageFactory; +import org.apache.james.jmap.model.MessageFactory.MetaDataWithContent; 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.MailboxManager; import org.apache.james.mailbox.MailboxSession; import org.apache.james.mailbox.MessageManager; -import org.apache.james.mailbox.exception.MailboxException; import org.apache.james.mailbox.model.FetchGroupImpl; -import org.apache.james.mailbox.model.MailboxId; import org.apache.james.mailbox.model.MailboxPath; -import org.apache.james.mailbox.model.MessageAttachment; -import org.apache.james.mailbox.model.MessageResult; import org.apache.james.mailbox.model.MessageResultIterator; -import org.javatuples.Triplet; +import org.apache.james.util.streams.Iterators; import com.fasterxml.jackson.databind.ser.PropertyFilter; import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider; @@ -113,8 +109,8 @@ public class GetMessagesMethod implements Method { private GetMessagesResponse getMessagesResponse(MailboxSession mailboxSession, GetMessagesRequest getMessagesRequest) { getMessagesRequest.getAccountId().ifPresent(GetMessagesMethod::notImplemented); - Function<MessageId, Stream<CompletedMessageResult>> loadMessages = loadMessage(mailboxSession); - Function<CompletedMessageResult, Message> convertToJmapMessage = toJmapMessage(mailboxSession); + Function<MessageId, Stream<MetaDataWithContent>> loadMessages = loadMessage(mailboxSession); + Function<MetaDataWithContent, Message> convertToJmapMessage = Throwing.function(messageFactory::fromMetaDataWithContent).sneakyThrow(); List<Message> result = getMessagesRequest.getIds().stream() .flatMap(loadMessages) @@ -128,110 +124,17 @@ public class GetMessagesMethod implements Method { throw new NotImplementedException(); } - - private Function<CompletedMessageResult, Message> toJmapMessage(MailboxSession mailboxSession) { - ThrowingFunction<CompletedMessageResult, Message> function = (completedMessageResult) -> messageFactory.fromMessageResult( - completedMessageResult.messageResult, - completedMessageResult.attachments, - completedMessageResult.mailboxId, - uid -> new MessageId(mailboxSession.getUser(), completedMessageResult.mailboxPath , uid)); - return Throwing.function(function).sneakyThrow(); - } - - private Function<MessageId, Stream<CompletedMessageResult>> - loadMessage(MailboxSession mailboxSession) { - - return Throwing - .function((MessageId messageId) -> { - MailboxPath mailboxPath = messageId.getMailboxPath(); - MessageManager messageManager = mailboxManager.getMailbox(messageId.getMailboxPath(), mailboxSession); - return Triplet.with( - messageManager.getMessages(messageId.getUidAsRange(), FetchGroupImpl.FULL_CONTENT, mailboxSession), - mailboxPath, - messageManager.getId() - ); - }) - .andThen(Throwing.function((triplet) -> retrieveCompleteMessageResults(triplet, mailboxSession))); - } - - private Stream<CompletedMessageResult> retrieveCompleteMessageResults(Triplet<MessageResultIterator, MailboxPath, MailboxId> value, MailboxSession mailboxSession) throws MailboxException { - Iterable<MessageResult> iterable = () -> value.getValue0(); - Stream<MessageResult> targetStream = StreamSupport.stream(iterable.spliterator(), false); - - MailboxPath mailboxPath = value.getValue1(); - MailboxId mailboxId = value.getValue2(); - return targetStream - .map(Throwing.function(this::initializeBuilder).sneakyThrow()) - .map(builder -> builder.mailboxId(mailboxId)) - .map(builder -> builder.mailboxPath(mailboxPath)) - .map(builder -> builder.build()); - } - - private CompletedMessageResult.Builder initializeBuilder(MessageResult message) throws MailboxException { - return CompletedMessageResult.builder() - .messageResult(message) - .attachments(message.getAttachments()); - } - - private static class CompletedMessageResult { - - public static Builder builder() { - return new Builder(); - } - - public static class Builder { - - private MessageResult messageResult; - private List<MessageAttachment> attachments; - private MailboxPath mailboxPath; - private MailboxId mailboxId; - - private Builder() { - } - - public Builder messageResult(MessageResult messageResult) { - Preconditions.checkArgument(messageResult != null); - this.messageResult = messageResult; - return this; - } - - public Builder attachments(List<MessageAttachment> attachments) { - Preconditions.checkArgument(attachments != null); - this.attachments = attachments; - return this; - } - - public Builder mailboxPath(MailboxPath mailboxPath) { - Preconditions.checkArgument(mailboxPath != null); - this.mailboxPath = mailboxPath; - return this; - } - - public Builder mailboxId(MailboxId mailboxId) { - Preconditions.checkArgument(mailboxId != null); - this.mailboxId = mailboxId; - return this; - } - - public CompletedMessageResult build() { - Preconditions.checkState(messageResult != null); - Preconditions.checkState(attachments != null); - Preconditions.checkState(mailboxPath != null); - Preconditions.checkState(mailboxId != null); - return new CompletedMessageResult(messageResult, attachments, mailboxPath, mailboxId); - } - } - - private final MessageResult messageResult; - private final List<MessageAttachment> attachments; - private final MailboxPath mailboxPath; - private final MailboxId mailboxId; - - public CompletedMessageResult(MessageResult messageResult, List<MessageAttachment> attachments, MailboxPath mailboxPath, MailboxId mailboxId) { - this.messageResult = messageResult; - this.attachments = attachments; - this.mailboxPath = mailboxPath; - this.mailboxId = mailboxId; - } + private Function<MessageId, Stream<MetaDataWithContent>> loadMessage(MailboxSession mailboxSession) { + ThrowingFunction<MessageId, Stream<MetaDataWithContent>> toMetaDataWithContentStream = (MessageId messageId) -> { + MailboxPath mailboxPath = messageId.getMailboxPath(); + MessageManager messageManager = mailboxManager.getMailbox(mailboxPath, mailboxSession); + MessageResultIterator messageResultIterator = messageManager.getMessages(messageId.getUidAsRange(), FetchGroupImpl.FULL_CONTENT, mailboxSession); + return Iterators.toStream(messageResultIterator) + .map(Throwing.function(MetaDataWithContent::builderFromMessageResult).sneakyThrow()) + .map(builder -> builder.mailboxId(messageManager.getId())) + .map(builder -> builder.messageId(messageId)) + .map(MetaDataWithContent.Builder::build); + }; + return Throwing.function(toMetaDataWithContentStream).sneakyThrow(); } -} +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/james-project/blob/7bfb0cd8/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/MessageFactory.java ---------------------------------------------------------------------- diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/MessageFactory.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/MessageFactory.java index b401b62..c92293c 100644 --- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/MessageFactory.java +++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/MessageFactory.java @@ -19,6 +19,7 @@ package org.apache.james.jmap.model; import java.io.IOException; +import java.io.InputStream; import java.time.ZoneId; import java.time.ZonedDateTime; import java.util.Collection; @@ -28,6 +29,7 @@ import java.util.Map; import java.util.Map.Entry; import java.util.Optional; import java.util.Set; +import java.util.TimeZone; import java.util.function.Function; import java.util.stream.Collectors; @@ -41,6 +43,7 @@ import org.apache.james.mailbox.exception.MailboxException; import org.apache.james.mailbox.model.Cid; import org.apache.james.mailbox.model.MailboxId; import org.apache.james.mailbox.model.MessageAttachment; +import org.apache.james.mailbox.model.MessageMetaData; import org.apache.james.mailbox.model.MessageResult; import org.apache.james.mailbox.store.extractor.DefaultTextExtractor; import org.apache.james.mailbox.store.mail.model.MailboxMessage; @@ -51,6 +54,7 @@ import org.apache.james.mime4j.message.MessageBuilder; import org.apache.james.mime4j.stream.Field; import com.github.steveash.guavate.Guavate; +import com.google.common.base.Preconditions; import com.google.common.base.Strings; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; @@ -71,47 +75,54 @@ public class MessageFactory { this.messageContentExtractor = messageContentExtractor; } - public Message fromMessageResult(MessageResult messageResult, - List<MessageAttachment> attachments, - MailboxId mailboxId, - Function<Long, MessageId> uidToMessageId) throws MailboxException { - MessageId messageId = uidToMessageId.apply(messageResult.getUid()); - - MessageBuilder parsedMessageResult; - MessageContent messageContent; - try { - parsedMessageResult = MessageBuilder.read(messageResult.getFullContent().getInputStream()); - messageContent = messageContentExtractor.extract(parsedMessageResult.build()); - } catch (IOException e) { - throw new MailboxException("Unable to parse message: " + e.getMessage(), e); - } + public Message fromMetaDataWithContent(MetaDataWithContent message) throws MailboxException { + org.apache.james.mime4j.dom.Message mimeMessage = parse(message); + MessageContent messageContent = extractContent(mimeMessage); return Message.builder() - .id(messageId) - .blobId(BlobId.of(String.valueOf(messageResult.getUid()))) - .threadId(messageId.serialize()) - .mailboxIds(ImmutableList.of(mailboxId.serialize())) - .inReplyToMessageId(getHeader(parsedMessageResult, "in-reply-to")) - .isUnread(! messageResult.getFlags().contains(Flags.Flag.SEEN)) - .isFlagged(messageResult.getFlags().contains(Flags.Flag.FLAGGED)) - .isAnswered(messageResult.getFlags().contains(Flags.Flag.ANSWERED)) - .isDraft(messageResult.getFlags().contains(Flags.Flag.DRAFT)) - .subject(Strings.nullToEmpty(parsedMessageResult.getSubject())) - .headers(toMap(parsedMessageResult.getFields())) - .from(firstFromMailboxList(parsedMessageResult.getFrom())) - .to(fromAddressList(parsedMessageResult.getTo())) - .cc(fromAddressList(parsedMessageResult.getCc())) - .bcc(fromAddressList(parsedMessageResult.getBcc())) - .replyTo(fromAddressList(parsedMessageResult.getReplyTo())) - .size(parsedMessageResult.getSize()) - .date(toZonedDateTime(messageResult.getInternalDate())) + .id(message.getMessageId()) + .blobId(BlobId.of(String.valueOf(message.getUid()))) + .threadId(message.getMessageId().serialize()) + .mailboxIds(ImmutableList.of(message.getMailboxId().serialize())) + .inReplyToMessageId(getHeader(mimeMessage, "in-reply-to")) + .isUnread(! message.getFlags().contains(Flags.Flag.SEEN)) + .isFlagged(message.getFlags().contains(Flags.Flag.FLAGGED)) + .isAnswered(message.getFlags().contains(Flags.Flag.ANSWERED)) + .isDraft(message.getFlags().contains(Flags.Flag.DRAFT)) + .subject(Strings.nullToEmpty(mimeMessage.getSubject()).trim()) + .headers(toMap(mimeMessage.getHeader().getFields())) + .from(firstFromMailboxList(mimeMessage.getFrom())) + .to(fromAddressList(mimeMessage.getTo())) + .cc(fromAddressList(mimeMessage.getCc())) + .bcc(fromAddressList(mimeMessage.getBcc())) + .replyTo(fromAddressList(mimeMessage.getReplyTo())) + .size(message.getSize()) + .date(message.getInternalDateAsZonedDateTime()) .textBody(messageContent.getTextBody().orElse(null)) .htmlBody(messageContent.getHtmlBody().orElse(null)) .preview(getPreview(messageContent)) - .attachments(getAttachments(attachments)) + .attachments(getAttachments(message.getAttachments())) .build(); } + private org.apache.james.mime4j.dom.Message parse(MetaDataWithContent message) throws MailboxException { + try { + return MessageBuilder.read(message.getContent()) + .setDate(message.getInternalDate(), TimeZone.getTimeZone(UTC_ZONE_ID)) + .build(); + } catch (IOException e) { + throw new MailboxException("Unable to parse message: " + e.getMessage(), e); + } + } + + private MessageContent extractContent(org.apache.james.mime4j.dom.Message mimeMessage) throws MailboxException { + try { + return messageContentExtractor.extract(mimeMessage); + } catch (IOException e) { + throw new MailboxException("Unable to extract content: " + e.getMessage(), e); + } + } + public Message fromMailboxMessage(MailboxMessage mailboxMessage, List<MessageAttachment> attachments, Function<Long, MessageId> uidToMessageId) { @@ -242,8 +253,8 @@ public class MessageFactory { .collect(Guavate.toImmutableMap(Map.Entry::getKey, bodyConcatenator)); } - private String getHeader(MessageBuilder message, String header) { - Field field = message.getField(header); + private String getHeader(org.apache.james.mime4j.dom.Message message, String header) { + Field field = message.getHeader().getField(header); if (field == null) { return null; } @@ -262,10 +273,6 @@ public class MessageFactory { return ZonedDateTime.ofInstant(mailboxMessage.getInternalDate().toInstant(), UTC_ZONE_ID); } - private ZonedDateTime toZonedDateTime(Date date) { - return ZonedDateTime.ofInstant(date.toInstant(), UTC_ZONE_ID); - } - private String getTextBody(IndexableMessage im) { return im.getBodyText().map(Strings::emptyToNull).orElse(null); } @@ -290,4 +297,165 @@ public class MessageFactory { .isInline(attachment.isInline()) .build(); } + + public static class MetaDataWithContent implements MessageMetaData { + public static Builder builder() { + return new Builder(); + } + + public static Builder builderFromMessageResult(MessageResult messageResult) throws MailboxException { + Builder builder = builder() + .uid(messageResult.getUid()) + .modSeq(messageResult.getModSeq()) + .flags(messageResult.getFlags()) + .size(messageResult.getSize()) + .internalDate(messageResult.getInternalDate()) + .attachments(messageResult.getAttachments()); + try { + return builder.content(messageResult.getFullContent().getInputStream()); + } catch (IOException e) { + throw new MailboxException("Can't get message full content: " + e.getMessage(), e); + } + } + + public static class Builder { + private Long uid; + private Long modSeq; + private Flags flags; + private Long size; + private Date internalDate; + private InputStream content; + private List<MessageAttachment> attachments; + private MailboxId mailboxId; + private MessageId messageId; + + public Builder uid(long uid) { + this.uid = uid; + return this; + } + + public Builder modSeq(long modSeq) { + this.modSeq = modSeq; + return this; + } + + public Builder flags(Flags flags) { + this.flags = flags; + return this; + } + + public Builder size(long size) { + this.size = size; + return this; + } + + public Builder internalDate(Date internalDate) { + this.internalDate = internalDate; + return this; + } + + public Builder content(InputStream content) { + this.content = content; + return this; + } + + public Builder attachments(List<MessageAttachment> attachments) { + this.attachments = attachments; + return this; + } + + public Builder mailboxId(MailboxId mailboxId) { + this.mailboxId = mailboxId; + return this; + } + + public Builder messageId(MessageId messageId) { + this.messageId = messageId; + return this; + } + + public MetaDataWithContent build() { + Preconditions.checkArgument(uid != null); + if (modSeq == null) { + modSeq = -1L; + } + Preconditions.checkArgument(flags != null); + Preconditions.checkArgument(size != null); + Preconditions.checkArgument(internalDate != null); + Preconditions.checkArgument(content != null); + Preconditions.checkArgument(attachments != null); + Preconditions.checkArgument(mailboxId != null); + Preconditions.checkArgument(messageId != null); + return new MetaDataWithContent(uid, modSeq, flags, size, internalDate, content, attachments, mailboxId, messageId); + } + } + + private final long uid; + private final long modSeq; + private final Flags flags; + private final long size; + private final Date internalDate; + private final InputStream content; + private final List<MessageAttachment> attachments; + private final MailboxId mailboxId; + private final MessageId messageId; + + private MetaDataWithContent(long uid, long modSeq, Flags flags, long size, Date internalDate, InputStream content, List<MessageAttachment> attachments, MailboxId mailboxId, MessageId messageId) { + this.uid = uid; + this.modSeq = modSeq; + this.flags = flags; + this.size = size; + this.internalDate = internalDate; + this.content = content; + this.attachments = attachments; + this.mailboxId = mailboxId; + this.messageId = messageId; + } + + @Override + public long getUid() { + return uid; + } + + @Override + public long getModSeq() { + return modSeq; + } + + @Override + public Flags getFlags() { + return flags; + } + + @Override + public long getSize() { + return size; + } + + @Override + public Date getInternalDate() { + return internalDate; + } + + public ZonedDateTime getInternalDateAsZonedDateTime() { + return ZonedDateTime.ofInstant(internalDate.toInstant(), UTC_ZONE_ID); + } + + public InputStream getContent() { + return content; + } + + public List<MessageAttachment> getAttachments() { + return attachments; + } + + public MailboxId getMailboxId() { + return mailboxId; + } + + public MessageId getMessageId() { + return messageId; + } + + } } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/james-project/blob/7bfb0cd8/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 deleted file mode 100644 index da0f386..0000000 --- a/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/MailboxMessageTest.java +++ /dev/null @@ -1,480 +0,0 @@ -/**************************************************************** - * Licensed to the Apache Software Foundation (ASF) under one * - * or more contributor license agreements. See the NOTICE file * - * distributed with this work for additional information * - * regarding copyright ownership. The ASF licenses this file * - * to you under the Apache License, Version 2.0 (the * - * "License"); you may not use this file except in compliance * - * with the License. You may obtain a copy of the License at * - * * - * http://www.apache.org/licenses/LICENSE-2.0 * - * * - * Unless required by applicable law or agreed to in writing, * - * software distributed under the License is distributed on an * - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * - * KIND, either express or implied. See the License for the * - * specific language governing permissions and limitations * - * under the License. * - ****************************************************************/ -package org.apache.james.jmap.model; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.mock; - -import java.time.ZoneId; -import java.time.ZonedDateTime; -import java.util.Date; -import java.util.Optional; - -import javax.mail.Flags; -import javax.mail.Flags.Flag; -import javax.mail.util.SharedByteArrayInputStream; - -import org.apache.commons.io.IOUtils; -import org.apache.james.jmap.utils.HtmlTextExtractor; -import org.apache.james.mailbox.model.AttachmentId; -import org.apache.james.mailbox.model.Cid; -import org.apache.james.mailbox.model.MessageAttachment; -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.junit.Before; -import org.junit.Test; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; - -public class MailboxMessageTest { - private static final TestId MAILBOX_ID = TestId.of(18L); - private static final long MOD_SEQ = 42L; - private static final ZoneId UTC_ZONE_ID = ZoneId.of("Z"); - private static final ZonedDateTime ZONED_DATE = ZonedDateTime.of(2015, 07, 14, 12, 30, 42, 0, UTC_ZONE_ID); - private static final Date INTERNAL_DATE = Date.from(ZONED_DATE.toInstant()); - - private MessageFactory messageFactory; - private MessagePreviewGenerator messagePreview ; - private HtmlTextExtractor htmlTextExtractor; - - @Before - public void setUp() { - htmlTextExtractor = mock(HtmlTextExtractor.class); - messagePreview = new MessagePreviewGenerator(htmlTextExtractor); - MessageContentExtractor messageContentExtractor = new MessageContentExtractor(); - messageFactory = new MessageFactory(messagePreview, messageContentExtractor); - } - - @Test(expected=IllegalStateException.class) - public void buildShouldThrowWhenIdIsNull() { - Message.builder().build(); - } - - @Test(expected=IllegalStateException.class) - public void buildShouldThrowWhenBlobIdIsNull() { - Message.builder().id(MessageId.of("user|box|1")).build(); - } - - @Test(expected=IllegalStateException.class) - public void buildShouldThrowWhenThreadIdIsNull() { - Message.builder().id(MessageId.of("user|box|1")).blobId(BlobId.of("blobId")).build(); - } - - @Test(expected=IllegalStateException.class) - public void buildShouldThrowWhenThreadIdIsEmpty() { - Message.builder().id(MessageId.of("user|box|1")).blobId(BlobId.of("blobId")).threadId("").build(); - } - - @Test(expected=IllegalStateException.class) - public void buildShouldThrowWhenMailboxIdsIsNull() { - Message.builder().id(MessageId.of("user|box|1")).blobId(BlobId.of("blobId")).threadId("threadId").build(); - } - - @Test(expected=IllegalStateException.class) - public void buildShouldThrowWhenHeadersIsNull() { - Message.builder().id(MessageId.of("user|box|1")).blobId(BlobId.of("blobId")).threadId("threadId").mailboxIds(ImmutableList.of()).build(); - } - - @Test(expected=IllegalStateException.class) - public void buildShouldThrowWhenSubjectIsNull() { - Message.builder().id(MessageId.of("user|box|1")).blobId(BlobId.of("blobId")).threadId("threadId").mailboxIds(ImmutableList.of()).headers(ImmutableMap.of()).build(); - } - - @Test(expected=IllegalStateException.class) - public void buildShouldThrowWhenSubjectIsEmpty() { - Message.builder().id(MessageId.of("user|box|1")).blobId(BlobId.of("blobId")).threadId("threadId").mailboxIds(ImmutableList.of()).headers(ImmutableMap.of()) - .subject("").build(); - } - - @Test(expected=IllegalStateException.class) - public void buildShouldThrowWhenSizeIsNull() { - Message.builder().id(MessageId.of("user|box|1")).blobId(BlobId.of("blobId")).threadId("threadId").mailboxIds(ImmutableList.of()).headers(ImmutableMap.of()) - .subject("subject").build(); - } - - @Test(expected=IllegalStateException.class) - public void buildShouldThrowWhenDateIsNull() { - Message.builder().id(MessageId.of("user|box|1")).blobId(BlobId.of("blobId")).threadId("threadId").mailboxIds(ImmutableList.of()).headers(ImmutableMap.of()) - .subject("subject").size(123).build(); - } - - @Test(expected=IllegalStateException.class) - public void buildShouldThrowWhenPreviewIsNull() { - Message.builder().id(MessageId.of("user|box|1")).blobId(BlobId.of("blobId")).threadId("threadId").mailboxIds(ImmutableList.of()).headers(ImmutableMap.of()) - .subject("subject").size(123).date(ZonedDateTime.now()).build(); - } - - @Test(expected=IllegalStateException.class) - public void buildShouldThrowWhenPreviewIsEmpty() { - Message.builder().id(MessageId.of("user|box|1")).blobId(BlobId.of("blobId")).threadId("threadId").mailboxIds(ImmutableList.of()).headers(ImmutableMap.of()) - .subject("subject").size(123).date(ZonedDateTime.now()).preview("").build(); - } - - @Test - public void buildShouldWorkWhenMandatoryFieldsArePresent() { - ZonedDateTime currentDate = ZonedDateTime.now(); - Message expected = new Message(MessageId.of("user|box|1"), BlobId.of("blobId"), "threadId", ImmutableList.of("mailboxId"), Optional.empty(), false, false, false, false, false, ImmutableMap.of("key", "value"), Optional.empty(), - ImmutableList.of(), ImmutableList.of(), ImmutableList.of(), ImmutableList.of(), "subject", currentDate, 123, "preview", Optional.empty(), Optional.empty(), ImmutableList.of(), ImmutableMap.of()); - Message tested = Message.builder() - .id(MessageId.of("user|box|1")) - .blobId(BlobId.of("blobId")) - .threadId("threadId") - .mailboxIds(ImmutableList.of("mailboxId")) - .headers(ImmutableMap.of("key", "value")) - .subject("subject") - .size(123) - .date(currentDate) - .preview("preview") - .build(); - assertThat(tested).isEqualToComparingFieldByField(expected); - } - - @Test(expected=IllegalStateException.class) - public void buildShouldThrowWhenAttachedMessageIsNotMatchingAttachments() { - Attachment simpleAttachment = Attachment.builder().blobId(BlobId.of("blobId")).type("type").name("name").size(123).build(); - ImmutableList<Attachment> attachments = ImmutableList.of(simpleAttachment); - SubMessage simpleMessage = SubMessage.builder() - .headers(ImmutableMap.of("key", "value")) - .subject("subject") - .date(ZonedDateTime.now()) - .build(); - ImmutableMap<BlobId, SubMessage> attachedMessages = ImmutableMap.of(BlobId.of("differentBlobId"), simpleMessage); - Message.builder() - .id(MessageId.of("user|box|1")) - .blobId(BlobId.of("blobId")) - .threadId("threadId") - .mailboxIds(ImmutableList.of("mailboxId")) - .headers(ImmutableMap.of("key", "value")) - .subject("subject") - .size(123) - .date(ZonedDateTime.now()) - .preview("preview") - .attachments(attachments) - .attachedMessages(attachedMessages) - .build(); - } - - @Test - public void buildShouldWorkWhenAllFieldsArePresent() { - Emailer from = Emailer.builder().name("from").email("from@domain").build(); - ImmutableList<Emailer> to = ImmutableList.of(Emailer.builder().name("to").email("to@domain").build()); - ImmutableList<Emailer> cc = ImmutableList.of(Emailer.builder().name("cc").email("cc@domain").build()); - ImmutableList<Emailer> bcc = ImmutableList.of(Emailer.builder().name("bcc").email("bcc@domain").build()); - ImmutableList<Emailer> replyTo = ImmutableList.of(Emailer.builder().name("replyTo").email("replyTo@domain").build()); - ZonedDateTime currentDate = ZonedDateTime.now(); - Attachment simpleAttachment = Attachment.builder().blobId(BlobId.of("blobId")).type("type").name("name").size(123).build(); - ImmutableList<Attachment> attachments = ImmutableList.of(simpleAttachment); - SubMessage simpleMessage = SubMessage.builder() - .headers(ImmutableMap.of("key", "value")) - .subject("subject") - .date(currentDate) - .build(); - ImmutableMap<BlobId, SubMessage> attachedMessages = ImmutableMap.of(BlobId.of("blobId"), simpleMessage); - Message expected = new Message( - MessageId.of("user|box|1"), - BlobId.of("blobId"), - "threadId", - ImmutableList.of("mailboxId"), - Optional.of("inReplyToMessageId"), - true, - true, - true, - true, - true, - ImmutableMap.of("key", "value"), - Optional.of(from), - to, - cc, - bcc, - replyTo, - "subject", - currentDate, - 123, - "preview", - Optional.of("textBody"), - Optional.of("htmlBody"), - attachments, - attachedMessages); - Message tested = Message.builder() - .id(MessageId.of("user|box|1")) - .blobId(BlobId.of("blobId")) - .threadId("threadId") - .mailboxIds(ImmutableList.of("mailboxId")) - .inReplyToMessageId("inReplyToMessageId") - .isUnread(true) - .isFlagged(true) - .isAnswered(true) - .isDraft(true) - .headers(ImmutableMap.of("key", "value")) - .from(from) - .to(to) - .cc(cc) - .bcc(bcc) - .replyTo(replyTo) - .subject("subject") - .date(currentDate) - .size(123) - .preview("preview") - .textBody("textBody") - .htmlBody("htmlBody") - .attachments(attachments) - .attachedMessages(attachedMessages) - .build(); - assertThat(tested).isEqualToComparingFieldByField(expected); - } - - @Test - public void emptyMailShouldBeLoadedIntoMessage() throws Exception { - MailboxMessage testMail = new SimpleMailboxMessage( - INTERNAL_DATE, - 0, - 0, - new SharedByteArrayInputStream("".getBytes()), - new Flags(Flag.SEEN), - new PropertyBuilder(), - MAILBOX_ID); - testMail.setModSeq(MOD_SEQ); - Message testee = messageFactory.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, "", ImmutableMap.of(), ZONED_DATE); - } - - @Test - public void flagsShouldBeSetIntoMessage() throws Exception { - Flags flags = new Flags(); - flags.add(Flag.ANSWERED); - flags.add(Flag.FLAGGED); - flags.add(Flag.DRAFT); - MailboxMessage testMail = new SimpleMailboxMessage( - INTERNAL_DATE, - 0, - 0, - new SharedByteArrayInputStream("".getBytes()), - flags, - new PropertyBuilder(), - MAILBOX_ID); - testMail.setModSeq(MOD_SEQ); - Message testee = messageFactory.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); - } - - @Test - public void headersShouldBeSetIntoMessage() throws Exception { - String headers = "From: user <user@domain>\n" - + "Subject: test subject\n" - + "To: user1 <user1@domain>, user2 <user2@domain>\n" - + "Cc: usercc <usercc@domain>\n" - + "Bcc: userbcc <userbcc@domain>\n" - + "Reply-To: \"user to reply to\" <user.reply.to@domain>\n" - + "In-Reply-To: <[email protected]>\n" - + "Other-header: other header value"; - MailboxMessage testMail = new SimpleMailboxMessage( - INTERNAL_DATE, - headers.length(), - headers.length(), - new SharedByteArrayInputStream(headers.getBytes()), - new Flags(Flag.SEEN), - new PropertyBuilder(), - MAILBOX_ID); - testMail.setModSeq(MOD_SEQ); - - Emailer user = Emailer.builder().name("user").email("user@domain").build(); - Emailer user1 = Emailer.builder().name("user1").email("user1@domain").build(); - Emailer user2 = Emailer.builder().name("user2").email("user2@domain").build(); - Emailer usercc = Emailer.builder().name("usercc").email("usercc@domain").build(); - Emailer userbcc = Emailer.builder().name("userbcc").email("userbcc@domain").build(); - Emailer userRT = Emailer.builder().name("user to reply to").email("user.reply.to@domain").build(); - ImmutableMap<String, String> headersMap = ImmutableMap.<String, String>builder() - .put("cc", "usercc <usercc@domain>") - .put("bcc", "userbcc <userbcc@domain>") - .put("subject", "test subject") - .put("from", "user <user@domain>") - .put("to", "user1 <user1@domain>, user2 <user2@domain>") - .put("reply-to", "\"user to reply to\" <user.reply.to@domain>") - .put("in-reply-to", "<[email protected]>") - .put("other-header", "other header value") - .build(); - Message testee = messageFactory.fromMailboxMessage(testMail, ImmutableList.of(), x -> MessageId.of("user|box|" + x)); - Message expected = Message.builder() - .id(MessageId.of("user|box|0")) - .blobId(BlobId.of("0")) - .threadId("user|box|0") - .mailboxIds(ImmutableList.of(MAILBOX_ID.serialize())) - .inReplyToMessageId("<[email protected]>") - .headers(headersMap) - .from(user) - .to(ImmutableList.of(user1, user2)) - .cc(ImmutableList.of(usercc)) - .bcc(ImmutableList.of(userbcc)) - .replyTo(ImmutableList.of(userRT)) - .subject("test subject") - .date(ZONED_DATE) - .size(headers.length()) - .preview("(Empty)") - .build(); - assertThat(testee).isEqualToComparingFieldByField(expected); - } - - @Test - public void textBodyShouldBeSetIntoMessage() throws Exception { - String headers = "Subject: test subject\n"; - String body = "Mail body"; - String mail = headers + "\n" + body; - MailboxMessage testMail = new SimpleMailboxMessage( - INTERNAL_DATE, - mail.length(), - headers.length(), - new SharedByteArrayInputStream(mail.getBytes()), - new Flags(Flag.SEEN), - new PropertyBuilder(), - MAILBOX_ID); - testMail.setModSeq(MOD_SEQ); - Message testee = messageFactory.fromMailboxMessage(testMail, ImmutableList.of(), x -> MessageId.of("user|box|" + x)); - assertThat(testee.getTextBody()).hasValue("Mail body"); - } - - @Test - public void previewShouldBeLimitedTo256Length() throws Exception { - String headers = "Subject: test subject\n"; - String body300 = "0000000000111111111122222222223333333333444444444455555555556666666666777777777788888888889999999999" - + "0000000000111111111122222222223333333333444444444455555555556666666666777777777788888888889999999999" - + "0000000000111111111122222222223333333333444444444455555555556666666666777777777788888888889999999999"; - String expectedPreview = "0000000000111111111122222222223333333333444444444455555555556666666666777777777788888888889999999999" - + "0000000000111111111122222222223333333333444444444455555555556666666666777777777788888888889999999999" - + "00000000001111111111222222222233333333334444444444555..."; - assertThat(body300.length()).isEqualTo(300); - assertThat(expectedPreview.length()).isEqualTo(256); - String mail = headers + "\n" + body300; - MailboxMessage testMail = new SimpleMailboxMessage( - INTERNAL_DATE, - mail.length(), - headers.length(), - new SharedByteArrayInputStream(mail.getBytes()), - new Flags(Flag.SEEN), - new PropertyBuilder(), - MAILBOX_ID); - testMail.setModSeq(MOD_SEQ); - Message testee = messageFactory.fromMailboxMessage(testMail, ImmutableList.of(), x -> MessageId.of("user|box|" + x)); - assertThat(testee.getPreview()).isEqualTo(expectedPreview); - } - - @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 = messageFactory.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, - 0, - new SharedByteArrayInputStream(IOUtils.toByteArray(ClassLoader.getSystemResourceAsStream("spamMail.eml"))), - new Flags(Flag.SEEN), - new PropertyBuilder(), - MAILBOX_ID); - testMail.setModSeq(MOD_SEQ); - - String payload = "payload"; - BlobId blodId = BlobId.of("id1"); - String type = "content"; - Attachment expectedAttachment = Attachment.builder() - .blobId(blodId) - .size(payload.length()) - .type(type) - .cid("cid") - .isInline(true) - .build(); - Message testee = messageFactory.fromMailboxMessage(testMail, - ImmutableList.of(MessageAttachment.builder() - .attachment(org.apache.james.mailbox.model.Attachment.builder() - .attachmentId(AttachmentId.from(blodId.getRawValue())) - .bytes(payload.getBytes()) - .type(type) - .build()) - .cid(Cid.from("cid")) - .isInline(true) - .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(BlobId.of("blobId")) - .threadId("threadId") - .mailboxIds(ImmutableList.of("mailboxId")) - .headers(ImmutableMap.of("key", "value")) - .subject("subject") - .size(1) - .date(ZonedDateTime.now()) - .preview("preview") - .attachedMessages(ImmutableMap.of(BlobId.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(BlobId.of("blobId")) - .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(BlobId.of("key")) - .size(1) - .type("type") - .build())) - .attachedMessages(ImmutableMap.of(BlobId.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/7bfb0cd8/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/MessageFactoryTest.java ---------------------------------------------------------------------- diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/MessageFactoryTest.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/MessageFactoryTest.java new file mode 100644 index 0000000..5a22883 --- /dev/null +++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/MessageFactoryTest.java @@ -0,0 +1,262 @@ +/**************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you under the Apache License, Version 2.0 (the * + * "License"); you may not use this file except in compliance * + * with the License. You may obtain a copy of the License at * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, * + * software distributed under the License is distributed on an * + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * + * KIND, either express or implied. See the License for the * + * specific language governing permissions and limitations * + * under the License. * + ****************************************************************/ +package org.apache.james.jmap.model; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; + +import java.io.ByteArrayInputStream; +import java.time.ZoneId; +import java.time.ZonedDateTime; +import java.util.Date; + +import javax.mail.Flags; +import javax.mail.Flags.Flag; + +import org.apache.commons.io.IOUtils; +import org.apache.james.jmap.model.MessageFactory.MetaDataWithContent; +import org.apache.james.jmap.utils.HtmlTextExtractor; +import org.apache.james.mailbox.model.AttachmentId; +import org.apache.james.mailbox.model.Cid; +import org.apache.james.mailbox.model.MessageAttachment; +import org.apache.james.mailbox.store.TestId; +import org.junit.Before; +import org.junit.Test; + +import com.google.common.base.Charsets; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; + +public class MessageFactoryTest { + private static final TestId MAILBOX_ID = TestId.of(18L); + private static final ZoneId UTC_ZONE_ID = ZoneId.of("Z"); + private static final ZonedDateTime ZONED_DATE = ZonedDateTime.of(2015, 07, 14, 12, 30, 42, 0, UTC_ZONE_ID); + private static final Date INTERNAL_DATE = Date.from(ZONED_DATE.toInstant()); + + private MessageFactory messageFactory; + private MessagePreviewGenerator messagePreview ; + private HtmlTextExtractor htmlTextExtractor; + + @Before + public void setUp() { + htmlTextExtractor = mock(HtmlTextExtractor.class); + messagePreview = new MessagePreviewGenerator(htmlTextExtractor); + MessageContentExtractor messageContentExtractor = new MessageContentExtractor(); + messageFactory = new MessageFactory(messagePreview, messageContentExtractor); + } + @Test + public void emptyMailShouldBeLoadedIntoMessage() throws Exception { + MetaDataWithContent testMail = MetaDataWithContent.builder() + .uid(2) + .flags(new Flags(Flag.SEEN)) + .size(0) + .internalDate(INTERNAL_DATE) + .content(new ByteArrayInputStream("".getBytes(Charsets.UTF_8))) + .attachments(ImmutableList.of()) + .mailboxId(MAILBOX_ID) + .messageId(MessageId.of("test|test|2")) + .build(); + + Message testee = messageFactory.fromMetaDataWithContent(testMail); + assertThat(testee) + .extracting(Message::getPreview, Message::getSize, Message::getSubject, Message::getHeaders, Message::getDate) + .containsExactly("(Empty)", 0L, "", ImmutableMap.of("Date", "Tue, 14 Jul 2015 12:30:42 +0000", "MIME-Version", "1.0"), ZONED_DATE); + } + + @Test + public void flagsShouldBeSetIntoMessage() throws Exception { + Flags flags = new Flags(); + flags.add(Flag.ANSWERED); + flags.add(Flag.FLAGGED); + flags.add(Flag.DRAFT); + MetaDataWithContent testMail = MetaDataWithContent.builder() + .uid(2) + .flags(flags) + .size(0) + .internalDate(INTERNAL_DATE) + .content(new ByteArrayInputStream("".getBytes(Charsets.UTF_8))) + .attachments(ImmutableList.of()) + .mailboxId(MAILBOX_ID) + .messageId(MessageId.of("test|test|2")) + .build(); + Message testee = messageFactory.fromMetaDataWithContent(testMail); + assertThat(testee) + .extracting(Message::isIsUnread, Message::isIsFlagged, Message::isIsAnswered, Message::isIsDraft) + .containsExactly(true, true, true, true); + } + + @Test + public void headersShouldBeSetIntoMessage() throws Exception { + String headers = "From: user <user@domain>\n" + + "Subject: test subject\n" + + "To: user1 <user1@domain>, user2 <user2@domain>\n" + + "Cc: usercc <usercc@domain>\n" + + "Bcc: userbcc <userbcc@domain>\n" + + "Reply-To: \"user to reply to\" <user.reply.to@domain>\n" + + "In-Reply-To: <[email protected]>\n" + + "Other-header: other header value"; + MetaDataWithContent testMail = MetaDataWithContent.builder() + .uid(2) + .flags(new Flags(Flag.SEEN)) + .size(headers.length()) + .internalDate(INTERNAL_DATE) + .content(new ByteArrayInputStream(headers.getBytes(Charsets.UTF_8))) + .attachments(ImmutableList.of()) + .mailboxId(MAILBOX_ID) + .messageId(MessageId.of("user|box|2")) + .build(); + + Emailer user = Emailer.builder().name("user").email("user@domain").build(); + Emailer user1 = Emailer.builder().name("user1").email("user1@domain").build(); + Emailer user2 = Emailer.builder().name("user2").email("user2@domain").build(); + Emailer usercc = Emailer.builder().name("usercc").email("usercc@domain").build(); + Emailer userbcc = Emailer.builder().name("userbcc").email("userbcc@domain").build(); + Emailer userRT = Emailer.builder().name("user to reply to").email("user.reply.to@domain").build(); + ImmutableMap<String, String> headersMap = ImmutableMap.<String, String>builder() + .put("Cc", "usercc <usercc@domain>") + .put("Bcc", "userbcc <userbcc@domain>") + .put("Subject", "test subject") + .put("From", "user <user@domain>") + .put("To", "user1 <user1@domain>, user2 <user2@domain>") + .put("Reply-To", "\"user to reply to\" <user.reply.to@domain>") + .put("In-Reply-To", "<[email protected]>") + .put("Other-header", "other header value") + .put("Date", "Tue, 14 Jul 2015 12:30:42 +0000") + .put("MIME-Version", "1.0") + .build(); + Message testee = messageFactory.fromMetaDataWithContent(testMail); + Message expected = Message.builder() + .id(MessageId.of("user|box|2")) + .blobId(BlobId.of("2")) + .threadId("user|box|2") + .mailboxIds(ImmutableList.of(MAILBOX_ID.serialize())) + .inReplyToMessageId("<[email protected]>") + .headers(headersMap) + .from(user) + .to(ImmutableList.of(user1, user2)) + .cc(ImmutableList.of(usercc)) + .bcc(ImmutableList.of(userbcc)) + .replyTo(ImmutableList.of(userRT)) + .subject("test subject") + .date(ZONED_DATE) + .size(headers.length()) + .preview("(Empty)") + .textBody("") + .build(); + assertThat(testee).isEqualToComparingFieldByField(expected); + } + + @Test + public void textBodyShouldBeSetIntoMessage() throws Exception { + String headers = "Subject: test subject\n"; + String body = "Mail body"; + String mail = headers + "\n" + body; + MetaDataWithContent testMail = MetaDataWithContent.builder() + .uid(2) + .flags(new Flags(Flag.SEEN)) + .size(mail.length()) + .internalDate(INTERNAL_DATE) + .content(new ByteArrayInputStream(mail.getBytes(Charsets.UTF_8))) + .attachments(ImmutableList.of()) + .mailboxId(MAILBOX_ID) + .messageId(MessageId.of("user|box|2")) + .build(); + Message testee = messageFactory.fromMetaDataWithContent(testMail); + assertThat(testee.getTextBody()).hasValue("Mail body"); + } + + @Test + public void previewShouldBeLimitedTo256Length() throws Exception { + String headers = "Subject: test subject\n"; + String body300 = "0000000000111111111122222222223333333333444444444455555555556666666666777777777788888888889999999999" + + "0000000000111111111122222222223333333333444444444455555555556666666666777777777788888888889999999999" + + "0000000000111111111122222222223333333333444444444455555555556666666666777777777788888888889999999999"; + String expectedPreview = "0000000000111111111122222222223333333333444444444455555555556666666666777777777788888888889999999999" + + "0000000000111111111122222222223333333333444444444455555555556666666666777777777788888888889999999999" + + "00000000001111111111222222222233333333334444444444555..."; + assertThat(body300.length()).isEqualTo(300); + assertThat(expectedPreview.length()).isEqualTo(256); + String mail = headers + "\n" + body300; + MetaDataWithContent testMail = MetaDataWithContent.builder() + .uid(2) + .flags(new Flags(Flag.SEEN)) + .size(mail.length()) + .internalDate(INTERNAL_DATE) + .content(new ByteArrayInputStream(mail.getBytes(Charsets.UTF_8))) + .attachments(ImmutableList.of()) + .mailboxId(MAILBOX_ID) + .messageId(MessageId.of("user|box|2")) + .build(); + Message testee = messageFactory.fromMetaDataWithContent(testMail); + assertThat(testee.getPreview()).isEqualTo(expectedPreview); + } + + @Test + public void attachmentsShouldBeEmptyWhenNone() throws Exception { + MetaDataWithContent testMail = MetaDataWithContent.builder() + .uid(2) + .flags(new Flags(Flag.SEEN)) + .size(0) + .internalDate(INTERNAL_DATE) + .content(new ByteArrayInputStream(IOUtils.toByteArray(ClassLoader.getSystemResourceAsStream("spamMail.eml")))) + .attachments(ImmutableList.of()) + .mailboxId(MAILBOX_ID) + .messageId(MessageId.of("user|box|2")) + .build(); + Message testee = messageFactory.fromMetaDataWithContent(testMail); + assertThat(testee.getAttachments()).isEmpty(); + } + + @Test + public void attachmentsShouldBeRetrievedWhenSome() throws Exception { + String payload = "payload"; + BlobId blodId = BlobId.of("id1"); + String type = "content"; + Attachment expectedAttachment = Attachment.builder() + .blobId(blodId) + .size(payload.length()) + .type(type) + .cid("cid") + .isInline(true) + .build(); + MetaDataWithContent testMail = MetaDataWithContent.builder() + .uid(2) + .flags(new Flags(Flag.SEEN)) + .size(0) + .internalDate(INTERNAL_DATE) + .content(new ByteArrayInputStream(IOUtils.toByteArray(ClassLoader.getSystemResourceAsStream("spamMail.eml")))) + .attachments(ImmutableList.of(MessageAttachment.builder() + .attachment(org.apache.james.mailbox.model.Attachment.builder() + .attachmentId(AttachmentId.from(blodId.getRawValue())) + .bytes(payload.getBytes()) + .type(type) + .build()) + .cid(Cid.from("cid")) + .isInline(true) + .build())) + .mailboxId(MAILBOX_ID) + .messageId(MessageId.of("user|box|2")) + .build(); + + Message testee = messageFactory.fromMetaDataWithContent(testMail); + + assertThat(testee.getAttachments()).hasSize(1); + assertThat(testee.getAttachments().get(0)).isEqualToComparingFieldByField(expectedAttachment); + } +} http://git-wip-us.apache.org/repos/asf/james-project/blob/7bfb0cd8/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/MessageTest.java ---------------------------------------------------------------------- diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/MessageTest.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/MessageTest.java new file mode 100644 index 0000000..8953bc1 --- /dev/null +++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/MessageTest.java @@ -0,0 +1,256 @@ +/**************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you under the Apache License, Version 2.0 (the * + * "License"); you may not use this file except in compliance * + * with the License. You may obtain a copy of the License at * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, * + * software distributed under the License is distributed on an * + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * + * KIND, either express or implied. See the License for the * + * specific language governing permissions and limitations * + * under the License. * + ****************************************************************/ +package org.apache.james.jmap.model; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.time.ZonedDateTime; +import java.util.Optional; + +import org.junit.Test; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; + +public class MessageTest { + + + @Test(expected=IllegalStateException.class) + public void buildShouldThrowWhenIdIsNull() { + Message.builder().build(); + } + + @Test(expected=IllegalStateException.class) + public void buildShouldThrowWhenBlobIdIsNull() { + Message.builder().id(MessageId.of("user|box|1")).build(); + } + + @Test(expected=IllegalStateException.class) + public void buildShouldThrowWhenThreadIdIsNull() { + Message.builder().id(MessageId.of("user|box|1")).blobId(BlobId.of("blobId")).build(); + } + + @Test(expected=IllegalStateException.class) + public void buildShouldThrowWhenThreadIdIsEmpty() { + Message.builder().id(MessageId.of("user|box|1")).blobId(BlobId.of("blobId")).threadId("").build(); + } + + @Test(expected=IllegalStateException.class) + public void buildShouldThrowWhenMailboxIdsIsNull() { + Message.builder().id(MessageId.of("user|box|1")).blobId(BlobId.of("blobId")).threadId("threadId").build(); + } + + @Test(expected=IllegalStateException.class) + public void buildShouldThrowWhenHeadersIsNull() { + Message.builder().id(MessageId.of("user|box|1")).blobId(BlobId.of("blobId")).threadId("threadId").mailboxIds(ImmutableList.of()).build(); + } + + @Test(expected=IllegalStateException.class) + public void buildShouldThrowWhenSubjectIsNull() { + Message.builder().id(MessageId.of("user|box|1")).blobId(BlobId.of("blobId")).threadId("threadId").mailboxIds(ImmutableList.of()).headers(ImmutableMap.of()).build(); + } + + @Test(expected=IllegalStateException.class) + public void buildShouldThrowWhenSubjectIsEmpty() { + Message.builder().id(MessageId.of("user|box|1")).blobId(BlobId.of("blobId")).threadId("threadId").mailboxIds(ImmutableList.of()).headers(ImmutableMap.of()) + .subject("").build(); + } + + @Test(expected=IllegalStateException.class) + public void buildShouldThrowWhenSizeIsNull() { + Message.builder().id(MessageId.of("user|box|1")).blobId(BlobId.of("blobId")).threadId("threadId").mailboxIds(ImmutableList.of()).headers(ImmutableMap.of()) + .subject("subject").build(); + } + + @Test(expected=IllegalStateException.class) + public void buildShouldThrowWhenDateIsNull() { + Message.builder().id(MessageId.of("user|box|1")).blobId(BlobId.of("blobId")).threadId("threadId").mailboxIds(ImmutableList.of()).headers(ImmutableMap.of()) + .subject("subject").size(123).build(); + } + + @Test(expected=IllegalStateException.class) + public void buildShouldThrowWhenPreviewIsNull() { + Message.builder().id(MessageId.of("user|box|1")).blobId(BlobId.of("blobId")).threadId("threadId").mailboxIds(ImmutableList.of()).headers(ImmutableMap.of()) + .subject("subject").size(123).date(ZonedDateTime.now()).build(); + } + + @Test(expected=IllegalStateException.class) + public void buildShouldThrowWhenPreviewIsEmpty() { + Message.builder().id(MessageId.of("user|box|1")).blobId(BlobId.of("blobId")).threadId("threadId").mailboxIds(ImmutableList.of()).headers(ImmutableMap.of()) + .subject("subject").size(123).date(ZonedDateTime.now()).preview("").build(); + } + + @Test + public void buildShouldWorkWhenMandatoryFieldsArePresent() { + ZonedDateTime currentDate = ZonedDateTime.now(); + Message expected = new Message(MessageId.of("user|box|1"), BlobId.of("blobId"), "threadId", ImmutableList.of("mailboxId"), Optional.empty(), false, false, false, false, false, ImmutableMap.of("key", "value"), Optional.empty(), + ImmutableList.of(), ImmutableList.of(), ImmutableList.of(), ImmutableList.of(), "subject", currentDate, 123, "preview", Optional.empty(), Optional.empty(), ImmutableList.of(), ImmutableMap.of()); + Message tested = Message.builder() + .id(MessageId.of("user|box|1")) + .blobId(BlobId.of("blobId")) + .threadId("threadId") + .mailboxIds(ImmutableList.of("mailboxId")) + .headers(ImmutableMap.of("key", "value")) + .subject("subject") + .size(123) + .date(currentDate) + .preview("preview") + .build(); + assertThat(tested).isEqualToComparingFieldByField(expected); + } + + @Test(expected=IllegalStateException.class) + public void buildShouldThrowWhenAttachedMessageIsNotMatchingAttachments() { + Attachment simpleAttachment = Attachment.builder().blobId(BlobId.of("blobId")).type("type").name("name").size(123).build(); + ImmutableList<Attachment> attachments = ImmutableList.of(simpleAttachment); + SubMessage simpleMessage = SubMessage.builder() + .headers(ImmutableMap.of("key", "value")) + .subject("subject") + .date(ZonedDateTime.now()) + .build(); + ImmutableMap<BlobId, SubMessage> attachedMessages = ImmutableMap.of(BlobId.of("differentBlobId"), simpleMessage); + Message.builder() + .id(MessageId.of("user|box|1")) + .blobId(BlobId.of("blobId")) + .threadId("threadId") + .mailboxIds(ImmutableList.of("mailboxId")) + .headers(ImmutableMap.of("key", "value")) + .subject("subject") + .size(123) + .date(ZonedDateTime.now()) + .preview("preview") + .attachments(attachments) + .attachedMessages(attachedMessages) + .build(); + } + + @Test + public void buildShouldWorkWhenAllFieldsArePresent() { + Emailer from = Emailer.builder().name("from").email("from@domain").build(); + ImmutableList<Emailer> to = ImmutableList.of(Emailer.builder().name("to").email("to@domain").build()); + ImmutableList<Emailer> cc = ImmutableList.of(Emailer.builder().name("cc").email("cc@domain").build()); + ImmutableList<Emailer> bcc = ImmutableList.of(Emailer.builder().name("bcc").email("bcc@domain").build()); + ImmutableList<Emailer> replyTo = ImmutableList.of(Emailer.builder().name("replyTo").email("replyTo@domain").build()); + ZonedDateTime currentDate = ZonedDateTime.now(); + Attachment simpleAttachment = Attachment.builder().blobId(BlobId.of("blobId")).type("type").name("name").size(123).build(); + ImmutableList<Attachment> attachments = ImmutableList.of(simpleAttachment); + SubMessage simpleMessage = SubMessage.builder() + .headers(ImmutableMap.of("key", "value")) + .subject("subject") + .date(currentDate) + .build(); + ImmutableMap<BlobId, SubMessage> attachedMessages = ImmutableMap.of(BlobId.of("blobId"), simpleMessage); + Message expected = new Message( + MessageId.of("user|box|1"), + BlobId.of("blobId"), + "threadId", + ImmutableList.of("mailboxId"), + Optional.of("inReplyToMessageId"), + true, + true, + true, + true, + true, + ImmutableMap.of("key", "value"), + Optional.of(from), + to, + cc, + bcc, + replyTo, + "subject", + currentDate, + 123, + "preview", + Optional.of("textBody"), + Optional.of("htmlBody"), + attachments, + attachedMessages); + Message tested = Message.builder() + .id(MessageId.of("user|box|1")) + .blobId(BlobId.of("blobId")) + .threadId("threadId") + .mailboxIds(ImmutableList.of("mailboxId")) + .inReplyToMessageId("inReplyToMessageId") + .isUnread(true) + .isFlagged(true) + .isAnswered(true) + .isDraft(true) + .headers(ImmutableMap.of("key", "value")) + .from(from) + .to(to) + .cc(cc) + .bcc(bcc) + .replyTo(replyTo) + .subject("subject") + .date(currentDate) + .size(123) + .preview("preview") + .textBody("textBody") + .htmlBody("htmlBody") + .attachments(attachments) + .attachedMessages(attachedMessages) + .build(); + assertThat(tested).isEqualToComparingFieldByField(expected); + } + + @Test(expected = IllegalStateException.class) + public void buildShouldThrowWhenOneAttachedMessageIsNotInAttachments() throws Exception { + Message.builder() + .id(MessageId.of("user|box|1")) + .blobId(BlobId.of("blobId")) + .threadId("threadId") + .mailboxIds(ImmutableList.of("mailboxId")) + .headers(ImmutableMap.of("key", "value")) + .subject("subject") + .size(1) + .date(ZonedDateTime.now()) + .preview("preview") + .attachedMessages(ImmutableMap.of(BlobId.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(BlobId.of("blobId")) + .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(BlobId.of("key")) + .size(1) + .type("type") + .build())) + .attachedMessages(ImmutableMap.of(BlobId.of("key"), SubMessage.builder() + .headers(ImmutableMap.of("key", "value")) + .subject("subject") + .date(ZonedDateTime.now()) + .build())) + .build(); + } +} --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
