From 327bef3a71561a6844ede3039a4d4e7bf38016cf Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Tue, 5 May 2026 13:54:16 +0100 Subject: [PATCH] Enable hostname verification by default in Mail auto-config Fixes gh-50742 --- .../autoconfigure/mail/MailProperties.java | 13 +++++++++ .../MailSenderPropertiesConfiguration.java | 19 ++++++++----- .../MailSenderAutoConfigurationTests.java | 28 +++++++++++++++---- 3 files changed, 48 insertions(+), 12 deletions(-) diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mail/MailProperties.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mail/MailProperties.java index c1760df7fe0..f1e6cec20c0 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mail/MailProperties.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mail/MailProperties.java @@ -153,6 +153,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. @@ -170,6 +175,14 @@ public class MailProperties { this.enabled = enabled; } + public boolean isVerifyHostname() { + return this.verifyHostname; + } + + public void setVerifyHostname(boolean verifyHostname) { + this.verifyHostname = verifyHostname; + } + public String getBundle() { return this.bundle; } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mail/MailSenderPropertiesConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mail/MailSenderPropertiesConfiguration.java index 8b91aaeb6d0..0dcf3b2b8ca 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mail/MailSenderPropertiesConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mail/MailSenderPropertiesConfiguration.java @@ -66,13 +66,18 @@ 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())) { - 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())) { + SslBundle sslBundle = sslBundles.getBundle(ssl.getBundle()); + javaMailProperties.put("mail." + protocol + ".ssl.socketFactory", + sslBundle.createSslContext().getSocketFactory()); + } } if (!javaMailProperties.isEmpty()) { sender.setJavaMailProperties(javaMailProperties); diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mail/MailSenderAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mail/MailSenderAutoConfigurationTests.java index 04975e8f230..587ec6f4059 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mail/MailSenderAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mail/MailSenderAutoConfigurationTests.java @@ -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); });