Skip to content

Commit d1c56a7

Browse files
committed
#399: Change the builder interface to support other content transfer encoders. Includes property default and Spring property support
1 parent 97ae85b commit d1c56a7

File tree

12 files changed

+200
-12
lines changed

12 files changed

+200
-12
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package org.simplejavamail.api.email;
2+
3+
import lombok.Getter;
4+
import lombok.RequiredArgsConstructor;
5+
import lombok.Value;
6+
7+
import java.util.Arrays;
8+
9+
/**
10+
* Possible encoders for email content (text/html/iCalendar). Default is {@link #QUOTED_PRINTABLE}. This list reflects Jakarta Mail's supported encoders as found at
11+
* {@code StreamProvider.EncoderTypes}
12+
*
13+
* @see "StreamProvider.EncoderTypes"
14+
*/
15+
@RequiredArgsConstructor
16+
@Getter
17+
public enum ContentTransferEncoding {
18+
19+
BASE_64("base64"),
20+
B("b"),
21+
Q("q"),
22+
BINARY("binary"),
23+
BIT7("7bit"),
24+
BIT8("8bit"),
25+
QUOTED_PRINTABLE("quoted-printable"),
26+
UU("uuencode"),
27+
X_UU("x-uuencode"),
28+
X_UUE("x-uue");
29+
30+
private final String encoder;
31+
}

modules/core-module/src/main/java/org/simplejavamail/api/email/Email.java

