/* * Copyright 2002-2012 the original author or authors. * * Licensed 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.springframework.integration.samples.mailattachments.support; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.util.List; import javax.mail.BodyPart; import javax.mail.MessagingException; import javax.mail.Multipart; import javax.mail.Part; import javax.mail.internet.ContentType; import javax.mail.internet.MimeBodyPart; import javax.mail.internet.ParseException; import org.apache.commons.io.IOUtils; import org.apache.log4j.Logger; import org.springframework.util.Assert; /** * Utility Class for parsing mail messages. * * @author Gunnar Hillert * @since 2.2 * */ public final class EmailParserUtils { private static final Logger LOGGER = Logger.getLogger(EmailParserUtils.class); /** Prevent instantiation. */ private EmailParserUtils() { throw new AssertionError(); } /** * Parses a mail message. The respective message can either be the root message * or another message that is attached to another message. * * If the mail message is an instance of {@link String}, then a {@link EmailFragment} * is being created using the email message's subject line as the file name, * which will contain the mail message's content. * * If the mail message is an instance of {@link Multipart} then we delegate * to {@link #handleMultipart(File, Multipart, javax.mail.Message, List)}. * * @param directory The directory for storing the message. If null this is the root message. * @param mailMessage The mail message to be parsed. Must not be null. * @param emailFragments Must not be null. */ public static void handleMessage(final File directory, final javax.mail.Message mailMessage, final List<EmailFragment> emailFragments) { Assert.notNull(mailMessage, "The mail message to be parsed must not be null."); Assert.notNull(emailFragments, "The collection of emailfragments must not be null."); final Object content; final String subject; try { content = mailMessage.getContent(); subject = mailMessage.getSubject(); } catch (IOException e) { throw new IllegalStateException("Error while retrieving the email contents.", e); } catch (MessagingException e) { throw new IllegalStateException("Error while retrieving the email contents.", e); } final File directoryToUse; if (directory == null) { directoryToUse = new File(subject); } else { directoryToUse = new File(directory, subject); } if (content instanceof String) { emailFragments.add(new EmailFragment(new File(subject), "message.txt", content)); } else if (content instanceof Multipart) { Multipart multipart = (Multipart) content; handleMultipart(directoryToUse, multipart, mailMessage, emailFragments); } else { throw new IllegalStateException("This content type is not handled - " + content.getClass().getSimpleName()); } } /** * Parses any {@link Multipart} instances that contain text or Html attachments, * {@link InputStream} instances, additional instances of {@link Multipart} * or other attached instances of {@link javax.mail.Message}. * * Will create the respective {@link EmailFragment}s representing those attachments. * * Instances of {@link javax.mail.Message} are delegated to * {@link #handleMessage(File, javax.mail.Message, List)}. Further instances * of {@link Multipart} are delegated to * {@link #handleMultipart(File, Multipart, javax.mail.Message, List)}. * * @param directory Must not be null * @param multipart Must not be null * @param mailMessage Must not be null * @param emailFragments Must not be null */ public static void handleMultipart(File directory, Multipart multipart, javax.mail.Message mailMessage, List<EmailFragment> emailFragments) { Assert.notNull(directory, "The directory must not be null."); Assert.notNull(multipart, "The multipart object to be parsed must not be null."); Assert.notNull(mailMessage, "The mail message to be parsed must not be null."); Assert.notNull(emailFragments, "The collection of emailfragments must not be null."); final int count; try { count = multipart.getCount(); if (LOGGER.isInfoEnabled()) { LOGGER.info(String.format("Number of enclosed BodyPart objects: %s.", count)); } } catch (MessagingException e) { throw new IllegalStateException("Error while retrieving the number of enclosed BodyPart objects.", e); } for (int i = 0; i < count; i++) { final BodyPart bp; try { bp = multipart.getBodyPart(i); } catch (MessagingException e) { throw new IllegalStateException("Error while retrieving body part.", e); } final String contentType; String filename; final String disposition; final String subject; try { contentType = bp.getContentType(); filename = bp.getFileName(); disposition = bp.getDisposition(); subject = mailMessage.getSubject(); if (filename == null && bp instanceof MimeBodyPart) { filename = ((MimeBodyPart) bp).getContentID(); } } catch (MessagingException e) { throw new IllegalStateException("Unable to retrieve body part meta data.", e); } if (LOGGER.isInfoEnabled()) { LOGGER.info(String.format("BodyPart - Content Type: '%s', filename: '%s', disposition: '%s', subject: '%s'", new Object[]{contentType, filename, disposition, subject})); } if (Part.ATTACHMENT.equalsIgnoreCase(disposition)) { LOGGER.info(String.format("Handdling attachment '%s', type: '%s'", filename, contentType)); } final Object content; try { content = bp.getContent(); } catch (IOException e) { throw new IllegalStateException("Error while retrieving the email contents.", e); } catch (MessagingException e) { throw new IllegalStateException("Error while retrieving the email contents.", e); } if (content instanceof String) { if (Part.ATTACHMENT.equalsIgnoreCase(disposition)) { emailFragments.add(new EmailFragment(directory, i + "-" + filename, content)); LOGGER.info(String.format("Handdling attachment '%s', type: '%s'", filename, contentType)); } else { final String textFilename; final ContentType ct; try { ct = new ContentType(contentType); } catch (ParseException e) { throw new IllegalStateException("Error while parsing content type '" + contentType + "'.", e); } if ("text/plain".equalsIgnoreCase(ct.getBaseType())) { textFilename = "message.txt"; } else if ("text/html".equalsIgnoreCase(ct.getBaseType())) { textFilename = "message.html"; } else { textFilename = "message.other"; } emailFragments.add(new EmailFragment(directory, textFilename, content)); } } else if (content instanceof InputStream) { final InputStream inputStream = (InputStream) content; final ByteArrayOutputStream bis = new ByteArrayOutputStream(); try { IOUtils.copy(inputStream, bis); } catch (IOException e) { throw new IllegalStateException("Error while copying input stream to the ByteArrayOutputStream.", e); } emailFragments.add(new EmailFragment(directory, filename, bis.toByteArray())); } else if (content instanceof javax.mail.Message) { handleMessage(directory, (javax.mail.Message) content, emailFragments); } else if (content instanceof Multipart) { final Multipart mp2 = (Multipart) content; handleMultipart(directory, mp2, mailMessage, emailFragments); } else { throw new IllegalStateException("Content type not handled: " + content.getClass().getSimpleName()); } } } }