Merge branch '3.5.x' into 4.0.x

Closes gh-50746
This commit is contained in:
Andy Wilkinson
2026-06-10 15:53:08 +01:00
3 changed files with 49 additions and 13 deletions
@@ -155,6 +155,11 @@ public class MailProperties {
*/
private boolean enabled;
/**
* Whether to enable hostname verification.
*/
private boolean verifyHostname = true;
/**
* SSL bundle name. If set, 'mail.(protocol).ssl.socketFactory' property is set to
* an SSLSocketFactory obtained from the corresponding SSL bundle.
@@ -172,6 +177,14 @@ public class MailProperties {
this.enabled = enabled;
}
public boolean isVerifyHostname() {
return this.verifyHostname;
}
public void setVerifyHostname(boolean verifyHostname) {
this.verifyHostname = verifyHostname;
}
public @Nullable String getBundle() {
return this.bundle;
}
@@ -70,14 +70,19 @@ class MailSenderPropertiesConfiguration {
String protocol = properties.getProtocol();
protocol = (!StringUtils.hasLength(protocol)) ? "smtp" : protocol;
Ssl ssl = properties.getSsl();
if (ssl.isEnabled()) {
javaMailProperties.setProperty("mail." + protocol + ".ssl.enable", "true");
}
if (StringUtils.hasLength(ssl.getBundle())) {
Assert.state(sslBundles != null, "'sslBundles' must not be null");
SslBundle sslBundle = sslBundles.getBundle(ssl.getBundle());
javaMailProperties.put("mail." + protocol + ".ssl.socketFactory",
sslBundle.createSslContext().getSocketFactory());
if (ssl.isEnabled() || StringUtils.hasLength(ssl.getBundle())) {
if (ssl.isVerifyHostname()) {
javaMailProperties.setProperty("mail." + protocol + ".ssl.checkserveridentity", "true");
}
if (ssl.isEnabled()) {
javaMailProperties.setProperty("mail." + protocol + ".ssl.enable", "true");
}
if (StringUtils.hasLength(ssl.getBundle())) {
Assert.state(sslBundles != null, "'sslBundles' must not be null");
SslBundle sslBundle = sslBundles.getBundle(ssl.getBundle());
javaMailProperties.put("mail." + protocol + ".ssl.socketFactory",
sslBundle.createSslContext().getSocketFactory());
}
}
if (!javaMailProperties.isEmpty()) {
sender.setJavaMailProperties(javaMailProperties);
@@ -266,22 +266,38 @@ class MailSenderAutoConfigurationTests {
.run((context) -> {
assertThat(context).hasSingleBean(JavaMailSenderImpl.class);
JavaMailSenderImpl mailSender = context.getBean(JavaMailSenderImpl.class);
assertThat(mailSender.getJavaMailProperties()).containsEntry("mail.smtp.ssl.enable", "true");
assertThat(mailSender.getJavaMailProperties()).containsEntry("mail.smtp.ssl.enable", "true")
.containsEntry("mail.smtp.ssl.checkserveridentity", "true");
});
}
@Test
void smtpSslEnabledWithHostnameVerificationDisabled() {
this.contextRunner
.withPropertyValues("spring.mail.host:localhost", "spring.mail.ssl.enabled:true",
"spring.mail.ssl.verify-hostname:false")
.run((context) -> {
assertThat(context).hasSingleBean(JavaMailSenderImpl.class);
JavaMailSenderImpl mailSender = context.getBean(JavaMailSenderImpl.class);
assertThat(mailSender.getJavaMailProperties()).containsEntry("mail.smtp.ssl.enable", "true")
.doesNotContainKey("mail.smtp.ssl.checkserveridentity");
});
}
@Test
@WithPackageResources("test.jks")
void smtpSslBundle() {
void smtpSslBundleWithHostnameVerificationDisabled() {
this.contextRunner
.withPropertyValues("spring.mail.host:localhost", "spring.mail.ssl.bundle:test-bundle",
"spring.mail.ssl.verify-hostname:false",
"spring.ssl.bundle.jks.test-bundle.keystore.location:classpath:test.jks",
"spring.ssl.bundle.jks.test-bundle.keystore.password:secret",
"spring.ssl.bundle.jks.test-bundle.key.password:password")
.run((context) -> {
assertThat(context).hasSingleBean(JavaMailSenderImpl.class);
JavaMailSenderImpl mailSender = context.getBean(JavaMailSenderImpl.class);
assertThat(mailSender.getJavaMailProperties()).doesNotContainKey("mail.smtp.ssl.enable");
assertThat(mailSender.getJavaMailProperties()).doesNotContainKey("mail.smtp.ssl.enable")
.doesNotContainKey("mail.smtp.ssl.checkserveridentity");
Object property = mailSender.getJavaMailProperties().get("mail.smtp.ssl.socketFactory");
assertThat(property).isInstanceOf(SSLSocketFactory.class);
});
@@ -295,7 +311,8 @@ class MailSenderAutoConfigurationTests {
.run((context) -> {
assertThat(context).hasSingleBean(JavaMailSenderImpl.class);
JavaMailSenderImpl mailSender = context.getBean(JavaMailSenderImpl.class);
assertThat(mailSender.getJavaMailProperties()).containsEntry("mail.smtps.ssl.enable", "true");
assertThat(mailSender.getJavaMailProperties()).containsEntry("mail.smtps.ssl.enable", "true")
.containsEntry("mail.smtps.ssl.checkserveridentity", "true");
});
}
@@ -311,7 +328,8 @@ class MailSenderAutoConfigurationTests {
.run((context) -> {
assertThat(context).hasSingleBean(JavaMailSenderImpl.class);
JavaMailSenderImpl mailSender = context.getBean(JavaMailSenderImpl.class);
assertThat(mailSender.getJavaMailProperties()).doesNotContainKey("mail.smtps.ssl.enable");
assertThat(mailSender.getJavaMailProperties()).doesNotContainKey("mail.smtps.ssl.enable")
.containsEntry("mail.smtps.ssl.checkserveridentity", "true");
Object property = mailSender.getJavaMailProperties().get("mail.smtps.ssl.socketFactory");
assertThat(property).isInstanceOf(SSLSocketFactory.class);
});