Commit f745f20c authored by Stephane Nicoll's avatar Stephane Nicoll

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
parent bb0550ab
/* /*
* Copyright 2012-2015 the original author or authors. * Copyright 2012-2018 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.
...@@ -66,12 +66,12 @@ public class MailProperties { ...@@ -66,12 +66,12 @@ public class MailProperties {
private Charset defaultEncoding = DEFAULT_CHARSET; private Charset defaultEncoding = DEFAULT_CHARSET;
/** /**
* Additional JavaMail session properties. * Additional JavaMail Session properties.
*/ */
private Map<String, String> properties = new HashMap<String, String>(); private Map<String, String> properties = new HashMap<String, String>();
/** /**
* Session JNDI name. When set, takes precedence to others mail settings. * Session JNDI name. When set, takes precedence to others Session settings.
*/ */
private String jndiName; private String jndiName;
......
/* /*
* Copyright 2012-2016 the original author or authors. * Copyright 2012-2018 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.
...@@ -16,14 +16,9 @@ ...@@ -16,14 +16,9 @@
package org.springframework.boot.autoconfigure.mail; package org.springframework.boot.autoconfigure.mail;
import java.util.Map;
import java.util.Properties;
import javax.activation.MimeType; import javax.activation.MimeType;
import javax.mail.Session;
import javax.mail.internet.MimeMessage; import javax.mail.internet.MimeMessage;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.AnyNestedCondition; import org.springframework.boot.autoconfigure.condition.AnyNestedCondition;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
...@@ -31,12 +26,10 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean ...@@ -31,12 +26,10 @@ 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.MailSenderAutoConfiguration.MailSenderCondition; import org.springframework.boot.autoconfigure.mail.MailSenderAutoConfiguration.MailSenderCondition;
import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import; import org.springframework.context.annotation.Import;
import org.springframework.mail.MailSender; import org.springframework.mail.MailSender;
import org.springframework.mail.javamail.JavaMailSenderImpl;
/** /**
* {@link EnableAutoConfiguration Auto configuration} for email support. * {@link EnableAutoConfiguration Auto configuration} for email support.
...@@ -47,60 +40,16 @@ import org.springframework.mail.javamail.JavaMailSenderImpl; ...@@ -47,60 +40,16 @@ import org.springframework.mail.javamail.JavaMailSenderImpl;
* @since 1.2.0 * @since 1.2.0
*/ */
@Configuration @Configuration
@ConditionalOnClass({ MimeMessage.class, MimeType.class }) @ConditionalOnClass({ MimeMessage.class, MimeType.class, MailSender.class })
@ConditionalOnMissingBean(MailSender.class) @ConditionalOnMissingBean(MailSender.class)
@Conditional(MailSenderCondition.class) @Conditional(MailSenderCondition.class)
@EnableConfigurationProperties(MailProperties.class) @EnableConfigurationProperties(MailProperties.class)
@Import(JndiSessionConfiguration.class) @Import({ MailSenderJndiConfiguration.class, MailSenderPropertiesConfiguration.class })
public class MailSenderAutoConfiguration { public class MailSenderAutoConfiguration {
private final MailProperties properties;
private final Session session;
public MailSenderAutoConfiguration(MailProperties properties,
ObjectProvider<Session> session) {
this.properties = properties;
this.session = session.getIfAvailable();
}
@Bean
public JavaMailSenderImpl mailSender() {
JavaMailSenderImpl sender = new JavaMailSenderImpl();
if (this.session != null) {
sender.setSession(this.session);
}
else {
applyProperties(sender);
}
return sender;
}
private void applyProperties(JavaMailSenderImpl sender) {
sender.setHost(this.properties.getHost());
if (this.properties.getPort() != null) {
sender.setPort(this.properties.getPort());
}
sender.setUsername(this.properties.getUsername());
sender.setPassword(this.properties.getPassword());
sender.setProtocol(this.properties.getProtocol());
if (this.properties.getDefaultEncoding() != null) {
sender.setDefaultEncoding(this.properties.getDefaultEncoding().name());
}
if (!this.properties.getProperties().isEmpty()) {
sender.setJavaMailProperties(asProperties(this.properties.getProperties()));
}
}
private Properties asProperties(Map<String, String> source) {
Properties properties = new Properties();
properties.putAll(source);
return properties;
}
/** /**
* Condition to trigger the creation of a {@link JavaMailSenderImpl}. This kicks in if * Condition to trigger the creation of a {@link MailSender}. This kicks in if either
* either the host or jndi name property is set. * the host or jndi name property is set.
*/ */
static class MailSenderCondition extends AnyNestedCondition { static class MailSenderCondition extends AnyNestedCondition {
......
/* /*
* Copyright 2012-2016 the original author or authors. * Copyright 2012-2018 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.
...@@ -26,9 +26,11 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; ...@@ -26,9 +26,11 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.jndi.JndiLocatorDelegate; import org.springframework.jndi.JndiLocatorDelegate;
import org.springframework.mail.MailSender;
import org.springframework.mail.javamail.JavaMailSenderImpl;
/** /**
* Auto-configure a {@link Session} available on JNDI. * Auto-configure a {@link MailSender} based on a {@link Session} available on JNDI.
* *
* @author Eddú Meléndez * @author Eddú Meléndez
* @author Stephane Nicoll * @author Stephane Nicoll
...@@ -37,14 +39,22 @@ import org.springframework.jndi.JndiLocatorDelegate; ...@@ -37,14 +39,22 @@ import org.springframework.jndi.JndiLocatorDelegate;
@ConditionalOnClass(Session.class) @ConditionalOnClass(Session.class)
@ConditionalOnProperty(prefix = "spring.mail", name = "jndi-name") @ConditionalOnProperty(prefix = "spring.mail", name = "jndi-name")
@ConditionalOnJndi @ConditionalOnJndi
class JndiSessionConfiguration { class MailSenderJndiConfiguration {
private final MailProperties properties; private final MailProperties properties;
JndiSessionConfiguration(MailProperties properties) { MailSenderJndiConfiguration(MailProperties properties) {
this.properties = properties; this.properties = properties;
} }
@Bean
public JavaMailSenderImpl mailSender(Session session) {
JavaMailSenderImpl sender = new JavaMailSenderImpl();
sender.setDefaultEncoding(this.properties.getDefaultEncoding().name());
sender.setSession(session);
return sender;
}
@Bean @Bean
@ConditionalOnMissingBean @ConditionalOnMissingBean
public Session session() { public Session session() {
......
/*
* Copyright 2012-2018 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
*
* http://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.util.Map;
import java.util.Properties;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.mail.MailSender;
import org.springframework.mail.javamail.JavaMailSenderImpl;
/**
* Auto-configure a {@link MailSender} based on properties configuration.
*
* @author Oliver Gierke
* @author Eddú Meléndez
* @author Stephane Nicoll
*/
@Configuration
@ConditionalOnProperty(prefix = "spring.mail", name = "host")
class MailSenderPropertiesConfiguration {
private final MailProperties properties;
MailSenderPropertiesConfiguration(MailProperties properties) {
this.properties = properties;
}
@Bean
@ConditionalOnMissingBean
public JavaMailSenderImpl mailSender() {
JavaMailSenderImpl sender = new JavaMailSenderImpl();
applyProperties(sender);
return sender;
}
private void applyProperties(JavaMailSenderImpl sender) {
sender.setHost(this.properties.getHost());
if (this.properties.getPort() != null) {
sender.setPort(this.properties.getPort());
}
sender.setUsername(this.properties.getUsername());
sender.setPassword(this.properties.getPassword());
sender.setProtocol(this.properties.getProtocol());
if (this.properties.getDefaultEncoding() != null) {
sender.setDefaultEncoding(this.properties.getDefaultEncoding().name());
}
if (!this.properties.getProperties().isEmpty()) {
sender.setJavaMailProperties(asProperties(this.properties.getProperties()));
}
}
private Properties asProperties(Map<String, String> source) {
Properties properties = new Properties();
properties.putAll(source);
return properties;
}
}
/* /*
* Copyright 2012-2016 the original author or authors. * Copyright 2012-2018 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.
...@@ -178,6 +178,36 @@ public class MailSenderAutoConfigurationTests { ...@@ -178,6 +178,36 @@ public class MailSenderAutoConfigurationTests {
load(EmptyConfig.class, "spring.mail.jndi-name:foo"); load(EmptyConfig.class, "spring.mail.jndi-name:foo");
} }
@Test
public void jndiSessionTakesPrecedenceOverProperties() throws NamingException {
Session session = configureJndiSession("foo");
load(EmptyConfig.class, "spring.mail.jndi-name:foo",
"spring.mail.host:localhost");
Session sessionBean = this.context.getBean(Session.class);
assertThat(sessionBean).isEqualTo(session);
assertThat(this.context.getBean(JavaMailSenderImpl.class).getSession())
.isEqualTo(sessionBean);
}
@Test
public void defaultEncodingWithProperties() {
load(EmptyConfig.class, "spring.mail.host:localhost",
"spring.mail.default-encoding:UTF-16");
JavaMailSenderImpl bean = (JavaMailSenderImpl) this.context
.getBean(JavaMailSender.class);
assertThat(bean.getDefaultEncoding()).isEqualTo("UTF-16");
}
@Test
public void defaultEncodingWithJndi() throws NamingException {
configureJndiSession("foo");
load(EmptyConfig.class, "spring.mail.jndi-name:foo",
"spring.mail.default-encoding:UTF-16");
JavaMailSenderImpl bean = (JavaMailSenderImpl) this.context
.getBean(JavaMailSender.class);
assertThat(bean.getDefaultEncoding()).isEqualTo("UTF-16");
}
@Test @Test
public void connectionOnStartup() throws MessagingException { public void connectionOnStartup() throws MessagingException {
load(MockMailConfiguration.class, "spring.mail.host:10.0.0.23", load(MockMailConfiguration.class, "spring.mail.host:10.0.0.23",
......
...@@ -96,10 +96,10 @@ content into your application; rather pick only the properties that you need. ...@@ -96,10 +96,10 @@ content into your application; rather pick only the properties that you need.
# Email ({sc-spring-boot-autoconfigure}/mail/MailProperties.{sc-ext}[MailProperties]) # Email ({sc-spring-boot-autoconfigure}/mail/MailProperties.{sc-ext}[MailProperties])
spring.mail.default-encoding=UTF-8 # Default MimeMessage encoding. spring.mail.default-encoding=UTF-8 # Default MimeMessage encoding.
spring.mail.host= # SMTP server host. For instance `smtp.example.com` spring.mail.host= # SMTP server host. For instance `smtp.example.com`
spring.mail.jndi-name= # Session JNDI name. When set, takes precedence to others mail settings. spring.mail.jndi-name= # Session JNDI name. When set, takes precedence to others Session settings.
spring.mail.password= # Login password of the SMTP server. spring.mail.password= # Login password of the SMTP server.
spring.mail.port= # SMTP server port. spring.mail.port= # SMTP server port.
spring.mail.properties.*= # Additional JavaMail session properties. spring.mail.properties.*= # Additional JavaMail Session properties.
spring.mail.protocol=smtp # Protocol used by the SMTP server. spring.mail.protocol=smtp # Protocol used by the SMTP server.
spring.mail.test-connection=false # Test that the mail server is available on startup. spring.mail.test-connection=false # Test that the mail server is available on startup.
spring.mail.username= # Login user of the SMTP server. spring.mail.username= # Login user of the SMTP server.
......
...@@ -5046,6 +5046,15 @@ to avoid having a thread blocked by an unresponsive mail server: ...@@ -5046,6 +5046,15 @@ to avoid having a thread blocked by an unresponsive mail server:
spring.mail.properties.mail.smtp.writetimeout=5000 spring.mail.properties.mail.smtp.writetimeout=5000
---- ----
It is also possible to configure a `JavaMailSender` with an existing `Session` from JNDI:
[source,properties,indent=0]
----
spring.mail.jndi-name=mail/Session
----
When a `jndi-name` is set, it takes precedence over all other Session-related settings.
[[boot-features-jta]] [[boot-features-jta]]
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment