Skip to content

Commit f745f20

Browse files
committed
Clarify scope of JNDI-based MailSenderAutoConfiguration
This commit separates the auto-configuration of JavaMailSender in two distinct configuration: one based on existing Session available on JNDI and the other one based on properties configuration. This clarifies the auto-configuration report and the fact that the JNDI variant overrides any Session-related properties that would have been set in the environment Closes gh-13026
1 parent bb0550a commit f745f20

File tree

7 files changed

+140
-66
lines changed

7 files changed

+140
-66
lines changed

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2015 the original author or authors.
2+
* Copyright 2012-2018 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.
@@ -66,12 +66,12 @@ public class MailProperties {
6666
private Charset defaultEncoding = DEFAULT_CHARSET;
6767

6868
/**
69-
* Additional JavaMail session properties.
69+
* Additional JavaMail Session properties.
7070
*/
7171
private Map<String, String> properties = new HashMap<String, String>();
7272

7373
/**
74-
* Session JNDI name. When set, takes precedence to others mail settings.
74+
* Session JNDI name. When set, takes precedence to others Session settings.
7575
*/
7676
private String jndiName;
7777

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

Lines changed: 5 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2016 the original author or authors.
2+
* Copyright 2012-2018 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.
@@ -16,27 +16,20 @@
1616

1717
package org.springframework.boot.autoconfigure.mail;
1818

19-
import java.util.Map;
20-
import java.util.Properties;
21-
2219
import javax.activation.MimeType;
23-
import javax.mail.Session;
2420
import javax.mail.internet.MimeMessage;
2521

26-
import org.springframework.beans.factory.ObjectProvider;
2722
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
2823
import org.springframework.boot.autoconfigure.condition.AnyNestedCondition;
2924
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
3025
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
3126
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
3227
import org.springframework.boot.autoconfigure.mail.MailSenderAutoConfiguration.MailSenderCondition;
3328
import org.springframework.boot.context.properties.EnableConfigurationProperties;
34-
import org.springframework.context.annotation.Bean;
3529
import org.springframework.context.annotation.Conditional;
3630
import org.springframework.context.annotation.Configuration;
3731
import org.springframework.context.annotation.Import;
3832
import org.springframework.mail.MailSender;
39-
import org.springframework.mail.javamail.JavaMailSenderImpl;
4033

4134
/**
4235
* {@link EnableAutoConfiguration Auto configuration} for email support.
@@ -47,60 +40,16 @@
4740
* @since 1.2.0
4841
*/
4942
@Configuration
50-
@ConditionalOnClass({ MimeMessage.class, MimeType.class })
43+
@ConditionalOnClass({ MimeMessage.class, MimeType.class, MailSender.class })
5144
@ConditionalOnMissingBean(MailSender.class)
5245
@Conditional(MailSenderCondition.class)
5346
@EnableConfigurationProperties(MailProperties.class)
54-
@Import(JndiSessionConfiguration.class)
47+
@Import({ MailSenderJndiConfiguration.class, MailSenderPropertiesConfiguration.class })
5548
public class MailSenderAutoConfiguration {
5649

57-
private final MailProperties properties;
58-
59-
private final Session session;
60-
61-
public MailSenderAutoConfiguration(MailProperties properties,
62-
ObjectProvider<Session> session) {
63-
this.properties = properties;
64-
this.session = session.getIfAvailable();
65-
}
66-
67-
@Bean
68-
public JavaMailSenderImpl mailSender() {
69-
JavaMailSenderImpl sender = new JavaMailSenderImpl();
70-
if (this.session != null) {
71-
sender.setSession(this.session);
72-
}
73-
else {
74-
applyProperties(sender);
75-
}
76-
return sender;
77-
}
78-
79-
private void applyProperties(JavaMailSenderImpl sender) {
80-
sender.setHost(this.properties.getHost());
81-
if (this.properties.getPort() != null) {
82-
sender.setPort(this.properties.getPort());
83-
}
84-
sender.setUsername(this.properties.getUsername());
85-
sender.setPassword(this.properties.getPassword());
86-
sender.setProtocol(this.properties.getProtocol());
87-
if (this.properties.getDefaultEncoding() != null) {
88-
sender.setDefaultEncoding(this.properties.getDefaultEncoding().name());
89-
}
90-
if (!this.properties.getProperties().isEmpty()) {
91-
sender.setJavaMailProperties(asProperties(this.properties.getProperties()));
92-
}
93-
}
94-
95-
private Properties asProperties(Map<String, String> source) {
96-
Properties properties = new Properties();
97-
properties.putAll(source);
98-
return properties;
99-
}
100-
10150
/**
102-
* Condition to trigger the creation of a {@link JavaMailSenderImpl}. This kicks in if
103-
* either the host or jndi name property is set.
51+
* Condition to trigger the creation of a {@link MailSender}. This kicks in if either
52+
* the host or jndi name property is set.
10453
*/
10554
static class MailSenderCondition extends AnyNestedCondition {
10655

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2016 the original author or authors.
2+
* Copyright 2012-2018 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.
@@ -26,9 +26,11 @@
2626
import org.springframework.context.annotation.Bean;
2727
import org.springframework.context.annotation.Configuration;
2828
import org.springframework.jndi.JndiLocatorDelegate;
29+
import org.springframework.mail.MailSender;
30+
import org.springframework.mail.javamail.JavaMailSenderImpl;
2931

3032
/**
31-
* Auto-configure a {@link Session} available on JNDI.
33+
* Auto-configure a {@link MailSender} based on a {@link Session} available on JNDI.
3234
*
3335
* @author Eddú Meléndez
3436
* @author Stephane Nicoll
@@ -37,14 +39,22 @@
3739
@ConditionalOnClass(Session.class)
3840
@ConditionalOnProperty(prefix = "spring.mail", name = "jndi-name")
3941
@ConditionalOnJndi
40-
class JndiSessionConfiguration {
42+
class MailSenderJndiConfiguration {
4143

4244
private final MailProperties properties;
4345

44-
JndiSessionConfiguration(MailProperties properties) {
46+
MailSenderJndiConfiguration(MailProperties properties) {
4547
this.properties = properties;
4648
}
4749

50+
@Bean
51+
public JavaMailSenderImpl mailSender(Session session) {
52+
JavaMailSenderImpl sender = new JavaMailSenderImpl();
53+
sender.setDefaultEncoding(this.properties.getDefaultEncoding().name());
54+
sender.setSession(session);
55+
return sender;
56+
}
57+
4858
@Bean
4959
@ConditionalOnMissingBean
5060
public Session session() {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
/*
2+
* Copyright 2012-2018 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+
* http://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.util.Map;
20+
import java.util.Properties;
21+
22+
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
23+
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
24+
import org.springframework.context.annotation.Bean;
25+
import org.springframework.context.annotation.Configuration;
26+
import org.springframework.mail.MailSender;
27+
import org.springframework.mail.javamail.JavaMailSenderImpl;
28+
29+
/**
30+
* Auto-configure a {@link MailSender} based on properties configuration.
31+
*
32+
* @author Oliver Gierke
33+
* @author Eddú Meléndez
34+
* @author Stephane Nicoll
35+
*/
36+
@Configuration
37+
@ConditionalOnProperty(prefix = "spring.mail", name = "host")
38+
class MailSenderPropertiesConfiguration {
39+
40+
private final MailProperties properties;
41+
42+
MailSenderPropertiesConfiguration(MailProperties properties) {
43+
this.properties = properties;
44+
}
45+
46+
@Bean
47+
@ConditionalOnMissingBean
48+
public JavaMailSenderImpl mailSender() {
49+
JavaMailSenderImpl sender = new JavaMailSenderImpl();
50+
applyProperties(sender);
51+
return sender;
52+
}
53+
54+
private void applyProperties(JavaMailSenderImpl sender) {
55+
sender.setHost(this.properties.getHost());
56+
if (this.properties.getPort() != null) {
57+
sender.setPort(this.properties.getPort());
58+
}
59+
sender.setUsername(this.properties.getUsername());
60+
sender.setPassword(this.properties.getPassword());
61+
sender.setProtocol(this.properties.getProtocol());
62+
if (this.properties.getDefaultEncoding() != null) {
63+
sender.setDefaultEncoding(this.properties.getDefaultEncoding().name());
64+
}
65+
if (!this.properties.getProperties().isEmpty()) {
66+
sender.setJavaMailProperties(asProperties(this.properties.getProperties()));
67+
}
68+
}
69+
70+
private Properties asProperties(Map<String, String> source) {
71+
Properties properties = new Properties();
72+
properties.putAll(source);
73+
return properties;
74+
}
75+
76+
}

spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mail/MailSenderAutoConfigurationTests.java

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2016 the original author or authors.
2+
* Copyright 2012-2018 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.
@@ -178,6 +178,36 @@ public void jndiSessionNotAvailableWithJndiName() throws NamingException {
178178
load(EmptyConfig.class, "spring.mail.jndi-name:foo");
179179
}
180180

181+
@Test
182+
public void jndiSessionTakesPrecedenceOverProperties() throws NamingException {
183+
Session session = configureJndiSession("foo");
184+
load(EmptyConfig.class, "spring.mail.jndi-name:foo",
185+
"spring.mail.host:localhost");
186+
Session sessionBean = this.context.getBean(Session.class);
187+
assertThat(sessionBean).isEqualTo(session);
188+
assertThat(this.context.getBean(JavaMailSenderImpl.class).getSession())
189+
.isEqualTo(sessionBean);
190+
}
191+
192+
@Test
193+
public void defaultEncodingWithProperties() {
194+
load(EmptyConfig.class, "spring.mail.host:localhost",
195+
"spring.mail.default-encoding:UTF-16");
196+
JavaMailSenderImpl bean = (JavaMailSenderImpl) this.context
197+
.getBean(JavaMailSender.class);
198+
assertThat(bean.getDefaultEncoding()).isEqualTo("UTF-16");
199+
}
200+
201+
@Test
202+
public void defaultEncodingWithJndi() throws NamingException {
203+
configureJndiSession("foo");
204+
load(EmptyConfig.class, "spring.mail.jndi-name:foo",
205+
"spring.mail.default-encoding:UTF-16");
206+
JavaMailSenderImpl bean = (JavaMailSenderImpl) this.context
207+
.getBean(JavaMailSender.class);
208+
assertThat(bean.getDefaultEncoding()).isEqualTo("UTF-16");
209+
}
210+
181211
@Test
182212
public void connectionOnStartup() throws MessagingException {
183213
load(MockMailConfiguration.class, "spring.mail.host:10.0.0.23",

spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,10 +96,10 @@ content into your application; rather pick only the properties that you need.
9696
# Email ({sc-spring-boot-autoconfigure}/mail/MailProperties.{sc-ext}[MailProperties])
9797
spring.mail.default-encoding=UTF-8 # Default MimeMessage encoding.
9898
spring.mail.host= # SMTP server host. For instance `smtp.example.com`
99-
spring.mail.jndi-name= # Session JNDI name. When set, takes precedence to others mail settings.
99+
spring.mail.jndi-name= # Session JNDI name. When set, takes precedence to others Session settings.
100100
spring.mail.password= # Login password of the SMTP server.
101101
spring.mail.port= # SMTP server port.
102-
spring.mail.properties.*= # Additional JavaMail session properties.
102+
spring.mail.properties.*= # Additional JavaMail Session properties.
103103
spring.mail.protocol=smtp # Protocol used by the SMTP server.
104104
spring.mail.test-connection=false # Test that the mail server is available on startup.
105105
spring.mail.username= # Login user of the SMTP server.

spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5046,6 +5046,15 @@ to avoid having a thread blocked by an unresponsive mail server:
50465046
spring.mail.properties.mail.smtp.writetimeout=5000
50475047
----
50485048

5049+
It is also possible to configure a `JavaMailSender` with an existing `Session` from JNDI:
5050+
5051+
[source,properties,indent=0]
5052+
----
5053+
spring.mail.jndi-name=mail/Session
5054+
----
5055+
5056+
When a `jndi-name` is set, it takes precedence over all other Session-related settings.
5057+
50495058

50505059

50515060
[[boot-features-jta]]

0 commit comments

Comments
 (0)