You are viewing a plain text version of this content. The canonical link for it is here.
Posted to server-dev@james.apache.org by ro...@apache.org on 2016/08/29 13:28:09 UTC
[12/17] james-project git commit: JAMES-1818 Remove store usage in
getMessagesMethod by using managers
JAMES-1818 Remove store usage in getMessagesMethod by using managers
Project: http://git-wip-us.apache.org/repos/asf/james-project/repo
Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/844a7409
Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/844a7409
Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/844a7409
Branch: refs/heads/master
Commit: 844a7409613678c7b3b34b060923d60cd32b0cee
Parents: 8c4e86d
Author: Raphael Ouazana <ra...@linagora.com>
Authored: Mon Aug 22 17:38:23 2016 +0200
Committer: Raphael Ouazana <ra...@linagora.com>
Committed: Mon Aug 29 15:15:44 2016 +0200
----------------------------------------------------------------------
.../org/apache/james/jmap/JMAPCommonModule.java | 2 +
.../integration/SetMessagesMethodTest.java | 1 -
.../test/resources/cucumber/GetMessages.feature | 10 +-
.../james/jmap/methods/GetMessagesMethod.java | 103 ++++++-----
.../jmap/model/MessageContentExtractor.java | 127 ++++++++++++++
.../apache/james/jmap/model/MessageFactory.java | 127 +++++++++++++-
.../jmap/methods/GetMessagesMethodTest.java | 25 +--
.../SetMessagesCreationProcessorTest.java | 4 +-
.../james/jmap/model/MailboxMessageTest.java | 3 +-
.../jmap/model/MessageContentExtractorTest.java | 171 +++++++++++++++++++
.../apache/james/jmap/send/MailFactoryTest.java | 4 +-
11 files changed, 506 insertions(+), 71 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/james-project/blob/844a7409/server/container/guice/guice-common/src/main/java/org/apache/james/jmap/JMAPCommonModule.java
----------------------------------------------------------------------
diff --git a/server/container/guice/guice-common/src/main/java/org/apache/james/jmap/JMAPCommonModule.java b/server/container/guice/guice-common/src/main/java/org/apache/james/jmap/JMAPCommonModule.java
index 77cfe0f..e9d5c6f 100644
--- a/server/container/guice/guice-common/src/main/java/org/apache/james/jmap/JMAPCommonModule.java
+++ b/server/container/guice/guice-common/src/main/java/org/apache/james/jmap/JMAPCommonModule.java
@@ -30,6 +30,7 @@ import org.apache.james.jmap.crypto.JamesSignatureHandler;
import org.apache.james.jmap.crypto.SignatureHandler;
import org.apache.james.jmap.crypto.SignedTokenFactory;
import org.apache.james.jmap.crypto.SignedTokenManager;
+import org.apache.james.jmap.model.MessageContentExtractor;
import org.apache.james.jmap.model.MessageFactory;
import org.apache.james.jmap.model.MessagePreviewGenerator;
import org.apache.james.jmap.send.MailFactory;
@@ -63,6 +64,7 @@ public class JMAPCommonModule extends AbstractModule {
bind(AutomaticallySentMailDetectorImpl.class).in(Scopes.SINGLETON);
bind(MessageFactory.class).in(Scopes.SINGLETON);
bind(MessagePreviewGenerator.class).in(Scopes.SINGLETON);
+ bind(MessageContentExtractor.class).in(Scopes.SINGLETON);
bind(HeadersAuthenticationExtractor.class).in(Scopes.SINGLETON);
bind(StoreAttachmentManager.class).in(Scopes.SINGLETON);
http://git-wip-us.apache.org/repos/asf/james-project/blob/844a7409/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/SetMessagesMethodTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/SetMessagesMethodTest.java b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/SetMessagesMethodTest.java
index c70a7be..7fa3e83 100644
--- a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/SetMessagesMethodTest.java
+++ b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/SetMessagesMethodTest.java
@@ -2014,7 +2014,6 @@ public abstract class SetMessagesMethodTest {
.body(firstAttachment + ".size", equalTo((int) attachment.getSize()));
}
- @Ignore("We should rework org.apache.james.jmap.model.message.MimePart to handle multipart/alternative and multipart/mixed")
@Test
public void attachmentsAndBodyShouldBeRetrievedWhenChainingSetMessagesAndGetMessagesWithTextBodyAndHtmlAttachment() throws Exception {
jmapServer.serverProbe().createMailbox(MailboxConstants.USER_NAMESPACE, username, "sent");
http://git-wip-us.apache.org/repos/asf/james-project/blob/844a7409/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/resources/cucumber/GetMessages.feature
----------------------------------------------------------------------
diff --git a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/resources/cucumber/GetMessages.feature b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/resources/cucumber/GetMessages.feature
index 0cf3fb7..1a8271b 100644
--- a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/resources/cucumber/GetMessages.feature
+++ b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/resources/cucumber/GetMessages.feature
@@ -44,7 +44,7 @@ Feature: GetMessages method
And the isUnread of the message is "true"
And the preview of the message is "testmail"
And the headers of the message contains:
- |subject |my test subject |
+ |Subject |my test subject |
And the date of the message is "2014-10-30T14:12:00Z"
And the hasAttachment of the message is "false"
And the list of attachments of the message is empty
@@ -61,8 +61,8 @@ Feature: GetMessages method
And the isUnread of the message is "true"
And the preview of the message is <preview>
And the headers of the message contains:
- |content-type |text/html |
- |subject |<subject-header> |
+ |Content-Type |text/html |
+ |Subject |<subject-header> |
And the date of the message is "2014-10-30T14:12:00Z"
Examples:
@@ -113,8 +113,8 @@ Feature: GetMessages method
And the property "isUnread" of the message is null
And the property "preview" of the message is null
And the headers of the message contains:
- |from |user@domain.tld |
- |header2 |Header2Content |
+ |From |user@domain.tld |
+ |HEADer2 |Header2Content |
And the property "date" of the message is null
Scenario: Retrieving message should return not found when id does not match
http://git-wip-us.apache.org/repos/asf/james-project/blob/844a7409/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 8bc0a3e..1ae5a60 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
@@ -19,7 +19,6 @@
package org.apache.james.jmap.methods;
-import java.util.Iterator;
import java.util.List;
import java.util.Optional;
import java.util.function.Function;
@@ -38,21 +37,22 @@ import org.apache.james.jmap.model.MessageFactory;
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.MessageRange;
-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.Mailbox;
-import org.apache.james.mailbox.store.mail.model.MailboxMessage;
-import org.javatuples.Pair;
+import org.apache.james.mailbox.model.MessageResult;
+import org.apache.james.mailbox.model.MessageResultIterator;
+import org.javatuples.Triplet;
import com.fasterxml.jackson.databind.ser.PropertyFilter;
import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider;
import com.github.fge.lambdas.Throwing;
+import com.github.fge.lambdas.functions.ThrowingFunction;
import com.github.steveash.guavate.Guavate;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
@@ -63,17 +63,14 @@ public class GetMessagesMethod implements Method {
public static final String HEADERS_FILTER = "headersFilter";
private static final Method.Request.Name METHOD_NAME = Method.Request.name("getMessages");
private static final Method.Response.Name RESPONSE_NAME = Method.Response.name("messages");
- private final MessageMapperFactory messageMapperFactory;
- private final MailboxMapperFactory mailboxMapperFactory;
+ private final MailboxManager mailboxManager;
private final MessageFactory messageFactory;
@Inject
@VisibleForTesting GetMessagesMethod(
- MessageMapperFactory messageMapperFactory,
- MailboxMapperFactory mailboxMapperFactory,
+ MailboxManager mailboxManager,
MessageFactory messageFactory) {
- this.messageMapperFactory = messageMapperFactory;
- this.mailboxMapperFactory = mailboxMapperFactory;
+ this.mailboxManager = mailboxManager;
this.messageFactory = messageFactory;
}
@@ -116,8 +113,8 @@ public class GetMessagesMethod implements Method {
private GetMessagesResponse getMessagesResponse(MailboxSession mailboxSession, GetMessagesRequest getMessagesRequest) {
getMessagesRequest.getAccountId().ifPresent(GetMessagesMethod::notImplemented);
- Function<MessageId, Stream<CompletedMailboxMessage>> loadMessages = loadMessage(mailboxSession);
- Function<CompletedMailboxMessage, Message> convertToJmapMessage = toJmapMessage(mailboxSession);
+ Function<MessageId, Stream<CompletedMessageResult>> loadMessages = loadMessage(mailboxSession);
+ Function<CompletedMessageResult, Message> convertToJmapMessage = toJmapMessage(mailboxSession);
List<Message> result = getMessagesRequest.getIds().stream()
.flatMap(loadMessages)
@@ -132,41 +129,51 @@ public class GetMessagesMethod implements Method {
}
- private Function<CompletedMailboxMessage, Message> toJmapMessage(MailboxSession mailboxSession) {
- return (completedMailboxMessage) -> messageFactory.fromMailboxMessage(
- completedMailboxMessage.mailboxMessage,
- completedMailboxMessage.attachments,
- uid -> new MessageId(mailboxSession.getUser(), completedMailboxMessage.mailboxPath , uid));
+ 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<CompletedMailboxMessage>>
+ private Function<MessageId, Stream<CompletedMessageResult>>
loadMessage(MailboxSession mailboxSession) {
return Throwing
.function((MessageId messageId) -> {
MailboxPath mailboxPath = messageId.getMailboxPath();
- MessageMapper messageMapper = messageMapperFactory.getMessageMapper(mailboxSession);
- Mailbox mailbox = mailboxMapperFactory.getMailboxMapper(mailboxSession).findMailboxByPath(mailboxPath);
- return Pair.with(
- messageMapper.findInMailbox(mailbox, MessageRange.one(messageId.getUid()), MessageMapper.FetchType.Full, 1),
- mailboxPath
+ MessageManager messageManager = mailboxManager.getMailbox(messageId.getMailboxPath(), mailboxSession);
+ return Triplet.with(
+ messageManager.getMessages(messageId.getUidAsRange(), FetchGroupImpl.FULL_CONTENT, mailboxSession),
+ mailboxPath,
+ messageManager.getId()
);
})
- .andThen(Throwing.function((pair) -> retrieveCompleteMailboxMessages(pair, mailboxSession)));
+ .andThen(Throwing.function((triplet) -> retrieveCompleteMessageResults(triplet, mailboxSession)));
}
- 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);
+ 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(message -> CompletedMailboxMessage.builder().mailboxMessage(message).attachments(message.getAttachments()))
+ .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 CompletedMailboxMessage {
+ private static class CompletedMessageResult {
public static Builder builder() {
return new Builder();
@@ -174,16 +181,17 @@ public class GetMessagesMethod implements Method {
public static class Builder {
- private MailboxMessage mailboxMessage;
+ private MessageResult messageResult;
private List<MessageAttachment> attachments;
private MailboxPath mailboxPath;
+ private MailboxId mailboxId;
private Builder() {
}
- public Builder mailboxMessage(MailboxMessage mailboxMessage) {
- Preconditions.checkArgument(mailboxMessage != null);
- this.mailboxMessage = mailboxMessage;
+ public Builder messageResult(MessageResult messageResult) {
+ Preconditions.checkArgument(messageResult != null);
+ this.messageResult = messageResult;
return this;
}
@@ -199,22 +207,31 @@ public class GetMessagesMethod implements Method {
return this;
}
- public CompletedMailboxMessage build() {
- Preconditions.checkState(mailboxMessage != null);
+ 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);
- return new CompletedMailboxMessage(mailboxMessage, attachments, mailboxPath);
+ Preconditions.checkState(mailboxId != null);
+ return new CompletedMessageResult(messageResult, attachments, mailboxPath, mailboxId);
}
}
- private final MailboxMessage mailboxMessage;
+ private final MessageResult messageResult;
private final List<MessageAttachment> attachments;
private final MailboxPath mailboxPath;
+ private final MailboxId mailboxId;
- public CompletedMailboxMessage(MailboxMessage mailboxMessage, List<MessageAttachment> attachments, MailboxPath mailboxPath) {
- this.mailboxMessage = mailboxMessage;
+ public CompletedMessageResult(MessageResult messageResult, List<MessageAttachment> attachments, MailboxPath mailboxPath, MailboxId mailboxId) {
+ this.messageResult = messageResult;
this.attachments = attachments;
this.mailboxPath = mailboxPath;
+ this.mailboxId = mailboxId;
}
}
}
http://git-wip-us.apache.org/repos/asf/james-project/blob/844a7409/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/MessageContentExtractor.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/MessageContentExtractor.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/MessageContentExtractor.java
new file mode 100644
index 0000000..ecb9f48
--- /dev/null
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/MessageContentExtractor.java
@@ -0,0 +1,127 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you under the Apache License, Version 2.0 (the *
+ * "License"); you may not use this file except in compliance *
+ * with the License. You may obtain a copy of the License at *
+ * *
+ * http://www.apache.org/licenses/LICENSE-2.0 *
+ * *
+ * Unless required by applicable law or agreed to in writing, *
+ * software distributed under the License is distributed on an *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
+ * KIND, either express or implied. See the License for the *
+ * specific language governing permissions and limitations *
+ * under the License. *
+ ****************************************************************/
+
+package org.apache.james.jmap.model;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Optional;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.james.mime4j.dom.Body;
+import org.apache.james.mime4j.dom.Entity;
+import org.apache.james.mime4j.dom.Multipart;
+import org.apache.james.mime4j.dom.TextBody;
+
+import com.github.fge.lambdas.Throwing;
+
+public class MessageContentExtractor {
+
+ public MessageContent extract(org.apache.james.mime4j.dom.Message message) throws IOException {
+ Body body = message.getBody();
+ if (body instanceof TextBody) {
+ return parseTextBody(message, (TextBody)body);
+ }
+ if (body instanceof Multipart){
+ return parseMultipart(message, (Multipart)body);
+ }
+ return MessageContent.empty();
+ }
+
+ private MessageContent parseTextBody(Entity entity, TextBody textBody) throws IOException {
+ String bodyContent = asString(textBody);
+ if ("text/html".equals(entity.getMimeType())) {
+ return MessageContent.ofHtmlOnly(bodyContent);
+ }
+ return MessageContent.ofTextOnly(bodyContent);
+ }
+
+ private MessageContent parseMultipart(Entity entity, Multipart multipart) throws IOException {
+ if ("multipart/alternative".equals(entity.getMimeType())) {
+ return parseMultipartAlternative(multipart);
+ }
+ return parseMultipartMixed(multipart);
+ }
+
+ private String asString(TextBody textBody) throws IOException {
+ return IOUtils.toString(textBody.getInputStream(), textBody.getMimeCharset());
+ }
+
+ private MessageContent parseMultipartMixed(Multipart multipart) throws IOException {
+ List<Entity> parts = multipart.getBodyParts();
+ if (! parts.isEmpty()) {
+ Entity firstPart = parts.get(0);
+ if (firstPart.getBody() instanceof Multipart && "multipart/alternative".equals(firstPart.getMimeType())) {
+ return parseMultipartAlternative((Multipart)firstPart.getBody());
+ } else {
+ if (firstPart.getBody() instanceof TextBody) {
+ return parseTextBody(firstPart, (TextBody)firstPart.getBody());
+ }
+ }
+ }
+ return MessageContent.empty();
+ }
+
+ private MessageContent parseMultipartAlternative(Multipart multipart) throws IOException {
+ Optional<String> textBody = getFirstMatchingTextBody(multipart, "text/plain");
+ Optional<String> htmlBody = getFirstMatchingTextBody(multipart, "text/html");
+ return new MessageContent(textBody, htmlBody);
+ }
+
+ private Optional<String> getFirstMatchingTextBody(Multipart multipart, String mimeType) throws IOException {
+ return multipart.getBodyParts()
+ .stream()
+ .filter(part -> mimeType.equals(part.getMimeType()))
+ .map(Entity::getBody)
+ .filter(TextBody.class::isInstance)
+ .map(TextBody.class::cast)
+ .findFirst()
+ .map(Throwing.function(this::asString).sneakyThrow());
+ }
+
+ public static class MessageContent {
+ private final Optional<String> textBody;
+ private final Optional<String> htmlBody;
+
+ public MessageContent(Optional<String> textBody, Optional<String> htmlBody) {
+ this.textBody = textBody;
+ this.htmlBody = htmlBody;
+ }
+
+ public static MessageContent ofTextOnly(String textBody) {
+ return new MessageContent(Optional.of(textBody), Optional.empty());
+ }
+
+ public static MessageContent ofHtmlOnly(String htmlBody) {
+ return new MessageContent(Optional.empty(), Optional.of(htmlBody));
+ }
+
+ public static MessageContent empty() {
+ return new MessageContent(Optional.empty(), Optional.empty());
+ }
+
+ public Optional<String> getTextBody() {
+ return textBody;
+ }
+
+ public Optional<String> getHtmlBody() {
+ return htmlBody;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/james-project/blob/844a7409/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 8790df3..b401b62 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
@@ -18,29 +18,44 @@
****************************************************************/
package org.apache.james.jmap.model;
+import java.io.IOException;
import java.time.ZoneId;
import java.time.ZonedDateTime;
+import java.util.Collection;
+import java.util.Date;
import java.util.List;
import java.util.Map;
+import java.util.Map.Entry;
import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import javax.inject.Inject;
+import javax.mail.Flags;
+import org.apache.james.jmap.model.MessageContentExtractor.MessageContent;
import org.apache.james.jmap.model.message.EMailer;
import org.apache.james.jmap.model.message.IndexableMessage;
+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.MessageResult;
import org.apache.james.mailbox.store.extractor.DefaultTextExtractor;
import org.apache.james.mailbox.store.mail.model.MailboxMessage;
+import org.apache.james.mime4j.dom.address.AddressList;
+import org.apache.james.mime4j.dom.address.Mailbox;
+import org.apache.james.mime4j.dom.address.MailboxList;
+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.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Multimap;
+import com.google.common.collect.Multimaps;
public class MessageFactory {
@@ -48,10 +63,53 @@ public class MessageFactory {
public static final ZoneId UTC_ZONE_ID = ZoneId.of("Z");
private final MessagePreviewGenerator messagePreview;
+ private final MessageContentExtractor messageContentExtractor;
@Inject
- public MessageFactory(MessagePreviewGenerator messagePreview) {
+ public MessageFactory(MessagePreviewGenerator messagePreview, MessageContentExtractor messageContentExtractor) {
this.messagePreview = messagePreview;
+ 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);
+ }
+
+ 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()))
+ .textBody(messageContent.getTextBody().orElse(null))
+ .htmlBody(messageContent.getHtmlBody().orElse(null))
+ .preview(getPreview(messageContent))
+ .attachments(getAttachments(attachments))
+ .build();
}
public Message fromMailboxMessage(MailboxMessage mailboxMessage,
@@ -86,6 +144,13 @@ public class MessageFactory {
.build();
}
+ private String getPreview(MessageContent messageContent) {
+ if (messageContent.getHtmlBody().isPresent()) {
+ return messagePreview.forHTMLBody(messageContent.getHtmlBody());
+ }
+ return messagePreview.forTextBody(messageContent.getTextBody());
+ }
+
private String getPreview(IndexableMessage im) {
Optional<String> bodyHtml = im.getBodyHtml();
if (bodyHtml.isPresent()) {
@@ -100,6 +165,40 @@ public class MessageFactory {
.map(String::trim)
.collect(Collectors.joining(MULTIVALUED_HEADERS_SEPARATOR));
}
+
+ private Emailer firstFromMailboxList(MailboxList list) {
+ if (list == null) {
+ return null;
+ }
+ return list.stream()
+ .map(this::fromMailbox)
+ .findFirst()
+ .orElse(null);
+ }
+
+ private ImmutableList<Emailer> fromAddressList(AddressList list) {
+ if (list == null) {
+ return ImmutableList.of();
+ }
+ return list.flatten()
+ .stream()
+ .map(this::fromMailbox)
+ .collect(Guavate.toImmutableList());
+ }
+
+ private Emailer fromMailbox(Mailbox mailbox) {
+ return Emailer.builder()
+ .name(getNameOrAddress(mailbox))
+ .email(mailbox.getAddress())
+ .build();
+ }
+
+ private String getNameOrAddress(Mailbox mailbox) {
+ if (mailbox.getName() != null) {
+ return mailbox.getName();
+ }
+ return mailbox.getAddress();
+ }
private Emailer firstElasticSearchEmailers(Set<EMailer> emailers) {
return emailers.stream()
@@ -129,6 +228,28 @@ public class MessageFactory {
.collect(Guavate.toImmutableMap(Map.Entry::getKey, x -> joinOnComma(x.getValue())));
}
+ private ImmutableMap<String, String> toMap(List<Field> fields) {
+ Function<Entry<String, Collection<Field>>, String> bodyConcatenator = fieldListEntry -> fieldListEntry.getValue()
+ .stream()
+ .map(Field::getBody)
+ .collect(Collectors.toList())
+ .stream()
+ .collect(Collectors.joining(","));
+ return Multimaps.index(fields, Field::getName)
+ .asMap()
+ .entrySet()
+ .stream()
+ .collect(Guavate.toImmutableMap(Map.Entry::getKey, bodyConcatenator));
+ }
+
+ private String getHeader(MessageBuilder message, String header) {
+ Field field = message.getField(header);
+ if (field == null) {
+ return null;
+ }
+ return field.getBody();
+ }
+
private String getHeaderAsSingleValue(IndexableMessage im, String header) {
return Strings.emptyToNull(joinOnComma(im.getHeaders().get(header)));
}
@@ -141,6 +262,10 @@ 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);
}
http://git-wip-us.apache.org/repos/asf/james-project/blob/844a7409/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 54463ea..8b2ccdd 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
@@ -37,6 +37,7 @@ import org.apache.james.jmap.model.ClientId;
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.MessageContentExtractor;
import org.apache.james.jmap.model.MessageFactory;
import org.apache.james.jmap.model.MessageId;
import org.apache.james.jmap.model.MessagePreviewGenerator;
@@ -102,21 +103,20 @@ public class GetMessagesMethodTest {
private static final User ROBERT = new User("robert", "secret");
private StoreMailboxManager mailboxManager;
- private InMemoryMailboxSessionMapperFactory mailboxSessionMapperFactory;
+ private GetMessagesMethod testee;
private MailboxSession session;
private MailboxPath inboxPath;
private ClientId clientId;
-
- private MessageFactory messageFactory;
@Before
public void setup() throws MailboxException {
clientId = ClientId.of("#0");
- mailboxSessionMapperFactory = new InMemoryMailboxSessionMapperFactory();
+ InMemoryMailboxSessionMapperFactory mailboxSessionMapperFactory = new InMemoryMailboxSessionMapperFactory();
HtmlTextExtractor htmlTextExtractor = new MailboxBasedHtmlTextExtractor(new DefaultTextExtractor());
MessagePreviewGenerator messagePreview = new MessagePreviewGenerator(htmlTextExtractor);
- messageFactory = new MessageFactory(messagePreview);
+ MessageContentExtractor messageContentExtractor = new MessageContentExtractor();
+ MessageFactory messageFactory = new MessageFactory(messagePreview, messageContentExtractor);
MockAuthenticator authenticator = new MockAuthenticator();
authenticator.addUser(ROBERT.username, ROBERT.password);
UnionMailboxACLResolver aclResolver = new UnionMailboxACLResolver();
@@ -129,32 +129,29 @@ public class GetMessagesMethodTest {
session = mailboxManager.login(ROBERT.username, ROBERT.password, LOGGER);
inboxPath = MailboxPath.inbox(session);
mailboxManager.createMailbox(inboxPath, session);
+ testee = new GetMessagesMethod(mailboxManager, messageFactory);
}
@Test
public void processShouldThrowWhenNullRequest() {
- GetMessagesMethod testee = new GetMessagesMethod(mailboxSessionMapperFactory, mailboxSessionMapperFactory, messageFactory);
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, messageFactory);
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, messageFactory);
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, messageFactory);
assertThatThrownBy(() -> testee.process(
GetMessagesRequest.builder().accountId("abc").build(), mock(ClientId.class), mock(MailboxSession.class))).isInstanceOf(NotImplementedException.class);
}
@@ -176,7 +173,6 @@ public class GetMessagesMethodTest {
new MessageId(ROBERT, inboxPath, message3Uid)))
.build();
- GetMessagesMethod testee = new GetMessagesMethod(mailboxSessionMapperFactory, mailboxSessionMapperFactory, messageFactory);
List<JmapResponse> result = testee.process(request, clientId, session).collect(Collectors.toList());
assertThat(result).hasSize(1)
@@ -205,7 +201,6 @@ public class GetMessagesMethodTest {
.ids(ImmutableList.of(new MessageId(ROBERT, inboxPath, messageUid)))
.build();
- GetMessagesMethod testee = new GetMessagesMethod(mailboxSessionMapperFactory, mailboxSessionMapperFactory, messageFactory);
List<JmapResponse> result = testee.process(request, clientId, session).collect(Collectors.toList());
assertThat(result).hasSize(1)
@@ -229,7 +224,6 @@ public class GetMessagesMethodTest {
.properties(ImmutableList.of())
.build();
- GetMessagesMethod testee = new GetMessagesMethod(mailboxSessionMapperFactory, mailboxSessionMapperFactory, messageFactory);
List<JmapResponse> result = testee.process(request, clientId, session).collect(Collectors.toList());
assertThat(result).hasSize(1)
@@ -250,7 +244,6 @@ public class GetMessagesMethodTest {
.ids(ImmutableList.of(new MessageId(ROBERT, inboxPath, message1Uid)))
.build();
- GetMessagesMethod testee = new GetMessagesMethod(mailboxSessionMapperFactory, mailboxSessionMapperFactory, messageFactory);
Stream<JmapResponse> result = testee.process(request, clientId, session);
assertThat(result).hasSize(1)
@@ -274,7 +267,6 @@ public class GetMessagesMethodTest {
Set<MessageProperty> expected = Sets.newHashSet(MessageProperty.id, MessageProperty.subject);
- GetMessagesMethod testee = new GetMessagesMethod(mailboxSessionMapperFactory, mailboxSessionMapperFactory, messageFactory);
List<JmapResponse> result = testee.process(request, clientId, session).collect(Collectors.toList());
assertThat(result).hasSize(1)
@@ -298,7 +290,6 @@ public class GetMessagesMethodTest {
Set<MessageProperty> expected = Sets.newHashSet(MessageProperty.id, MessageProperty.textBody);
- GetMessagesMethod testee = new GetMessagesMethod(mailboxSessionMapperFactory, mailboxSessionMapperFactory, messageFactory);
List<JmapResponse> result = testee.process(request, clientId, session).collect(Collectors.toList());
assertThat(result).hasSize(1)
@@ -325,7 +316,6 @@ public class GetMessagesMethodTest {
Set<MessageProperty> expected = Sets.newHashSet(MessageProperty.id, MessageProperty.headers);
- GetMessagesMethod testee = new GetMessagesMethod(mailboxSessionMapperFactory, mailboxSessionMapperFactory, messageFactory);
List<JmapResponse> result = testee.process(request, clientId, session).collect(Collectors.toList());
assertThat(result)
@@ -351,7 +341,6 @@ public class GetMessagesMethodTest {
.properties(ImmutableList.of("headers.from", "headers.heADER2"))
.build();
- GetMessagesMethod testee = new GetMessagesMethod(mailboxSessionMapperFactory, mailboxSessionMapperFactory, messageFactory);
List<JmapResponse> result = testee.process(request, clientId, session).collect(Collectors.toList());
assertThat(result)
@@ -362,6 +351,6 @@ public class GetMessagesMethodTest {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setFilterProvider(actualFilterProvider.setDefaultFilter(SimpleBeanPropertyFilter.serializeAll()));
String response = objectMapper.writer().writeValueAsString(result.get(0));
- assertThat(JsonPath.parse(response).<Map<String, String>>read("$.response.list[0].headers")).containsOnly(MapEntry.entry("from", "user@domain.tld"), MapEntry.entry("header2", "Header2Content"));
+ assertThat(JsonPath.parse(response).<Map<String, String>>read("$.response.list[0].headers")).containsOnly(MapEntry.entry("From", "user@domain.tld"), MapEntry.entry("HEADer2", "Header2Content"));
}
}
http://git-wip-us.apache.org/repos/asf/james-project/blob/844a7409/server/protocols/jmap/src/test/java/org/apache/james/jmap/methods/SetMessagesCreationProcessorTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/methods/SetMessagesCreationProcessorTest.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/methods/SetMessagesCreationProcessorTest.java
index f81ed55..40649f5 100644
--- a/server/protocols/jmap/src/test/java/org/apache/james/jmap/methods/SetMessagesCreationProcessorTest.java
+++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/methods/SetMessagesCreationProcessorTest.java
@@ -43,6 +43,7 @@ import org.apache.james.jmap.model.CreationMessage;
import org.apache.james.jmap.model.CreationMessage.DraftEmailer;
import org.apache.james.jmap.model.CreationMessageId;
import org.apache.james.jmap.model.Message;
+import org.apache.james.jmap.model.MessageContentExtractor;
import org.apache.james.jmap.model.MessageFactory;
import org.apache.james.jmap.model.MessageId;
import org.apache.james.jmap.model.MessagePreviewGenerator;
@@ -112,7 +113,8 @@ public class SetMessagesCreationProcessorTest {
public void setup() {
HtmlTextExtractor htmlTextExtractor = new MailboxBasedHtmlTextExtractor(new DefaultTextExtractor());
MessagePreviewGenerator messagePreview = new MessagePreviewGenerator(htmlTextExtractor);
- messageFactory = new MessageFactory(messagePreview);
+ MessageContentExtractor messageContentExtractor = new MessageContentExtractor();
+ messageFactory = new MessageFactory(messagePreview, messageContentExtractor);
}
private final CreationMessage.Builder creationMessageBuilder = CreationMessage.builder()
http://git-wip-us.apache.org/repos/asf/james-project/blob/844a7409/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 4ad127c..da0f386 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
@@ -60,7 +60,8 @@ public class MailboxMessageTest {
public void setUp() {
htmlTextExtractor = mock(HtmlTextExtractor.class);
messagePreview = new MessagePreviewGenerator(htmlTextExtractor);
- messageFactory = new MessageFactory(messagePreview);
+ MessageContentExtractor messageContentExtractor = new MessageContentExtractor();
+ messageFactory = new MessageFactory(messagePreview, messageContentExtractor);
}
@Test(expected=IllegalStateException.class)
http://git-wip-us.apache.org/repos/asf/james-project/blob/844a7409/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/MessageContentExtractorTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/MessageContentExtractorTest.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/MessageContentExtractorTest.java
new file mode 100644
index 0000000..388f115
--- /dev/null
+++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/MessageContentExtractorTest.java
@@ -0,0 +1,171 @@
+/****************************************************************
+ * 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.io.IOException;
+
+import org.apache.james.jmap.model.MessageContentExtractor.MessageContent;
+import org.apache.james.mime4j.dom.Message;
+import org.apache.james.mime4j.dom.Multipart;
+import org.apache.james.mime4j.message.BasicBodyFactory;
+import org.apache.james.mime4j.message.BodyPart;
+import org.apache.james.mime4j.message.BodyPartBuilder;
+import org.apache.james.mime4j.message.MessageBuilder;
+import org.apache.james.mime4j.message.MultipartBuilder;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.google.common.base.Charsets;
+
+public class MessageContentExtractorTest {
+ private static final String BINARY_CONTENT = "binary";
+ private static final String TEXT_CONTENT = "text content";
+ private static final String HTML_CONTENT = "<b>html</b> content";
+
+ private MessageContentExtractor testee;
+
+ private BodyPart htmlPart;
+ private BodyPart textPart;
+
+ @Before
+ public void setup() throws IOException {
+ testee = new MessageContentExtractor();
+ textPart = BodyPartBuilder.create().setBody(TEXT_CONTENT, "plain", Charsets.UTF_8).build();
+ htmlPart = BodyPartBuilder.create().setBody(HTML_CONTENT, "html", Charsets.UTF_8).build();
+ }
+
+ @Test
+ public void extractShouldReturnEmptyWhenBinaryContentOnly() throws IOException {
+ Message message = MessageBuilder.create()
+ .setBody(BasicBodyFactory.INSTANCE.binaryBody(BINARY_CONTENT, Charsets.UTF_8))
+ .build();
+ MessageContent actual = testee.extract(message);
+ assertThat(actual.getTextBody()).isEmpty();
+ assertThat(actual.getHtmlBody()).isEmpty();
+ }
+
+ @Test
+ public void extractShouldReturnTextOnlyWhenTextOnlyBody() throws IOException {
+ Message message = MessageBuilder.create()
+ .setBody(TEXT_CONTENT, Charsets.UTF_8)
+ .build();
+ MessageContent actual = testee.extract(message);
+ assertThat(actual.getTextBody()).contains(TEXT_CONTENT);
+ assertThat(actual.getHtmlBody()).isEmpty();
+ }
+
+ @Test
+ public void extractShouldReturnHtmlOnlyWhenHtmlOnlyBody() throws IOException {
+ Message message = MessageBuilder.create()
+ .setBody(HTML_CONTENT, "html", Charsets.UTF_8)
+ .build();
+ MessageContent actual = testee.extract(message);
+ assertThat(actual.getTextBody()).isEmpty();
+ assertThat(actual.getHtmlBody()).contains(HTML_CONTENT);
+ }
+
+ @Test
+ public void extractShouldReturnHtmlAndTextWhenMultipartAlternative() throws IOException {
+ Multipart multipart = MultipartBuilder.create("alternative")
+ .addBodyPart(textPart)
+ .addBodyPart(htmlPart)
+ .build();
+ Message message = MessageBuilder.create()
+ .setBody(multipart)
+ .build();
+ MessageContent actual = testee.extract(message);
+ assertThat(actual.getTextBody()).contains(TEXT_CONTENT);
+ assertThat(actual.getHtmlBody()).contains(HTML_CONTENT);
+ }
+
+ @Test
+ public void extractShouldReturnHtmlWhenMultipartAlternativeWithoutPlainPart() throws IOException {
+ Multipart multipart = MultipartBuilder.create("alternative")
+ .addBodyPart(htmlPart)
+ .build();
+ Message message = MessageBuilder.create()
+ .setBody(multipart)
+ .build();
+ MessageContent actual = testee.extract(message);
+ assertThat(actual.getTextBody()).isEmpty();
+ assertThat(actual.getHtmlBody()).contains(HTML_CONTENT);
+ }
+
+ @Test
+ public void extractShouldReturnTextWhenMultipartAlternativeWithoutHtmlPart() throws IOException {
+ Multipart multipart = MultipartBuilder.create("alternative")
+ .addBodyPart(textPart)
+ .build();
+ Message message = MessageBuilder.create()
+ .setBody(multipart)
+ .build();
+ MessageContent actual = testee.extract(message);
+ assertThat(actual.getTextBody()).contains(TEXT_CONTENT);
+ assertThat(actual.getHtmlBody()).isEmpty();
+ }
+
+ @Test
+ public void extractShouldReturnFirstPartOnlyWhenMultipartMixedAndFirstPartIsText() throws IOException {
+ Multipart multipart = MultipartBuilder.create("mixed")
+ .addBodyPart(textPart)
+ .addBodyPart(htmlPart)
+ .build();
+ Message message = MessageBuilder.create()
+ .setBody(multipart)
+ .build();
+ MessageContent actual = testee.extract(message);
+ assertThat(actual.getTextBody()).contains(TEXT_CONTENT);
+ assertThat(actual.getHtmlBody()).isEmpty();
+ }
+
+ @Test
+ public void extractShouldReturnFirstPartOnlyWhenMultipartMixedAndFirstPartIsHtml() throws IOException {
+ Multipart multipart = MultipartBuilder.create("mixed")
+ .addBodyPart(htmlPart)
+ .addBodyPart(textPart)
+ .build();
+ Message message = MessageBuilder.create()
+ .setBody(multipart)
+ .build();
+ MessageContent actual = testee.extract(message);
+ assertThat(actual.getTextBody()).isEmpty();
+ assertThat(actual.getHtmlBody()).contains(HTML_CONTENT);
+ }
+
+ @Test
+ public void extractShouldReturnHtmlAndTextWhenMultipartMixedAndFirstPartIsMultipartAlternative() throws IOException {
+ BodyPart multipartAlternative = BodyPartBuilder.create()
+ .setBody(MultipartBuilder.create("alternative")
+ .addBodyPart(htmlPart)
+ .addBodyPart(textPart)
+ .build())
+ .build();
+ Multipart multipartMixed = MultipartBuilder.create("mixed")
+ .addBodyPart(multipartAlternative)
+ .build();
+ Message message = MessageBuilder.create()
+ .setBody(multipartMixed)
+ .build();
+ MessageContent actual = testee.extract(message);
+ assertThat(actual.getTextBody()).contains(TEXT_CONTENT);
+ assertThat(actual.getHtmlBody()).contains(HTML_CONTENT);
+ }
+}
http://git-wip-us.apache.org/repos/asf/james-project/blob/844a7409/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 f5128a6..a527102 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
@@ -27,6 +27,7 @@ import javax.mail.Flags;
import javax.mail.util.SharedByteArrayInputStream;
import org.apache.james.jmap.model.Message;
+import org.apache.james.jmap.model.MessageContentExtractor;
import org.apache.james.jmap.model.MessageFactory;
import org.apache.james.jmap.model.MessageId;
import org.apache.james.jmap.model.MessagePreviewGenerator;
@@ -76,7 +77,8 @@ public class MailFactoryTest {
TestId.of(2));
HtmlTextExtractor htmlTextExtractor = new MailboxBasedHtmlTextExtractor(new DefaultTextExtractor());
MessagePreviewGenerator messagePreview = new MessagePreviewGenerator(htmlTextExtractor);
- MessageFactory messageFactory = new MessageFactory(messagePreview) ;
+ MessageContentExtractor messageContentExtractor = new MessageContentExtractor();
+ MessageFactory messageFactory = new MessageFactory(messagePreview, messageContentExtractor);
jmapMessage = messageFactory.fromMailboxMessage(mailboxMessage, ImmutableList.of(), x -> MessageId.of("test|test|" + x));
}
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org