Skip to content

Commit cf2b08b

Browse files
committed
Polish "Add SslBundle support to MailSender"
See gh-40037
1 parent e7424ea commit cf2b08b

File tree

2 files changed

+20
-38
lines changed

2 files changed

+20
-38
lines changed

spring-boot-project/spring-boot-autoconfigure/src/dockerTest/java/org/springframework/boot/autoconfigure/mail/MailSenderAutoConfigurationIntegrationTests.java

Lines changed: 9 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2023 the original author or authors.
2+
* Copyright 2012-2024 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -68,11 +68,11 @@ private String getSubject(Message message) {
6868
return message.getSubject();
6969
}
7070
catch (MessagingException ex) {
71-
throw new RuntimeException(ex);
71+
throw new RuntimeException("Failed to get message subject", ex);
7272
}
7373
}
7474

75-
private void assertMessagesContainSubject(Session session, String subject) {
75+
private void assertMessagesContainSubject(Session session, String subject) throws MessagingException {
7676
try (Store store = session.getStore("pop3")) {
7777
String host = session.getProperty("mail.pop3.host");
7878
int port = Integer.parseInt(session.getProperty("mail.pop3.port"));
@@ -86,27 +86,23 @@ private void assertMessagesContainSubject(Session session, String subject) {
8686
.contains(subject));
8787
}
8888
}
89-
catch (MessagingException ex) {
90-
throw new RuntimeException(ex);
91-
}
9289
}
9390

