Skip to content

Commit dabc518

Browse files
committed
#499: Expose finer-grained DKIM configuration through the builder api and disable 'l-param' by default
1 parent 15d2477 commit dabc518

File tree

9 files changed

+322
-163
lines changed

9 files changed

+322
-163
lines changed

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1228,6 +1228,8 @@ public interface EmailPopulatingBuilder {
12281228
* Primes this email for signing with a DKIM domain key. Actual signing is done when sending using a <code>Mailer</code>.
12291229
* <p>
12301230
* <strong>Note:</strong> this only works in combination with the {@value org.simplejavamail.internal.modules.DKIMModule#NAME}.
1231+
* <p>
1232+
* <strong>Note:</strong> for more fine-grained control over the DKIM signing process, use {@link #signWithDomainKey(DkimConfig)} instead.
12311233
*
12321234
* @param dkimPrivateKey De key content used to sign for the sending party.
12331235
* @param signingDomain The domain being authorized to send.
@@ -1245,6 +1247,10 @@ public interface EmailPopulatingBuilder {
12451247
EmailPopulatingBuilder signWithDomainKey(byte@NotNull[] dkimPrivateKey, @NotNull String signingDomain, @NotNull String dkimSelector, @Nullable Set<String> excludedHeadersFromDkimDefaultSigningList);
12461248

12471249
/**
1250+
* Allows for more customization of the DKIM signing process by providing a {@link DkimConfig} instance. Added config includes: <em>useLengthParam</em>,
1251+
* <em>signingAlgorithm</em>, <em>headerCanonicalization</em> and <em>bodyCanonicalizationAlgorithm</em>.
1252+
*
1253+
* @see DkimConfig
12481254
* @see #signWithDomainKey(byte[], String, String, Set)
12491255
*/
12501256
@Cli.ExcludeApi(reason = "delegated method is an identical api from CLI point of view")

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

Lines changed: 256 additions & 147 deletions
Large diffs are not rendered by default.

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

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import org.jetbrains.annotations.NotNull;
44
import org.jetbrains.annotations.Nullable;
55
import org.simplejavamail.api.email.ContentTransferEncoding;
6+
import org.simplejavamail.api.email.config.DkimConfig;
67
import org.simplejavamail.api.mailer.config.LoadBalancingStrategy;
78
import org.simplejavamail.api.mailer.config.TransportStrategy;
89
import org.simplejavamail.internal.util.SimpleConversions;
@@ -85,7 +86,11 @@
8586
* <li>simplejavamail.dkim.signing.private_key_file_or_data</li>
8687
* <li>simplejavamail.dkim.signing.selector</li>
8788
* <li>simplejavamail.dkim.signing.signing_domain</li>
89+
* <li>simplejavamail.dkim.signing.use_length_param</li>
8890
* <li>simplejavamail.dkim.signing.excluded_headers_from_default_signing_list</li>
91+
* <li>simplejavamail.dkim.signing.header_canonicalization</li>
92+
* <li>simplejavamail.dkim.signing.body_canonicalization</li>
93+
* <li>simplejavamail.dkim.signing.algorithm</li>
8994
* <li>simplejavamail.embeddedimages.dynamicresolution.enable.dir</li>
9095
* <li>simplejavamail.embeddedimages.dynamicresolution.enable.url</li>
9196
* <li>simplejavamail.embeddedimages.dynamicresolution.enable.classpath</li>
@@ -184,7 +189,11 @@ public enum Property {
184189
DKIM_PRIVATE_KEY_FILE_OR_DATA("simplejavamail.dkim.signing.private_key_file_or_data"),
185190
DKIM_SELECTOR("simplejavamail.dkim.signing.selector"),
186191
DKIM_SIGNING_DOMAIN("simplejavamail.dkim.signing.signing_domain"),
192+
DKIM_SIGNING_USE_LENGTH_PARAM("simplejavamail.dkim.signing.use_length_param"),
187193
DKIM_EXCLUDED_HEADERS_FROM_DEFAULT_SIGNING_LIST("simplejavamail.dkim.signing.excluded_headers_from_default_signing_list"),
194+
DKIM_SIGNING_HEADER_CANONICALIZATION("simplejavamail.dkim.signing.header_canonicalization"),
195+
DKIM_SIGNING_BODY_CANONICALIZATION("simplejavamail.dkim.signing.body_canonicalization"),
196+
DKIM_SIGNING_ALGORITHM("simplejavamail.dkim.signing.algorithm"),
188197
SMIME_ENCRYPTION_CERTIFICATE("simplejavamail.smime.encryption.certificate"),
189198
EMBEDDEDIMAGES_DYNAMICRESOLUTION_ENABLE_DIR("simplejavamail.embeddedimages.dynamicresolution.enable.dir"),
190199
EMBEDDEDIMAGES_DYNAMICRESOLUTION_ENABLE_CLASSPATH("simplejavamail.embeddedimages.dynamicresolution.enable.classpath"),
@@ -471,6 +480,12 @@ static Object parsePropertyValue(final @Nullable String propertyValue) {
471480
} catch (final IllegalArgumentException nfe2) {
472481
// ok, so not a ContentTransferEncoding either
473482
}
483+
// read ContentTransferEncoding value
484+
try {
485+
return DkimConfig.Canonicalization.valueOf(propertyValue);
486+
} catch (final IllegalArgumentException nfe2) {
487+
// ok, so not a Canonicalization either
488+
}
474489
// read LoadBalancingStrategy value
475490
try {
476491
return LoadBalancingStrategy.valueOf(propertyValue);

modules/dkim-module/src/main/java/org/simplejavamail/internal/dkimsupport/DKIMSigner.java

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
import org.simplejavamail.api.email.config.DkimConfig;
99
import org.simplejavamail.internal.modules.DKIMModule;
1010
import org.simplejavamail.utils.mail.dkim.Canonicalization;
11-
import org.simplejavamail.utils.mail.dkim.DkimMessage;
1211
import org.simplejavamail.utils.mail.dkim.DkimSigner;
1312
import org.simplejavamail.utils.mail.dkim.SigningAlgorithm;
1413
import org.slf4j.Logger;
@@ -21,6 +20,9 @@
2120
import java.util.Collections;
2221

2322
import static org.simplejavamail.internal.util.MiscUtil.defaultTo;
23+
import static org.simplejavamail.utils.mail.dkim.Canonicalization.RELAXED;
24+
import static org.simplejavamail.utils.mail.dkim.Canonicalization.SIMPLE;
25+
import static org.simplejavamail.utils.mail.dkim.SigningAlgorithm.SHA256_WITH_RSA;
2426

2527
/**
2628
* This class only serves to hide the DKIM implementation behind an easy-to-load-with-reflection class.
@@ -41,10 +43,10 @@ public MimeMessage signMessageWithDKIM(@NotNull Email email, @NotNull final Mime
4143
defaultTo(dkimConfig.getExcludedHeadersFromDkimDefaultSigningList(), Collections.<String>emptySet())
4244
.forEach(dkimSigner::removeHeaderToSign);
4345
dkimSigner.setIdentity(fromRecipient.getAddress());
44-
dkimSigner.setHeaderCanonicalization(Canonicalization.RELAXED);
45-
dkimSigner.setBodyCanonicalization(Canonicalization.RELAXED);
46-
dkimSigner.setSigningAlgorithm(SigningAlgorithm.SHA256_WITH_RSA);
47-
dkimSigner.setLengthParam(true);
46+
dkimSigner.setHeaderCanonicalization(mapToNativeCanonicalization(defaultTo(dkimConfig.getHeaderCanonicalization(), DkimConfig.Canonicalization.RELAXED)));
47+
dkimSigner.setBodyCanonicalization(mapToNativeCanonicalization(defaultTo(dkimConfig.getBodyCanonicalization(), DkimConfig.Canonicalization.RELAXED)));
48+
dkimSigner.setSigningAlgorithm(SigningAlgorithm.valueOf(defaultTo(dkimConfig.getSigningAlgorithm(), SHA256_WITH_RSA.name())));
49+
dkimSigner.setLengthParam(defaultTo(dkimConfig.getUseLengthParam(), false));
4850
dkimSigner.setZParam(false);
4951

5052
// during our junit tests, we don't want to actually connect to the internet to check the domain key
@@ -58,6 +60,10 @@ public MimeMessage signMessageWithDKIM(@NotNull Email email, @NotNull final Mime
5860
}
5961
}
6062

63+
private static Canonicalization mapToNativeCanonicalization(DkimConfig.Canonicalization canonicalization) {
64+
return canonicalization == DkimConfig.Canonicalization.SIMPLE ? SIMPLE : RELAXED;
65+
}
66+
6167
@Override
6268
public boolean isMessageIdFixingMessage(MimeMessage message) {
6369
return message instanceof DkimMessageIdFixingMimeMessage;

modules/simple-java-mail/src/main/java/org/simplejavamail/mailer/internal/EmailGovernanceImpl.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,11 @@
4848
import static org.simplejavamail.config.ConfigLoader.Property.DKIM_EXCLUDED_HEADERS_FROM_DEFAULT_SIGNING_LIST;
4949
import static org.simplejavamail.config.ConfigLoader.Property.DKIM_PRIVATE_KEY_FILE_OR_DATA;
5050
import static org.simplejavamail.config.ConfigLoader.Property.DKIM_SELECTOR;
51+
import static org.simplejavamail.config.ConfigLoader.Property.DKIM_SIGNING_ALGORITHM;
52+
import static org.simplejavamail.config.ConfigLoader.Property.DKIM_SIGNING_BODY_CANONICALIZATION;
5153
import static org.simplejavamail.config.ConfigLoader.Property.DKIM_SIGNING_DOMAIN;
54+
import static org.simplejavamail.config.ConfigLoader.Property.DKIM_SIGNING_HEADER_CANONICALIZATION;
55+
import static org.simplejavamail.config.ConfigLoader.Property.DKIM_SIGNING_USE_LENGTH_PARAM;
5256
import static org.simplejavamail.config.ConfigLoader.Property.SMIME_ENCRYPTION_CERTIFICATE;
5357
import static org.simplejavamail.config.ConfigLoader.Property.SMIME_ENCRYPTION_CIPHER;
5458
import static org.simplejavamail.config.ConfigLoader.Property.SMIME_ENCRYPTION_KEY_ENCAPSULATION_ALGORITHM;
@@ -57,6 +61,7 @@
5761
import static org.simplejavamail.config.ConfigLoader.Property.SMIME_SIGNING_KEYSTORE_PASSWORD;
5862
import static org.simplejavamail.config.ConfigLoader.Property.SMIME_SIGNING_KEY_ALIAS;
5963
import static org.simplejavamail.config.ConfigLoader.Property.SMIME_SIGNING_KEY_PASSWORD;
64+
import static org.simplejavamail.config.ConfigLoader.getBooleanProperty;
6065
import static org.simplejavamail.config.ConfigLoader.getProperty;
6166
import static org.simplejavamail.config.ConfigLoader.getStringProperty;
6267
import static org.simplejavamail.config.ConfigLoader.hasProperty;
@@ -184,7 +189,11 @@ private Email newDefaultsEmailWithDefaultDefaults() {
184189
val dkimConfigBuilder = DkimConfig.builder()
185190
.dkimSelector(verifyNonnullOrEmpty(getStringProperty(DKIM_SELECTOR)))
186191
.dkimSigningDomain(verifyNonnullOrEmpty(getStringProperty(DKIM_SIGNING_DOMAIN)))
187-
.excludedHeadersFromDkimDefaultSigningList(verifyNonnullOrEmpty(getStringProperty(DKIM_EXCLUDED_HEADERS_FROM_DEFAULT_SIGNING_LIST)));
192+
.useLengthParam(hasProperty(DKIM_SIGNING_USE_LENGTH_PARAM) ? getBooleanProperty(DKIM_SIGNING_USE_LENGTH_PARAM) : null)
193+
.excludedHeadersFromDkimDefaultSigningList(verifyNonnullOrEmpty(getStringProperty(DKIM_EXCLUDED_HEADERS_FROM_DEFAULT_SIGNING_LIST)))
194+
.headerCanonicalization(hasProperty(DKIM_SIGNING_HEADER_CANONICALIZATION) ? getProperty(DKIM_SIGNING_HEADER_CANONICALIZATION) : null)
195+
.bodyCanonicalization(hasProperty(DKIM_SIGNING_BODY_CANONICALIZATION) ? getProperty(DKIM_SIGNING_BODY_CANONICALIZATION) : null)
196+
.signingAlgorithm(hasProperty(DKIM_SIGNING_ALGORITHM) ? getStringProperty(DKIM_SIGNING_ALGORITHM) : null);
188197
val dkimPrivateKeyFileOrData = verifyNonnullOrEmpty(getStringProperty(DKIM_PRIVATE_KEY_FILE_OR_DATA));
189198
if (new File(dkimPrivateKeyFileOrData).exists()) {
190199
dkimConfigBuilder.dkimPrivateKeyPath(dkimPrivateKeyFileOrData);

modules/simple-java-mail/src/test/java/org/simplejavamail/api/email/EmailTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ public void testToStringFull() {
116116
+ " contentTransferEncoding='quoted-printable',\n"
117117
+ " subject='hey',\n"
118118
+ " recipients=[Recipient{name='C.Cane', address='[email protected]', type=To}],\n"
119-
+ " dkimConfig=DkimConfig(dkimSigningDomain=dkim_domain, dkimSelector=dkim_selector, excludedHeadersFromDkimDefaultSigningList=null),\n"
119+
+ " dkimConfig=DkimConfig(dkimSigningDomain=dkim_domain, dkimSelector=dkim_selector, useLengthParam=null, excludedHeadersFromDkimDefaultSigningList=null, headerCanonicalization=null, bodyCanonicalization=null, signingAlgorithm=null),\n"
120120
+ " useDispositionNotificationTo=true,\n"
121121
+ " dispositionNotificationTo=Recipient{name='dispo to', address='[email protected]', type=null},\n"
122122
+ " useReturnReceiptTo=true,\n"

modules/simple-java-mail/src/test/resources/simplejavamail.properties

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,11 @@ simplejavamail.smime.encryption.cipher=
3737
simplejavamail.dkim.signing.private_key_file_or_data=
3838
simplejavamail.dkim.signing.selector=
3939
simplejavamail.dkim.signing.signing_domain=
40+
simplejavamail.dkim.signing.use_length_param=
4041
simplejavamail.dkim.signing.excluded_headers_from_default_signing_list=
42+
simplejavamail.dkim.signing.header_canonicalization=
43+
simplejavamail.dkim.signing.body_canonicalization=
44+
simplejavamail.dkim.signing.algorithm=
4145
simplejavamail.embeddedimages.dynamicresolution.enable.dir=
4246
simplejavamail.embeddedimages.dynamicresolution.enable.url=
4347
simplejavamail.embeddedimages.dynamicresolution.enable.classpath=

modules/spring-module/src/main/java/org/simplejavamail/springsupport/SimpleJavaMailSpringSupport.java

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -83,8 +83,12 @@
8383
* <li>simplejavamail.dkim.signing.selector</li>
8484
* <li>simplejavamail.dkim.signing.signing_domain</li>
8585
* <li>simplejavamail.dkim.signing.signing-domain</li>
86+
* <li>simplejavamail.dkim.signing.use_length_param</li>
8687
* <li>simplejavamail.dkim.signing.excluded_headers_from_default_signing_list</li>
8788
* <li>simplejavamail.dkim.signing.excluded-headers-from-default-signing-list</li>
89+
* <li>simplejavamail.dkim.signing.header_canonicalization</li>
90+
* <li>simplejavamail.dkim.signing.body_canonicalization</li>
91+
* <li>simplejavamail.dkim.signing.algorithm</li>
8892
* <li>simplejavamail.embeddedimages.dynamicresolution.enable.dir</li>
8993
* <li>simplejavamail.embeddedimages.dynamicresolution.enable.url</li>
9094
* <li>simplejavamail.embeddedimages.dynamicresolution.enable.classpath</li>
@@ -169,8 +173,12 @@ public MailerGenericBuilder<?> loadGlobalConfigAndCreateDefaultMailer(
169173
@Nullable @Value("${simplejavamail.dkim.signing.selector:#{null}}") final String dkimSigningSelector,
170174
@Nullable @Value("${simplejavamail.dkim.signing.signing_domain:#{null}}") final String dkimSigningDomain,
171175
@Nullable @Value("${simplejavamail.dkim.signing.signing-domain:#{null}}") final String dkimSigningDomainSpringBoot,
176+
@Nullable @Value("${simplejavamail.dkim.signing.use_length_param:#{null}}") final String dkimSigningUseLengthParam,
172177
@Nullable @Value("${simplejavamail.dkim.signing.excluded_headers_from_default_signing_list:#{null}}") final String dkimSigningExcludedHeadersFromDefaultSigningList,
173178
@Nullable @Value("${simplejavamail.dkim.signing.excluded-headers-from-default-signing-list:#{null}}") final String dkimSigningExcludedHeadersFromDefaultSigningListSpringBoot,
179+
@Nullable @Value("${simplejavamail.dkim.signing.header_canonicalization:#{null}}") final String dkimSigningHeaderCanonicalization,
180+
@Nullable @Value("${simplejavamail.dkim.signing.body_canonicalization:#{null}}") final String dkimSigningBodyCanonicalization,
181+
@Nullable @Value("${simplejavamail.dkim.signing.algorithm:#{null}}") final String dkimSigningAlgorithm,
174182
@Nullable @Value("${simplejavamail.embeddedimages.dynamicresolution.enable.dir:#{null}}") final String embeddedimagesDynamicresolutionEnableDir,
175183
@Nullable @Value("${simplejavamail.embeddedimages.dynamicresolution.enable.url:#{null}}") final String embeddedimagesDynamicresolutionEnableUrl,
176184
@Nullable @Value("${simplejavamail.embeddedimages.dynamicresolution.enable.classpath:#{null}}") final String embeddedimagesDynamicresolutionEnableClassPath,
@@ -247,15 +255,9 @@ public MailerGenericBuilder<?> loadGlobalConfigAndCreateDefaultMailer(
247255
} else {
248256
setNullableProperty(emailProperties, Property.SMIME_SIGNING_KEY_PASSWORD.key(), smimeSigningKeyPasswordSpringBoot);
249257
}
250-
if (smimeSigningAlgorithm != null) {
251-
setNullableProperty(emailProperties, Property.SMIME_SIGNING_ALGORITHM.key(), smimeSigningAlgorithm);
252-
}
253-
if (smimeEncryptionKeyEncapsulationAlgorithm != null) {
254-
setNullableProperty(emailProperties, Property.SMIME_ENCRYPTION_KEY_ENCAPSULATION_ALGORITHM.key(), smimeEncryptionKeyEncapsulationAlgorithm);
255-
}
256-
if (smimeEncryptionCipher != null) {
257-
setNullableProperty(emailProperties, Property.SMIME_ENCRYPTION_CIPHER.key(), smimeEncryptionCipher);
258-
}
258+
setNullableProperty(emailProperties, Property.SMIME_SIGNING_ALGORITHM.key(), smimeSigningAlgorithm);
259+
setNullableProperty(emailProperties, Property.SMIME_ENCRYPTION_KEY_ENCAPSULATION_ALGORITHM.key(), smimeEncryptionKeyEncapsulationAlgorithm);
260+
setNullableProperty(emailProperties, Property.SMIME_ENCRYPTION_CIPHER.key(), smimeEncryptionCipher);
259261
setNullableProperty(emailProperties, Property.SMIME_ENCRYPTION_CERTIFICATE.key(), smimeEncryptionCertificate);
260262
if (dkimSigningPrivateKeyFileOrData != null) {
261263
setNullableProperty(emailProperties, Property.DKIM_PRIVATE_KEY_FILE_OR_DATA.key(), dkimSigningPrivateKeyFileOrData);
@@ -268,11 +270,15 @@ public MailerGenericBuilder<?> loadGlobalConfigAndCreateDefaultMailer(
268270
} else {
269271
setNullableProperty(emailProperties, Property.DKIM_SIGNING_DOMAIN.key(), dkimSigningDomainSpringBoot);
270272
}
273+
setNullableProperty(emailProperties, Property.DKIM_SIGNING_USE_LENGTH_PARAM.key(), dkimSigningUseLengthParam);
271274
if (dkimSigningExcludedHeadersFromDefaultSigningList != null) {
272275
setNullableProperty(emailProperties, Property.DKIM_EXCLUDED_HEADERS_FROM_DEFAULT_SIGNING_LIST.key(), dkimSigningExcludedHeadersFromDefaultSigningList);
273276
} else {
274277
setNullableProperty(emailProperties, Property.DKIM_EXCLUDED_HEADERS_FROM_DEFAULT_SIGNING_LIST.key(), dkimSigningExcludedHeadersFromDefaultSigningListSpringBoot);
275278
}
279+
setNullableProperty(emailProperties, Property.DKIM_SIGNING_HEADER_CANONICALIZATION.key(), dkimSigningHeaderCanonicalization);
280+
setNullableProperty(emailProperties, Property.DKIM_SIGNING_BODY_CANONICALIZATION.key(), dkimSigningBodyCanonicalization);
281+
setNullableProperty(emailProperties, Property.DKIM_SIGNING_ALGORITHM.key(), dkimSigningAlgorithm);
276282
setNullableProperty(emailProperties, Property.EMBEDDEDIMAGES_DYNAMICRESOLUTION_ENABLE_DIR.key(), embeddedimagesDynamicresolutionEnableDir);
277283
setNullableProperty(emailProperties, Property.EMBEDDEDIMAGES_DYNAMICRESOLUTION_ENABLE_CLASSPATH.key(), embeddedimagesDynamicresolutionEnableClassPath);
278284
setNullableProperty(emailProperties, Property.EMBEDDEDIMAGES_DYNAMICRESOLUTION_ENABLE_URL.key(), embeddedimagesDynamicresolutionEnableUrl);

modules/spring-module/src/test/resources/simplejavamail.properties

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,11 @@ simplejavamail.smime.encryption.cipher=
3737
simplejavamail.dkim.signing.private_key_file_or_data=
3838
simplejavamail.dkim.signing.selector=
3939
simplejavamail.dkim.signing.signing_domain=
40+
simplejavamail.dkim.signing.use_length_param=
4041
simplejavamail.dkim.signing.excluded_headers_from_default_signing_list=
42+
simplejavamail.dkim.signing.header_canonicalization=
43+
simplejavamail.dkim.signing.body_canonicalization=
44+
simplejavamail.dkim.signing.algorithm=
4145
simplejavamail.embeddedimages.dynamicresolution.enable.dir=
4246
simplejavamail.embeddedimages.dynamicresolution.enable.url=
4347
simplejavamail.embeddedimages.dynamicresolution.enable.classpath=

0 commit comments

Comments
 (0)