package org.simplejavamail.converter; import org.simplejavamail.converter.internal.mimemessage.MimeMessageHelper; import org.simplejavamail.converter.internal.mimemessage.MimeMessageParser; import org.simplejavamail.converter.internal.msgparser.OutlookMessageParser; import org.simplejavamail.email.Email; import org.simplejavamail.internal.util.MiscUtil; import org.simplejavamail.outlookmessageparser.model.OutlookFileAttachment; import org.simplejavamail.outlookmessageparser.model.OutlookMessage; import org.simplejavamail.outlookmessageparser.model.OutlookRecipient; import javax.activation.DataSource; import javax.annotation.Nonnull; import javax.mail.Message; import javax.mail.MessagingException; import javax.mail.Session; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeMessage; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.UnsupportedEncodingException; import java.util.Map; import java.util.Properties; import static java.lang.String.format; import static java.nio.charset.StandardCharsets.UTF_8; import static org.simplejavamail.converter.internal.mimemessage.MimeMessageHelper.produceMimeMessage; import static org.simplejavamail.internal.util.MiscUtil.extractCID; import static org.simplejavamail.internal.util.Preconditions.checkNonEmptyArgument; /** * Utility to help convert {@link org.simplejavamail.email.Email} instances to other formats (MimeMessage, EML etc.) and vice versa. */ @SuppressWarnings("WeakerAccess") public final class EmailConverter { private EmailConverter() { // util / helper class } /* To Email instance */ /** * @param mimeMessage The MimeMessage from which to create the {@link Email}. */ public static Email mimeMessageToEmail(@Nonnull final MimeMessage mimeMessage) { final Email email = new Email(false); try { fillEmailFromMimeMessage(email, checkNonEmptyArgument(mimeMessage, "mimeMessage")); } catch (MessagingException | IOException e) { throw new EmailConverterException(format(EmailConverterException.PARSE_ERROR_MIMEMESSAGE, e.getMessage()), e); } return email; } /** * @param msgData The content of an Outlook (.msg) message from which to create the {@link Email}. */ public static Email outlookMsgToEmail(@Nonnull final String msgData) { final Email email = new Email(false); final OutlookMessage outlookMessage = OutlookMessageParser.parseOutlookMsg(checkNonEmptyArgument(msgData, "msgData")); fillEmailFromOutlookMessage(email, outlookMessage); return email; } /** * @param msgfile The content of an Outlook (.msg) message from which to create the {@link Email}. */ public static Email outlookMsgToEmail(@Nonnull final File msgfile) { final Email email = new Email(false); final OutlookMessage outlookMessage = OutlookMessageParser.parseOutlookMsg(checkNonEmptyArgument(msgfile, "msgfile")); fillEmailFromOutlookMessage(email, outlookMessage); return email; } /** * @param msgInputStream The content of an Outlook (.msg) message from which to create the {@link Email}. */ public static Email outlookMsgToEmail(@Nonnull final InputStream msgInputStream) { final Email email = new Email(false); final OutlookMessage outlookMessage = OutlookMessageParser.parseOutlookMsg(checkNonEmptyArgument(msgInputStream, "msgInputStream")); fillEmailFromOutlookMessage(email, outlookMessage); return email; } /** * Delegates to {@link #emlToMimeMessage(String, Session)} using a dummy {@link Session} instance and passes the result to {@link * #mimeMessageToEmail(MimeMessage)}; */ public static Email emlToEmail(@Nonnull final String eml) { final MimeMessage mimeMessage = emlToMimeMessage(checkNonEmptyArgument(eml, "eml"), createDummySession()); return mimeMessageToEmail(mimeMessage); } /* To MimeMessage instance */ /** * @return Result of {@link #outlookMsgToEmail(String)} and {@link #emailToMimeMessage(Email)} */ @Nonnull public static MimeMessage outlookMsgToMimeMessage(@Nonnull final String outlookMsgData) { checkNonEmptyArgument(outlookMsgData, "outlookMsgData"); return emailToMimeMessage(outlookMsgToEmail(outlookMsgData)); } /** * @return Result of {@link #outlookMsgToEmail(File)} and {@link #emailToMimeMessage(Email)} */ @Nonnull public static MimeMessage outlookMsgToMimeMessage(@Nonnull final File outlookMsgFile) { checkNonEmptyArgument(outlookMsgFile, "outlookMsgFile"); return emailToMimeMessage(outlookMsgToEmail(outlookMsgFile)); } /** * @return Result of {@link #outlookMsgToEmail(InputStream)} and {@link #emailToMimeMessage(Email)} */ @Nonnull public static MimeMessage outlookMsgToMimeMessage(@Nonnull final InputStream outloookMsgInputStream) { checkNonEmptyArgument(outloookMsgInputStream, "outloookMsgInputStream"); return emailToMimeMessage(outlookMsgToEmail(outloookMsgInputStream)); } /** * Delegates to {@link #emailToMimeMessage(Email, Session)}, using a new empty {@link Session} instance. * * @see #emailToMimeMessage(Email, Session) */ public static MimeMessage emailToMimeMessage(@Nonnull final Email email) { return emailToMimeMessage(checkNonEmptyArgument(email, "email"), createDummySession()); } /** * Refer to {@link MimeMessageHelper#produceMimeMessage(Email, Session)} */ public static MimeMessage emailToMimeMessage(@Nonnull final Email email, @Nonnull final Session session) { try { return produceMimeMessage(checkNonEmptyArgument(email, "email"), checkNonEmptyArgument(session, "session")); } catch (UnsupportedEncodingException | MessagingException e) { // this should never happen, so we don't acknowledge this exception (and simply bubble up) throw new RuntimeException(e.getMessage(), e); } } /** * Delegates to {@link #emlToMimeMessage(String, Session)} with an empty {@link Session} instance. * * @see #emailToMimeMessage(Email, Session) */ public static MimeMessage emlToMimeMessage(@Nonnull final String eml) { return emlToMimeMessage(checkNonEmptyArgument(eml, "eml"), createDummySession()); } /** * Relies on JavaMail's native parser of EML data, {@link MimeMessage#MimeMessage(Session, InputStream)}. */ public static MimeMessage emlToMimeMessage(@Nonnull final String eml, @Nonnull final Session session) { checkNonEmptyArgument(session, "session"); checkNonEmptyArgument(eml, "eml"); try { return new MimeMessage(session, new ByteArrayInputStream(eml.getBytes(UTF_8))); } catch (final MessagingException e) { throw new EmailConverterException(format(EmailConverterException.PARSE_ERROR_EML, e.getMessage()), e); } } /* To EML String */ /** * @return The result of {@link MimeMessage#writeTo(OutputStream)} which should be in the standard EML format. */ public static String mimeMessageToEML(@Nonnull final MimeMessage mimeMessage) { final ByteArrayOutputStream os = new ByteArrayOutputStream(); try { checkNonEmptyArgument(mimeMessage, "mimeMessage").writeTo(os); return os.toString(UTF_8.name()); } catch (IOException | MessagingException e) { // this should never happen, so we don't acknowledge this exception (and simply bubble up) throw new RuntimeException(e.getMessage(), e); } } /** * Delegates to {@link #emailToMimeMessage(Email)} and passes the result to {@link #mimeMessageToEML(MimeMessage)}. * * @see #emailToMimeMessage(Email, Session) */ public static String emailToEML(@Nonnull final Email email) { return mimeMessageToEML(emailToMimeMessage(checkNonEmptyArgument(email, "email"))); } /** * @return Result of {@link #outlookMsgToEmail(String)} and {@link #emailToEML(Email)} */ @Nonnull public static String outlookMsgToEML(@Nonnull final String outlookMsgData) { checkNonEmptyArgument(outlookMsgData, "outlookMsgData"); return emailToEML(outlookMsgToEmail(outlookMsgData)); } /** * @return Result of {@link #outlookMsgToEmail(File)} and {@link #emailToEML(Email)} */ @Nonnull public static String outlookMsgToEML(@Nonnull final File outlookMsgFile) { checkNonEmptyArgument(outlookMsgFile, "outlookMsgFile"); return emailToEML(outlookMsgToEmail(outlookMsgFile)); } /** * @return Result of {@link #outlookMsgToEmail(InputStream)} and {@link #emailToEML(Email)} */ @Nonnull public static String outlookMsgToEML(@Nonnull final InputStream outloookMsgInputStream) { checkNonEmptyArgument(outloookMsgInputStream, "outloookMsgInputStream"); return emailToEML(outlookMsgToEmail(outloookMsgInputStream)); } /* Helpers */ private static void fillEmailFromMimeMessage(@Nonnull final Email email, @Nonnull final MimeMessage mimeMessage) throws MessagingException, IOException { checkNonEmptyArgument(email, "email"); checkNonEmptyArgument(mimeMessage, "mimeMessage"); final MimeMessageParser parser = new MimeMessageParser(mimeMessage).parse(); final InternetAddress from = parser.getFrom(); email.setFromAddress(from.getPersonal(), from.getAddress()); final InternetAddress replyTo = parser.getReplyTo(); email.setReplyToAddress(replyTo.getPersonal(), replyTo.getAddress()); for (final Map.Entry<String, Object> header : parser.getHeaders().entrySet()) { email.addHeader(header.getKey(), header.getValue()); } for (final InternetAddress to : parser.getTo()) { email.addRecipient(to.getPersonal(), to.getAddress(), Message.RecipientType.TO); } //noinspection QuestionableName for (final InternetAddress cc : parser.getCc()) { email.addRecipient(cc.getPersonal(), cc.getAddress(), Message.RecipientType.CC); } for (final InternetAddress bcc : parser.getBcc()) { email.addRecipient(bcc.getPersonal(), bcc.getAddress(), Message.RecipientType.BCC); } email.setSubject(parser.getSubject()); email.setText(parser.getPlainContent()); email.setTextHTML(parser.getHtmlContent()); for (final Map.Entry<String, DataSource> cid : parser.getCidMap().entrySet()) { final String cidName = checkNonEmptyArgument(cid.getKey(), "cid.key"); email.addEmbeddedImage(extractCID(cidName), cid.getValue()); } for (final Map.Entry<String, DataSource> attachment : parser.getAttachmentList().entrySet()) { email.addAttachment(extractCID(attachment.getKey()), attachment.getValue()); } } private static void fillEmailFromOutlookMessage(@Nonnull final Email email, @Nonnull final OutlookMessage outlookMessage) { checkNonEmptyArgument(email, "email"); checkNonEmptyArgument(outlookMessage, "outlookMessage"); email.setFromAddress(outlookMessage.getFromName(), outlookMessage.getFromEmail()); if (!MiscUtil.valueNullOrEmpty(outlookMessage.getReplyToEmail())) { email.setReplyToAddress(outlookMessage.getReplyToName(), outlookMessage.getReplyToEmail()); } for (final OutlookRecipient to : outlookMessage.getRecipients()) { email.addRecipient(to.getName(), to.getAddress(), Message.RecipientType.TO); } //noinspection QuestionableName for (final OutlookRecipient cc : outlookMessage.getCcRecipients()) { email.addRecipient(cc.getName(), cc.getAddress(), Message.RecipientType.CC); } for (final OutlookRecipient bcc : outlookMessage.getBccRecipients()) { email.addRecipient(bcc.getName(), bcc.getAddress(), Message.RecipientType.BCC); } email.setSubject(outlookMessage.getSubject()); email.setText(outlookMessage.getBodyText()); email.setTextHTML(outlookMessage.getBodyHTML() != null ? outlookMessage.getBodyHTML() : outlookMessage.getConvertedBodyHTML()); for (final Map.Entry<String, OutlookFileAttachment> cid : outlookMessage.fetchCIDMap().entrySet()) { final String cidName = checkNonEmptyArgument(cid.getKey(), "cid.key"); //noinspection ConstantConditions email.addEmbeddedImage(extractCID(cidName), cid.getValue().getData(), cid.getValue().getMimeTag()); } for (final OutlookFileAttachment attachment : outlookMessage.fetchTrueAttachments()) { email.addAttachment(attachment.getLongFilename(), attachment.getData(), attachment.getMimeTag()); } } private static Session createDummySession() { return Session.getDefaultInstance(new Properties()); } }