+15
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,12 @@ public class Email implements Serializable {
7474
*/
7575
private final String textCalendar;
7676

77+
/**
78+
* @see EmailPopulatingBuilder#withContentTransferEncoding(ContentTransferEncoding)
79+
*/
80+
@NotNull
81+
private final ContentTransferEncoding contentTransferEncoding;
82+
7783
/**
7884
* @see EmailPopulatingBuilder#withSubject(String)
7985
*/
@@ -233,6 +239,7 @@ public Email(@NotNull final EmailPopulatingBuilder builder) {
233239
textHTML = smimeMerge ? smimeSignedEmail.getHTMLText() : builder.getTextHTML();
234240
calendarMethod = builder.getCalendarMethod();
235241
textCalendar = builder.getTextCalendar();
242+
contentTransferEncoding = builder.getContentTransferEncoding();
236243
subject = builder.getSubject();
237244

238245
useDispositionNotificationTo = builder.isUseDispositionNotificationTo();
@@ -605,4 +612,12 @@ public OriginalSmimeDetails getOriginalSmimeDetails() {
605612
public Date getSentDate() {
606613
return sentDate != null ? new Date(sentDate.getTime()) : null;
607614
}
615+
616+
/**
617+
* @see EmailPopulatingBuilder#withContentTransferEncoding(ContentTransferEncoding)
618+
*/
619+
@NotNull
620+
public ContentTransferEncoding getContentTransferEncoding() {
621+
return contentTransferEncoding;
622+
}
608623
}

modules/core-module/src/main/java/org/simplejavamail/api/email/EmailPopulatingBuilder.java

+32-2
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,18 @@ public interface EmailPopulatingBuilder {
324324
* @see "The Test demo app in Simple Java Mail's source for a working example."
325325
*/
326326
EmailPopulatingBuilder withCalendarText(@NotNull CalendarMethod calendarMethod, @NotNull String textCalendar);
327-
327+
328+
/**
329+
* Determines what encoding is applied to the text/html/iCalendar encoding in the MimeMessage/EML. Default is {@link ContentTransferEncoding#QUOTED_PRINTABLE}, which basicallt means plain
330+
* text, so you can just read the content of the EML (if not encrypted).
331+
* <p>
332+
* However, you can choose another encoding as supported by Jakarta Mail. The list is quite extensive, but the most common alternative is base64. This might be useful for example for obfuscating
333+
* the content to some extent.
334+
*
335+
* @param contentTransferEncoding The encoder to use for the text/html/iCalendar content.
336+
*/
337+
EmailPopulatingBuilder withContentTransferEncoding(@NotNull ContentTransferEncoding contentTransferEncoding);
338+
328339
/**
329340
* Delegates to {@link #withRecipients(Collection, Message.RecipientType)} with <code>recipientType=</code>{@link Message.RecipientType#TO}.
330341
*/
@@ -1376,6 +1387,16 @@ public interface EmailPopulatingBuilder {
13761387
* Resets <em>textHTML</em> to empty.
13771388
*/
13781389
EmailPopulatingBuilder clearHTMLText();
1390+
1391+
/**
1392+
* Resets <em>calendarText</em> to empty.
1393+
*/
1394+
EmailPopulatingBuilder clearCalendarText();
1395+
1396+
/**
1397+
* Resets <em>contentTransferEncoding</em> to {@link ContentTransferEncoding#QUOTED_PRINTABLE}.
1398+
*/
1399+
EmailPopulatingBuilder clearContentTransferEncoding();
13791400

13801401
/**
13811402
* Resets <em>subject</em> to empty.
@@ -1510,9 +1531,18 @@ public interface EmailPopulatingBuilder {
15101531
*/
15111532
@Nullable
15121533
CalendarMethod getCalendarMethod();
1513-
1534+
1535+
/**
1536+
* @see #withCalendarText(CalendarMethod, String)
1537+
*/
15141538
@Nullable
15151539
String getTextCalendar();
1540+
1541+
/**
1542+
* @see #withContentTransferEncoding(ContentTransferEncoding)
1543+
* @see #clearContentTransferEncoding()
1544+
*/
1545+
ContentTransferEncoding getContentTransferEncoding();
15161546

15171547
/**
15181548
* @see #withSubject(String)

modules/core-module/src/main/java/org/simplejavamail/config/ConfigLoader.java

+9
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import org.jetbrains.annotations.NotNull;
44
import org.jetbrains.annotations.Nullable;
5+
import org.simplejavamail.api.email.ContentTransferEncoding;
56
import org.simplejavamail.api.mailer.config.LoadBalancingStrategy;
67
import org.simplejavamail.api.mailer.config.TransportStrategy;
78
import org.simplejavamail.internal.util.SimpleConversions;
@@ -44,6 +45,7 @@
4445
* <li>simplejavamail.proxy.username</li>
4546
* <li>simplejavamail.proxy.password</li>
4647
* <li>simplejavamail.proxy.socks5bridge.port</li>
48+
* <li>simplejavamail.defaults.content.transfer.encoding</li>
4749
* <li>simplejavamail.defaults.subject</li>
4850
* <li>simplejavamail.defaults.from.name</li>
4951
* <li>simplejavamail.defaults.from.address</li>
@@ -136,6 +138,7 @@ public enum Property {
136138
PROXY_PASSWORD("simplejavamail.proxy.password"),
137139
PROXY_SOCKS5BRIDGE_PORT("simplejavamail.proxy.socks5bridge.port"),
138140
DEFAULT_SUBJECT("simplejavamail.defaults.subject"),
141+
DEFAULT_CONTENT_TRANSFER_ENCODING("simplejavamail.defaults.content.transfer.encoding"),
139142
DEFAULT_FROM_NAME("simplejavamail.defaults.from.name"),
140143
DEFAULT_FROM_ADDRESS("simplejavamail.defaults.from.address"),
141144
DEFAULT_REPLYTO_NAME("simplejavamail.defaults.replyto.name"),
@@ -446,6 +449,12 @@ static Object parsePropertyValue(final @Nullable String propertyValue) {
446449
} catch (final IllegalArgumentException nfe) {
447450
// ok, so not a TransportStrategy either
448451
}
452+
// read ContentTransferEncoding value
453+
try {
454+
return ContentTransferEncoding.valueOf(propertyValue);
455+
} catch (final IllegalArgumentException nfe2) {
456+
// ok, so not a ContentTransferEncoding either
457+
}
449458
// read LoadBalancingStrategy value
450459
try {
451460
return LoadBalancingStrategy.valueOf(propertyValue);

modules/simple-java-mail/src/main/java/org/simplejavamail/converter/internal/mimemessage/MimeMessageHelper.java

+11-6
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ public class MimeMessageHelper {
4141
*/
4242
private static final String CHARACTER_ENCODING = StandardCharsets.UTF_8.name();
4343

44+
private static final String HEADER_CONTENT_TRANSFER_ENCODING = "Content-Transfer-Encoding";
45+
4446
private MimeMessageHelper() {
4547

4648
}
@@ -90,37 +92,39 @@ static void setReplyTo(final Email email, final Message message)
9092
}
9193

9294
/**
93-
* Fills the {@link Message} instance with the content bodies (text, html and calendar).
95+
* Fills the {@link Message} instance with the content bodies (text, html and calendar), with Content-Transfer-Encoding header taken from Email.
9496
*
9597
* @param email The message in which the content is defined.
9698
* @param multipartAlternativeMessages See {@link MimeMultipart#addBodyPart(BodyPart)}
97-
* @throws MessagingException See {@link BodyPart#setText(String)}, {@link BodyPart#setContent(Object, String)} and {@link
98-
* MimeMultipart#addBodyPart(BodyPart)}.
99+
* @throws MessagingException See {@link BodyPart#setText(String)}, {@link BodyPart#setContent(Object, String)} and {@link MimeMultipart#addBodyPart(BodyPart)}.
99100
*/
100101
static void setTexts(final Email email, final MimeMultipart multipartAlternativeMessages)
101102
throws MessagingException {
102103
if (email.getPlainText() != null) {
103104
final MimeBodyPart messagePart = new MimeBodyPart();
104105
messagePart.setText(email.getPlainText(), CHARACTER_ENCODING);
106+
messagePart.addHeader(HEADER_CONTENT_TRANSFER_ENCODING, email.getContentTransferEncoding().getEncoder());
105107
multipartAlternativeMessages.addBodyPart(messagePart);
106108
}
107109
if (email.getHTMLText() != null) {
108110
final MimeBodyPart messagePartHTML = new MimeBodyPart();
109111
messagePartHTML.setContent(email.getHTMLText(), "text/html; charset=\"" + CHARACTER_ENCODING + "\"");
112+
messagePartHTML.addHeader(HEADER_CONTENT_TRANSFER_ENCODING, email.getContentTransferEncoding().getEncoder());
110113
multipartAlternativeMessages.addBodyPart(messagePartHTML);
111114
}
112115
if (email.getCalendarText() != null && email.getCalendarMethod() != null) {
113116
final MimeBodyPart messagePartCalendar = new MimeBodyPart();
114117
messagePartCalendar.setContent(email.getCalendarText(), "text/calendar; charset=\"" + CHARACTER_ENCODING + "\"; method=\"" + email.getCalendarMethod().toString() + "\"");
118+
messagePartCalendar.addHeader(HEADER_CONTENT_TRANSFER_ENCODING, email.getContentTransferEncoding().getEncoder());
115119
multipartAlternativeMessages.addBodyPart(messagePartCalendar);
116120
}
117121
}
118122

119123
/**
120-
* Fills the {@link MimeBodyPart} instance with the content body content (text, html and calendar).
124+
* Fills the {@link MimeBodyPart} instance with the content body content (text, html and calendar), with Content-Transfer-Encoding header taken from Email.
121125
*
122-
* @param email The message in which the content is defined.
123-
* @param messagePart The {@link MimeBodyPart} that will contain the body content (either plain text, HTML text or iCalendar text)
126+
* @param email The message in which the content is defined.
127+
* @param messagePart The {@link MimeBodyPart} that will contain the body content (either plain text, HTML text or iCalendar text)
124128
*
125129
* @throws MessagingException See {@link BodyPart#setText(String)}, {@link BodyPart#setContent(Object, String)}.
126130
*/
@@ -135,6 +139,7 @@ static void setTexts(final Email email, final MimePart messagePart)
135139
if (email.getCalendarText() != null && email.getCalendarMethod() != null) {
136140
messagePart.setContent(email.getCalendarText(), "text/calendar; charset=\"" + CHARACTER_ENCODING + "\"; method=\"" + email.getCalendarMethod().toString() + "\"");
137141
}
142+
messagePart.addHeader(HEADER_CONTENT_TRANSFER_ENCODING, email.getContentTransferEncoding().getEncoder());
138143
}
139144

140145
/**

modules/simple-java-mail/src/main/java/org/simplejavamail/email/internal/EmailPopulatingBuilderImpl.java

+50-3
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import org.jetbrains.annotations.Nullable;
1111
import org.simplejavamail.api.email.AttachmentResource;
1212
import org.simplejavamail.api.email.CalendarMethod;
13+
import org.simplejavamail.api.email.ContentTransferEncoding;
1314
import org.simplejavamail.api.email.Email;
1415
import org.simplejavamail.api.email.EmailPopulatingBuilder;
1516
import org.simplejavamail.api.email.EmailStartingBuilder;
@@ -18,6 +19,7 @@
1819
import org.simplejavamail.api.internal.clisupport.model.Cli;
1920
import org.simplejavamail.api.internal.smimesupport.model.PlainSmimeDetails;
2021
import org.simplejavamail.api.mailer.config.Pkcs12Config;
22+
import org.simplejavamail.api.mailer.config.TransportStrategy;
2123
import org.simplejavamail.email.EmailBuilder;
2224
import org.simplejavamail.internal.util.CertificationUtil;
2325
import org.simplejavamail.internal.util.FileUtil;
@@ -56,6 +58,7 @@
5658
import static org.simplejavamail.config.ConfigLoader.Property.DEFAULT_BOUNCETO_NAME;
5759
import static org.simplejavamail.config.ConfigLoader.Property.DEFAULT_CC_ADDRESS;
5860
import static org.simplejavamail.config.ConfigLoader.Property.DEFAULT_CC_NAME;
61+
import static org.simplejavamail.config.ConfigLoader.Property.DEFAULT_CONTENT_TRANSFER_ENCODING;
5962
import static org.simplejavamail.config.ConfigLoader.Property.DEFAULT_FROM_ADDRESS;
6063
import static org.simplejavamail.config.ConfigLoader.Property.DEFAULT_FROM_NAME;
6164
import static org.simplejavamail.config.ConfigLoader.Property.DEFAULT_REPLYTO_ADDRESS;
@@ -149,6 +152,11 @@ public class EmailPopulatingBuilderImpl implements InternalEmailPopulatingBuilde
149152
* @see #withCalendarText(CalendarMethod, String)
150153
*/
151154
private String textCalendar;
155+
156+
/**
157+
* @see #withContentTransferEncoding(ContentTransferEncoding)
158+
*/
159+
private ContentTransferEncoding contentTransferEncoding = ContentTransferEncoding.QUOTED_PRINTABLE;
152160

153161
/**
154162
* @see #to(Recipient...)
@@ -361,6 +369,9 @@ public class EmailPopulatingBuilderImpl implements InternalEmailPopulatingBuilde
361369
bcc(verifyNonnullOrEmpty(getStringProperty(DEFAULT_BCC_ADDRESS)));
362370
}
363371
}
372+
if (hasProperty(DEFAULT_CONTENT_TRANSFER_ENCODING)) {
373+
withContentTransferEncoding(verifyNonnullOrEmpty(getProperty(DEFAULT_CONTENT_TRANSFER_ENCODING)));
374+
}
364375
if (hasProperty(DEFAULT_SUBJECT)) {
365376
withSubject(getProperty(DEFAULT_SUBJECT));
366377
}
@@ -618,7 +629,7 @@ public EmailPopulatingBuilder withBounceTo(@Nullable final Recipient recipient)
618629
this.bounceToRecipient = recipient != null ? new Recipient(recipient.getName(), recipient.getAddress(), null) : null;
619630
return this;
620631
}
621-
632+
622633
/**
623634
* @see EmailPopulatingBuilder#withSubject(String)
624635
*/
@@ -778,6 +789,15 @@ public EmailPopulatingBuilder withCalendarText(@NotNull final CalendarMethod cal
778789
this.textCalendar = textCalendar;
779790
return this;
780791
}
792+
793+
/**
794+
* @see EmailPopulatingBuilder#withContentTransferEncoding(ContentTransferEncoding)
795+
*/
796+
@Override
797+
public EmailPopulatingBuilder withContentTransferEncoding(@NotNull final ContentTransferEncoding contentTransferEncoding) {
798+
this.contentTransferEncoding = contentTransferEncoding;
799+
return this;
800+
}
781801

782802
/*
783803
TO: Recipient
@@ -2085,7 +2105,7 @@ public EmailPopulatingBuilder clearPlainText() {
20852105
this.text = null;
20862106
return this;
20872107
}
2088-
2108+
20892109
/**
20902110
* @see EmailPopulatingBuilder#clearHTMLText()
20912111
*/
@@ -2094,6 +2114,25 @@ public EmailPopulatingBuilder clearHTMLText() {
20942114
this.textHTML = null;
20952115
return this;
20962116
}
2117+
2118+
/**
2119+
* @see EmailPopulatingBuilder#clearCalendarText()
2120+
*/
2121+
@Override
2122+
public EmailPopulatingBuilder clearCalendarText() {
2123+
this.calendarMethod = null;
2124+
this.textCalendar = null;
2125+
return this;
2126+
}
2127+
2128+
/**
2129+
* @see EmailPopulatingBuilder#clearContentTransferEncoding()
2130+
*/
2131+
@Override
2132+
public EmailPopulatingBuilder clearContentTransferEncoding() {
2133+
this.contentTransferEncoding = ContentTransferEncoding.QUOTED_PRINTABLE;
2134+
return this;
2135+
}
20972136

20982137
/**
20992138
* @see EmailPopulatingBuilder#clearSubject()
@@ -2289,7 +2328,7 @@ public String getTextHTML() {
22892328
public CalendarMethod getCalendarMethod() {
22902329
return calendarMethod;
22912330
}
2292-
2331+
22932332
/**
22942333
* @see EmailPopulatingBuilder#getTextCalendar()
22952334
*/
@@ -2298,6 +2337,14 @@ public CalendarMethod getCalendarMethod() {
22982337
public String getTextCalendar() {
22992338
return textCalendar;
23002339
}
2340+
2341+
/**
2342+
* @see EmailPopulatingBuilder#getContentTransferEncoding()
2343+
*/
2344+
@Override
2345+
public ContentTransferEncoding getContentTransferEncoding() {
2346+
return contentTransferEncoding;
2347+
}
23012348

23022349
/**
23032350
* @see EmailPopulatingBuilder#getSubject()

modules/simple-java-mail/src/test/java/org/simplejavamail/config/ConfigLoaderTest.java

+5
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import org.junit.Before;
44
import org.junit.Test;
5+
import org.simplejavamail.api.email.ContentTransferEncoding;
56
import org.simplejavamail.api.mailer.config.TransportStrategy;
67
import org.simplejavamail.config.ConfigLoader.Property;
78
import testutil.ConfigLoaderTestHelper;
@@ -13,12 +14,15 @@
1314
import java.util.Properties;
1415

1516
import static org.assertj.core.api.Assertions.assertThat;
17+
import static org.simplejavamail.api.email.ContentTransferEncoding.BINARY;
18+
import static org.simplejavamail.api.email.ContentTransferEncoding.QUOTED_PRINTABLE;
1619
import static org.simplejavamail.api.mailer.config.TransportStrategy.SMTPS;
1720
import static org.simplejavamail.config.ConfigLoader.Property.CUSTOM_SSLFACTORY_CLASS;
1821
import static org.simplejavamail.config.ConfigLoader.Property.DEFAULT_BCC_ADDRESS;
1922
import static org.simplejavamail.config.ConfigLoader.Property.DEFAULT_BCC_NAME;
2023
import static org.simplejavamail.config.ConfigLoader.Property.DEFAULT_CC_ADDRESS;
2124
import static org.simplejavamail.config.ConfigLoader.Property.DEFAULT_CC_NAME;
25+
import static org.simplejavamail.config.ConfigLoader.Property.DEFAULT_CONTENT_TRANSFER_ENCODING;
2226
import static org.simplejavamail.config.ConfigLoader.Property.DEFAULT_FROM_ADDRESS;
2327
import static org.simplejavamail.config.ConfigLoader.Property.DEFAULT_FROM_NAME;
2428
import static org.simplejavamail.config.ConfigLoader.Property.DEFAULT_REPLYTO_ADDRESS;
@@ -195,6 +199,7 @@ public void loadPropertiesFromFileClassPath() {
195199
assertThat(ConfigLoader.<String>getProperty(DEFAULT_BCC_NAME)).isEqualTo("BCC Default");
196200
assertThat(ConfigLoader.<String>getProperty(DEFAULT_BCC_ADDRESS)).isEqualTo("[email protected]");
197201
assertThat(ConfigLoader.<String>getProperty(DEFAULT_SUBJECT)).isEqualTo("Default Subject");
202+
assertThat(ConfigLoader.<ContentTransferEncoding>getProperty(DEFAULT_CONTENT_TRANSFER_ENCODING)).isSameAs(BINARY);
198203

199204
assertThat(ConfigLoader.<String>getProperty(SMIME_SIGNING_KEYSTORE)).isEqualTo("src/test/resources/pkcs12/smime_keystore.pkcs12");
200205
assertThat(ConfigLoader.<String>getProperty(SMIME_SIGNING_KEYSTORE_PASSWORD)).isEqualTo("letmein");

0 commit comments

Comments
 (0)