Skip to content

Commit 1e005ca

Browse files
committed
Merge pull request #40037 from ruifigueira
* pr/40037: Polish "Add SslBundle support to MailSender" Add SslBundle support to MailSender Closes gh-40037
2 parents ee8a706 + cf2b08b commit 1e005ca

File tree

13 files changed

+626
-8
lines changed

13 files changed

+626
-8
lines changed

spring-boot-project/spring-boot-autoconfigure/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ dependencies {
2727
dockerTestImplementation("org.testcontainers:neo4j")
2828
dockerTestImplementation("org.testcontainers:pulsar")
2929
dockerTestImplementation("org.testcontainers:testcontainers")
30+
dockerTestImplementation("org.awaitility:awaitility")
3031

3132
optional("co.elastic.clients:elasticsearch-java") {
3233
exclude group: "commons-logging", module: "commons-logging"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,219 @@
1+
/*
2+
* Copyright 2012-2024 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.autoconfigure.mail;
18+
19+
import java.net.SocketTimeoutException;
20+
import java.security.cert.CertPathBuilderException;
21+
import java.time.Duration;
22+
import java.util.Arrays;
23+
24+
import javax.net.ssl.SSLException;
25+
26+
import jakarta.mail.Folder;
27+
import jakarta.mail.Message;
28+
import jakarta.mail.MessagingException;
29+
import jakarta.mail.Session;
30+
import jakarta.mail.Store;
31+
import org.awaitility.Awaitility;
32+
import org.junit.jupiter.api.Nested;
33+
import org.junit.jupiter.api.Test;
34+
import org.testcontainers.junit.jupiter.Container;
35+
import org.testcontainers.junit.jupiter.Testcontainers;
36+
import org.testcontainers.utility.MountableFile;
37+
38+
import org.springframework.boot.autoconfigure.AutoConfigurations;
39+
import org.springframework.boot.autoconfigure.ssl.SslAutoConfiguration;
40+
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
41+
import org.springframework.boot.testsupport.container.MailpitContainer;
42+
import org.springframework.boot.testsupport.container.TestImage;
43+
import org.springframework.mail.SimpleMailMessage;
44+
import org.springframework.mail.javamail.JavaMailSenderImpl;
45+
46+
import static org.assertj.core.api.Assertions.assertThat;
47+
import static org.assertj.core.api.Assertions.assertThatException;
48+
49+
/**
50+
* Integration tests for {@link MailSenderAutoConfiguration}.
51+
*
52+
* @author Rui Figueira
53+
*/
54+
@Testcontainers(disabledWithoutDocker = true)
55+
class MailSenderAutoConfigurationIntegrationTests {
56+
57+
private SimpleMailMessage createMessage(String subject) {
58+
SimpleMailMessage msg = new SimpleMailMessage();
59+
msg.setFrom("[email protected]");
60+
msg.setTo("[email protected]");
61+
msg.setSubject(subject);
62+
msg.setText("Subject: " + subject);
63+
return msg;
64+
}
65+
66+
private String getSubject(Message message) {
67+
try {
68+
return message.getSubject();
69+
}
70+
catch (MessagingException ex) {
71+
throw new RuntimeException("Failed to get message subject", ex);
72+
}
73+
}
74+
75+
private void assertMessagesContainSubject(Session session, String subject) throws MessagingException {
76+
try (Store store = session.getStore("pop3")) {
77+
String host = session.getProperty("mail.pop3.host");
78+
int port = Integer.parseInt(session.getProperty("mail.pop3.port"));
79+
store.connect(host, port, "user", "pass");
80+
try (Folder folder = store.getFolder("inbox")) {
81+
folder.open(Folder.READ_ONLY);
82+
Awaitility.await()
83+
.atMost(Duration.ofSeconds(5))
84+
.ignoreExceptions()
85+
.untilAsserted(() -> assertThat(Arrays.stream(folder.getMessages()).map(this::getSubject))
86+
.contains(subject));
87+
}
88+
}
89+
}
90+
91+
@Nested
92+
class ImplicitTlsTests {
93+
94+
@Container
95+
private static final MailpitContainer mailpit = TestImage.container(MailpitContainer.class)
96+
.withSmtpRequireTls(true)
97+
.withSmtpTlsCert(MountableFile
98+
.forClasspathResource("/org/springframework/boot/autoconfigure/mail/ssl/test-server.crt"))
99+
.withSmtpTlsKey(MountableFile
100+
.forClasspathResource("/org/springframework/boot/autoconfigure/mail/ssl/test-server.key"))
101+
.withPop3Auth("user:pass");
102+
103+
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
104+
.withConfiguration(AutoConfigurations.of(MailSenderAutoConfiguration.class, SslAutoConfiguration.class));
105+
106+
@Test
107+
void sendEmailWithSslEnabledAndCert() {
108+
this.contextRunner.withPropertyValues("spring.mail.host:" + mailpit.getHost(),
109+
"spring.mail.port:" + mailpit.getSmtpPort(), "spring.mail.ssl.enabled:true",
110+
"spring.mail.ssl.bundle:test-bundle",
111+
"spring.ssl.bundle.pem.test-bundle.truststore.certificate=classpath:org/springframework/boot/autoconfigure/mail/ssl/test-ca.crt",
112+
"spring.ssl.bundle.pem.test-bundle.keystore.certificate=classpath:org/springframework/boot/autoconfigure/mail/ssl/test-client.crt",
113+
"spring.ssl.bundle.pem.test-bundle.keystore.private-key=classpath:org/springframework/boot/autoconfigure/mail/ssl/test-client.key",
114+
"spring.mail.properties.mail.pop3.host:" + mailpit.getHost(),
115+
"spring.mail.properties.mail.pop3.port:" + mailpit.getPop3Port())
116+
.run((context) -> {
117+
JavaMailSenderImpl mailSender = context.getBean(JavaMailSenderImpl.class);
118+
mailSender.send(createMessage("Hello World!"));
119+
assertMessagesContainSubject(mailSender.getSession(), "Hello World!");
120+
});
121+
}
122+
123+
@Test
124+
void sendEmailWithSslEnabledWithoutCert() {
125+
this.contextRunner
126+
.withPropertyValues("spring.mail.host:" + mailpit.getHost(),
127+
"spring.mail.port:" + mailpit.getSmtpPort(), "spring.mail.ssl.enabled:true")
128+
.run((context) -> {
129+
JavaMailSenderImpl mailSender = context.getBean(JavaMailSenderImpl.class);
130+
assertThatException().isThrownBy(() -> mailSender.send(createMessage("Should fail")))
131+
.withRootCauseInstanceOf(CertPathBuilderException.class);
132+
});
133+
}
134+
135+
@Test
136+
void sendEmailWithoutSslWithCert() {
137+
this.contextRunner.withPropertyValues("spring.mail.host:" + mailpit.getHost(),
138+
"spring.mail.port:" + mailpit.getSmtpPort(), "spring.mail.properties.mail.smtp.timeout:1000",
139+
"spring.mail.ssl.bundle:test-bundle",
140+
"spring.ssl.bundle.pem.test-bundle.truststore.certificate=classpath:org/springframework/boot/autoconfigure/mail/ssl/test-ca.crt",
141+
"spring.ssl.bundle.pem.test-bundle.keystore.certificate=classpath:org/springframework/boot/autoconfigure/mail/ssl/test-client.crt",
142+
"spring.ssl.bundle.pem.test-bundle.keystore.private-key=classpath:org/springframework/boot/autoconfigure/mail/ssl/test-client.key")
143+
.run((context) -> {
144+
JavaMailSenderImpl mailSender = context.getBean(JavaMailSenderImpl.class);
145+
assertThatException().isThrownBy(() -> mailSender.send(createMessage("Should fail")))
146+
.withRootCauseInstanceOf(SocketTimeoutException.class);
147+
});
148+
}
149+
150+
}
151+
152+
@Nested
153+
class StarttlsTests {
154+
155+
@Container
156+
private static final MailpitContainer mailpit = TestImage.container(MailpitContainer.class)
157+
.withSmtpRequireStarttls(true)
158+
.withSmtpTlsCert(MountableFile
159+
.forClasspathResource("/org/springframework/boot/autoconfigure/mail/ssl/test-server.crt"))
160+
.withSmtpTlsKey(MountableFile
161+
.forClasspathResource("/org/springframework/boot/autoconfigure/mail/ssl/test-server.key"))
162+
.withPop3Auth("user:pass");
163+
164+
final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
165+
.withConfiguration(AutoConfigurations.of(MailSenderAutoConfiguration.class, SslAutoConfiguration.class));
166+
167+
@Test
168+
void sendEmailWithStarttlsAndCertAndSslDisabled() {
169+
this.contextRunner.withPropertyValues("spring.mail.host:" + mailpit.getHost(),
170+
"spring.mail.port:" + mailpit.getSmtpPort(),
171+
"spring.mail.properties.mail.smtp.starttls.enable:true",
172+
"spring.mail.properties.mail.smtp.starttls.required:true", "spring.mail.ssl.bundle:test-bundle",
173+
"spring.ssl.bundle.pem.test-bundle.truststore.certificate=classpath:org/springframework/boot/autoconfigure/mail/ssl/test-ca.crt",
174+
"spring.ssl.bundle.pem.test-bundle.keystore.certificate=classpath:org/springframework/boot/autoconfigure/mail/ssl/test-client.crt",
175+
"spring.ssl.bundle.pem.test-bundle.keystore.private-key=classpath:org/springframework/boot/autoconfigure/mail/ssl/test-client.key",
176+
"spring.mail.properties.mail.pop3.host:" + mailpit.getHost(),
177+
"spring.mail.properties.mail.pop3.port:" + mailpit.getPop3Port())
178+
.run((context) -> {
179+
JavaMailSenderImpl mailSender = context.getBean(JavaMailSenderImpl.class);
180+
mailSender.send(createMessage("Sent with STARTTLS"));
181+
assertMessagesContainSubject(mailSender.getSession(), "Sent with STARTTLS");
182+
});
183+
}
184+
185+
@Test
186+
void sendEmailWithStarttlsAndCertAndSslEnabled() {
187+
this.contextRunner.withPropertyValues("spring.mail.host:" + mailpit.getHost(),
188+
"spring.mail.port:" + mailpit.getSmtpPort(), "spring.mail.ssl.enabled:true",
189+
"spring.mail.properties.mail.smtp.starttls.enable:true",
190+
"spring.mail.properties.mail.smtp.starttls.required:true", "spring.mail.ssl.bundle:test-bundle",
191+
"spring.ssl.bundle.pem.test-bundle.truststore.certificate=classpath:org/springframework/boot/autoconfigure/mail/ssl/test-ca.crt",
192+
"spring.ssl.bundle.pem.test-bundle.keystore.certificate=classpath:org/springframework/boot/autoconfigure/mail/ssl/test-client.crt",
193+
"spring.ssl.bundle.pem.test-bundle.keystore.private-key=classpath:org/springframework/boot/autoconfigure/mail/ssl/test-client.key",
194+
"spring.mail.properties.mail.pop3.host:" + mailpit.getHost(),
195+
"spring.mail.properties.mail.pop3.port:" + mailpit.getPop3Port())
196+
.run((context) -> {
197+
JavaMailSenderImpl mailSender = context.getBean(JavaMailSenderImpl.class);
198+
assertThatException().isThrownBy(() -> mailSender.send(createMessage("Should fail")))
199+
.withRootCauseInstanceOf(SSLException.class);
200+
});
201+
}
202+
203+
@Test
204+
void sendEmailWithStarttlsWithoutCert() {
205+
this.contextRunner
206+
.withPropertyValues("spring.mail.host:" + mailpit.getHost(),
207+
"spring.mail.port:" + mailpit.getSmtpPort(),
208+
"spring.mail.properties.mail.smtp.starttls.enable:true",
209+
"spring.mail.properties.mail.smtp.starttls.required:true")
210+
.run((context) -> {
211+
JavaMailSenderImpl mailSender = context.getBean(JavaMailSenderImpl.class);
212+
assertThatException().isThrownBy(() -> mailSender.send(createMessage("Should fail")))
213+
.withRootCauseInstanceOf(CertPathBuilderException.class);
214+
});
215+
}
216+
217+
}
218+
219+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
-----BEGIN CERTIFICATE-----
2+
MIIFhjCCA26gAwIBAgIUfIkk29IT9OpbgfjL8oRIPSLjUcAwDQYJKoZIhvcNAQEL
3+
BQAwOzEZMBcGA1UECgwQU3ByaW5nIEJvb3QgVGVzdDEeMBwGA1UEAwwVQ2VydGlm
4+
aWNhdGUgQXV0aG9yaXR5MB4XDTI0MDUwMTE2NTMyNVoXDTM0MDQyOTE2NTMyNVow
5+
OzEZMBcGA1UECgwQU3ByaW5nIEJvb3QgVGVzdDEeMBwGA1UEAwwVQ2VydGlmaWNh
6+
dGUgQXV0aG9yaXR5MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAusN2
7+
KzQQUUxZSiI3ZZuZohFwq2KXSUNPdJ6rgD3/YKNTDSZXKZPO53kYPP0DXf0sm3CH
8+
cyWSWVabyimZYuPWena1MElSL4ZpJ9WwkZoOQ3bPFK1utz6kMOwrgAUcky8H/rIK
9+
j2JEBhkSHUIGr57NjUEwG1ygaSerM8RzWw1PtMq+C8LOu3v94qzE3NDg1QRpyvV9
10+
OmsLsjISd0ZmAJNi9vmiEH923KnPyiqnQmWKpYicdgQmX1GXylS22jZqAwaOkYGj
11+
X8UdeyvrohkZkM0hn9uaSufQGEW4yKACn3PkjJtzi8drBIyjIi9YcAzBxZB9oVKq
12+
XZMlltgO2fDMmIJi0Ngt0Ci7fCoEMqSocKyDKML6YLr9UWtx4bfsrk+rVO9Q/D/v
13+
8RKgstv7dCf2KWRX3ZJEC0IBHS5gLNq0qqqVcGx3LcSyhdiKJOtSwAnNkHMh+jSQ
14+
xLSlBjcSqTPiGTRK/Rddl+xnU/mBgk7ZBGNrUFaD5McMFjddS7Ih82aHnpQ1gekW
15+
nUGv+Tm/G68h2BvZ5U2q+RfeOCgRW9i/AYW2jgT7IFnfjyUXgBQveauMAchomqFE
16+
VLe95ZgViF6vmH34EKo3w9L5TQiwk/r53YlM7TSOTyDqx66t4zGYDsVMicpKmzi4
17+
2Rp8EpErARRyREUIKSvWs9O9+uT3+7arNLgHe5ECAwEAAaOBgTB/MB0GA1UdDgQW
18+
BBRVMLDVqPECWaH6GruL9E52VcTrPjAfBgNVHSMEGDAWgBRVMLDVqPECWaH6GruL
19+
9E52VcTrPjAPBgNVHRMBAf8EBTADAQH/MCwGA1UdEQQlMCOCC2V4YW1wbGUuY29t
20+
gglsb2NhbGhvc3SCCTEyNy4wLjAuMTANBgkqhkiG9w0BAQsFAAOCAgEAeSpjCL3j
21+
2GIFBNKr/5amLOYa0kZ6r1dJs+K6xvMsUvsBJ/QQsV5nYDMIoV/NYUd8SyYV4lEj
22+
7LHX5ZbmJrvPk30LGEBG/5Vy2MIATrQrQ14S4nXtEdSnBvTQwPOOaHc+2dTp3YpM
23+
f4ffELKWyispTifx1eqdiUJhURKeQBh+3W7zpyaiN4vJaqEDKGgFQtHA/OyZL2hZ
24+
BpxHB0zpb2iDHV8MeyfOT7HQWUk6p13vdYm6EnyJT8fzWvE+TqYNbqFmB+CLRSXy
25+
R3p1yaeTd4LnVknJ0UBKqEyul3ziHZDhKhBpwdglYOQz4eWjSFhikX9XZ8NaI38Q
26+
QqLZVn0DsH2ztkjrQrUVgK2xn4aUuqoLDk4Hu6h5baUn+f2GLuzx+EXc/i3ikYvw
27+
Y3JyufOgw6nGGFG+/QXEj85XtLPhN7Wm42z2e/BGzi0MLl65sfpEDXvFTA72Yzws
28+
OYaeg/HxeYwUHQgs2fKl/LgV4chntSCvTqfNl6OnQafD/ISJNpx3xWR3HwF+ypFG
29+
UaLE+e1soqEJbzL31U/6pypHLsj8Y8r9hJbZXo2ibnhjFV6fypUAP0rbIzaoWcrJ
30+
T0Sbliz+KQTMzCcubiAi4bI/kZ5FJ4kkaHqUpIWzlx1h2WVJ65ASFDjBWb8eVmB6
31+
Dyno/RVFR/rUL5091gjGRXhLsi1oUHKdEzU=
32+
-----END CERTIFICATE-----
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
-----BEGIN PRIVATE KEY-----
2+
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
51+
lTLiho2DATppaxNUQKh/5k70hzbipDg=
52+
-----END PRIVATE KEY-----
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
-----BEGIN CERTIFICATE-----
2+
MIIEWjCCAkKgAwIBAgIURBZvq442tp+/K9TZII5Vy/LzVx0wDQYJKoZIhvcNAQEL
3+
BQAwOzEZMBcGA1UECgwQU3ByaW5nIEJvb3QgVGVzdDEeMBwGA1UEAwwVQ2VydGlm
4+
aWNhdGUgQXV0aG9yaXR5MB4XDTI0MDUwMTE2NTMyNVoXDTM0MDQyOTE2NTMyNVow
5+
LzEZMBcGA1UECgwQU3ByaW5nIEJvb3QgVGVzdDESMBAGA1UEAwwJbG9jYWxob3N0
6+
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvGb7tu0odSuOjeY1lHlh
7+
sRR4PayAvlryjfrrp49hjoVTiL3d/Jo6Po5HlqwJcYuclm0EWQR5Vur/zYJpfUE7
8+
b8+E9Qwe50+YzfQ2tVFEdq/VfqemrYRGee+pMelOCI90enOKCxfpo6EHbz+WnUP0
9+
mnD8OAF9QpolSdWAMOGJoPdWX65KQvyMXvQbj9VIHmsx7NCaIOYxjHXB/dI2FmXV
10+
+m4VT6mb8he9dXmgK/ozMq6XIPOAXe0n3dlfMTSEddeNeVwnBpr/n5e0cpwGFhdf
11+
NNu5CI4ecipBhXljJi/4/47M/6hd69HwE05C4zyH4ZDZ2JTfaSKOLV+jYdBUqJP5
12+
dwIDAQABo2IwYDALBgNVHQ8EBAMCBaAwEQYJYIZIAYb4QgEBBAQDAgeAMB0GA1Ud
13+
DgQWBBRWiWOo9cm2IF/ZlhWLVjifLzYa/DAfBgNVHSMEGDAWgBRVMLDVqPECWaH6
14+
GruL9E52VcTrPjANBgkqhkiG9w0BAQsFAAOCAgEAA5Wphtu2nBhY+QNOBOwXq4zF
15+
N5qt2IYTLfR7xqpKhhXx9VkIjdPWpcsGuCuMmfPVNvQWE6iK0/jMMqToTj4H6K7e
16+
MN74j0GwwcknT1P42tUzEpg8LKR8VMdhWhyqdniCDNWWuaz1iVSoF0S2i4jFSzH5
17+
1q3KMKMZ4niK5aJI0fAGa4fCjyuun1Mfg/qGBGwLnqDkIXjeAopZf4Jb64TtzjAs
18+
j9NT6mYbe3E0tw3fHT9ihYdbZDZgSjeCsuq9OiRMVb0DWWmRoLmmOrlN8IJlHV/3
19+
WyI/ta4Cw5EZ0oaOg0lIyOxXyvElth1xIvh+kdqZSBsU0gNBri6ZIzYbbTh2KTTO
20+
BJHQt9L5naWG27pDrIxBicWXS/MIYonktm3YgCLfuW3kWcVk8bIlNhfcoAYBBgfM
21+
IEYSYEq+bH2IQ+YoWQz3AxjJ8gEuuSUP6R6mYY65FfpjkKgcpGBvw4EIAmqKDtPS
22+
hlLY/F0XVj9KZzrMyH4/vonu+DAb/P7Zmt2fyk/dQO6bAc3ltRmJbJm4VJ2v/T8I
23+
LVu2FtcUYgtLNtkWUPfdb3GSUUgkKlUpWSty31TKSUszJjW1oRykQhEko6o5U3S8
24+
ptQzXdApsb1lGOqewkubE25tIu2RLiNkKcjFOjJ/lu0vP9k76wWwRVnFLFvfo4lW
25+
pgywiOifs5JbcCt0ZQ0=
26+
-----END CERTIFICATE-----
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
-----BEGIN PRIVATE KEY-----
2+
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC8Zvu27Sh1K46N
3+
5jWUeWGxFHg9rIC+WvKN+uunj2GOhVOIvd38mjo+jkeWrAlxi5yWbQRZBHlW6v/N
4+
gml9QTtvz4T1DB7nT5jN9Da1UUR2r9V+p6athEZ576kx6U4Ij3R6c4oLF+mjoQdv
5+
P5adQ/SacPw4AX1CmiVJ1YAw4Ymg91ZfrkpC/Ixe9BuP1UgeazHs0Jog5jGMdcH9
6+
0jYWZdX6bhVPqZvyF711eaAr+jMyrpcg84Bd7Sfd2V8xNIR11415XCcGmv+fl7Ry
7+
nAYWF18027kIjh5yKkGFeWMmL/j/jsz/qF3r0fATTkLjPIfhkNnYlN9pIo4tX6Nh
8+
0FSok/l3AgMBAAECggEABXnBe3MwXAMQENzNypOiXK4VE3XMYkePfdsSK163byOD
9+
w3ZeTgQNfU4g8LJK8/homzO0SQIJAdz2+ZFbpsp4A2W2zJ+1jvN5RuX/8/UcVhmk
10+
tb1IL/LWCvx5/aoYBWkgIA70UfQJa2jDbdM0v5j/Gu9yE7GI14jh6DFC3xGMGV3b
11+
fOwManxf7sDibCI1nGjnFYNGxninRr+tpb+a1KNbVzhett68LrgPmtph6B3HCPAJ
12+
zBigk1Phgb8WHozTXxnLyw9/RdKJ0Ro4PFmtQv0EvCSlytptnF+0nXkqr3f851XS
13+
bUWwYFchIFWPMhPfD5B3niNWCV42/sU/bQlk+BMQAQKBgQD6NvMq8EdYy2Y7fXT5
14+
FgB4s+7EkLgI2d5LUaCXCFgc6iZtCTQKUXj1rIWeRfGrFVCCe8qV+XIMKt/G5eEi
15+
tn5ifHhktA2A8GK1scj026qHP3bVn0hMaUnkCF1UpDRKPiEO5G/apPtav8PbCNaX
16+
GAimLGw+WZNZuv7+T33bEBeUdwKBgQDAwiidayLXkRkz2deefdDKcXQsB7RHFGGy
17+
vfZPBCGqizxml+6ojJkkDsVUKL1IXFfyK9KpQAI6tezn4oktgu4jAQqkYY7QZobs
18+
RpQx1dR+KxEm7ISDBTq/B1Q9cFKUKVvQQy8N2pnIbCdzb6MTOKLmJqFGTjr+5T8q
19+
F32B5vkDAQKBgDCKfH42AwFc5EZiPlEcTZcdARMtKCa/bXqbKVZjjgR+AFpi0K+3
20+
womWoI1l8E5KYkYOEe0qaU+m+aaybgy37qjYkNqoe34qJFwvU1b9ToXScBFdRz9b
21+
pbQRU1naSTKl/u/OrUxzeTfPwAU8H7VMOlFSiOVHp2he+J0JetcGtixdAoGBAIJQ
22+
QMj7rxhxHcqyEVUy1b6nKNTDeJs9Kjd+uU/+CQyVCQaK3GvScY2w9rLIv/51f3dX
23+
LRoDDf7HExxJSFgeVgQQJjOvSK+XQMvngzSVzQxm7TeVWpiBJpAS0l6e2xUTSODp
24+
KpyBFsoqZBlkdaj+9xIFN66iILxGG4fHTbBOiDYBAoGBAOZMKjM5N/hGcCmik/6t
25+
p/zBA2pN9O6zwPndITTsdyVWSlVqCZhXlRX47CerAN+/WVCidlh7Vp5Tuy75Wa77
26+
v16IDLO01txgWNobcLaM4VgFsyLi5JuxK73S18Vb1cKWdHFRF0LH3cUIq20fjpv6
27+
Odl4vjNOncXMZCLPHQ+bKWaf
28+
-----END PRIVATE KEY-----

0 commit comments

Comments
 (0)