From 859b2b97478cbd37c4f68eadcc9f5672d25cbb35 Mon Sep 17 00:00:00 2001 From: bbottema Date: Sun, 5 Mar 2017 20:38:51 +0100 Subject: [PATCH] restructured internal parser classes and added support for parsing Outlook messages! --- pom.xml | 7 ++ .../converter/EmailConverter.java | 80 +++++++++++++++++-- .../MimeMessageException.java | 4 +- .../{ => mimemessage}/MimeMessageHelper.java | 2 +- .../{ => mimemessage}/MimeMessageParser.java | 5 +- .../{ => mimemessage}/NamedDataSource.java | 2 +- .../msgparser/OutlookMessageException.java | 19 +++++ .../msgparser/OutlookMessageParser.java | 37 +++++++++ .../org/simplejavamail/mailer/Mailer.java | 2 +- .../internal/mailsender/MailSender.java | 2 +- .../MimeMessageHelperTest.java | 3 +- .../NamedDataSourceTest.java | 3 +- 12 files changed, 146 insertions(+), 20 deletions(-) rename src/main/java/org/simplejavamail/converter/internal/{ => mimemessage}/MimeMessageException.java (66%) rename src/main/java/org/simplejavamail/converter/internal/{ => mimemessage}/MimeMessageHelper.java (99%) rename src/main/java/org/simplejavamail/converter/internal/{ => mimemessage}/MimeMessageParser.java (99%) rename src/main/java/org/simplejavamail/converter/internal/{ => mimemessage}/NamedDataSource.java (96%) create mode 100644 src/main/java/org/simplejavamail/converter/internal/msgparser/OutlookMessageException.java create mode 100644 src/main/java/org/simplejavamail/converter/internal/msgparser/OutlookMessageParser.java rename src/test/java/org/simplejavamail/converter/internal/{ => mimemessage}/MimeMessageHelperTest.java (96%) rename src/test/java/org/simplejavamail/converter/internal/{ => mimemessage}/NamedDataSourceTest.java (93%) diff --git a/pom.xml b/pom.xml index e398ae23d..f7cddd5bd 100644 --- a/pom.xml +++ b/pom.xml @@ -91,6 +91,11 @@ utils-mail-dkim 1.1.6 + + org.simplejavamail + outlook-message-parser + 1.1.16-SNAPSHOT + @@ -166,6 +171,7 @@ 1.7 + maven-release-plugin 2.5.2 @@ -254,6 +260,7 @@ com.github.bbottema:emailaddress-rfc2822 net.markenwerk:utils-mail-dkim + org.simplejavamail:outlook-message-parser diff --git a/src/main/java/org/simplejavamail/converter/EmailConverter.java b/src/main/java/org/simplejavamail/converter/EmailConverter.java index 0f5e8ed50..bd3a9f11e 100644 --- a/src/main/java/org/simplejavamail/converter/EmailConverter.java +++ b/src/main/java/org/simplejavamail/converter/EmailConverter.java @@ -1,8 +1,13 @@ package org.simplejavamail.converter; -import org.simplejavamail.converter.internal.MimeMessageHelper; -import org.simplejavamail.converter.internal.MimeMessageParser; +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; @@ -11,13 +16,19 @@ import javax.mail.Session; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeMessage; -import java.io.*; +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.MimeMessageHelper.produceMimeMessage; +import static org.simplejavamail.converter.internal.mimemessage.MimeMessageHelper.produceMimeMessage; import static org.simplejavamail.internal.util.MiscUtil.extractCID; /** @@ -36,15 +47,43 @@ private EmailConverter() { public static Email mimeMessageToEmail(@Nonnull final MimeMessage mimeMessage) { final Email email = new Email(false); try { - fillEmailFromMimeMessage(email, new MimeMessageParser(mimeMessage).parse()); + fillEmailFromMimeMessage(email, mimeMessage); } catch (MessagingException | IOException e) { throw new EmailConverterException(format(EmailConverterException.PARSE_ERROR_MIMEMESSAGE, e.getMessage()), e); } return email; } - private static void fillEmailFromMimeMessage(@Nonnull final Email email, @Nonnull final MimeMessageParser parser) - throws MessagingException { + /** + * @param msgData The content of an Outlook (.msg) message from which to create the email. + */ + public static Email outlookMsgToEmail(@Nonnull final String msgData) { + final Email email = new Email(false); + fillEmailFromOutlookMessage(email, OutlookMessageParser.parseOutlookMsg(msgData)); + return email; + } + + /** + * @param msgfile The content of an Outlook (.msg) message from which to create the email. + */ + public static Email outlookMsgToEmail(@Nonnull final File msgfile) { + final Email email = new Email(false); + fillEmailFromOutlookMessage(email, OutlookMessageParser.parseOutlookMsg(msgfile)); + return email; + } + + /** + * @param msgInputStream The content of an Outlook (.msg) message from which to create the email. + */ + public static Email outlookMsgToEmail(@Nonnull final InputStream msgInputStream) { + final Email email = new Email(false); + fillEmailFromOutlookMessage(email, OutlookMessageParser.parseOutlookMsg(msgInputStream)); + return email; + } + + private static void fillEmailFromMimeMessage(@Nonnull final Email email, @Nonnull final MimeMessage mimeMessage) + throws MessagingException, IOException { + final MimeMessageParser parser = new MimeMessageParser(mimeMessage).parse(); final InternetAddress from = parser.getFrom(); email.setFromAddress(from.getPersonal(), from.getAddress()); final InternetAddress replyTo = parser.getReplyTo(); @@ -73,6 +112,33 @@ private static void fillEmailFromMimeMessage(@Nonnull final Email email, @Nonnul } } + private static void fillEmailFromOutlookMessage(@Nonnull final Email email, @Nonnull final 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 cid : outlookMessage.fetchCIDMap().entrySet()) { + email.addEmbeddedImage(extractCID(cid.getKey()), cid.getValue().getData(), cid.getValue().getMimeTag()); + } + for (final OutlookFileAttachment attachment : outlookMessage.fetchTrueAttachments()) { + email.addAttachment(attachment.getLongFilename(), attachment.getData(), attachment.getMimeTag()); + } + } + /** * Delegates to {@link #emailToMimeMessage(Email, Session)}, using a new empty {@link Session} instance. * diff --git a/src/main/java/org/simplejavamail/converter/internal/MimeMessageException.java b/src/main/java/org/simplejavamail/converter/internal/mimemessage/MimeMessageException.java similarity index 66% rename from src/main/java/org/simplejavamail/converter/internal/MimeMessageException.java rename to src/main/java/org/simplejavamail/converter/internal/mimemessage/MimeMessageException.java index cde72f46d..bb3f53382 100644 --- a/src/main/java/org/simplejavamail/converter/internal/MimeMessageException.java +++ b/src/main/java/org/simplejavamail/converter/internal/mimemessage/MimeMessageException.java @@ -1,9 +1,9 @@ -package org.simplejavamail.converter.internal; +package org.simplejavamail.converter.internal.mimemessage; import org.simplejavamail.MailException; /** - * This exception is used to communicate errors during the sending of email. + * This exception is used to communicate errors during parsing of a {@link javax.mail.internet.MimeMessage}. * * @author Benny Bottema */ diff --git a/src/main/java/org/simplejavamail/converter/internal/MimeMessageHelper.java b/src/main/java/org/simplejavamail/converter/internal/mimemessage/MimeMessageHelper.java similarity index 99% rename from src/main/java/org/simplejavamail/converter/internal/MimeMessageHelper.java rename to src/main/java/org/simplejavamail/converter/internal/mimemessage/MimeMessageHelper.java index 314ae30ea..9b5f9a73f 100644 --- a/src/main/java/org/simplejavamail/converter/internal/MimeMessageHelper.java +++ b/src/main/java/org/simplejavamail/converter/internal/mimemessage/MimeMessageHelper.java @@ -1,4 +1,4 @@ -package org.simplejavamail.converter.internal; +package org.simplejavamail.converter.internal.mimemessage; import net.markenwerk.utils.mail.dkim.Canonicalization; import net.markenwerk.utils.mail.dkim.DkimMessage; diff --git a/src/main/java/org/simplejavamail/converter/internal/MimeMessageParser.java b/src/main/java/org/simplejavamail/converter/internal/mimemessage/MimeMessageParser.java similarity index 99% rename from src/main/java/org/simplejavamail/converter/internal/MimeMessageParser.java rename to src/main/java/org/simplejavamail/converter/internal/mimemessage/MimeMessageParser.java index f5c0cb242..20200459b 100644 --- a/src/main/java/org/simplejavamail/converter/internal/MimeMessageParser.java +++ b/src/main/java/org/simplejavamail/converter/internal/mimemessage/MimeMessageParser.java @@ -15,7 +15,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.simplejavamail.converter.internal; +package org.simplejavamail.converter.internal.mimemessage; import javax.activation.DataHandler; import javax.activation.DataSource; @@ -29,8 +29,7 @@ /** * heavily modified version based on org.apache.commons.mail.util.MimeMessageParser.html - * Parses a MimeMessage and stores the individual parts such a plain text, - * HTML text and attachments. + * Parses a MimeMessage and stores the individual parts such a plain text, HTML text and attachments. * * @version current: MimeMessageParser.java 2016-02-25 Benny Bottema */ diff --git a/src/main/java/org/simplejavamail/converter/internal/NamedDataSource.java b/src/main/java/org/simplejavamail/converter/internal/mimemessage/NamedDataSource.java similarity index 96% rename from src/main/java/org/simplejavamail/converter/internal/NamedDataSource.java rename to src/main/java/org/simplejavamail/converter/internal/mimemessage/NamedDataSource.java index 6f3710473..f242186ed 100644 --- a/src/main/java/org/simplejavamail/converter/internal/NamedDataSource.java +++ b/src/main/java/org/simplejavamail/converter/internal/mimemessage/NamedDataSource.java @@ -1,4 +1,4 @@ -package org.simplejavamail.converter.internal; +package org.simplejavamail.converter.internal.mimemessage; import javax.activation.DataSource; import java.io.IOException; diff --git a/src/main/java/org/simplejavamail/converter/internal/msgparser/OutlookMessageException.java b/src/main/java/org/simplejavamail/converter/internal/msgparser/OutlookMessageException.java new file mode 100644 index 000000000..1a7c5c43e --- /dev/null +++ b/src/main/java/org/simplejavamail/converter/internal/msgparser/OutlookMessageException.java @@ -0,0 +1,19 @@ +package org.simplejavamail.converter.internal.msgparser; + +import org.simplejavamail.MailException; + +/** + * This exception is used to communicate errors during parsing of a MsgParser {@link org.simplejavamail.outlookmessageparser.model.OutlookMessage} of Outlook + * .msg data. + * + * @author Benny Bottema + */ +@SuppressWarnings("serial") +class OutlookMessageException extends MailException { + + static final String ERROR_PARSING_OUTLOOK_MSG = "Unable to parse Outlook message"; + + OutlookMessageException(final String message, final Exception cause) { + super(message, cause); + } +} \ No newline at end of file diff --git a/src/main/java/org/simplejavamail/converter/internal/msgparser/OutlookMessageParser.java b/src/main/java/org/simplejavamail/converter/internal/msgparser/OutlookMessageParser.java new file mode 100644 index 000000000..9bd068793 --- /dev/null +++ b/src/main/java/org/simplejavamail/converter/internal/msgparser/OutlookMessageParser.java @@ -0,0 +1,37 @@ +package org.simplejavamail.converter.internal.msgparser; + +import org.simplejavamail.outlookmessageparser.model.OutlookMessage; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; + +/** + * Helper class that parses {@link OutlookMessage} instances from the {@link org.simplejavamail.outlookmessageparser.OutlookMessageParser} library. + */ +public class OutlookMessageParser { + + public static OutlookMessage parseOutlookMsg(File msgFile) { + try { + return new org.simplejavamail.outlookmessageparser.OutlookMessageParser().parseMsg(msgFile); + } catch (IOException e) { + throw new OutlookMessageException(OutlookMessageException.ERROR_PARSING_OUTLOOK_MSG, e); + } + } + + public static OutlookMessage parseOutlookMsg(InputStream msgInputStream) { + try { + return new org.simplejavamail.outlookmessageparser.OutlookMessageParser().parseMsg(msgInputStream); + } catch (IOException e) { + throw new OutlookMessageException(OutlookMessageException.ERROR_PARSING_OUTLOOK_MSG, e); + } + } + + public static OutlookMessage parseOutlookMsg(String msgData) { + try { + return new org.simplejavamail.outlookmessageparser.OutlookMessageParser().parseMsg(msgData); + } catch (IOException e) { + throw new OutlookMessageException(OutlookMessageException.ERROR_PARSING_OUTLOOK_MSG, e); + } + } +} \ No newline at end of file diff --git a/src/main/java/org/simplejavamail/mailer/Mailer.java b/src/main/java/org/simplejavamail/mailer/Mailer.java index 69a11d157..2eeb93573 100644 --- a/src/main/java/org/simplejavamail/mailer/Mailer.java +++ b/src/main/java/org/simplejavamail/mailer/Mailer.java @@ -9,7 +9,7 @@ import org.simplejavamail.mailer.config.ServerConfig; import org.simplejavamail.mailer.config.TransportStrategy; import org.simplejavamail.mailer.internal.mailsender.MailSender; -import org.simplejavamail.converter.internal.MimeMessageHelper; +import org.simplejavamail.converter.internal.mimemessage.MimeMessageHelper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/src/main/java/org/simplejavamail/mailer/internal/mailsender/MailSender.java b/src/main/java/org/simplejavamail/mailer/internal/mailsender/MailSender.java index d80efb665..c41d5a1e7 100644 --- a/src/main/java/org/simplejavamail/mailer/internal/mailsender/MailSender.java +++ b/src/main/java/org/simplejavamail/mailer/internal/mailsender/MailSender.java @@ -1,7 +1,7 @@ package org.simplejavamail.mailer.internal.mailsender; import org.simplejavamail.MailException; -import org.simplejavamail.converter.internal.MimeMessageHelper; +import org.simplejavamail.converter.internal.mimemessage.MimeMessageHelper; import org.simplejavamail.email.Email; import org.simplejavamail.mailer.config.ProxyConfig; import org.simplejavamail.mailer.config.TransportStrategy; diff --git a/src/test/java/org/simplejavamail/converter/internal/MimeMessageHelperTest.java b/src/test/java/org/simplejavamail/converter/internal/mimemessage/MimeMessageHelperTest.java similarity index 96% rename from src/test/java/org/simplejavamail/converter/internal/MimeMessageHelperTest.java rename to src/test/java/org/simplejavamail/converter/internal/mimemessage/MimeMessageHelperTest.java index 99c1e7584..0d6e165df 100644 --- a/src/test/java/org/simplejavamail/converter/internal/MimeMessageHelperTest.java +++ b/src/test/java/org/simplejavamail/converter/internal/mimemessage/MimeMessageHelperTest.java @@ -1,8 +1,7 @@ -package org.simplejavamail.converter.internal; +package org.simplejavamail.converter.internal.mimemessage; import org.junit.Test; import org.simplejavamail.email.AttachmentResource; -import org.simplejavamail.converter.internal.MimeMessageHelper; import javax.mail.util.ByteArrayDataSource; import java.io.IOException; diff --git a/src/test/java/org/simplejavamail/converter/internal/NamedDataSourceTest.java b/src/test/java/org/simplejavamail/converter/internal/mimemessage/NamedDataSourceTest.java similarity index 93% rename from src/test/java/org/simplejavamail/converter/internal/NamedDataSourceTest.java rename to src/test/java/org/simplejavamail/converter/internal/mimemessage/NamedDataSourceTest.java index 0b7593405..392653de6 100644 --- a/src/test/java/org/simplejavamail/converter/internal/NamedDataSourceTest.java +++ b/src/test/java/org/simplejavamail/converter/internal/mimemessage/NamedDataSourceTest.java @@ -1,11 +1,10 @@ -package org.simplejavamail.converter.internal; +package org.simplejavamail.converter.internal.mimemessage; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; -import org.simplejavamail.converter.internal.NamedDataSource; import javax.activation.DataSource;