mirror of
https://github.com/spring-projects/spring-boot.git
synced 2024-07-05 00:56:58 +08:00
Merge pull request #40037 from ruifigueira
* pr/40037: Polish "Add SslBundle support to MailSender" Add SslBundle support to MailSender Closes gh-40037
This commit is contained in:
commit
1e005cace2
@ -27,6 +27,7 @@ dependencies {
|
||||
dockerTestImplementation("org.testcontainers:neo4j")
|
||||
dockerTestImplementation("org.testcontainers:pulsar")
|
||||
dockerTestImplementation("org.testcontainers:testcontainers")
|
||||
dockerTestImplementation("org.awaitility:awaitility")
|
||||
|
||||
optional("co.elastic.clients:elasticsearch-java") {
|
||||
exclude group: "commons-logging", module: "commons-logging"
|
||||
|
@ -0,0 +1,219 @@
|
||||
/*
|
||||
* Copyright 2012-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.autoconfigure.mail;
|
||||
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.security.cert.CertPathBuilderException;
|
||||
import java.time.Duration;
|
||||
import java.util.Arrays;
|
||||
|
||||
import javax.net.ssl.SSLException;
|
||||
|
||||
import jakarta.mail.Folder;
|
||||
import jakarta.mail.Message;
|
||||
import jakarta.mail.MessagingException;
|
||||
import jakarta.mail.Session;
|
||||
import jakarta.mail.Store;
|
||||
import org.awaitility.Awaitility;
|
||||
import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.testcontainers.junit.jupiter.Container;
|
||||
import org.testcontainers.junit.jupiter.Testcontainers;
|
||||
import org.testcontainers.utility.MountableFile;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.autoconfigure.ssl.SslAutoConfiguration;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
import org.springframework.boot.testsupport.container.MailpitContainer;
|
||||
import org.springframework.boot.testsupport.container.TestImage;
|
||||
import org.springframework.mail.SimpleMailMessage;
|
||||
import org.springframework.mail.javamail.JavaMailSenderImpl;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatException;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link MailSenderAutoConfiguration}.
|
||||
*
|
||||
* @author Rui Figueira
|
||||
*/
|
||||
@Testcontainers(disabledWithoutDocker = true)
|
||||
class MailSenderAutoConfigurationIntegrationTests {
|
||||
|
||||
private SimpleMailMessage createMessage(String subject) {
|
||||
SimpleMailMessage msg = new SimpleMailMessage();
|
||||
msg.setFrom("from@example.com");
|
||||
msg.setTo("to@example.com");
|
||||
msg.setSubject(subject);
|
||||
msg.setText("Subject: " + subject);
|
||||
return msg;
|
||||
}
|
||||
|
||||
private String getSubject(Message message) {
|
||||
try {
|
||||
return message.getSubject();
|
||||
}
|
||||
catch (MessagingException ex) {
|
||||
throw new RuntimeException("Failed to get message subject", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void assertMessagesContainSubject(Session session, String subject) throws MessagingException {
|
||||
try (Store store = session.getStore("pop3")) {
|
||||
String host = session.getProperty("mail.pop3.host");
|
||||
int port = Integer.parseInt(session.getProperty("mail.pop3.port"));
|
||||
store.connect(host, port, "user", "pass");
|
||||
try (Folder folder = store.getFolder("inbox")) {
|
||||
folder.open(Folder.READ_ONLY);
|
||||
Awaitility.await()
|
||||
.atMost(Duration.ofSeconds(5))
|
||||
.ignoreExceptions()
|
||||
.untilAsserted(() -> assertThat(Arrays.stream(folder.getMessages()).map(this::getSubject))
|
||||
.contains(subject));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
class ImplicitTlsTests {
|
||||
|
||||
@Container
|
||||
private static final MailpitContainer mailpit = TestImage.container(MailpitContainer.class)
|
||||
.withSmtpRequireTls(true)
|
||||
.withSmtpTlsCert(MountableFile
|
||||
.forClasspathResource("/org/springframework/boot/autoconfigure/mail/ssl/test-server.crt"))
|
||||
.withSmtpTlsKey(MountableFile
|
||||
.forClasspathResource("/org/springframework/boot/autoconfigure/mail/ssl/test-server.key"))
|
||||
.withPop3Auth("user:pass");
|
||||
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(MailSenderAutoConfiguration.class, SslAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
void sendEmailWithSslEnabledAndCert() {
|
||||
this.contextRunner.withPropertyValues("spring.mail.host:" + mailpit.getHost(),
|
||||
"spring.mail.port:" + mailpit.getSmtpPort(), "spring.mail.ssl.enabled:true",
|
||||
"spring.mail.ssl.bundle:test-bundle",
|
||||
"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.private-key=classpath:org/springframework/boot/autoconfigure/mail/ssl/test-client.key",
|
||||
"spring.mail.properties.mail.pop3.host:" + mailpit.getHost(),
|
||||
"spring.mail.properties.mail.pop3.port:" + mailpit.getPop3Port())
|
||||
.run((context) -> {
|
||||
JavaMailSenderImpl mailSender = context.getBean(JavaMailSenderImpl.class);
|
||||
mailSender.send(createMessage("Hello World!"));
|
||||
assertMessagesContainSubject(mailSender.getSession(), "Hello World!");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void sendEmailWithSslEnabledWithoutCert() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("spring.mail.host:" + mailpit.getHost(),
|
||||
"spring.mail.port:" + mailpit.getSmtpPort(), "spring.mail.ssl.enabled:true")
|
||||
.run((context) -> {
|
||||
JavaMailSenderImpl mailSender = context.getBean(JavaMailSenderImpl.class);
|
||||
assertThatException().isThrownBy(() -> mailSender.send(createMessage("Should fail")))
|
||||
.withRootCauseInstanceOf(CertPathBuilderException.class);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void sendEmailWithoutSslWithCert() {
|
||||
this.contextRunner.withPropertyValues("spring.mail.host:" + mailpit.getHost(),
|
||||
"spring.mail.port:" + mailpit.getSmtpPort(), "spring.mail.properties.mail.smtp.timeout:1000",
|
||||
"spring.mail.ssl.bundle:test-bundle",
|
||||
"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.private-key=classpath:org/springframework/boot/autoconfigure/mail/ssl/test-client.key")
|
||||
.run((context) -> {
|
||||
JavaMailSenderImpl mailSender = context.getBean(JavaMailSenderImpl.class);
|
||||
assertThatException().isThrownBy(() -> mailSender.send(createMessage("Should fail")))
|
||||
.withRootCauseInstanceOf(SocketTimeoutException.class);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Nested
|
||||
class StarttlsTests {
|
||||
|
||||
@Container
|
||||
private static final MailpitContainer mailpit = TestImage.container(MailpitContainer.class)
|
||||
.withSmtpRequireStarttls(true)
|
||||
.withSmtpTlsCert(MountableFile
|
||||
.forClasspathResource("/org/springframework/boot/autoconfigure/mail/ssl/test-server.crt"))
|
||||
.withSmtpTlsKey(MountableFile
|
||||
.forClasspathResource("/org/springframework/boot/autoconfigure/mail/ssl/test-server.key"))
|
||||
.withPop3Auth("user:pass");
|
||||
|
||||
final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(MailSenderAutoConfiguration.class, SslAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
void sendEmailWithStarttlsAndCertAndSslDisabled() {
|
||||
this.contextRunner.withPropertyValues("spring.mail.host:" + mailpit.getHost(),
|
||||
"spring.mail.port:" + mailpit.getSmtpPort(),
|
||||
"spring.mail.properties.mail.smtp.starttls.enable:true",
|
||||
"spring.mail.properties.mail.smtp.starttls.required:true", "spring.mail.ssl.bundle:test-bundle",
|
||||
"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.private-key=classpath:org/springframework/boot/autoconfigure/mail/ssl/test-client.key",
|
||||
"spring.mail.properties.mail.pop3.host:" + mailpit.getHost(),
|
||||
"spring.mail.properties.mail.pop3.port:" + mailpit.getPop3Port())
|
||||
.run((context) -> {
|
||||
JavaMailSenderImpl mailSender = context.getBean(JavaMailSenderImpl.class);
|
||||
mailSender.send(createMessage("Sent with STARTTLS"));
|
||||
assertMessagesContainSubject(mailSender.getSession(), "Sent with STARTTLS");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void sendEmailWithStarttlsAndCertAndSslEnabled() {
|
||||
this.contextRunner.withPropertyValues("spring.mail.host:" + mailpit.getHost(),
|
||||
"spring.mail.port:" + mailpit.getSmtpPort(), "spring.mail.ssl.enabled:true",
|
||||
"spring.mail.properties.mail.smtp.starttls.enable:true",
|
||||
"spring.mail.properties.mail.smtp.starttls.required:true", "spring.mail.ssl.bundle:test-bundle",
|
||||
"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.private-key=classpath:org/springframework/boot/autoconfigure/mail/ssl/test-client.key",
|
||||
"spring.mail.properties.mail.pop3.host:" + mailpit.getHost(),
|
||||
"spring.mail.properties.mail.pop3.port:" + mailpit.getPop3Port())
|
||||
.run((context) -> {
|
||||
JavaMailSenderImpl mailSender = context.getBean(JavaMailSenderImpl.class);
|
||||
assertThatException().isThrownBy(() -> mailSender.send(createMessage("Should fail")))
|
||||
.withRootCauseInstanceOf(SSLException.class);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void sendEmailWithStarttlsWithoutCert() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("spring.mail.host:" + mailpit.getHost(),
|
||||
"spring.mail.port:" + mailpit.getSmtpPort(),
|
||||
"spring.mail.properties.mail.smtp.starttls.enable:true",
|
||||
"spring.mail.properties.mail.smtp.starttls.required:true")
|
||||
.run((context) -> {
|
||||
JavaMailSenderImpl mailSender = context.getBean(JavaMailSenderImpl.class);
|
||||
assertThatException().isThrownBy(() -> mailSender.send(createMessage("Should fail")))
|
||||
.withRootCauseInstanceOf(CertPathBuilderException.class);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
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
|
||||
Dyno/RVFR/rUL5091gjGRXhLsi1oUHKdEzU=
|
||||
-----END CERTIFICATE-----
|
@ -0,0 +1,52 @@
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
MIIJQwIBADANBgkqhkiG9w0BAQEFAASCCS0wggkpAgEAAoICAQC6w3YrNBBRTFlK
|
||||
Ijdlm5miEXCrYpdJQ090nquAPf9go1MNJlcpk87neRg8/QNd/SybcIdzJZJZVpvK
|
||||
KZli49Z6drUwSVIvhmkn1bCRmg5Dds8UrW63PqQw7CuABRyTLwf+sgqPYkQGGRId
|
||||
Qgavns2NQTAbXKBpJ6szxHNbDU+0yr4Lws67e/3irMTc0ODVBGnK9X06awuyMhJ3
|
||||
RmYAk2L2+aIQf3bcqc/KKqdCZYqliJx2BCZfUZfKVLbaNmoDBo6RgaNfxR17K+ui
|
||||
GRmQzSGf25pK59AYRbjIoAKfc+SMm3OLx2sEjKMiL1hwDMHFkH2hUqpdkyWW2A7Z
|
||||
8MyYgmLQ2C3QKLt8KgQypKhwrIMowvpguv1Ra3Hht+yuT6tU71D8P+/xEqCy2/t0
|
||||
J/YpZFfdkkQLQgEdLmAs2rSqqpVwbHctxLKF2Iok61LACc2QcyH6NJDEtKUGNxKp
|
||||
M+IZNEr9F12X7GdT+YGCTtkEY2tQVoPkxwwWN11LsiHzZoeelDWB6RadQa/5Ob8b
|
||||
ryHYG9nlTar5F944KBFb2L8BhbaOBPsgWd+PJReAFC95q4wByGiaoURUt73lmBWI
|
||||
Xq+YffgQqjfD0vlNCLCT+vndiUztNI5PIOrHrq3jMZgOxUyJykqbOLjZGnwSkSsB
|
||||
FHJERQgpK9az07365Pf7tqs0uAd7kQIDAQABAoICAAthB10ggfICHdqXdRqavWST
|
||||
fXLjweXz1O59EGPy4xFnQhMmB99/ovaVeTWWENN0LniWBZqtalpJHZrWqALPcOzr
|
||||
OKTlgr1kihmkOmrUoRPZNErFOl6t0WEtsoTNSu1oyyrofB46VXytoF3p/PBMU6fM
|
||||
lfrEzP07LoIr8P9WM0oHpEahKulfZ5uc/S2bCGfSKgP0qxmZFhBYXqmnv2U/laMI
|
||||
mKg6q+pL6l4d9SzldOobBbVnEVNzbDUmrjFjaVgf2SXiaSrXnrE3ftbUgqtA5FCS
|
||||
F7eCojooXVbT8PT4Ia+zdPnKP6n6S6I0kkXZcSDxacYffEPRSFQFe/opYr3UC+Mk
|
||||
1/UmOnoI8X8+N9SPcVD9cbVQUzBuuXfTy+LMx9mg3QxFebRSRre22xSOSlM7MF9B
|
||||
6MPeNgwCk3Z0NTr+IedGfyA+d6+iHTMGnv0hF4b4UkcXbC3HdeR3K4hf+msGD2oG
|
||||
7JF423T/d7t+g883y4CZm7p096apR8cCLIe2HKSwcYbKhft7LkAdm8kpnqkr5ER1
|
||||
anI7RDmucrx3HgrXeuCz9Uai6EMU6jNU1MAEBVeu4jz1rlO4e9zS2Ak68AwIz0zI
|
||||
tl5el3paHjlRYY6YTslM5qjGerJt19IyHvZxXXIzF7JdF7w1nSK9bjvninALJl49
|
||||
YZAPRIbyQ8P6DLqiDNBFAoIBAQDvQoow86vNg6zHdb8eBC10l2Y6M5DAKTWPE8RJ
|
||||
n0td1TLwEHzKvkR25v6yGKABbBO1+7ABACCqA8rkcB7M5jugak/kR9vuDrFPAsqf
|
||||
lgckf1Up7ekDheTH8X1VSDiRZPv07UElO0M3aFeMVR/xi9Wae8C3WZo9dT2wKnM0
|
||||
d0Acr4Kt4SYm1Dw7kuh+Y1L/vvWuryPm1btxhfKO6JN5v2W8DTrqVkxuxYEM1VnR
|
||||
69LfauLVico2q8EGXmQTth/Iok5wj1qI6kmrlgQR+eSY1qgNk1qzwjJVsbSmAOL8
|
||||
6Y9Ksct53bEN6DIdYRE/SrEVCz/FY1Pry2DNTjdiwImaSOZ3AoIBAQDH1KRkqsET
|
||||
YUnPJxp9pHWlynicEVE/Y7FFhhtpUKzhY1nZ+NsNy91FrZiyx5Os7pSxhLNID8g5
|
||||
xKCOfYd7qdvZCg/5bMXhtagQ3gwa/wyuyamc29dKkCpHDz/GkoEkgVe6eYu1GNdR
|
||||
iNpY5ye5T9fBE1s3odbDcnRVeHAP7vqz5z17JKrlqZVhbLYlR4qGHmAogq7vWlyd
|
||||
IR5qLoXMgyqq5OHl1GaaiqfViBpJeoEWYze0cARUWOcrJRblJYS03WHMuLDG5RZd
|
||||
5nmf2xwEcMgW5AX7+GB8CdXRVZy6OZcGn7TU9+xnBJA2LbzxJlHBXjWEd8Uma2Al
|
||||
+ohlDbGrd8g3AoIBAHsWzGlqstREDbt/xBb5Jzl4OktvA+UYTkmRbcZCgU+Aw3fl
|
||||
w426XRaeuCF/sbGJnIpfNakOG7/bu6HSXMYlHD/m8bsLjQXn4Sg4021OjdYk+/da
|
||||
Qiph09VZU5VwVknWnhjfhkhVOLtknsW/dXOa8QVM7VRmcId1rYrYC/TN9NnNIXm6
|
||||
/xmyzloHtjxvdN/Fqjd4OwwioRBCTQtgc56K7RfV5p1wUFocmcu0Z0UsAYyXPKOH
|
||||
A9Ukf2V7YhkR9UAO4DPgTD9r6QKxZt6opQZMSKDTUjJwkdysU7ejdSOQNPvEhF3p
|
||||
w5DYCBA9Q9Y/4uJkqyYtd5szQlXdC3lufFw3bPkCggEBAKPA3GpmB0xjWEG6UJoP
|
||||
UB1pWwbBpivk/Rr097eI1fLpIHNf29plalE0HcK7i4eWByGllekCjdjRCaVattCe
|
||||
9DraZRbHjS0WWMBhxdfFk9YUCbsx6C4BD7QlieSmn8+TcpmsCtF/psr4870Qx9uy
|
||||
0yI0Q3bGV6DYRP7ZcDOOacFNSHOGK8mB+5jXpjfMdXbMo43u8X3RNb3JqwvmTdy2
|
||||
zBs47ukQ8nfIEhsIqkn2apw2+CoT9WhNZjpT7XwgD6zLEd7apnqGtpqCSL63pjD5
|
||||
Xu5rM4A1HJPo11/w4Ts2AE38SAqRlBcjhS3wszmGZk6obgC8yUFfkm3s7SKqYyMZ
|
||||
SGcCggEBAO0IDB/h1meZ2y+6bSsCVaDSxdRl0JF0CDUYVTANQsJ+q7u7CpF9xOo8
|
||||
YNrSy8eM0K6RMY/3WbTm+4z9tOldxEV2dn+29oVeMKkgpJYo0k2Au3wTMI2xMyyl
|
||||
HZ+ZttsqSZsj2CPx83LMaPwKdzVjwA7alVx4P+AkQKn7jGJgidj5xyw0G3gnzdfT
|
||||
nGzuitQFlcrcPyrVHAAmRhIw+B5CsvMFlM8PAvojN7burGswjWGeZjkgqoLvKlgq
|
||||
jRMGzLTzF9Pay7P/D/pWQwPVGiseJq+QVIA+iILpy9Zb9T6DnBFaPFGOKAduzVU9
|
||||
lTLiho2DATppaxNUQKh/5k70hzbipDg=
|
||||
-----END PRIVATE KEY-----
|
@ -0,0 +1,26 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIEWjCCAkKgAwIBAgIURBZvq442tp+/K9TZII5Vy/LzVx0wDQYJKoZIhvcNAQEL
|
||||
BQAwOzEZMBcGA1UECgwQU3ByaW5nIEJvb3QgVGVzdDEeMBwGA1UEAwwVQ2VydGlm
|
||||
aWNhdGUgQXV0aG9yaXR5MB4XDTI0MDUwMTE2NTMyNVoXDTM0MDQyOTE2NTMyNVow
|
||||
LzEZMBcGA1UECgwQU3ByaW5nIEJvb3QgVGVzdDESMBAGA1UEAwwJbG9jYWxob3N0
|
||||
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvGb7tu0odSuOjeY1lHlh
|
||||
sRR4PayAvlryjfrrp49hjoVTiL3d/Jo6Po5HlqwJcYuclm0EWQR5Vur/zYJpfUE7
|
||||
b8+E9Qwe50+YzfQ2tVFEdq/VfqemrYRGee+pMelOCI90enOKCxfpo6EHbz+WnUP0
|
||||
mnD8OAF9QpolSdWAMOGJoPdWX65KQvyMXvQbj9VIHmsx7NCaIOYxjHXB/dI2FmXV
|
||||
+m4VT6mb8he9dXmgK/ozMq6XIPOAXe0n3dlfMTSEddeNeVwnBpr/n5e0cpwGFhdf
|
||||
NNu5CI4ecipBhXljJi/4/47M/6hd69HwE05C4zyH4ZDZ2JTfaSKOLV+jYdBUqJP5
|
||||
dwIDAQABo2IwYDALBgNVHQ8EBAMCBaAwEQYJYIZIAYb4QgEBBAQDAgeAMB0GA1Ud
|
||||
DgQWBBRWiWOo9cm2IF/ZlhWLVjifLzYa/DAfBgNVHSMEGDAWgBRVMLDVqPECWaH6
|
||||
GruL9E52VcTrPjANBgkqhkiG9w0BAQsFAAOCAgEAA5Wphtu2nBhY+QNOBOwXq4zF
|
||||
N5qt2IYTLfR7xqpKhhXx9VkIjdPWpcsGuCuMmfPVNvQWE6iK0/jMMqToTj4H6K7e
|
||||
MN74j0GwwcknT1P42tUzEpg8LKR8VMdhWhyqdniCDNWWuaz1iVSoF0S2i4jFSzH5
|
||||
1q3KMKMZ4niK5aJI0fAGa4fCjyuun1Mfg/qGBGwLnqDkIXjeAopZf4Jb64TtzjAs
|
||||
j9NT6mYbe3E0tw3fHT9ihYdbZDZgSjeCsuq9OiRMVb0DWWmRoLmmOrlN8IJlHV/3
|
||||
WyI/ta4Cw5EZ0oaOg0lIyOxXyvElth1xIvh+kdqZSBsU0gNBri6ZIzYbbTh2KTTO
|
||||
BJHQt9L5naWG27pDrIxBicWXS/MIYonktm3YgCLfuW3kWcVk8bIlNhfcoAYBBgfM
|
||||
IEYSYEq+bH2IQ+YoWQz3AxjJ8gEuuSUP6R6mYY65FfpjkKgcpGBvw4EIAmqKDtPS
|
||||
hlLY/F0XVj9KZzrMyH4/vonu+DAb/P7Zmt2fyk/dQO6bAc3ltRmJbJm4VJ2v/T8I
|
||||
LVu2FtcUYgtLNtkWUPfdb3GSUUgkKlUpWSty31TKSUszJjW1oRykQhEko6o5U3S8
|
||||
ptQzXdApsb1lGOqewkubE25tIu2RLiNkKcjFOjJ/lu0vP9k76wWwRVnFLFvfo4lW
|
||||
pgywiOifs5JbcCt0ZQ0=
|
||||
-----END CERTIFICATE-----
|
@ -0,0 +1,28 @@
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC8Zvu27Sh1K46N
|
||||
5jWUeWGxFHg9rIC+WvKN+uunj2GOhVOIvd38mjo+jkeWrAlxi5yWbQRZBHlW6v/N
|
||||
gml9QTtvz4T1DB7nT5jN9Da1UUR2r9V+p6athEZ576kx6U4Ij3R6c4oLF+mjoQdv
|
||||
P5adQ/SacPw4AX1CmiVJ1YAw4Ymg91ZfrkpC/Ixe9BuP1UgeazHs0Jog5jGMdcH9
|
||||
0jYWZdX6bhVPqZvyF711eaAr+jMyrpcg84Bd7Sfd2V8xNIR11415XCcGmv+fl7Ry
|
||||
nAYWF18027kIjh5yKkGFeWMmL/j/jsz/qF3r0fATTkLjPIfhkNnYlN9pIo4tX6Nh
|
||||
0FSok/l3AgMBAAECggEABXnBe3MwXAMQENzNypOiXK4VE3XMYkePfdsSK163byOD
|
||||
w3ZeTgQNfU4g8LJK8/homzO0SQIJAdz2+ZFbpsp4A2W2zJ+1jvN5RuX/8/UcVhmk
|
||||
tb1IL/LWCvx5/aoYBWkgIA70UfQJa2jDbdM0v5j/Gu9yE7GI14jh6DFC3xGMGV3b
|
||||
fOwManxf7sDibCI1nGjnFYNGxninRr+tpb+a1KNbVzhett68LrgPmtph6B3HCPAJ
|
||||
zBigk1Phgb8WHozTXxnLyw9/RdKJ0Ro4PFmtQv0EvCSlytptnF+0nXkqr3f851XS
|
||||
bUWwYFchIFWPMhPfD5B3niNWCV42/sU/bQlk+BMQAQKBgQD6NvMq8EdYy2Y7fXT5
|
||||
FgB4s+7EkLgI2d5LUaCXCFgc6iZtCTQKUXj1rIWeRfGrFVCCe8qV+XIMKt/G5eEi
|
||||
tn5ifHhktA2A8GK1scj026qHP3bVn0hMaUnkCF1UpDRKPiEO5G/apPtav8PbCNaX
|
||||
GAimLGw+WZNZuv7+T33bEBeUdwKBgQDAwiidayLXkRkz2deefdDKcXQsB7RHFGGy
|
||||
vfZPBCGqizxml+6ojJkkDsVUKL1IXFfyK9KpQAI6tezn4oktgu4jAQqkYY7QZobs
|
||||
RpQx1dR+KxEm7ISDBTq/B1Q9cFKUKVvQQy8N2pnIbCdzb6MTOKLmJqFGTjr+5T8q
|
||||
F32B5vkDAQKBgDCKfH42AwFc5EZiPlEcTZcdARMtKCa/bXqbKVZjjgR+AFpi0K+3
|
||||
womWoI1l8E5KYkYOEe0qaU+m+aaybgy37qjYkNqoe34qJFwvU1b9ToXScBFdRz9b
|
||||
pbQRU1naSTKl/u/OrUxzeTfPwAU8H7VMOlFSiOVHp2he+J0JetcGtixdAoGBAIJQ
|
||||
QMj7rxhxHcqyEVUy1b6nKNTDeJs9Kjd+uU/+CQyVCQaK3GvScY2w9rLIv/51f3dX
|
||||
LRoDDf7HExxJSFgeVgQQJjOvSK+XQMvngzSVzQxm7TeVWpiBJpAS0l6e2xUTSODp
|
||||
KpyBFsoqZBlkdaj+9xIFN66iILxGG4fHTbBOiDYBAoGBAOZMKjM5N/hGcCmik/6t
|
||||
p/zBA2pN9O6zwPndITTsdyVWSlVqCZhXlRX47CerAN+/WVCidlh7Vp5Tuy75Wa77
|
||||
v16IDLO01txgWNobcLaM4VgFsyLi5JuxK73S18Vb1cKWdHFRF0LH3cUIq20fjpv6
|
||||
Odl4vjNOncXMZCLPHQ+bKWaf
|
||||
-----END PRIVATE KEY-----
|
@ -0,0 +1,26 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIEWjCCAkKgAwIBAgIURBZvq442tp+/K9TZII5Vy/LzVxwwDQYJKoZIhvcNAQEL
|
||||
BQAwOzEZMBcGA1UECgwQU3ByaW5nIEJvb3QgVGVzdDEeMBwGA1UEAwwVQ2VydGlm
|
||||
aWNhdGUgQXV0aG9yaXR5MB4XDTI0MDUwMTE2NTMyNVoXDTM0MDQyOTE2NTMyNVow
|
||||
LzEZMBcGA1UECgwQU3ByaW5nIEJvb3QgVGVzdDESMBAGA1UEAwwJbG9jYWxob3N0
|
||||
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsllxsSQzTTJlNHMfXC2b
|
||||
CIXCPsfCgCBl7FbPz828jwJk+EYcXh0+WTFGks0WxSwb8NQza5UtyCUDEueZj9fV
|
||||
j5mWBY97WCu01Sl/3xClHmYisXfyyv27GKec7PaSOurCm2JDkyHRNumiJROa4jte
|
||||
N0GOHzw7FYsM3779TuNw14/gtW+eBrGnvgrpU7fbUvx42Di6ftGYQUwIi+3uIaqT
|
||||
//i7ktDMaAQJtkL6haTzZ5JN2qKO5a34/WRz/ApvPw3lpDV8c4qoTk3C0Bg9MP+a
|
||||
DnZtjtLBSN9CJWwr+n11QaMgHTotEKsOahGdi3J2zYxCvJP0LT+hjN2O9aRzSMIs
|
||||
MwIDAQABo2IwYDALBgNVHQ8EBAMCBaAwEQYJYIZIAYb4QgEBBAQDAgZAMB0GA1Ud
|
||||
DgQWBBS9XQHGwJZhG0olAGM1UMNuwZ65DzAfBgNVHSMEGDAWgBRVMLDVqPECWaH6
|
||||
GruL9E52VcTrPjANBgkqhkiG9w0BAQsFAAOCAgEAhBcqm5UQahn8iFMETXvfLMR6
|
||||
OOPijsHQ5lVfhig08s46a9O5eaJ9EYSYyiDnxYvZ4gYVH03f/kPwNLamvGR5KIBQ
|
||||
R0DltkPPX4a11/vjwlSq1cXAt9r59nY+sNcVXWgIWH7zNodL8lyTpYhqvB2wEQkx
|
||||
t2/JKZ8A0sGjed4S6I5HofYd7bnBxQZgfZShQ2SdDbzbcyg4SCEb8ghwnsH0KNZo
|
||||
jJF+20RpK2VMViE6lylLTEMd/PyAdST/NPoqVxyva3QjTrKt+tkkFTsmNVMXcmYC
|
||||
f1xo1/YFp73FFE63VYFI+Yw+Ajau8sYSo4+YvgFCy+Efhf3h3GFDtaiNod56uX9G
|
||||
9M/cu8XsFzFP2e/0YWY3XL+v7ESOdc3g7yS4FQZ7Z6YvfAed9hCB25cDECvZXqJG
|
||||
HSYDR38NHyAPROuCwlEwDyVmWRl9bpwZt+hr9kaTQScIDx+rV/EF3o0GKIwtR7AK
|
||||
jaPAta0f4/Uu+EuWAcccSRUMtfx5/Jse/6iliBvy7JXmA+Y0PrT7K4uHO7iktdI+
|
||||
x8WbfZKfnLVuqw5fneTjC1n48Ltjis/f8DgO7BuWTmLdZXddjqqxzBSukFTBn4Hg
|
||||
/oSg3XiMywOAVrRCNJehcdTG0u/BqZsrRjcYAJaf5qG/0tMLNsuF9Y53XQQAeezE
|
||||
etL+7y0mkeQhVF+Kmy4=
|
||||
-----END CERTIFICATE-----
|
@ -0,0 +1,28 @@
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
MIIEugIBADANBgkqhkiG9w0BAQEFAASCBKQwggSgAgEAAoIBAQCyWXGxJDNNMmU0
|
||||
cx9cLZsIhcI+x8KAIGXsVs/PzbyPAmT4RhxeHT5ZMUaSzRbFLBvw1DNrlS3IJQMS
|
||||
55mP19WPmZYFj3tYK7TVKX/fEKUeZiKxd/LK/bsYp5zs9pI66sKbYkOTIdE26aIl
|
||||
E5riO143QY4fPDsViwzfvv1O43DXj+C1b54Gsae+CulTt9tS/HjYOLp+0ZhBTAiL
|
||||
7e4hqpP/+LuS0MxoBAm2QvqFpPNnkk3aoo7lrfj9ZHP8Cm8/DeWkNXxziqhOTcLQ
|
||||
GD0w/5oOdm2O0sFI30IlbCv6fXVBoyAdOi0Qqw5qEZ2LcnbNjEK8k/QtP6GM3Y71
|
||||
pHNIwiwzAgMBAAECgf9REZuCvy2Bi8SoTnjqQuHG5FuA6cPuisuFZr1k88IO+zJQ
|
||||
uY3WKNs29BV+LcxnoK29W8jQnjqPHXcMfrF5dVWmkrrJdu8JLaGWVHF+uBq8nRb0
|
||||
2LvREh5XhZTGzIESNdc/7GIxdouag/8FlzCUYQGuT3v9+wUCiim+4CuIuPvv7ncD
|
||||
8vANe3Ua5G0mHjVshOiMNpegg45zYlzYpMtUFPs+asLilW6A7UlgC+pLZ1cHUUlU
|
||||
ZB7KOGT9JdrZpilTidl6LLvDDQK30TSWz8A26SuEAE71DR2VEjLVpjTNS76vlx+c
|
||||
CrYr/WwpMb0xul+e/uHiNgo+51FiTiJ/IfuGeskCgYEA804CXQM6i5m4/Upps2yG
|
||||
aTae5xBaYUquZREp5Zb054U6lUAHI41iTMTIwTTvWn5ogNojgi+YjljkzRj2RQ5k
|
||||
NccBkjBBwwUNVWpBoGeZ73KAdejNB4C4ucGc2kkqEDo4MU5x3IE4JK1Yi1jl9mKb
|
||||
IR6m3pqb2PCQHjO8sqKNHYkCgYEAu6fH/qUd/XGmCZJWY5K6jg3dISXH16MTO5M+
|
||||
jetprkGMMybWKZQa1GedXurPexE48oRlRhkjdQkW6Wcj1Qh6OKp6N2Zx8sY4dLeQ
|
||||
yVChnMPFE2LK+UlRCKJUZi+rzX415ML6pZg+yW7O2cHpMKv7PlXISw2YDqtboCAi
|
||||
Y+doqNsCgYBE1yqmBJbZDuqfiCF2KduyA0lcmWzpIEdNw1h2ZIrwwup7dj1O2t8Y
|
||||
V4lx2TdsBF4vLwli+XKRvCcovMpZaaQC70bLhSnmMxS9uS3OY+HTNTORqQfx+oLJ
|
||||
1DU8Mf1b0A08LjTbLhijkASAkOuoFehMq66NR3OXIyGz2fGnHYUN+QKBgCC47SL2
|
||||
X/hl7PIWVoIef/FtcXXqRKLRiPUGhA3zUwZT38K7rvSpItSPDN4UTAHFywxfEdnb
|
||||
YFd0Mk6Y8aKgS8+9ynoGnzAaaJXRvKmeKdBQQvlSbNpzcnHy/IylG2xF6dfuOA7Q
|
||||
MYKmk+Nc8PDPzIveIYMU58MHFn8hm12YaKOpAoGAV1CE8hFkEK9sbRGoKNJkx9nm
|
||||
CZTv7PybaG/RN4ZrBSwVmnER0FEagA/Tzrlp1pi3sC8ZsC9onSOf6Btq8ZE0zbO1
|
||||
vsAm3gTBXcrCJxzw0Wjt8pzEbk3yELm4WE6VDEx4da2jWocdspslpIwdjHnPwsbH
|
||||
r5O3ZAgigZs/ZtKW/U4=
|
||||
-----END PRIVATE KEY-----
|
@ -76,6 +76,11 @@ public class MailProperties {
|
||||
*/
|
||||
private String jndiName;
|
||||
|
||||
/**
|
||||
* SSL configuration.
|
||||
*/
|
||||
private final Ssl ssl = new Ssl();
|
||||
|
||||
public String getHost() {
|
||||
return this.host;
|
||||
}
|
||||
@ -136,4 +141,45 @@ public class MailProperties {
|
||||
return this.jndiName;
|
||||
}
|
||||
|
||||
public Ssl getSsl() {
|
||||
return this.ssl;
|
||||
}
|
||||
|
||||
public static class Ssl {
|
||||
|
||||
/**
|
||||
* Whether to enable SSL support. If enabled, {@code mail.<protocol>.ssl.enable}
|
||||
* property is set to {@code true}.
|
||||
*/
|
||||
private boolean enabled = false;
|
||||
|
||||
/**
|
||||
* SSL bundle name. If not null, {@code mail.<protocol>.ssl.socketFactory}
|
||||
* property is set to a {@code SSLSocketFactory} obtained from the corresponding
|
||||
* SSL bundle.
|
||||
* <p>
|
||||
* Note that the {@code STARTTLS} command can use the corresponding
|
||||
* {@code SSLSocketFactory}, even if {@code mail.<protocol>.ssl.enable} property
|
||||
* is not set.
|
||||
*/
|
||||
private String bundle;
|
||||
|
||||
public boolean isEnabled() {
|
||||
return this.enabled;
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
public String getBundle() {
|
||||
return this.bundle;
|
||||
}
|
||||
|
||||
public void setBundle(String bundle) {
|
||||
this.bundle = bundle;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -19,13 +19,18 @@ package org.springframework.boot.autoconfigure.mail;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
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.SslBundles;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.mail.MailSender;
|
||||
import org.springframework.mail.javamail.JavaMailSender;
|
||||
import org.springframework.mail.javamail.JavaMailSenderImpl;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Auto-configure a {@link MailSender} based on properties configuration.
|
||||
@ -40,13 +45,13 @@ class MailSenderPropertiesConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(JavaMailSender.class)
|
||||
JavaMailSenderImpl mailSender(MailProperties properties) {
|
||||
JavaMailSenderImpl mailSender(MailProperties properties, ObjectProvider<SslBundles> sslBundles) {
|
||||
JavaMailSenderImpl sender = new JavaMailSenderImpl();
|
||||
applyProperties(properties, sender);
|
||||
applyProperties(properties, sender, sslBundles.getIfAvailable());
|
||||
return sender;
|
||||
}
|
||||
|
||||
private void applyProperties(MailProperties properties, JavaMailSenderImpl sender) {
|
||||
private void applyProperties(MailProperties properties, JavaMailSenderImpl sender, SslBundles sslBundles) {
|
||||
sender.setHost(properties.getHost());
|
||||
if (properties.getPort() != null) {
|
||||
sender.setPort(properties.getPort());
|
||||
@ -57,8 +62,22 @@ class MailSenderPropertiesConfiguration {
|
||||
if (properties.getDefaultEncoding() != null) {
|
||||
sender.setDefaultEncoding(properties.getDefaultEncoding().name());
|
||||
}
|
||||
if (!properties.getProperties().isEmpty()) {
|
||||
sender.setJavaMailProperties(asProperties(properties.getProperties()));
|
||||
Properties javaMailProperties = asProperties(properties.getProperties());
|
||||
String protocol = properties.getProtocol();
|
||||
if (!StringUtils.hasLength(protocol)) {
|
||||
protocol = "smtp";
|
||||
}
|
||||
Ssl ssl = properties.getSsl();
|
||||
if (ssl.isEnabled()) {
|
||||
javaMailProperties.setProperty("mail." + protocol + ".ssl.enable", "true");
|
||||
}
|
||||
if (ssl.getBundle() != null) {
|
||||
SslBundle sslBundle = sslBundles.getBundle(ssl.getBundle());
|
||||
javaMailProperties.put("mail." + protocol + ".ssl.socketFactory",
|
||||
sslBundle.createSslContext().getSocketFactory());
|
||||
}
|
||||
if (!javaMailProperties.isEmpty()) {
|
||||
sender.setJavaMailProperties(javaMailProperties);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -19,6 +19,7 @@ package org.springframework.boot.autoconfigure.mail;
|
||||
import java.util.Properties;
|
||||
|
||||
import javax.naming.Context;
|
||||
import javax.net.ssl.SSLSocketFactory;
|
||||
|
||||
import jakarta.mail.Session;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
@ -29,6 +30,7 @@ import org.springframework.beans.factory.BeanCreationException;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.autoconfigure.jndi.JndiPropertiesHidingClassLoader;
|
||||
import org.springframework.boot.autoconfigure.jndi.TestableInitialContextFactory;
|
||||
import org.springframework.boot.autoconfigure.ssl.SslAutoConfiguration;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
@ -49,8 +51,9 @@ import static org.mockito.Mockito.never;
|
||||
*/
|
||||
class MailSenderAutoConfigurationTests {
|
||||
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner().withConfiguration(
|
||||
AutoConfigurations.of(MailSenderAutoConfiguration.class, MailSenderValidatorAutoConfiguration.class));
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(MailSenderAutoConfiguration.class,
|
||||
MailSenderValidatorAutoConfiguration.class, SslAutoConfiguration.class));
|
||||
|
||||
private ClassLoader threadContextClassLoader;
|
||||
|
||||
@ -240,6 +243,61 @@ class MailSenderAutoConfigurationTests {
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void smtpSslEnabled() {
|
||||
this.contextRunner.withPropertyValues("spring.mail.host:localhost", "spring.mail.ssl.enabled:true")
|
||||
.run((context) -> {
|
||||
assertThat(context).hasSingleBean(JavaMailSenderImpl.class);
|
||||
JavaMailSenderImpl mailSender = context.getBean(JavaMailSenderImpl.class);
|
||||
assertThat(mailSender.getJavaMailProperties()).containsEntry("mail.smtp.ssl.enable", "true");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void smtpSslBundle() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("spring.mail.host:localhost", "spring.mail.ssl.bundle:test-bundle",
|
||||
"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");
|
||||
Object property = mailSender.getJavaMailProperties().get("mail.smtp.ssl.socketFactory");
|
||||
assertThat(property).isInstanceOf(SSLSocketFactory.class);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void smtpsSslEnabled() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("spring.mail.host:localhost", "spring.mail.protocol:smtps",
|
||||
"spring.mail.ssl.enabled:true")
|
||||
.run((context) -> {
|
||||
assertThat(context).hasSingleBean(JavaMailSenderImpl.class);
|
||||
JavaMailSenderImpl mailSender = context.getBean(JavaMailSenderImpl.class);
|
||||
assertThat(mailSender.getJavaMailProperties()).containsEntry("mail.smtps.ssl.enable", "true");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void smtpsSslBundle() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("spring.mail.host:localhost", "spring.mail.protocol:smtps",
|
||||
"spring.mail.ssl.bundle:test-bundle",
|
||||
"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.smtps.ssl.enable");
|
||||
Object property = mailSender.getJavaMailProperties().get("mail.smtps.ssl.socketFactory");
|
||||
assertThat(property).isInstanceOf(SSLSocketFactory.class);
|
||||
});
|
||||
}
|
||||
|
||||
private Session configureJndiSession(String name) {
|
||||
Properties properties = new Properties();
|
||||
Session session = Session.getDefaultInstance(properties);
|
||||
|
@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright 2012-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.testsupport.container;
|
||||
|
||||
import org.testcontainers.containers.GenericContainer;
|
||||
import org.testcontainers.utility.DockerImageName;
|
||||
import org.testcontainers.utility.MountableFile;
|
||||
|
||||
/**
|
||||
* A {@link GenericContainer} for MailDev.
|
||||
*
|
||||
* @author Rui Figueira
|
||||
*/
|
||||
public class MailpitContainer extends GenericContainer<MailpitContainer> {
|
||||
|
||||
private static final int DEFAULT_SMTP_PORT = 1025;
|
||||
|
||||
private static final int DEFAULT_POP3_PORT = 1110;
|
||||
|
||||
public MailpitContainer(DockerImageName dockerImageName) {
|
||||
super(dockerImageName);
|
||||
addExposedPorts(DEFAULT_SMTP_PORT, DEFAULT_POP3_PORT);
|
||||
}
|
||||
|
||||
public int getSmtpPort() {
|
||||
return getMappedPort(DEFAULT_SMTP_PORT);
|
||||
}
|
||||
|
||||
public int getPop3Port() {
|
||||
return getMappedPort(DEFAULT_POP3_PORT);
|
||||
}
|
||||
|
||||
public MailpitContainer withSmtpTlsCert(MountableFile cert) {
|
||||
this.withCopyFileToContainer(cert, "/tmp/ssl/public.crt");
|
||||
this.withEnv("MP_SMTP_TLS_CERT", "/tmp/ssl/public.crt");
|
||||
return this.self();
|
||||
}
|
||||
|
||||
public MailpitContainer withSmtpTlsKey(MountableFile key) {
|
||||
this.withCopyFileToContainer(key, "/tmp/ssl/private.key");
|
||||
this.withEnv("MP_SMTP_TLS_KEY", "/tmp/ssl/private.key");
|
||||
return this.self();
|
||||
}
|
||||
|
||||
public MailpitContainer withSmtpRequireTls(boolean requireTls) {
|
||||
if (requireTls) {
|
||||
this.withEnv("MP_SMTP_REQUIRE_TLS", "true");
|
||||
}
|
||||
return this.self();
|
||||
}
|
||||
|
||||
public MailpitContainer withSmtpRequireStarttls(boolean requireStarttls) {
|
||||
if (requireStarttls) {
|
||||
this.withEnv("MP_SMTP_REQUIRE_STARTTLS", "true");
|
||||
}
|
||||
return this.self();
|
||||
}
|
||||
|
||||
public MailpitContainer withPop3Auth(String... auths) {
|
||||
this.withEnv("MP_POP3_AUTH", String.join(" ", auths));
|
||||
return this.self();
|
||||
}
|
||||
|
||||
}
|
@ -110,6 +110,11 @@ public enum TestImage {
|
||||
*/
|
||||
OPEN_LDAP("osixia/openldap", "1.5.0", () -> OpenLdapContainer.class),
|
||||
|
||||
/**
|
||||
* A container image suitable for testing SMTP.
|
||||
*/
|
||||
MAILPIT("axllent/mailpit", "v1.19.0", () -> MailpitContainer.class),
|
||||
|
||||
/**
|
||||
* A container image suitable for testing MariaDB.
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user