Skip to content

Commit 5d7dfd1

Browse files
committed
#390: added api to disable client sided validations on email addresses and CRLF injection scanning
1 parent 09f74df commit 5d7dfd1

File tree

14 files changed

+370
-27
lines changed

14 files changed

+370
-27
lines changed

modules/core-module/src/main/java/org/simplejavamail/api/mailer/MailerGenericBuilder.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,10 @@ public interface MailerGenericBuilder<T extends MailerGenericBuilder<?>> {
105105
* Defaults to <code>{@value}</code>, sending mails rather than just only logging the mails.
106106
*/
107107
boolean DEFAULT_JAVAXMAIL_DEBUG = false;
108+
/**
109+
* Defaults to <code>{@value}</code>, validating emailaddresses (can be configured seperately, but this does override it) and CRLF injection detection (will arn instead).
110+
*/
111+
boolean DEFAULT_DISABLE_ALL_CLIENTVALIDATION = false;
108112

109113
/**
110114
* Changes the default for sending emails and testing server connections to asynchronous (batch mode).
@@ -203,6 +207,13 @@ public interface MailerGenericBuilder<T extends MailerGenericBuilder<?>> {
203207
*/
204208
T withDebugLogging(@NotNull Boolean debugLogging);
205209

210+
/**
211+
* Controls whether there will be any client-sided validation, including email address validation and CRLF injection attack detection (which will be warning instead).
212+
* <p>
213+
* If set to {@code true}, this silences the client completely and just delegates all responsibility of correctness/security to the server.
214+
*/
215+
T disablingAllClientValidation(@NotNull Boolean disableAllClientValidation);
216+
206217
/**
207218
* Controls the timeout to use when sending emails (affects socket connect-, read- and write timeouts).
208219
* <p>
@@ -497,6 +508,14 @@ public interface MailerGenericBuilder<T extends MailerGenericBuilder<?>> {
497508
*/
498509
T withCustomMailer(@NotNull CustomMailer customMailer);
499510

511+
/**
512+
* Reverts to default value '{@value #DEFAULT_VERIFY_SERVER_IDENTITY}' for the behaviour of disabling client-sided
513+
* validations (email addresses and CLRF injection scanning).
514+
*
515+
* @see #disablingAllClientValidation(Boolean)
516+
*/
517+
T resetDisableAllClientValidations();
518+
500519
/**
501520
* Resets session time to its default ({@value DEFAULT_SESSION_TIMEOUT_MILLIS}).
502521
*
@@ -698,6 +717,11 @@ public interface MailerGenericBuilder<T extends MailerGenericBuilder<?>> {
698717
*/
699718
boolean isDebugLogging();
700719

720+
/**
721+
* @see #disablingAllClientValidation(Boolean)
722+
*/
723+
boolean isDisableAllClientValidation();
724+
701725
/**
702726
* @see #withSessionTimeout(Integer)
703727
*/

modules/core-module/src/main/java/org/simplejavamail/api/mailer/config/OperationalConfig.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,12 +69,17 @@ public interface OperationalConfig {
6969
* @see MailerGenericBuilder#withTransportModeLoggingOnly(Boolean)
7070
*/
7171
boolean isTransportModeLoggingOnly();
72-
72+
7373
/**
7474
* @see MailerGenericBuilder#withDebugLogging(Boolean)
7575
*/
7676
boolean isDebugLogging();
77-
77+
78+
/**
79+
* @see MailerGenericBuilder#disablingAllClientValidation(Boolean)
80+
*/
81+
boolean isDisableAllClientValidation();
82+
7883
/**
7984
* @see MailerGenericBuilder#trustingSSLHosts(String...)
8085
*/

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
* <li>simplejavamail.smtp.port</li>
4040
* <li>simplejavamail.smtp.username</li>
4141
* <li>simplejavamail.smtp.password</li>
42+
* <li>simplejavamail.disable.all.clientvalidation</li>
4243
* <li>simplejavamail.custom.sslfactory.class</li>
4344
* <li>simplejavamail.proxy.host</li>
4445
* <li>simplejavamail.proxy.port</li>
@@ -131,6 +132,7 @@ public enum Property {
131132
SMTP_PORT("simplejavamail.smtp.port"),
132133
SMTP_USERNAME("simplejavamail.smtp.username"),
133134
SMTP_PASSWORD("simplejavamail.smtp.password"),
135+
DISABLE_ALL_CLIENTVALIDATION("simplejavamail.disable.all.clientvalidation"),
134136
CUSTOM_SSLFACTORY_CLASS("simplejavamail.custom.sslfactory.class"),
135137
PROXY_HOST("simplejavamail.proxy.host"),
136138
PROXY_PORT("simplejavamail.proxy.port"),

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

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,34 @@ public static boolean validate(@NotNull final Email email, @Nullable final Email
5151
return true;
5252
}
5353

54+
/**
55+
* Lenient validation only checks for missing fields (which implies incorrect configuration or missing data),
56+
* but only warns for invalid address and suspected CRLF injections.
57+
*
58+
* @see #validateCompleteness(Email)
59+
* @see #validateAddresses(Email, EmailValidator)
60+
* @see #scanForInjectionAttacks(Email)
61+
*/
62+
@SuppressWarnings({ "SameReturnValue" })
63+
public static boolean validateLenient(@NotNull final Email email, @Nullable final EmailValidator emailValidator)
64+
throws MailException {
65+
LOGGER.debug("validating email...");
66+
MailerHelper.validateCompleteness(email);
67+
try {
68+
MailerHelper.validateAddresses(email, emailValidator);
69+
} catch (MailInvalidAddressException e) {
70+
LOGGER.warn("encountered (and ignored) invalid address: {}", e.getMessage());
71+
}
72+
try {
73+
MailerHelper.scanForInjectionAttacks(email);
74+
} catch (MailSuspiciousCRLFValueException e) {
75+
LOGGER.warn("encountered (and ignored) suspected CRLF injection: {}", e.getMessage());
76+
}
77+
LOGGER.debug("...no blocking problems found");
78+
79+
return true;
80+
}
81+
5482
/**
5583
* Checks whether:
5684
* <ol>

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

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,11 @@ abstract class MailerGenericBuilderImpl<T extends MailerGenericBuilderImpl<?>> i
9292
* @see MailerGenericBuilder#withDebugLogging(Boolean)
9393
*/
9494
private boolean debugLogging;
95+
96+
/**
97+
* @see #disablingAllClientValidation(Boolean)
98+
*/
99+
private boolean disableAllClientValidation;
95100

96101
/**
97102
* @see MailerGenericBuilder#withSessionTimeout(Integer)
@@ -219,6 +224,7 @@ abstract class MailerGenericBuilderImpl<T extends MailerGenericBuilderImpl<?>> i
219224

220225
this.proxyPort = verifyNonnullOrEmpty(valueOrPropertyAsInteger(null, Property.PROXY_PORT, DEFAULT_PROXY_PORT));
221226
this.proxyBridgePort = verifyNonnullOrEmpty(valueOrPropertyAsInteger(null, Property.PROXY_SOCKS5BRIDGE_PORT, DEFAULT_PROXY_BRIDGE_PORT));
227+
this.disableAllClientValidation = verifyNonnullOrEmpty(valueOrPropertyAsBoolean(null, Property.DISABLE_ALL_CLIENTVALIDATION, DEFAULT_DISABLE_ALL_CLIENTVALIDATION));
222228
this.debugLogging = verifyNonnullOrEmpty(valueOrPropertyAsBoolean(null, Property.JAVAXMAIL_DEBUG, DEFAULT_JAVAXMAIL_DEBUG));
223229
this.sessionTimeout = verifyNonnullOrEmpty(valueOrPropertyAsInteger(null, Property.DEFAULT_SESSION_TIMEOUT_MILLIS, DEFAULT_SESSION_TIMEOUT_MILLIS));
224230
this.trustAllSSLHost = verifyNonnullOrEmpty(valueOrPropertyAsBoolean(null, Property.DEFAULT_TRUST_ALL_HOSTS, DEFAULT_TRUST_ALL_HOSTS));
@@ -298,6 +304,7 @@ OperationalConfig buildOperationalConfig() {
298304
getConnectionPoolLoadBalancingStrategy(),
299305
isTransportModeLoggingOnly(),
300306
isDebugLogging(),
307+
isDisableAllClientValidation(),
301308
getSslHostsToTrust(),
302309
isTrustAllSSLHost(),
303310
isVerifyingServerIdentity(),
@@ -379,7 +386,7 @@ public T withProxyBridgePort(@NotNull final Integer proxyBridgePort) {
379386
this.proxyBridgePort = proxyBridgePort;
380387
return (T) this;
381388
}
382-
389+
383390
/**
384391
* @see MailerGenericBuilder#withDebugLogging(Boolean)
385392
*/
@@ -388,6 +395,15 @@ public T withDebugLogging(@NotNull final Boolean debugLogging) {
388395
this.debugLogging = debugLogging;
389396
return (T) this;
390397
}
398+
399+
/**
400+
* @see MailerGenericBuilder#disablingAllClientValidation(Boolean)
401+
*/
402+
@Override
403+
public T disablingAllClientValidation(@NotNull final Boolean disableAllClientValidation) {
404+
this.disableAllClientValidation = disableAllClientValidation;
405+
return (T) this;
406+
}
391407

392408
/**
393409
* @see MailerGenericBuilder#withSessionTimeout(Integer)
@@ -632,6 +648,14 @@ public T withCustomMailer(@NotNull CustomMailer customMailer) {
632648
return (T) this;
633649
}
634650

651+
/**
652+
* @see MailerGenericBuilder#resetDisableAllClientValidations()
653+
*/
654+
@Override
655+
public T resetDisableAllClientValidations() {
656+
return disablingAllClientValidation(DEFAULT_DISABLE_ALL_CLIENTVALIDATION);
657+
}
658+
635659
/**
636660
* @see MailerGenericBuilder#resetSessionTimeout()
637661
*/
@@ -848,14 +872,22 @@ public String getProxyPassword() {
848872
public Integer getProxyBridgePort() {
849873
return proxyBridgePort;
850874
}
851-
875+
852876
/**
853877
* @see MailerGenericBuilder#isDebugLogging()
854878
*/
855879
@Override
856880
public boolean isDebugLogging() {
857881
return debugLogging;
858882
}
883+
884+
/**
885+
* @see MailerGenericBuilder#isDisableAllClientValidation()
886+
*/
887+
@Override
888+
public boolean isDisableAllClientValidation() {
889+
return disableAllClientValidation;
890+
}
859891

860892
/**
861893
* @see MailerGenericBuilder#getSessionTimeout()

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -343,10 +343,11 @@ public final CompletableFuture<Void> sendMail(final Email email, @SuppressWarnin
343343
* @see Mailer#validate(Email)
344344
*/
345345
@Override
346-
@SuppressWarnings({"SameReturnValue"})
347346
public boolean validate(@NotNull final Email email)
348347
throws MailException {
349-
return MailerHelper.validate(email, emailGovernance.getEmailValidator());
348+
return operationalConfig.isDisableAllClientValidation() ?
349+
MailerHelper.validateLenient(email, emailGovernance.getEmailValidator()) :
350+
MailerHelper.validate(email, emailGovernance.getEmailValidator());
350351
}
351352

352353
/**

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,12 @@ class OperationalConfigImpl implements OperationalConfig {
9090
* @see org.simplejavamail.api.mailer.MailerGenericBuilder#withDebugLogging(Boolean)
9191
*/
9292
private final boolean debugLogging;
93-
93+
94+
/**
95+
* @see org.simplejavamail.api.mailer.MailerGenericBuilder#disablingAllClientValidation(Boolean)
96+
*/
97+
private final boolean disableAllClientValidation;
98+
9499
/**
95100
* @see org.simplejavamail.api.mailer.MailerGenericBuilder#trustingSSLHosts(String...)
96101
*/

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515

1616
import static org.assertj.core.api.Assertions.assertThat;
1717
import static org.simplejavamail.api.email.ContentTransferEncoding.BINARY;
18-
import static org.simplejavamail.api.email.ContentTransferEncoding.QUOTED_PRINTABLE;
1918
import static org.simplejavamail.api.mailer.config.TransportStrategy.SMTPS;
2019
import static org.simplejavamail.config.ConfigLoader.Property.CUSTOM_SSLFACTORY_CLASS;
2120
import static org.simplejavamail.config.ConfigLoader.Property.DEFAULT_BCC_ADDRESS;
@@ -30,6 +29,7 @@
3029
import static org.simplejavamail.config.ConfigLoader.Property.DEFAULT_SUBJECT;
3130
import static org.simplejavamail.config.ConfigLoader.Property.DEFAULT_TO_ADDRESS;
3231
import static org.simplejavamail.config.ConfigLoader.Property.DEFAULT_TO_NAME;
32+
import static org.simplejavamail.config.ConfigLoader.Property.DISABLE_ALL_CLIENTVALIDATION;
3333
import static org.simplejavamail.config.ConfigLoader.Property.EMBEDDEDIMAGES_DYNAMICRESOLUTION_BASE_CLASSPATH;
3434
import static org.simplejavamail.config.ConfigLoader.Property.EMBEDDEDIMAGES_DYNAMICRESOLUTION_BASE_DIR;
3535
import static org.simplejavamail.config.ConfigLoader.Property.EMBEDDEDIMAGES_DYNAMICRESOLUTION_BASE_URL;
@@ -186,6 +186,7 @@ public void loadPropertiesFromFileClassPath() {
186186
assertThat(ConfigLoader.<Integer>getProperty(PROXY_PORT)).isEqualTo(1080);
187187
assertThat(ConfigLoader.<String>getProperty(PROXY_USERNAME)).isEqualTo("username proxy");
188188
assertThat(ConfigLoader.<String>getProperty(PROXY_PASSWORD)).isEqualTo("password proxy");
189+
assertThat(ConfigLoader.<Boolean>getProperty(DISABLE_ALL_CLIENTVALIDATION)).isFalse();
189190
assertThat(ConfigLoader.<Integer>getProperty(PROXY_SOCKS5BRIDGE_PORT)).isEqualTo(1081);
190191

191192
assertThat(ConfigLoader.<String>getProperty(DEFAULT_FROM_NAME)).isEqualTo("From Default");

0 commit comments

Comments
 (0)