mirror of
https://github.com/spring-projects/spring-boot.git
synced 2024-08-29 03:06:45 +08:00
Polish "Add SslBundle support to MailSender"
See gh-40037
This commit is contained in:
parent
e7424eacf8
commit
cf2b08b8a6
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2012-2023 the original author or authors.
|
* Copyright 2012-2024 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -68,11 +68,11 @@ class MailSenderAutoConfigurationIntegrationTests {
|
|||||||
return message.getSubject();
|
return message.getSubject();
|
||||||
}
|
}
|
||||||
catch (MessagingException ex) {
|
catch (MessagingException ex) {
|
||||||
throw new RuntimeException(ex);
|
throw new RuntimeException("Failed to get message subject", ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertMessagesContainSubject(Session session, String subject) {
|
private void assertMessagesContainSubject(Session session, String subject) throws MessagingException {
|
||||||
try (Store store = session.getStore("pop3")) {
|
try (Store store = session.getStore("pop3")) {
|
||||||
String host = session.getProperty("mail.pop3.host");
|
String host = session.getProperty("mail.pop3.host");
|
||||||
int port = Integer.parseInt(session.getProperty("mail.pop3.port"));
|
int port = Integer.parseInt(session.getProperty("mail.pop3.port"));
|
||||||
@ -86,20 +86,13 @@ class MailSenderAutoConfigurationIntegrationTests {
|
|||||||
.contains(subject));
|
.contains(subject));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (MessagingException ex) {
|
|
||||||
throw new RuntimeException(ex);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
class ImplicitTlsTests {
|
class ImplicitTlsTests {
|
||||||
|
|
||||||
final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
|
||||||
.withConfiguration(AutoConfigurations.of(MailSenderAutoConfiguration.class, SslAutoConfiguration.class));
|
|
||||||
|
|
||||||
@Container
|
@Container
|
||||||
private static final MailpitContainer mailpit = TestImage.container(MailpitContainer.class)
|
private static final MailpitContainer mailpit = TestImage.container(MailpitContainer.class)
|
||||||
// force ssl connection
|
|
||||||
.withSmtpRequireTls(true)
|
.withSmtpRequireTls(true)
|
||||||
.withSmtpTlsCert(MountableFile
|
.withSmtpTlsCert(MountableFile
|
||||||
.forClasspathResource("/org/springframework/boot/autoconfigure/mail/ssl/test-server.crt"))
|
.forClasspathResource("/org/springframework/boot/autoconfigure/mail/ssl/test-server.crt"))
|
||||||
@ -107,6 +100,9 @@ class MailSenderAutoConfigurationIntegrationTests {
|
|||||||
.forClasspathResource("/org/springframework/boot/autoconfigure/mail/ssl/test-server.key"))
|
.forClasspathResource("/org/springframework/boot/autoconfigure/mail/ssl/test-server.key"))
|
||||||
.withPop3Auth("user:pass");
|
.withPop3Auth("user:pass");
|
||||||
|
|
||||||
|
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||||
|
.withConfiguration(AutoConfigurations.of(MailSenderAutoConfiguration.class, SslAutoConfiguration.class));
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void sendEmailWithSslEnabledAndCert() {
|
void sendEmailWithSslEnabledAndCert() {
|
||||||
this.contextRunner.withPropertyValues("spring.mail.host:" + mailpit.getHost(),
|
this.contextRunner.withPropertyValues("spring.mail.host:" + mailpit.getHost(),
|
||||||
@ -115,14 +111,11 @@ class MailSenderAutoConfigurationIntegrationTests {
|
|||||||
"spring.ssl.bundle.pem.test-bundle.truststore.certificate=classpath:org/springframework/boot/autoconfigure/mail/ssl/test-ca.crt",
|
"spring.ssl.bundle.pem.test-bundle.truststore.certificate=classpath:org/springframework/boot/autoconfigure/mail/ssl/test-ca.crt",
|
||||||
"spring.ssl.bundle.pem.test-bundle.keystore.certificate=classpath:org/springframework/boot/autoconfigure/mail/ssl/test-client.crt",
|
"spring.ssl.bundle.pem.test-bundle.keystore.certificate=classpath:org/springframework/boot/autoconfigure/mail/ssl/test-client.crt",
|
||||||
"spring.ssl.bundle.pem.test-bundle.keystore.private-key=classpath:org/springframework/boot/autoconfigure/mail/ssl/test-client.key",
|
"spring.ssl.bundle.pem.test-bundle.keystore.private-key=classpath:org/springframework/boot/autoconfigure/mail/ssl/test-client.key",
|
||||||
// pop3
|
|
||||||
"spring.mail.properties.mail.pop3.host:" + mailpit.getHost(),
|
"spring.mail.properties.mail.pop3.host:" + mailpit.getHost(),
|
||||||
"spring.mail.properties.mail.pop3.port:" + mailpit.getPop3Port())
|
"spring.mail.properties.mail.pop3.port:" + mailpit.getPop3Port())
|
||||||
.run((context) -> {
|
.run((context) -> {
|
||||||
JavaMailSenderImpl mailSender = context.getBean(JavaMailSenderImpl.class);
|
JavaMailSenderImpl mailSender = context.getBean(JavaMailSenderImpl.class);
|
||||||
|
|
||||||
mailSender.send(createMessage("Hello World!"));
|
mailSender.send(createMessage("Hello World!"));
|
||||||
|
|
||||||
assertMessagesContainSubject(mailSender.getSession(), "Hello World!");
|
assertMessagesContainSubject(mailSender.getSession(), "Hello World!");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -134,7 +127,6 @@ class MailSenderAutoConfigurationIntegrationTests {
|
|||||||
"spring.mail.port:" + mailpit.getSmtpPort(), "spring.mail.ssl.enabled:true")
|
"spring.mail.port:" + mailpit.getSmtpPort(), "spring.mail.ssl.enabled:true")
|
||||||
.run((context) -> {
|
.run((context) -> {
|
||||||
JavaMailSenderImpl mailSender = context.getBean(JavaMailSenderImpl.class);
|
JavaMailSenderImpl mailSender = context.getBean(JavaMailSenderImpl.class);
|
||||||
|
|
||||||
assertThatException().isThrownBy(() -> mailSender.send(createMessage("Should fail")))
|
assertThatException().isThrownBy(() -> mailSender.send(createMessage("Should fail")))
|
||||||
.withRootCauseInstanceOf(CertPathBuilderException.class);
|
.withRootCauseInstanceOf(CertPathBuilderException.class);
|
||||||
});
|
});
|
||||||
@ -150,7 +142,6 @@ class MailSenderAutoConfigurationIntegrationTests {
|
|||||||
"spring.ssl.bundle.pem.test-bundle.keystore.private-key=classpath:org/springframework/boot/autoconfigure/mail/ssl/test-client.key")
|
"spring.ssl.bundle.pem.test-bundle.keystore.private-key=classpath:org/springframework/boot/autoconfigure/mail/ssl/test-client.key")
|
||||||
.run((context) -> {
|
.run((context) -> {
|
||||||
JavaMailSenderImpl mailSender = context.getBean(JavaMailSenderImpl.class);
|
JavaMailSenderImpl mailSender = context.getBean(JavaMailSenderImpl.class);
|
||||||
|
|
||||||
assertThatException().isThrownBy(() -> mailSender.send(createMessage("Should fail")))
|
assertThatException().isThrownBy(() -> mailSender.send(createMessage("Should fail")))
|
||||||
.withRootCauseInstanceOf(SocketTimeoutException.class);
|
.withRootCauseInstanceOf(SocketTimeoutException.class);
|
||||||
});
|
});
|
||||||
@ -161,9 +152,6 @@ class MailSenderAutoConfigurationIntegrationTests {
|
|||||||
@Nested
|
@Nested
|
||||||
class StarttlsTests {
|
class StarttlsTests {
|
||||||
|
|
||||||
final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
|
||||||
.withConfiguration(AutoConfigurations.of(MailSenderAutoConfiguration.class, SslAutoConfiguration.class));
|
|
||||||
|
|
||||||
@Container
|
@Container
|
||||||
private static final MailpitContainer mailpit = TestImage.container(MailpitContainer.class)
|
private static final MailpitContainer mailpit = TestImage.container(MailpitContainer.class)
|
||||||
.withSmtpRequireStarttls(true)
|
.withSmtpRequireStarttls(true)
|
||||||
@ -173,6 +161,9 @@ class MailSenderAutoConfigurationIntegrationTests {
|
|||||||
.forClasspathResource("/org/springframework/boot/autoconfigure/mail/ssl/test-server.key"))
|
.forClasspathResource("/org/springframework/boot/autoconfigure/mail/ssl/test-server.key"))
|
||||||
.withPop3Auth("user:pass");
|
.withPop3Auth("user:pass");
|
||||||
|
|
||||||
|
final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||||
|
.withConfiguration(AutoConfigurations.of(MailSenderAutoConfiguration.class, SslAutoConfiguration.class));
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void sendEmailWithStarttlsAndCertAndSslDisabled() {
|
void sendEmailWithStarttlsAndCertAndSslDisabled() {
|
||||||
this.contextRunner.withPropertyValues("spring.mail.host:" + mailpit.getHost(),
|
this.contextRunner.withPropertyValues("spring.mail.host:" + mailpit.getHost(),
|
||||||
@ -182,14 +173,11 @@ class MailSenderAutoConfigurationIntegrationTests {
|
|||||||
"spring.ssl.bundle.pem.test-bundle.truststore.certificate=classpath:org/springframework/boot/autoconfigure/mail/ssl/test-ca.crt",
|
"spring.ssl.bundle.pem.test-bundle.truststore.certificate=classpath:org/springframework/boot/autoconfigure/mail/ssl/test-ca.crt",
|
||||||
"spring.ssl.bundle.pem.test-bundle.keystore.certificate=classpath:org/springframework/boot/autoconfigure/mail/ssl/test-client.crt",
|
"spring.ssl.bundle.pem.test-bundle.keystore.certificate=classpath:org/springframework/boot/autoconfigure/mail/ssl/test-client.crt",
|
||||||
"spring.ssl.bundle.pem.test-bundle.keystore.private-key=classpath:org/springframework/boot/autoconfigure/mail/ssl/test-client.key",
|
"spring.ssl.bundle.pem.test-bundle.keystore.private-key=classpath:org/springframework/boot/autoconfigure/mail/ssl/test-client.key",
|
||||||
// pop3
|
|
||||||
"spring.mail.properties.mail.pop3.host:" + mailpit.getHost(),
|
"spring.mail.properties.mail.pop3.host:" + mailpit.getHost(),
|
||||||
"spring.mail.properties.mail.pop3.port:" + mailpit.getPop3Port())
|
"spring.mail.properties.mail.pop3.port:" + mailpit.getPop3Port())
|
||||||
.run((context) -> {
|
.run((context) -> {
|
||||||
JavaMailSenderImpl mailSender = context.getBean(JavaMailSenderImpl.class);
|
JavaMailSenderImpl mailSender = context.getBean(JavaMailSenderImpl.class);
|
||||||
|
|
||||||
mailSender.send(createMessage("Sent with STARTTLS"));
|
mailSender.send(createMessage("Sent with STARTTLS"));
|
||||||
|
|
||||||
assertMessagesContainSubject(mailSender.getSession(), "Sent with STARTTLS");
|
assertMessagesContainSubject(mailSender.getSession(), "Sent with STARTTLS");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -203,12 +191,10 @@ class MailSenderAutoConfigurationIntegrationTests {
|
|||||||
"spring.ssl.bundle.pem.test-bundle.truststore.certificate=classpath:org/springframework/boot/autoconfigure/mail/ssl/test-ca.crt",
|
"spring.ssl.bundle.pem.test-bundle.truststore.certificate=classpath:org/springframework/boot/autoconfigure/mail/ssl/test-ca.crt",
|
||||||
"spring.ssl.bundle.pem.test-bundle.keystore.certificate=classpath:org/springframework/boot/autoconfigure/mail/ssl/test-client.crt",
|
"spring.ssl.bundle.pem.test-bundle.keystore.certificate=classpath:org/springframework/boot/autoconfigure/mail/ssl/test-client.crt",
|
||||||
"spring.ssl.bundle.pem.test-bundle.keystore.private-key=classpath:org/springframework/boot/autoconfigure/mail/ssl/test-client.key",
|
"spring.ssl.bundle.pem.test-bundle.keystore.private-key=classpath:org/springframework/boot/autoconfigure/mail/ssl/test-client.key",
|
||||||
// pop3
|
|
||||||
"spring.mail.properties.mail.pop3.host:" + mailpit.getHost(),
|
"spring.mail.properties.mail.pop3.host:" + mailpit.getHost(),
|
||||||
"spring.mail.properties.mail.pop3.port:" + mailpit.getPop3Port())
|
"spring.mail.properties.mail.pop3.port:" + mailpit.getPop3Port())
|
||||||
.run((context) -> {
|
.run((context) -> {
|
||||||
JavaMailSenderImpl mailSender = context.getBean(JavaMailSenderImpl.class);
|
JavaMailSenderImpl mailSender = context.getBean(JavaMailSenderImpl.class);
|
||||||
|
|
||||||
assertThatException().isThrownBy(() -> mailSender.send(createMessage("Should fail")))
|
assertThatException().isThrownBy(() -> mailSender.send(createMessage("Should fail")))
|
||||||
.withRootCauseInstanceOf(SSLException.class);
|
.withRootCauseInstanceOf(SSLException.class);
|
||||||
});
|
});
|
||||||
@ -223,7 +209,6 @@ class MailSenderAutoConfigurationIntegrationTests {
|
|||||||
"spring.mail.properties.mail.smtp.starttls.required:true")
|
"spring.mail.properties.mail.smtp.starttls.required:true")
|
||||||
.run((context) -> {
|
.run((context) -> {
|
||||||
JavaMailSenderImpl mailSender = context.getBean(JavaMailSenderImpl.class);
|
JavaMailSenderImpl mailSender = context.getBean(JavaMailSenderImpl.class);
|
||||||
|
|
||||||
assertThatException().isThrownBy(() -> mailSender.send(createMessage("Should fail")))
|
assertThatException().isThrownBy(() -> mailSender.send(createMessage("Should fail")))
|
||||||
.withRootCauseInstanceOf(CertPathBuilderException.class);
|
.withRootCauseInstanceOf(CertPathBuilderException.class);
|
||||||
});
|
});
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2012-2019 the original author or authors.
|
* Copyright 2012-2024 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -22,6 +22,7 @@ import java.util.Properties;
|
|||||||
import org.springframework.beans.factory.ObjectProvider;
|
import org.springframework.beans.factory.ObjectProvider;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
|
import org.springframework.boot.autoconfigure.mail.MailProperties.Ssl;
|
||||||
import org.springframework.boot.ssl.SslBundle;
|
import org.springframework.boot.ssl.SslBundle;
|
||||||
import org.springframework.boot.ssl.SslBundles;
|
import org.springframework.boot.ssl.SslBundles;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
@ -29,6 +30,7 @@ import org.springframework.context.annotation.Configuration;
|
|||||||
import org.springframework.mail.MailSender;
|
import org.springframework.mail.MailSender;
|
||||||
import org.springframework.mail.javamail.JavaMailSender;
|
import org.springframework.mail.javamail.JavaMailSender;
|
||||||
import org.springframework.mail.javamail.JavaMailSenderImpl;
|
import org.springframework.mail.javamail.JavaMailSenderImpl;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Auto-configure a {@link MailSender} based on properties configuration.
|
* Auto-configure a {@link MailSender} based on properties configuration.
|
||||||
@ -41,21 +43,15 @@ import org.springframework.mail.javamail.JavaMailSenderImpl;
|
|||||||
@ConditionalOnProperty(prefix = "spring.mail", name = "host")
|
@ConditionalOnProperty(prefix = "spring.mail", name = "host")
|
||||||
class MailSenderPropertiesConfiguration {
|
class MailSenderPropertiesConfiguration {
|
||||||
|
|
||||||
private final ObjectProvider<SslBundles> sslBundles;
|
|
||||||
|
|
||||||
MailSenderPropertiesConfiguration(ObjectProvider<SslBundles> sslBundles) {
|
|
||||||
this.sslBundles = sslBundles;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@ConditionalOnMissingBean(JavaMailSender.class)
|
@ConditionalOnMissingBean(JavaMailSender.class)
|
||||||
JavaMailSenderImpl mailSender(MailProperties properties) {
|
JavaMailSenderImpl mailSender(MailProperties properties, ObjectProvider<SslBundles> sslBundles) {
|
||||||
JavaMailSenderImpl sender = new JavaMailSenderImpl();
|
JavaMailSenderImpl sender = new JavaMailSenderImpl();
|
||||||
applyProperties(properties, sender);
|
applyProperties(properties, sender, sslBundles.getIfAvailable());
|
||||||
return sender;
|
return sender;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void applyProperties(MailProperties properties, JavaMailSenderImpl sender) {
|
private void applyProperties(MailProperties properties, JavaMailSenderImpl sender, SslBundles sslBundles) {
|
||||||
sender.setHost(properties.getHost());
|
sender.setHost(properties.getHost());
|
||||||
if (properties.getPort() != null) {
|
if (properties.getPort() != null) {
|
||||||
sender.setPort(properties.getPort());
|
sender.setPort(properties.getPort());
|
||||||
@ -68,14 +64,15 @@ class MailSenderPropertiesConfiguration {
|
|||||||
}
|
}
|
||||||
Properties javaMailProperties = asProperties(properties.getProperties());
|
Properties javaMailProperties = asProperties(properties.getProperties());
|
||||||
String protocol = properties.getProtocol();
|
String protocol = properties.getProtocol();
|
||||||
if (protocol == null || protocol.isEmpty()) {
|
if (!StringUtils.hasLength(protocol)) {
|
||||||
protocol = "smtp";
|
protocol = "smtp";
|
||||||
}
|
}
|
||||||
if (properties.getSsl().isEnabled()) {
|
Ssl ssl = properties.getSsl();
|
||||||
|
if (ssl.isEnabled()) {
|
||||||
javaMailProperties.setProperty("mail." + protocol + ".ssl.enable", "true");
|
javaMailProperties.setProperty("mail." + protocol + ".ssl.enable", "true");
|
||||||
}
|
}
|
||||||
if (properties.getSsl().getBundle() != null) {
|
if (ssl.getBundle() != null) {
|
||||||
SslBundle sslBundle = this.sslBundles.getObject().getBundle(properties.getSsl().getBundle());
|
SslBundle sslBundle = sslBundles.getBundle(ssl.getBundle());
|
||||||
javaMailProperties.put("mail." + protocol + ".ssl.socketFactory",
|
javaMailProperties.put("mail." + protocol + ".ssl.socketFactory",
|
||||||
sslBundle.createSslContext().getSocketFactory());
|
sslBundle.createSslContext().getSocketFactory());
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user