// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
package jodd.mail;
import jodd.io.FastByteArrayOutputStream;
import jodd.io.StreamUtil;
import jodd.mail.att.ByteArrayAttachment;
import jodd.util.StringPool;
import javax.mail.Address;
import javax.mail.Flags;
import javax.mail.Header;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.Part;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimePart;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.Enumeration;
import java.util.List;
/**
* Received email.
*/
public class ReceivedEmail extends CommonEmail {
public ReceivedEmail(Message message) {
try {
parseMessage(message);
} catch (Exception ex) {
throw new MailException("Message parsing failed", ex);
}
}
/**
* Parse java <code>Message</code> and extracts all data for the received message.
*/
@SuppressWarnings("unchecked")
protected void parseMessage(Message msg) throws MessagingException, IOException {
// flags
setFlags(msg.getFlags());
// msg no
setMessageNumber(msg.getMessageNumber());
// single from
Address[] addresses = msg.getFrom();
if (addresses != null && addresses.length > 0) {
setFrom(new EmailAddress(addresses[0]));
}
// common field
setTo(EmailAddress.createFrom(msg.getRecipients(Message.RecipientType.TO)));
setCc(EmailAddress.createFrom(msg.getRecipients(Message.RecipientType.CC)));
setBcc(EmailAddress.createFrom(msg.getRecipients(Message.RecipientType.BCC)));
// reply to
setReplyTo(EmailAddress.createFrom(msg.getReplyTo()));
setSubject(msg.getSubject());
setReceiveDate(parseReceiveDate(msg));
setSentDate(parseSendDate(msg));
// copy headers
Enumeration<Header> headers = msg.getAllHeaders();
while (headers.hasMoreElements()) {
Header header = headers.nextElement();
setHeader(header.getName(), header.getValue());
}
// content
processPart(this, msg);
}
/**
* Process single part of received message. All parts are simple added to the message, i.e. hierarchy is not saved.
*/
protected void processPart(ReceivedEmail email, Part part) throws IOException, MessagingException {
Object content = part.getContent();
if (content instanceof String) {
String stringContent = (String) content;
String disposition = part.getDisposition();
if (disposition != null && disposition.equalsIgnoreCase(Part.ATTACHMENT)) {
String contentType = part.getContentType();
String mimeType = EmailUtil.extractMimeType(contentType);
String encoding = EmailUtil.extractEncoding(contentType);
String fileName = part.getFileName();
String contentId = parseContentId(part);
boolean inline = parseInline(part);
if (encoding == null) {
encoding = StringPool.US_ASCII;
}
email.addAttachment(fileName, mimeType, contentId, inline, stringContent.getBytes(encoding));
} else {
String contentType = part.getContentType();
String encoding = EmailUtil.extractEncoding(contentType);
String mimeType = EmailUtil.extractMimeType(contentType);
if (encoding == null) {
encoding = StringPool.US_ASCII;
}
email.addMessage(stringContent, mimeType, encoding);
}
}
else if (content instanceof Multipart) {
Multipart mp = (Multipart) content;
int count = mp.getCount();
for (int i = 0; i < count; i++) {
Part innerPart = mp.getBodyPart(i);
processPart(email, innerPart);
}
}
else if (content instanceof InputStream) {
String fileName = EmailUtil.resolveFileName(part);
String contentId = parseContentId(part);
boolean inline = parseInline(part);
String mimeType = EmailUtil.extractMimeType(part.getContentType());
InputStream is = (InputStream) content;
FastByteArrayOutputStream fbaos = new FastByteArrayOutputStream();
StreamUtil.copy(is, fbaos);
email.addAttachment(fileName, mimeType, contentId, inline, fbaos.toByteArray());
}
else if (content instanceof MimeMessage) {
MimeMessage mimeMessage = (MimeMessage) content;
addAttachmentMessage(new ReceivedEmail(mimeMessage));
}
else {
String fileName = part.getFileName();
String contentId = parseContentId(part);
boolean inline = parseInline(part);
String mimeType = EmailUtil.extractMimeType(part.getContentType());
InputStream is = part.getInputStream();
FastByteArrayOutputStream fbaos = new FastByteArrayOutputStream();
StreamUtil.copy(is, fbaos);
StreamUtil.close(is);
email.addAttachment(fileName, mimeType, contentId, inline, fbaos.toByteArray());
}
}
protected String parseContentId(Part part) throws MessagingException {
return (part instanceof MimePart) ? ((MimePart) part).getContentID() : null;
}
protected boolean parseInline(Part part) throws MessagingException {
if (part instanceof MimePart) {
String dispositionId = part.getDisposition();
if (dispositionId != null && dispositionId.equalsIgnoreCase("inline")) {
return true;
}
}
return false;
}
protected Date parseReceiveDate(Message msg) throws MessagingException {
return msg.getReceivedDate();
}
protected Date parseSendDate(Message msg) throws MessagingException {
return msg.getSentDate();
}
// ---------------------------------------------------------------- flags
protected Flags flags;
public Flags getFlags() {
return flags;
}
public void setFlags(Flags flags) {
this.flags = flags;
}
/**
* Returns <code>true</code> if message is answered.
*/
public boolean isAnswered() {
return flags.contains(Flags.Flag.ANSWERED);
}
/**
* Returns <code>true</code> if message is deleted.
*/
public boolean isDeleted() {
return flags.contains(Flags.Flag.DELETED);
}
/**
* Returns <code>true</code> if message is draft.
*/
public boolean isDraf() {
return flags.contains(Flags.Flag.DRAFT);
}
/**
* Returns <code>true</code> is message is flagged.
*/
public boolean isFlagged() {
return flags.contains(Flags.Flag.FLAGGED);
}
/**
* Returns <code>true</code> if message is recent.
*/
public boolean isRecent() {
return flags.contains(Flags.Flag.RECENT);
}
/**
* Returns <code>true</code> if message is seen.
*/
public boolean isSeen() {
return flags.contains(Flags.Flag.SEEN);
}
// ---------------------------------------------------------------- additional properties
protected int messageNumber;
protected Date recvDate;
/**
* Returns message number.
*/
public int getMessageNumber() {
return messageNumber;
}
/**
* Sets message number.
*/
public void setMessageNumber(int messageNumber) {
this.messageNumber = messageNumber;
}
/**
* Sets e-mails receive date.
*/
public void setReceiveDate(Date date) {
recvDate = date;
}
/**
* Returns emails received date.
*/
public Date getReceiveDate() {
return recvDate;
}
// ---------------------------------------------------------------- attachments
protected List<EmailAttachment> attachments;
/**
* Adds received attachment.
*/
public void addAttachment(String filename, String mimeType, String contentId, boolean inline, byte[] content) {
if (attachments == null) {
attachments = new ArrayList<>();
}
EmailAttachment emailAttachment = new ByteArrayAttachment(content, mimeType, filename, contentId, inline);
emailAttachment.setSize(content.length);
attachments.add(emailAttachment);
}
/**
* Returns the list of all attachments.
* If no attachment is available, returns <code>null</code>.
*/
public List<EmailAttachment> getAttachments() {
return attachments;
}
// ---------------------------------------------------------------- inner messages
protected List<ReceivedEmail> attachedMessages;
/**
* Adds attached messages.
*/
public void addAttachmentMessage(ReceivedEmail receivedEmail) {
if (attachedMessages == null) {
attachedMessages = new ArrayList<>();
}
attachedMessages.add(receivedEmail);
}
/**
* Returns the list of attached messages.
* If not attached message is available, returns <code>null</code>.
*/
public List<ReceivedEmail> getAttachedMessages() {
return attachedMessages;
}
}