fr.sii.ogham.helper.email.EmailUtils Maven / Gradle / Ivy
package fr.sii.ogham.helper.email;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;
import javax.mail.BodyPart;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.Part;
import org.apache.commons.io.IOUtils;
import com.google.common.base.Predicate;
public class EmailUtils {
private static final Pattern TEXT_OR_HTML_MIMETYPES = Pattern.compile("^((text/)|(application/x?html)).*", Pattern.CASE_INSENSITIVE);
public static final String ATTACHMENT_DISPOSITION = "attachment";
public static final String INLINE_DISPOSITION = "inline";
/**
* Retrieve the main part of the message (recursively):
*
* - The part of the message when it contains only one part
* - The part with text or HTML mimetype if only one part with one of that
* mimetype
* - The second part with text or HTML mimetype if there are two text or
* HTML parts
*
*
* @param actualEmail
* the message
* @return the body of the message
* @throws MessagingException
* when message can't be read
*/
public static Part getBodyPart(Part actualEmail) throws MessagingException {
List bodyParts = getTextualParts(actualEmail);
if (bodyParts.isEmpty()) {
return null;
}
// if only one part matching => not Mltipart with alternative => take
// the first one
// if several matching parts => alternative + main content => the second
// is the main
return bodyParts.size() == 1 ? bodyParts.get(0) : bodyParts.get(1);
}
/**
* Retrieve the alternative part of the message (recursively). The
* alternative is useful when sending HTML email that may be unreadable on
* some email clients. For example, a smartphone will display the 2 or 3
* first lines as a summary. Many smartphones will take the HTML message
* as-is and will display HTML tags instead of content of email. Alternative
* is used to provide a textual visualization of the message that will be
* readable by any system.
*
*
* The alternative of the message is either:
*
* - null if there is only one part
* - null if there is only one text or HTML part
* - the first part if there are more than one text or HTML part
*
*
* @param actualEmail
* the message
* @return the alternative part of the message if exists, null otherwise
* @throws MessagingException
* when message can't be read
*/
public static Part getAlternativePart(Part actualEmail) throws MessagingException {
List bodyParts = getTextualParts(actualEmail);
if (bodyParts.size() < 2) {
return null;
}
return bodyParts.get(0);
}
/**
* Get the whole list of "textual" parts (text or HTML mimetypes).
*
* @param actualEmail
* the message
* @return the list of "textual" parts
* @throws MessagingException
* when message can't be read
*/
public static List getTextualParts(Part actualEmail) throws MessagingException {
List founds = new ArrayList<>();
getBodyParts(actualEmail, founds);
return founds;
}
/**
* Get the content as byte array of a particular part.
*
* @param part
* the part
* @return the content
* @throws IOException
* when part can't be read
* @throws MessagingException
* when message can"t be read
*/
public static byte[] getContent(Part part) throws IOException, MessagingException {
InputStream stream = part.getInputStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
IOUtils.copy(stream, baos);
return baos.toByteArray();
}
/**
* Get a particular attachment (found using exact filename field).
*
* @param multipart
* the email that contains several parts
* @param filename
* the name of the attachment to find
* @return the found attachment or null
* @throws MessagingException
* when message can't be read
*/
public static BodyPart getAttachment(Multipart multipart, final String filename) throws MessagingException {
return getAttachment(multipart, new FileNamePredicate(filename));
}
/**
* Get a particular attachment (found using provided predicate). If several
* attachments match the predicate, only the first one is retrieved.
*
* @param multipart
* the email that contains several parts
* @param filter
* the predicate used to find the attachment
* @return the found attachment or null
* @throws MessagingException
* when message can't be read
*/
public static BodyPart getAttachment(Multipart multipart, Predicate filter) throws MessagingException {
List attachments = getAttachments(multipart, filter);
return attachments.isEmpty() ? null : attachments.get(0);
}
/**
* Get a list of attachments that match the provided predicate.
*
* @param multipart
* the email that contains several parts
* @param filter
* the predicate used to find the attachments
* @return the found attachments or empty list
* @throws MessagingException
* when message can't be read
*/
public static List getAttachments(Multipart multipart, Predicate filter) throws MessagingException {
List found = new ArrayList<>();
for (int i = 0; i < multipart.getCount(); i++) {
BodyPart bodyPart = multipart.getBodyPart(i);
if (filter.apply(bodyPart)) {
found.add(bodyPart);
}
}
return found;
}
/**
* Get the whole list of attachments.
*
* @param multipart
* the email that contains several parts
* @return the found attachments or empty list
* @throws MessagingException
* when message can't be read
*/
public static List getAttachments(Multipart multipart) throws MessagingException {
List attachments = new ArrayList<>();
for (int i = 0; i < multipart.getCount(); i++) {
BodyPart bodyPart = multipart.getBodyPart(i);
if (!isContent(bodyPart) && !isMultipart(bodyPart)) {
attachments.add(bodyPart);
}
}
return attachments;
}
private static void getBodyParts(Part actualEmail, List founds) throws MessagingException {
try {
Object content = actualEmail.getContent();
if (content instanceof Multipart) {
Multipart mp = (Multipart) content;
for (int i = 0; i < mp.getCount(); i++) {
BodyPart part = mp.getBodyPart(i);
if (isMultipart(part)) {
getBodyParts(part, founds);
} else if (isContent(part)) {
founds.add(part);
}
}
}
} catch (IOException e) {
throw new MessagingException("Failed to access content of the mail", e);
}
}
private static boolean isMultipart(BodyPart part) throws MessagingException {
return part.getContentType().startsWith("multipart/");
}
private static boolean isContent(BodyPart part) throws MessagingException {
return TEXT_OR_HTML_MIMETYPES.matcher(part.getContentType()).matches();
}
private EmailUtils() {
super();
}
}