From dfd64074ccfda36b923f1d21e7d4402d218291d8 Mon Sep 17 00:00:00 2001 From: bbottema Date: Sun, 17 Nov 2019 13:37:18 +0100 Subject: [PATCH] #235: Be able to fix the sent date for a new email --- modules/cli-module/pom.xml | 2 +- .../BuilderApiToPicocliCommandsMapper.java | 9 ++- .../src/test/java/demo/CliDemoApp.java | 1 + .../org/simplejavamail/api/email/Email.java | 38 +++++++++++- .../api/email/EmailPopulatingBuilder.java | 32 +++++++++- .../converter/EmailConverter.java | 3 + .../MimeMessageParseException.java | 1 + .../mimemessage/MimeMessageParser.java | 18 ++++++ .../mimemessage/MimeMessageProducer.java | 4 +- .../internal/EmailPopulatingBuilderImpl.java | 61 ++++++++++++++++++- .../internal/EmailStartingBuilderImpl.java | 8 ++- .../InternalEmailPopulatingBuilder.java | 2 + .../simplejavamail/mailer/MailerLiveTest.java | 43 ++++++++----- .../src/test/java/testutil/EmailHelper.java | 13 +++- 14 files changed, 209 insertions(+), 26 deletions(-) diff --git a/modules/cli-module/pom.xml b/modules/cli-module/pom.xml index fbc3b57e9..1b7c5c410 100644 --- a/modules/cli-module/pom.xml +++ b/modules/cli-module/pom.xml @@ -29,7 +29,7 @@ com.github.bbottema java-reflection - 3.11.0 + 3.13.0 diff --git a/modules/cli-module/src/main/java/org/simplejavamail/internal/clisupport/BuilderApiToPicocliCommandsMapper.java b/modules/cli-module/src/main/java/org/simplejavamail/internal/clisupport/BuilderApiToPicocliCommandsMapper.java index 2229c06c7..b2fdf3be2 100644 --- a/modules/cli-module/src/main/java/org/simplejavamail/internal/clisupport/BuilderApiToPicocliCommandsMapper.java +++ b/modules/cli-module/src/main/java/org/simplejavamail/internal/clisupport/BuilderApiToPicocliCommandsMapper.java @@ -38,6 +38,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -83,6 +84,7 @@ public final class BuilderApiToPicocliCommandsMapper { put(X509Certificate.class, "PEM FILE"); put(UUID.class, "UUID"); put(LoadBalancingStrategy.class, "NAME"); + put(Date.class, "yyyy-[M]M-[d]d[ HH:mm]"); }}; static { @@ -139,8 +141,11 @@ private static void generateOptionsFromBuilderApi(Class apiNode, Set // assertion check for (CliDeclaredOptionSpec knownOption : cliOptionsFoundSoFar) { if (knownOption.getName().equals(optionName)) { - String msg = "@CliOptionNameOverride needed one of the following two methods:\n\t%s\n\t%s\n\t----------"; - throw new AssertionError(format(msg, knownOption.getSourceMethod(), m)); + final boolean methodIsActuallyTheSame = knownOption.getSourceMethod().equals(m); + if (!methodIsActuallyTheSame) { + String msg = "@CliOptionNameOverride needed one of the following two methods:\n\t%s\n\t%s\n\t----------"; + throw new AssertionError(format(msg, knownOption.getSourceMethod(), m)); + } } } diff --git a/modules/cli-module/src/test/java/demo/CliDemoApp.java b/modules/cli-module/src/test/java/demo/CliDemoApp.java index b61c695ad..047200bda 100644 --- a/modules/cli-module/src/test/java/demo/CliDemoApp.java +++ b/modules/cli-module/src/test/java/demo/CliDemoApp.java @@ -38,6 +38,7 @@ private static void demoSend(ServerConfig serverConfig) { "--email:forwarding", SOURCE_FOLDER + "/test/resources/test-messages/HTML mail with replyto and attachment and embedded image.msg", "--email:from", "Test sender", DemoAppBase.YOUR_GMAIL_ADDRESS, "--email:to", "Test Receiver", DemoAppBase.YOUR_GMAIL_ADDRESS, + "--email:fixingSentDate", "2011-5-10 11:15", "--mailer:withSMTPServer", "smtp.gmail.com", "587", serverConfig.getUsername(), serverConfig.getPassword(), "--mailer:withTransportStrategy", "SMTP_TLS" }); diff --git a/modules/core-module/src/main/java/org/simplejavamail/api/email/Email.java b/modules/core-module/src/main/java/org/simplejavamail/api/email/Email.java index 66b437131..b22e4faf5 100644 --- a/modules/core-module/src/main/java/org/simplejavamail/api/email/Email.java +++ b/modules/core-module/src/main/java/org/simplejavamail/api/email/Email.java @@ -11,6 +11,7 @@ import java.io.InputStream; import java.security.cert.X509Certificate; import java.io.Serializable; +import java.util.Date; import java.util.List; import java.util.Map; @@ -189,6 +190,18 @@ public class Email implements Serializable { @SuppressWarnings("deprecation") private final boolean wasMergedWithSmimeSignedMessage; + /** + * @see EmailPopulatingBuilder#fixingSentDate(Date) + */ + @Nullable + private final Date sentDate; + + /** + * @see EmailPopulatingBuilder#getOriginalSentDate() + */ + @Nullable + private final Date originalSentDate; + /** * Simply transfers everything from {@link EmailPopulatingBuilder} to this Email instance. * @@ -233,6 +246,9 @@ public Email(@NotNull final EmailPopulatingBuilder builder) { originalSmimeDetails = builder.getOriginalSmimeDetails(); + sentDate = builder.getSentDate(); + originalSentDate = builder.getOriginalSentDate(); + x509CertificateForSmimeEncryption = builder.getX509CertificateForSmimeEncryption(); pkcs12ConfigForSmimeSigning = builder.getPkcs12ConfigForSmimeSigning(); @@ -310,7 +326,11 @@ public boolean equals(final Object o) { @Override public String toString() { String s = "Email{" + - "\n\tid=" + id + + "\n\tid=" + id; + if (originalSentDate != null) { + s += "\n\toriginalSentDate=" + originalSentDate; + } + s += "\n\tsentDate=" + sentDate + "\n\tfromRecipient=" + fromRecipient + ",\n\treplyToRecipient=" + replyToRecipient + ",\n\tbounceToRecipient=" + bounceToRecipient + @@ -584,4 +604,20 @@ public Email getSmimeSignedEmail() { public OriginalSmimeDetails getOriginalSmimeDetails() { return originalSmimeDetails; } + + /** + * @see EmailPopulatingBuilder#fixingSentDate(Date) + */ + @Nullable + public Date getSentDate() { + return sentDate; + } + + /** + * @see EmailPopulatingBuilder#getOriginalSentDate() + */ + @Nullable + public Date getOriginalSentDate() { + return originalSentDate; + } } \ No newline at end of file diff --git a/modules/core-module/src/main/java/org/simplejavamail/api/email/EmailPopulatingBuilder.java b/modules/core-module/src/main/java/org/simplejavamail/api/email/EmailPopulatingBuilder.java index 15e474a8d..dc2554ef2 100644 --- a/modules/core-module/src/main/java/org/simplejavamail/api/email/EmailPopulatingBuilder.java +++ b/modules/core-module/src/main/java/org/simplejavamail/api/email/EmailPopulatingBuilder.java @@ -16,6 +16,7 @@ import java.io.InputStream; import java.security.cert.X509Certificate; import java.util.Collection; +import java.util.Date; import java.util.List; import java.util.Map; @@ -1163,7 +1164,7 @@ EmailPopulatingBuilder signWithDomainKey(@NotNull InputStream dkimPrivateKeyInpu */ @SuppressWarnings("unused") EmailPopulatingBuilder withReturnReceiptTo(@Nullable String fixedName, @NotNull InternetAddress address); - + /** * Indicates that this email should use the RRT flag "Return-Receipt-To" with the * preconfigured {@link Recipient}. This flag can be used to request a notification from the SMTP server recipient to signal that the recipient @@ -1174,6 +1175,16 @@ EmailPopulatingBuilder signWithDomainKey(@NotNull InputStream dkimPrivateKeyInpu */ EmailPopulatingBuilder withReturnReceiptTo(@NotNull Recipient recipient); + /** + * When the an email is sent it is converted to a MimeMessage at which time the sent-date is filled with the current date. With this method + * this can be fixed to a date of choice. + *