9491
@Nested
9592
class ImplicitTlsTests {
9693

97-
final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
98-
.withConfiguration(AutoConfigurations.of(MailSenderAutoConfiguration.class, SslAutoConfiguration.class));
99-
10094
@Container
10195
private static final MailpitContainer mailpit = TestImage.container(MailpitContainer.class)
102-
// force ssl connection
10396
.withSmtpRequireTls(true)
10497
.withSmtpTlsCert(MountableFile
10598
.forClasspathResource("/org/springframework/boot/autoconfigure/mail/ssl/test-server.crt"))
10699
.withSmtpTlsKey(MountableFile
107100
.forClasspathResource("/org/springframework/boot/autoconfigure/mail/ssl/test-server.key"))
108101
.withPop3Auth("user:pass");
109102

103+
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
104+
.withConfiguration(AutoConfigurations.of(MailSenderAutoConfiguration.class, SslAutoConfiguration.class));
105+
110106
@Test
111107
void sendEmailWithSslEnabledAndCert() {
112108
this.contextRunner.withPropertyValues("spring.mail.host:" + mailpit.getHost(),
@@ -115,14 +111,11 @@ void sendEmailWithSslEnabledAndCert() {
115111
"spring.ssl.bundle.pem.test-bundle.truststore.certificate=classpath:org/springframework/boot/autoconfigure/mail/ssl/test-ca.crt",
116112
"spring.ssl.bundle.pem.test-bundle.keystore.certificate=classpath:org/springframework/boot/autoconfigure/mail/ssl/test-client.crt",
117113
"spring.ssl.bundle.pem.test-bundle.keystore.private-key=classpath:org/springframework/boot/autoconfigure/mail/ssl/test-client.key",
118-
// pop3
119114
"spring.mail.properties.mail.pop3.host:" + mailpit.getHost(),
120115
"spring.mail.properties.mail.pop3.port:" + mailpit.getPop3Port())
121116
.run((context) -> {
122117
JavaMailSenderImpl mailSender = context.getBean(JavaMailSenderImpl.class);
123-
124118
mailSender.send(createMessage("Hello World!"));
125-
126119
assertMessagesContainSubject(mailSender.getSession(), "Hello World!");
127120
});
128121
}
@@ -134,7 +127,6 @@ void sendEmailWithSslEnabledWithoutCert() {
134127
"spring.mail.port:" + mailpit.getSmtpPort(), "spring.mail.ssl.enabled:true")
135128
.run((context) -> {
136129
JavaMailSenderImpl mailSender = context.getBean(JavaMailSenderImpl.class);
137-
138130
assertThatException().isThrownBy(() -> mailSender.send(createMessage("Should fail")))
139131
.withRootCauseInstanceOf(CertPathBuilderException.class);
140132
});
@@ -150,7 +142,6 @@ void sendEmailWithoutSslWithCert() {
150142
"spring.ssl.bundle.pem.test-bundle.keystore.private-key=classpath:org/springframework/boot/autoconfigure/mail/ssl/test-client.key")
151143
.run((context) -> {
152144
JavaMailSenderImpl mailSender = context.getBean(JavaMailSenderImpl.class);
153-
154145
assertThatException().isThrownBy(() -> mailSender.send(createMessage("Should fail")))
155146
.withRootCauseInstanceOf(SocketTimeoutException.class);
156147
});
@@ -161,9 +152,6 @@ void sendEmailWithoutSslWithCert() {
161152
@Nested
162153
class StarttlsTests {
163154

164-
final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
165-
.withConfiguration(AutoConfigurations.of(MailSenderAutoConfiguration.class, SslAutoConfiguration.class));
166-
167155
@Container
168156
private static final MailpitContainer mailpit = TestImage.container(MailpitContainer.class)
169157
.withSmtpRequireStarttls(true)
@@ -173,6 +161,9 @@ class StarttlsTests {
173161
.forClasspathResource("/org/springframework/boot/autoconfigure/mail/ssl/test-server.key"))
174162
.withPop3Auth("user:pass");
175163

164+
final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
165+
.withConfiguration(AutoConfigurations.of(MailSenderAutoConfiguration.class, SslAutoConfiguration.class));
166+
176167
@Test
177168
void sendEmailWithStarttlsAndCertAndSslDisabled() {
178169
this.contextRunner.withPropertyValues("spring.mail.host:" + mailpit.getHost(),
@@ -182,14 +173,11 @@ void sendEmailWithStarttlsAndCertAndSslDisabled() {
182173
"spring.ssl.bundle.pem.test-bundle.truststore.certificate=classpath:org/springframework/boot/autoconfigure/mail/ssl/test-ca.crt",
183174
"spring.ssl.bundle.pem.test-bundle.keystore.certificate=classpath:org/springframework/boot/autoconfigure/mail/ssl/test-client.crt",
184175
"spring.ssl.bundle.pem.test-bundle.keystore.private-key=classpath:org/springframework/boot/autoconfigure/mail/ssl/test-client.key",
185-
// pop3
186176
"spring.mail.properties.mail.pop3.host:" + mailpit.getHost(),
187177
"spring.mail.properties.mail.pop3.port:" + mailpit.getPop3Port())
188178
.run((context) -> {
189179
JavaMailSenderImpl mailSender = context.getBean(JavaMailSenderImpl.class);
190-
191180
mailSender.send(createMessage("Sent with STARTTLS"));
192-
193181
assertMessagesContainSubject(mailSender.getSession(), "Sent with STARTTLS");
194182
});
195183
}
@@ -203,12 +191,10 @@ void sendEmailWithStarttlsAndCertAndSslEnabled() {
203191
"spring.ssl.bundle.pem.test-bundle.truststore.certificate=classpath:org/springframework/boot/autoconfigure/mail/ssl/test-ca.crt",
204192
"spring.ssl.bundle.pem.test-bundle.keystore.certificate=classpath:org/springframework/boot/autoconfigure/mail/ssl/test-client.crt",
205193
"spring.ssl.bundle.pem.test-bundle.keystore.private-key=classpath:org/springframework/boot/autoconfigure/mail/ssl/test-client.key",
206-
// pop3
207194
"spring.mail.properties.mail.pop3.host:" + mailpit.getHost(),
208195
"spring.mail.properties.mail.pop3.port:" + mailpit.getPop3Port())
209196
.run((context) -> {
210197
JavaMailSenderImpl mailSender = context.getBean(JavaMailSenderImpl.class);
211-
212198
assertThatException().isThrownBy(() -> mailSender.send(createMessage("Should fail")))
213199
.withRootCauseInstanceOf(SSLException.class);
214200
});
@@ -223,7 +209,6 @@ void sendEmailWithStarttlsWithoutCert() {
223209
"spring.mail.properties.mail.smtp.starttls.required:true")
224210
.run((context) -> {
225211
JavaMailSenderImpl mailSender = context.getBean(JavaMailSenderImpl.class);
226-
227212
assertThatException().isThrownBy(() -> mailSender.send(createMessage("Should fail")))
228213
.withRootCauseInstanceOf(CertPathBuilderException.class);
229214
});

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mail/MailSenderPropertiesConfiguration.java

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2019 the original author or authors.
2+
* Copyright 2012-2024 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -22,13 +22,15 @@
2222
import org.springframework.beans.factory.ObjectProvider;
2323
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
2424
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
25+
import org.springframework.boot.autoconfigure.mail.MailProperties.Ssl;
2526
import org.springframework.boot.ssl.SslBundle;
2627
import org.springframework.boot.ssl.SslBundles;
2728
import org.springframework.context.annotation.Bean;
2829
import org.springframework.context.annotation.Configuration;
2930
import org.springframework.mail.MailSender;
3031
import org.springframework.mail.javamail.JavaMailSender;
3132
import org.springframework.mail.javamail.JavaMailSenderImpl;
33+
import org.springframework.util.StringUtils;
3234

3335
/**
3436
* Auto-configure a {@link MailSender} based on properties configuration.
@@ -41,21 +43,15 @@
4143
@ConditionalOnProperty(prefix = "spring.mail", name = "host")
4244
class MailSenderPropertiesConfiguration {
4345

44-
private final ObjectProvider<SslBundles> sslBundles;
45-
46-
MailSenderPropertiesConfiguration(ObjectProvider<SslBundles> sslBundles) {
47-
this.sslBundles = sslBundles;
48-
}
49-
5046
@Bean
5147
@ConditionalOnMissingBean(JavaMailSender.class)
52-
JavaMailSenderImpl mailSender(MailProperties properties) {
48+
JavaMailSenderImpl mailSender(MailProperties properties, ObjectProvider<SslBundles> sslBundles) {
5349
JavaMailSenderImpl sender = new JavaMailSenderImpl();
54-
applyProperties(properties, sender);
50+
applyProperties(properties, sender, sslBundles.getIfAvailable());
5551
return sender;
5652
}
5753

58-
private void applyProperties(MailProperties properties, JavaMailSenderImpl sender) {
54+
private void applyProperties(MailProperties properties, JavaMailSenderImpl sender, SslBundles sslBundles) {
5955
sender.setHost(properties.getHost());
6056
if (properties.getPort() != null) {
6157
sender.setPort(properties.getPort());
@@ -68,14 +64,15 @@ private void applyProperties(MailProperties properties, JavaMailSenderImpl sende
6864
}
6965
Properties javaMailProperties = asProperties(properties.getProperties());
7066
String protocol = properties.getProtocol();
71-
if (protocol == null || protocol.isEmpty()) {
67+
if (!StringUtils.hasLength(protocol)) {
7268
protocol = "smtp";
7369
}
74-
if (properties.getSsl().isEnabled()) {
70+
Ssl ssl = properties.getSsl();
71+
if (ssl.isEnabled()) {
7572
javaMailProperties.setProperty("mail." + protocol + ".ssl.enable", "true");
7673
}
77-
if (properties.getSsl().getBundle() != null) {
78-
SslBundle sslBundle = this.sslBundles.getObject().getBundle(properties.getSsl().getBundle());
74+
if (ssl.getBundle() != null) {
75+
SslBundle sslBundle = sslBundles.getBundle(ssl.getBundle());
7976
javaMailProperties.put("mail." + protocol + ".ssl.socketFactory",
8077
sslBundle.createSslContext().getSocketFactory());
8178
}

0 commit comments

Comments
 (0)