Skip to content

Commit

Permalink
#105: Opportunistic TLS for SMTP plain protocol can now be configured…
Browse files Browse the repository at this point in the history
… programmatically as well as with a property
  • Loading branch information
bbottema committed Nov 5, 2017
1 parent 2d82ff0 commit 94b87b2
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 7 deletions.
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
package org.simplejavamail.mailer.config;

import org.simplejavamail.util.ConfigLoader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.Nullable;
import javax.mail.Session;
import java.util.Properties;

import static java.lang.String.format;
import static org.simplejavamail.util.ConfigLoader.Property.OPPORTUNISTIC_TLS;
import static org.simplejavamail.util.ConfigLoader.getProperty;
import static org.simplejavamail.util.ConfigLoader.hasProperty;

/**
* Defines the various types of transport protocols and implements respective properties so that a {@link Session} may be configured using a
Expand Down Expand Up @@ -47,15 +47,31 @@ public enum TransportStrategy {
* </ul>
*/
SMTP {

/**
* Defaults to enabled opportunistic TLS behavior ({@link #opportunisticTLS}), in case value was not programmatically set or provided
* as property value.
*/
private static final boolean DEFAULT_OPPORTUNISTIC_TLS = true;

/**
* Determines whether TLS should be attempted for SMTP plain protocol (optional if offered by the SMTP server). If not set and no property
* was provided, this value defaults to {@value DEFAULT_OPPORTUNISTIC_TLS}.
* <p>
* Setting this flag to false causes the {@link TransportStrategy#SMTP} to revert back to the legacy behavior.
*/
@Nullable
private Boolean opportunisticTLS;

/**
* @see TransportStrategy#SMTP
*/
@Override
public Properties generateProperties() {
final Properties props = super.generateProperties();
props.put("mail.transport.protocol", "smtp");
if (!hasProperty(OPPORTUNISTIC_TLS) || (Boolean) getProperty(OPPORTUNISTIC_TLS)) {
LOGGER.debug("Opportunistic TLS mode enabled for SMTP plain protocol (can be disabled with property 'simplejavamail.opportunistic.tls').");
if (ConfigLoader.valueOrProperty(opportunisticTLS, OPPORTUNISTIC_TLS, DEFAULT_OPPORTUNISTIC_TLS)) {
LOGGER.debug("Opportunistic TLS mode enabled for SMTP plain protocol.");
props.put("mail.smtp.starttls.enable", "true");
props.put("mail.smtp.starttls.required", "false");
props.put("mail.smtp.ssl.trust", "*");
Expand Down Expand Up @@ -151,6 +167,22 @@ public String propertyNameEnvelopeFrom() {
public String propertyNameSSLTrust() {
return "mail.smtp.ssl.trust";
}

/**
* @return {@link #opportunisticTLS}
*/
@Nullable
public Boolean getOpportunisticTLS() {
return opportunisticTLS;
}

/**
* Sets {@link #opportunisticTLS}. Setting <code>null</code> will revert to property value if available or default to {@value
* DEFAULT_OPPORTUNISTIC_TLS}
*/
public void setOpportunisticTLS(@Nullable Boolean opportunisticTLS) {
this.opportunisticTLS = opportunisticTLS;
}
},
/**
* SMTP entirely encapsulated by TLS. Commonly known as SMTPS.
Expand All @@ -169,9 +201,7 @@ public String propertyNameSSLTrust() {
* javax.mail.MessagingException: Exception reading response;
* nested exception is:
* javax.net.ssl.SSLException: Unsupported record version Unknown-50.49
* (..)
* </pre>
* <p>
* (..)</pre>
* <blockquote>The mail is sent but the exception is unwanted. The property <em>quitwait</em> means If set to false, the QUIT command is sent and
* the connection is immediately closed. If set to true (the default), causes the transport to wait for the response to the QUIT
* command</blockquote><br> <strong>- <a href="http://www.rgagnon.com/javadetails/java-0570.html">source</a></strong>
Expand Down Expand Up @@ -432,6 +462,15 @@ public Properties generateProperties() {
public abstract String propertyNameSSLTrust();
public abstract String propertyNameTimeout();

/**
* @see TransportStrategy#SMTP#getOpportunisticTLS()
*/
@Nullable public Boolean getOpportunisticTLS() { return false; }
/**
* @see TransportStrategy#SMTP#setOpportunisticTLS(Boolean)
*/
public void setOpportunisticTLS(@Nullable Boolean opportunisticTLS) {}

/**
* @param session The session to determine the current transport strategy for
* @return Which strategy matches the current Session properties.
Expand Down
28 changes: 28 additions & 0 deletions src/test/java/org/simplejavamail/mailer/MailerTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,34 @@ public void createMailSession_MinimalConstructor_WithConfig_OPPORTUNISTIC_TLS()
assertThat(session.getProperty("mail.smtp.socks.port")).isEqualTo("1081");
}

@Test
public void createMailSession_MinimalConstructor_WithConfig_OPPORTUNISTIC_TLS_Manually_Disabled() {
Properties properties = new Properties();
properties.setProperty(OPPORTUNISTIC_TLS.key(), "false");
ConfigLoader.loadProperties(properties, true);

TransportStrategy.SMTP.setOpportunisticTLS(true);

Mailer mailer = new Mailer(TransportStrategy.SMTP);
Session session = mailer.getSession();

assertThat(session.getDebug()).isTrue();
assertThat(session.getProperty("mail.smtp.host")).isEqualTo("smtp.default.com");
assertThat(session.getProperty("mail.smtp.port")).isEqualTo("25");
assertThat(session.getProperty("mail.transport.protocol")).isEqualTo("smtp");

assertThat(session.getProperty("mail.smtp.starttls.enable")).isEqualTo("true");
assertThat(session.getProperty("mail.smtp.starttls.required")).isEqualTo("false");
assertThat(session.getProperty("mail.smtp.ssl.trust")).isEqualTo("*");
assertThat(session.getProperty("mail.smtp.ssl.checkserveridentity")).isEqualTo("false");

assertThat(session.getProperty("mail.smtp.username")).isEqualTo("username smtp");
assertThat(session.getProperty("mail.smtp.auth")).isEqualTo("true");
// the following two are because authentication is needed, otherwise proxy would be straightworward
assertThat(session.getProperty("mail.smtp.socks.host")).isEqualTo("localhost");
assertThat(session.getProperty("mail.smtp.socks.port")).isEqualTo("1081");
}

@Test
public void createMailSession_MaximumConstructor_WithConfig()
throws Exception {
Expand Down

0 comments on commit 94b87b2

Please # to comment.