+ * Note that the sent date is never filled by Simple Java Mail, for example when converting from an Outlook or MimeMessage to Email. + * + * @param sentDate The date to use as sent date. + */ + EmailPopulatingBuilder fixingSentDate(@NotNull Date sentDate); + /** * Resets id to empty. */ @@ -1269,6 +1280,12 @@ EmailPopulatingBuilder signWithDomainKey(@NotNull InputStream dkimPrivateKeyInpu @SuppressWarnings("unused") EmailPopulatingBuilder clearReturnReceiptTo(); + /** + * Clears the fixed sent-date so that the current date is used again at the time of sending. + */ + @SuppressWarnings("unused") + EmailPopulatingBuilder clearSentDate(); + /** * When readig and converting an email, this flag makes the behavior revert back to the default merging * behavior for single S/MIME signed attachments, which is that it is merged into the root message. @@ -1466,5 +1483,16 @@ EmailPopulatingBuilder signWithDomainKey(@NotNull InputStream dkimPrivateKeyInpu */ @Nullable X509Certificate getX509CertificateForSmimeEncryption(); -} + /** + * @see EmailPopulatingBuilder#fixingSentDate(Date) + */ + @Nullable + Date getSentDate(); + + /** + * Contains the original sent-date when converting an existing message to Email. Not used when creating new mails. + */ + @Nullable + Date getOriginalSentDate(); +} \ No newline at end of file diff --git a/modules/simple-java-mail/src/main/java/org/simplejavamail/converter/EmailConverter.java b/modules/simple-java-mail/src/main/java/org/simplejavamail/converter/EmailConverter.java index 3a3f8797c..461c01a3e 100644 --- a/modules/simple-java-mail/src/main/java/org/simplejavamail/converter/EmailConverter.java +++ b/modules/simple-java-mail/src/main/java/org/simplejavamail/converter/EmailConverter.java @@ -581,6 +581,9 @@ public static String outlookMsgToEML(@NotNull final InputStream outlookMsgInputS private static EmailPopulatingBuilder buildEmailFromMimeMessage(@NotNull final EmailPopulatingBuilder builder, @NotNull final ParsedMimeMessageComponents parsed) { checkNonEmptyArgument(builder, "emailBuilder"); checkNonEmptyArgument(parsed, "parsedMimeMessageComponents"); + if (parsed.getSentDate() != null) { + ((InternalEmailPopulatingBuilder) builder).withOriginalSentDate(parsed.getSentDate()); + } if (parsed.getFromAddress() != null) { builder.from(parsed.getFromAddress().getPersonal(), parsed.getFromAddress().getAddress()); } diff --git a/modules/simple-java-mail/src/main/java/org/simplejavamail/converter/internal/mimemessage/MimeMessageParseException.java b/modules/simple-java-mail/src/main/java/org/simplejavamail/converter/internal/mimemessage/MimeMessageParseException.java index c0a09e5ee..b00db3a2d 100644 --- a/modules/simple-java-mail/src/main/java/org/simplejavamail/converter/internal/mimemessage/MimeMessageParseException.java +++ b/modules/simple-java-mail/src/main/java/org/simplejavamail/converter/internal/mimemessage/MimeMessageParseException.java @@ -31,6 +31,7 @@ class MimeMessageParseException extends MailException { static final String ERROR_GETTING_RECIPIENTS = "Error getting [%s] recipient types"; static final String ERROR_GETTING_SUBJECT = "Error getting subject"; static final String ERROR_GETTING_MESSAGE_ID = "Error getting message ID"; + static final String ERROR_GETTING_SEND_DATE = "Error getting sent-date"; static final String ERROR_PARSING_REPLY_TO_ADDRESSES = "Error parsing replyTo addresses"; MimeMessageParseException(@NotNull final String message, @Nullable final Exception cause) { diff --git a/modules/simple-java-mail/src/main/java/org/simplejavamail/converter/internal/mimemessage/MimeMessageParser.java b/modules/simple-java-mail/src/main/java/org/simplejavamail/converter/internal/mimemessage/MimeMessageParser.java index 12cedae81..2cd883025 100644 --- a/modules/simple-java-mail/src/main/java/org/simplejavamail/converter/internal/mimemessage/MimeMessageParser.java +++ b/modules/simple-java-mail/src/main/java/org/simplejavamail/converter/internal/mimemessage/MimeMessageParser.java @@ -36,6 +36,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.Date; import java.util.HashMap; import java.util.Iterator; import java.util.List; @@ -119,6 +120,7 @@ public final class MimeMessageParser { public static ParsedMimeMessageComponents parseMimeMessage(@NotNull final MimeMessage mimeMessage) { final ParsedMimeMessageComponents parsedComponents = new ParsedMimeMessageComponents(); parsedComponents.messageId = parseMessageId(mimeMessage); + parsedComponents.sentDate = parseSentDate(mimeMessage); parsedComponents.subject = parseSubject(mimeMessage); parsedComponents.toAddresses.addAll(parseToAddresses(mimeMessage)); parsedComponents.ccAddresses.addAll(parseCcAddresses(mimeMessage)); @@ -515,6 +517,16 @@ public static String parseMessageId(@NotNull final MimeMessage mimeMessage) { } } + @SuppressWarnings("WeakerAccess") + @Nullable + public static Date parseSentDate(@NotNull final MimeMessage mimeMessage) { + try { + return mimeMessage.getSentDate(); + } catch (final MessagingException e) { + throw new MimeMessageParseException(MimeMessageParseException.ERROR_GETTING_SEND_DATE, e); + } + } + static void moveInvalidEmbeddedResourcesToAttachments(ParsedMimeMessageComponents parsedComponents) { final String htmlContent = parsedComponents.htmlContent.toString(); for(Iterator> it = parsedComponents.cidMap.entrySet().iterator(); it.hasNext(); ) { @@ -546,6 +558,7 @@ public static class ParsedMimeMessageComponents { final StringBuilder htmlContent = new StringBuilder(); private String calendarMethod; private String calendarContent; + private Date sentDate; @Nullable public String getMessageId() { @@ -625,6 +638,11 @@ public String getCalendarContent() { public String getCalendarMethod() { return calendarMethod; } + + @Nullable + public Date getSentDate() { + return sentDate; + } } /** diff --git a/modules/simple-java-mail/src/main/java/org/simplejavamail/converter/internal/mimemessage/MimeMessageProducer.java b/modules/simple-java-mail/src/main/java/org/simplejavamail/converter/internal/mimemessage/MimeMessageProducer.java index d443fb9ef..c7eae18de 100644 --- a/modules/simple-java-mail/src/main/java/org/simplejavamail/converter/internal/mimemessage/MimeMessageProducer.java +++ b/modules/simple-java-mail/src/main/java/org/simplejavamail/converter/internal/mimemessage/MimeMessageProducer.java @@ -4,6 +4,7 @@ import org.simplejavamail.internal.modules.ModuleLoader; import org.jetbrains.annotations.NotNull; + import javax.mail.MessagingException; import javax.mail.Session; import javax.mail.internet.MimeMessage; @@ -12,6 +13,7 @@ import static org.simplejavamail.internal.util.MiscUtil.checkArgumentNotEmpty; import static org.simplejavamail.internal.util.MiscUtil.valueNullOrEmpty; +import static org.simplejavamail.internal.util.SimpleOptional.ofNullable; /** * Helper class that produces and populates a mime messages. Deals with javax.mail RFC MimeMessage stuff, as well as @@ -69,7 +71,7 @@ public String toString() { populateMimeMessageMultipartStructure(message, email); MimeMessageHelper.setHeaders(email, message); - message.setSentDate(new Date()); + message.setSentDate(ofNullable(email.getSentDate()).orElse(new Date())); /* The following order is important: diff --git a/modules/simple-java-mail/src/main/java/org/simplejavamail/email/internal/EmailPopulatingBuilderImpl.java b/modules/simple-java-mail/src/main/java/org/simplejavamail/email/internal/EmailPopulatingBuilderImpl.java index a45992343..f641801e6 100644 --- a/modules/simple-java-mail/src/main/java/org/simplejavamail/email/internal/EmailPopulatingBuilderImpl.java +++ b/modules/simple-java-mail/src/main/java/org/simplejavamail/email/internal/EmailPopulatingBuilderImpl.java @@ -32,6 +32,7 @@ import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.Collection; +import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -237,6 +238,18 @@ public class EmailPopulatingBuilderImpl implements InternalEmailPopulatingBuilde */ private boolean mergeSingleSMIMESignedAttachment = true; + /** + * @see EmailPopulatingBuilder#fixingSentDate(Date) + */ + @Nullable + private Date sentDate; + + /** + * @see EmailPopulatingBuilder#getOriginalSentDate() + */ + @Nullable + private Date originalSentDate; + /** * @see EmailStartingBuilder#startingBlank() */ @@ -313,7 +326,7 @@ private void validateDkim() { checkNonEmptyArgument(getFromRecipient(), "fromRecipient required when signing DKIM"); } } - + /** * @see EmailPopulatingBuilder#fixingMessageId(String) */ @@ -1714,6 +1727,25 @@ public InternalEmailPopulatingBuilder withSmimeSignedEmail(@NotNull final Email return this; } + /** + * @see EmailPopulatingBuilder#fixingSentDate(Date) + */ + @Override + public EmailPopulatingBuilder fixingSentDate(@NotNull final Date sentDate) { + this.sentDate = sentDate; + return this; + } + + /** + * @see EmailPopulatingBuilder#getOriginalSentDate() + */ + @Override + @NotNull + public InternalEmailPopulatingBuilder withOriginalSentDate(@NotNull final Date originalSentDate) { + this.originalSentDate = originalSentDate; + return this; + } + /** * @see EmailPopulatingBuilder#notMergingSingleSMIMESignedAttachment() */ @@ -1863,6 +1895,15 @@ public EmailPopulatingBuilder clearReturnReceiptTo() { return this; } + /** + * @see EmailPopulatingBuilder#fixingSentDate(Date) + */ + @Override + public EmailPopulatingBuilder clearSentDate() { + this.sentDate = null; + return this; + } + /** * @see EmailPopulatingBuilder#clearSMIMESignedAttachmentMergingBehavior() */ @@ -2124,4 +2165,22 @@ public Pkcs12Config getPkcs12ConfigForSmimeSigning() { public X509Certificate getX509CertificateForSmimeEncryption() { return x509CertificateForSmimeEncryption; } + + /** + * @see EmailPopulatingBuilder#fixingSentDate(Date) + */ + @Override + @Nullable + public Date getSentDate() { + return sentDate; + } + + /** + * @see EmailPopulatingBuilder#getOriginalSentDate() + */ + @Override + @Nullable + public Date getOriginalSentDate() { + return originalSentDate; + } } \ No newline at end of file diff --git a/modules/simple-java-mail/src/main/java/org/simplejavamail/email/internal/EmailStartingBuilderImpl.java b/modules/simple-java-mail/src/main/java/org/simplejavamail/email/internal/EmailStartingBuilderImpl.java index 06dc4ec6b..80c4c8167 100644 --- a/modules/simple-java-mail/src/main/java/org/simplejavamail/email/internal/EmailStartingBuilderImpl.java +++ b/modules/simple-java-mail/src/main/java/org/simplejavamail/email/internal/EmailStartingBuilderImpl.java @@ -1,5 +1,6 @@ package org.simplejavamail.email.internal; +import org.jetbrains.annotations.NotNull; import org.simplejavamail.api.email.Email; import org.simplejavamail.api.email.EmailPopulatingBuilder; import org.simplejavamail.api.email.EmailStartingBuilder; @@ -7,7 +8,6 @@ import org.simplejavamail.converter.internal.mimemessage.MimeMessageParser; import org.simplejavamail.email.EmailBuilder; -import org.jetbrains.annotations.NotNull; import javax.mail.MessagingException; import javax.mail.internet.MimeMessage; @@ -208,6 +208,12 @@ public EmailPopulatingBuilder copying(@NotNull final Email email) { builder.withEmbeddedImages(email.getEmbeddedImages()); builder.withAttachments(email.getAttachments()); ((InternalEmailPopulatingBuilder) builder).withHeaders(email.getHeaders(), true); + if (email.getOriginalSentDate() != null) { + ((InternalEmailPopulatingBuilder) builder).withOriginalSentDate(email.getOriginalSentDate()); + } + if (email.getSentDate() != null) { + builder.fixingSentDate(email.getSentDate()); + } if (email.getDkimPrivateKeyFile() != null) { builder.signWithDomainKey(email.getDkimPrivateKeyFile(), assumeNonNull(email.getDkimSigningDomain()), assumeNonNull(email.getDkimSelector())); } diff --git a/modules/simple-java-mail/src/main/java/org/simplejavamail/email/internal/InternalEmailPopulatingBuilder.java b/modules/simple-java-mail/src/main/java/org/simplejavamail/email/internal/InternalEmailPopulatingBuilder.java index 1f3a0e140..2cfc15eb4 100644 --- a/modules/simple-java-mail/src/main/java/org/simplejavamail/email/internal/InternalEmailPopulatingBuilder.java +++ b/modules/simple-java-mail/src/main/java/org/simplejavamail/email/internal/InternalEmailPopulatingBuilder.java @@ -8,6 +8,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.mail.internet.MimeMessage; +import java.util.Date; import java.util.List; import java.util.Map; @@ -21,4 +22,5 @@ public interface InternalEmailPopulatingBuilder extends EmailPopulatingBuilder @NotNull InternalEmailPopulatingBuilder withDecryptedAttachments(List decryptedAttachments); @NotNull InternalEmailPopulatingBuilder withSmimeSignedEmail(@NotNull Email smimeSignedEmail); @NotNull InternalEmailPopulatingBuilder withOriginalSmimeDetails(@NotNull OriginalSmimeDetails originalSmimeDetails); + @NotNull InternalEmailPopulatingBuilder withOriginalSentDate(@NotNull Date originalSentDate); } \ No newline at end of file diff --git a/modules/simple-java-mail/src/test/java/org/simplejavamail/mailer/MailerLiveTest.java b/modules/simple-java-mail/src/test/java/org/simplejavamail/mailer/MailerLiveTest.java index f3ab19dad..e872fa6b1 100644 --- a/modules/simple-java-mail/src/test/java/org/simplejavamail/mailer/MailerLiveTest.java +++ b/modules/simple-java-mail/src/test/java/org/simplejavamail/mailer/MailerLiveTest.java @@ -26,6 +26,9 @@ import javax.mail.internet.MimeUtility; import java.io.File; import java.io.IOException; +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; import java.util.concurrent.ExecutionException; import static demo.ResourceFolderHelper.determineResourceFolder; @@ -38,6 +41,7 @@ import static org.simplejavamail.internal.util.MiscUtil.normalizeNewlines; import static org.simplejavamail.internal.util.Preconditions.assumeNonNull; import static org.simplejavamail.util.TestDataHelper.loadPkcs12KeyStore; +import static testutil.EmailHelper.CUSTOM_SENT_DATE; import static testutil.EmailHelper.readOutlookMessage; /* @@ -66,43 +70,43 @@ public void setup() { @Test public void createMailSession_EmptySubjectAndBody() throws IOException, MessagingException, ExecutionException, InterruptedException { - assertSendingEmail(EmailHelper.createDummyEmailBuilder(true, true, false, true), true, false, false); + assertSendingEmail(EmailHelper.createDummyEmailBuilder(true, true, false, true), true, false, false, false); } @Test public void createMailSession_StandardDummyMailBasicFields() throws IOException, MessagingException, ExecutionException, InterruptedException { - assertSendingEmail(EmailHelper.createDummyEmailBuilder(true, true, false, true), true, false, false); + assertSendingEmail(EmailHelper.createDummyEmailBuilder(true, true, false, true), true, false, false, false); } @Test public void createMailSession_StandardDummyMailBasicFields_Async() throws IOException, MessagingException, ExecutionException, InterruptedException { - assertSendingEmail(EmailHelper.createDummyEmailBuilder(true, true, false, true), true, false, true); + assertSendingEmail(EmailHelper.createDummyEmailBuilder(true, true, false, true), true, false, true, false); } @Test public void createMailSession_StandardDummyMail_AllFields() throws IOException, MessagingException, ExecutionException, InterruptedException { - assertSendingEmail(EmailHelper.createDummyEmailBuilder(true, false, false, true), true, false, false); + assertSendingEmail(EmailHelper.createDummyEmailBuilder(true, false, false, true), true, false, false, false); } @Test public void createMailSession_StandardDummyMail_IncludingCustomHeaders() throws IOException, MessagingException, ExecutionException, InterruptedException { - assertSendingEmail(EmailHelper.createDummyEmailBuilder(true, false, true, true), true, false, false); + assertSendingEmail(EmailHelper.createDummyEmailBuilder(true, false, true, true), true, false, false, false); } @Test - public void createMailSession_StandardDummyMailWithId() + public void createMailSession_StandardDummyMailWithIdAndSendDate() throws IOException, MessagingException, ExecutionException, InterruptedException { - assertSendingEmail(EmailHelper.createDummyEmailBuilder("<123@456>", true, false, false, true), true, false, false); + assertSendingEmail(EmailHelper.createDummyEmailBuilder("<123@456>", true, false, false, true, true), true, false, false, true); } @Test public void createMailSession_OutlookMessageTest() throws IOException, MessagingException, ExecutionException, InterruptedException { - Email email = assertSendingEmail(readOutlookMessage("test-messages/HTML mail with replyto and attachment and embedded image.msg"), false, false, false); + Email email = assertSendingEmail(readOutlookMessage("test-messages/HTML mail with replyto and attachment and embedded image.msg"), false, false, false, false); verifyReceivedOutlookEmail(email, false, false); } @@ -111,7 +115,7 @@ public void createMailSession_OutlookMessageSmimeSignTest() throws IOException, MessagingException, ExecutionException, InterruptedException { EmailPopulatingBuilder builder = readOutlookMessage("test-messages/HTML mail with replyto and attachment and embedded image.msg"); builder.signWithSmime(new File(RESOURCES_PKCS + "/smime_keystore.pkcs12"), "letmein", "smime_test_user_alias", "letmein"); - Email email = assertSendingEmail(builder, false, true, false); + Email email = assertSendingEmail(builder, false, true, false, false); verifyReceivedOutlookEmail(email, true, false); EmailAssert.assertThat(email).wasNotMergedWithSmimeSignedMessage(); @@ -131,7 +135,7 @@ public void createMailSession_OutlookMessageSmimeEncryptTest() throws IOException, MessagingException, ExecutionException, InterruptedException { EmailPopulatingBuilder builder = readOutlookMessage("test-messages/HTML mail with replyto and attachment and embedded image.msg"); builder.encryptWithSmime(new File(RESOURCES_PKCS + "/smime_test_user.pem.standard.crt")); - Email email = assertSendingEmail(builder, false, true, false); + Email email = assertSendingEmail(builder, false, true, false, false); verifyReceivedOutlookEmail(email, false, true); EmailAssert.assertThat(email).wasMergedWithSmimeSignedMessage(); @@ -150,7 +154,7 @@ public void createMailSession_OutlookMessageSmimeSignEncryptTest() EmailPopulatingBuilder builder = readOutlookMessage("test-messages/HTML mail with replyto and attachment and embedded image.msg"); builder.signWithSmime(new File(RESOURCES_PKCS + "/smime_keystore.pkcs12"), "letmein", "smime_test_user_alias", "letmein"); builder.encryptWithSmime(new File(RESOURCES_PKCS + "/smime_test_user.pem.standard.crt")); - Email email = assertSendingEmail(builder, false, true, false); + Email email = assertSendingEmail(builder, false, true, false, false); verifyReceivedOutlookEmail(email, true, true); EmailAssert.assertThat(email).wasMergedWithSmimeSignedMessage(); @@ -226,7 +230,7 @@ private void verifyReceivedOutlookEmail(final Email email, final boolean smimeSi } private Email assertSendingEmail(final EmailPopulatingBuilder originalEmailPopulatingBuilder, boolean compensateForDresscodeAttachmentNameOverrideErasure, boolean skipChecksDueToSmime, - boolean async) + boolean async, final boolean fixedSentDate) throws MessagingException, ExecutionException, InterruptedException { Email originalEmail = originalEmailPopulatingBuilder.buildEmail(); @@ -245,6 +249,15 @@ private Email assertSendingEmail(final EmailPopulatingBuilder originalEmailPopul } Email receivedEmail = mimeMessageToEmail(receivedMimeMessage.getMimeMessage(), loadPkcs12KeyStore()); + + if (!fixedSentDate) { + GregorianCalendar receiveWindowStart = new GregorianCalendar(); + receiveWindowStart.add(Calendar.SECOND, -5); + assertThat(receivedEmail.getOriginalSentDate()).isBetween(receiveWindowStart.getTime(), new Date()); + } else { + assertThat(receivedEmail.getOriginalSentDate()).isEqualTo(CUSTOM_SENT_DATE); + } + // hack: it seems Wiser automatically defaults replyTo address to the From address if left empty if (originalEmailPopulatingBuilder.getReplyToRecipient() == null) { originalEmailPopulatingBuilder.withReplyTo(originalEmailPopulatingBuilder.getFromRecipient()); @@ -285,7 +298,7 @@ public void createMailSession_ReplyToMessage() // send reply to initial mail Email reply = EmailBuilder - .replyingToAll(assertSendingEmail(receivedEmailPopulatingBuilder, false, false, false)) + .replyingToAll(assertSendingEmail(receivedEmailPopulatingBuilder, false, false, false, false)) .from("dummy@domain.com") .withPlainText("This is the reply") .buildEmail(); @@ -317,7 +330,7 @@ public void createMailSession_ReplyToMessage_NotAll_AndCustomReferences() // send reply to initial mail Email reply = EmailBuilder - .replyingTo(assertSendingEmail(receivedEmailPopulatingBuilder, false, false, false)) + .replyingTo(assertSendingEmail(receivedEmailPopulatingBuilder, false, false, false, false)) .from("Moo Shmoo", "dummy@domain.com") .withPlainText("This is the reply") .buildEmail(); @@ -335,7 +348,7 @@ public void createMailSession_ReplyToMessage_NotAll_AndCustomReferences() EmailPopulatingBuilder receivedEmailReplyPopulatingBuilder = mimeMessageToEmailBuilder(receivedMimeMessageReply); Email replyToReply = EmailBuilder - .replyingTo(assertSendingEmail(receivedEmailReplyPopulatingBuilder, false, false, false)) + .replyingTo(assertSendingEmail(receivedEmailReplyPopulatingBuilder, false, false, false, false)) .from("Pappa Moo", "dummy@domain.com") .withPlainText("This is the reply to the reply") .buildEmail(); diff --git a/modules/simple-java-mail/src/test/java/testutil/EmailHelper.java b/modules/simple-java-mail/src/test/java/testutil/EmailHelper.java index 68449d143..c36458b91 100644 --- a/modules/simple-java-mail/src/test/java/testutil/EmailHelper.java +++ b/modules/simple-java-mail/src/test/java/testutil/EmailHelper.java @@ -18,11 +18,14 @@ import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.nio.charset.Charset; +import java.util.Date; +import java.util.GregorianCalendar; import java.util.List; import java.util.Properties; import java.util.UUID; import java.util.concurrent.ExecutorService; +import static java.util.Calendar.SEPTEMBER; import static java.util.UUID.randomUUID; import static java.util.concurrent.Executors.newSingleThreadExecutor; import static javax.xml.bind.DatatypeConverter.parseBase64Binary; @@ -32,13 +35,15 @@ public class EmailHelper { + public static final Date CUSTOM_SENT_DATE = new GregorianCalendar(2011, SEPTEMBER, 15, 12, 5, 43).getTime(); + public static EmailPopulatingBuilder createDummyEmailBuilder(boolean includeSubjectAndBody, boolean basicFields, boolean includeCustomHeaders, boolean useSmimeDetailsImplFromSmimeModule) throws IOException { - return createDummyEmailBuilder(null, includeSubjectAndBody, basicFields, includeCustomHeaders, useSmimeDetailsImplFromSmimeModule); + return createDummyEmailBuilder(null, includeSubjectAndBody, basicFields, includeCustomHeaders, useSmimeDetailsImplFromSmimeModule, false); } public static EmailPopulatingBuilder createDummyEmailBuilder(@Nullable String id, boolean includeSubjectAndBody, boolean basicFields, boolean includeCustomHeaders, - boolean useSmimeDetailsImplFromSmimeModule) + boolean useSmimeDetailsImplFromSmimeModule, final boolean fixSentDate) throws IOException { EmailPopulatingBuilder builder = EmailBuilder.startingBlank() .fixingMessageId(id) @@ -68,6 +73,10 @@ public static EmailPopulatingBuilder createDummyEmailBuilder(@Nullable String id .withReturnReceiptTo("Complex Email", "simple@address.com"); } + if (fixSentDate) { + builder = builder.fixingSentDate(CUSTOM_SENT_DATE); + } + // add two text files in different ways and a black thumbs up embedded image -> ByteArrayDataSource namedAttachment = new ByteArrayDataSource("Black Tie Optional", "text/plain"); namedAttachment.setName("dresscode-ignored-because-of-override.txt");