blob: d36b1ec91109284283fb1d7d1216d2d2d90fa585 [file] [log] [blame]
/****************************************************************
* 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.mailbox.elasticsearch.json;
import java.io.IOException;
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import org.apache.james.mailbox.MailboxSession.User;
import org.apache.james.mailbox.elasticsearch.query.DateResolutionFormater;
import org.apache.james.mailbox.store.extractor.TextExtractor;
import org.apache.james.mailbox.store.mail.model.MailboxMessage;
import org.apache.james.mailbox.store.mail.model.Property;
import org.apache.james.mime4j.MimeException;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.github.steveash.guavate.Guavate;
import com.google.common.base.Preconditions;
import com.google.common.base.Throwables;
import com.google.common.collect.Multimap;
public class IndexableMessage {
public static IndexableMessage from(MailboxMessage message, List<User> users, TextExtractor textExtractor, ZoneId zoneId) {
Preconditions.checkNotNull(message.getMailboxId());
Preconditions.checkArgument(!users.isEmpty());
IndexableMessage indexableMessage = new IndexableMessage();
try {
MimePart parsingResult = new MimePartParser(message, textExtractor).parse();
indexableMessage.users = users.stream().map(User::getUserName).collect(Guavate.toImmutableList());
indexableMessage.bodyText = parsingResult.locateFirstTextualBody();
indexableMessage.setFlattenedAttachments(parsingResult);
indexableMessage.copyHeaderFields(parsingResult.getHeaderCollection(), getSanitizedInternalDate(message, zoneId));
} catch (IOException | MimeException e) {
throw Throwables.propagate(e);
}
indexableMessage.copyMessageFields(message, zoneId);
return indexableMessage;
}
private void setFlattenedAttachments(MimePart parsingResult) {
attachments = parsingResult.getAttachmentsStream()
.collect(Collectors.toList());
}
private void copyHeaderFields(HeaderCollection headerCollection, ZonedDateTime internalDate) {
this.headers = headerCollection.getHeaders();
this.subjects = headerCollection.getSubjectSet();
this.from = EMailers.from(headerCollection.getFromAddressSet());
this.to = EMailers.from(headerCollection.getToAddressSet());
this.replyTo = EMailers.from(headerCollection.getReplyToAddressSet());
this.cc = EMailers.from(headerCollection.getCcAddressSet());
this.bcc = EMailers.from(headerCollection.getBccAddressSet());
this.sentDate = DateResolutionFormater.DATE_TIME_FOMATTER.format(headerCollection.getSentDate().orElse(internalDate));
}
private void copyMessageFields(MailboxMessage message, ZoneId zoneId) {
this.id = message.getUid();
this.mailboxId = message.getMailboxId().serialize();
this.modSeq = message.getModSeq();
this.size = message.getFullContentOctets();
this.date = DateResolutionFormater.DATE_TIME_FOMATTER.format(getSanitizedInternalDate(message, zoneId));
this.mediaType = message.getMediaType();
this.subType = message.getSubType();
this.isAnswered = message.isAnswered();
this.isDeleted = message.isDeleted();
this.isDraft = message.isDraft();
this.isFlagged = message.isFlagged();
this.isRecent = message.isRecent();
this.isUnRead = ! message.isSeen();
this.userFlags = message.createFlags().getUserFlags();
this.properties = message.getProperties();
}
private static ZonedDateTime getSanitizedInternalDate(MailboxMessage message, ZoneId zoneId) {
if (message.getInternalDate() == null) {
return ZonedDateTime.now();
}
return ZonedDateTime.ofInstant(
Instant.ofEpochMilli(message.getInternalDate().getTime()),
zoneId);
}
private Long id;
private String mailboxId;
private List<String> users;
private long modSeq;
private long size;
private String date;
private String mediaType;
private String subType;
private boolean isUnRead;
private boolean isRecent;
private boolean isFlagged;
private boolean isDeleted;
private boolean isDraft;
private boolean isAnswered;
private String[] userFlags;
private Multimap<String, String> headers;
private EMailers from;
private EMailers to;
private EMailers cc;
private EMailers bcc;
private EMailers replyTo;
private Set<String> subjects;
private String sentDate;
private List<Property> properties;
private List<MimePart> attachments;
private Optional<String> bodyText;
@JsonProperty(JsonMessageConstants.ID)
public Long getId() {
return id;
}
@JsonProperty(JsonMessageConstants.MAILBOX_ID)
public String getMailboxId() {
return mailboxId;
}
@JsonProperty(JsonMessageConstants.USERS)
public List<String> getUsers() {
return users;
}
@JsonProperty(JsonMessageConstants.MODSEQ)
public long getModSeq() {
return modSeq;
}
@JsonProperty(JsonMessageConstants.SIZE)
public long getSize() {
return size;
}
@JsonProperty(JsonMessageConstants.DATE)
public String getDate() {
return date;
}
@JsonProperty(JsonMessageConstants.MEDIA_TYPE)
public String getMediaType() {
return mediaType;
}
@JsonProperty(JsonMessageConstants.SUBTYPE)
public String getSubType() {
return subType;
}
@JsonProperty(JsonMessageConstants.IS_UNREAD)
public boolean isUnRead() {
return isUnRead;
}
@JsonProperty(JsonMessageConstants.IS_RECENT)
public boolean isRecent() {
return isRecent;
}
@JsonProperty(JsonMessageConstants.IS_FLAGGED)
public boolean isFlagged() {
return isFlagged;
}
@JsonProperty(JsonMessageConstants.IS_DELETED)
public boolean isDeleted() {
return isDeleted;
}
@JsonProperty(JsonMessageConstants.IS_DRAFT)
public boolean isDraft() {
return isDraft;
}
@JsonProperty(JsonMessageConstants.IS_ANSWERED)
public boolean isAnswered() {
return isAnswered;
}
@JsonProperty(JsonMessageConstants.USER_FLAGS)
public String[] getUserFlags() {
return userFlags;
}
@JsonProperty(JsonMessageConstants.HEADERS)
public Multimap<String, String> getHeaders() {
return headers;
}
@JsonProperty(JsonMessageConstants.SUBJECT)
public Set<String> getSubjects() {
return subjects;
}
@JsonProperty(JsonMessageConstants.FROM)
public EMailers getFrom() {
return from;
}
@JsonProperty(JsonMessageConstants.TO)
public EMailers getTo() {
return to;
}
@JsonProperty(JsonMessageConstants.CC)
public EMailers getCc() {
return cc;
}
@JsonProperty(JsonMessageConstants.BCC)
public EMailers getBcc() {
return bcc;
}
@JsonProperty(JsonMessageConstants.REPLY_TO)
public EMailers getReplyTo() {
return replyTo;
}
@JsonProperty(JsonMessageConstants.SENT_DATE)
public String getSentDate() {
return sentDate;
}
@JsonProperty(JsonMessageConstants.PROPERTIES)
public List<Property> getProperties() {
return properties;
}
@JsonProperty(JsonMessageConstants.ATTACHMENTS)
public List<MimePart> getAttachments() {
return attachments;
}
@JsonProperty(JsonMessageConstants.TEXT_BODY)
public Optional<String> getBodyText() {
return bodyText;
}
@JsonProperty(JsonMessageConstants.HAS_ATTACHMENT)
public boolean getHasAttachment() {
return attachments.size() > 0;
}
}