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");
* you may not use this file except in compliance with the License.
......@@ -66,12 +66,12 @@ public class MailProperties {
private Charset defaultEncoding = DEFAULT_CHARSET;
/**
* Additional JavaMail session properties.
* Additional JavaMail Session properties.
*/
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;
......
/*
* 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");
* you may not use this file except in compliance with the License.
......@@ -16,14 +16,9 @@
package org.springframework.boot.autoconfigure.mail;
import java.util.Map;
import java.util.Properties;
import javax.activation.MimeType;
import javax.mail.Session;
import javax.mail.internet.MimeMessage;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.AnyNestedCondition;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
......@@ -31,12 +26,10 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.mail.MailSenderAutoConfiguration.MailSenderCondition;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.mail.MailSender;
import org.springframework.mail.javamail.JavaMailSenderImpl;
/**
* {@link EnableAutoConfiguration Auto configuration} for email support.
......@@ -47,60 +40,16 @@ import org.springframework.mail.javamail.JavaMailSenderImpl;
* @since 1.2.0
*/
@Configuration
@ConditionalOnClass({ MimeMessage.class, MimeType.class })
@ConditionalOnClass({ MimeMessage.class, MimeType.class, MailSender.class })
@ConditionalOnMissingBean(MailSender.class)
@Conditional(MailSenderCondition.class)
@EnableConfigurationProperties(MailProperties.class)
@Import(JndiSessionConfiguration.class)
@Import({ MailSenderJndiConfiguration.class, MailSenderPropertiesConfiguration.class })
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
* either the host or jndi name property is set.
* Condition to trigger the creation of a {@link MailSender}. This kicks in if either
* the host or jndi name property is set.
*/
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");
* you may not use this file except in compliance with the License.
......@@ -26,9 +26,11 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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 Stephane Nicoll
......@@ -37,14 +39,22 @@ import org.springframework.jndi.JndiLocatorDelegate;
@ConditionalOnClass(Session.class)
@ConditionalOnProperty(prefix = "spring.mail", name = "jndi-name")
@ConditionalOnJndi
class JndiSessionConfiguration {
class MailSenderJndiConfiguration {
private final MailProperties properties;
JndiSessionConfiguration(MailProperties properties) {
MailSenderJndiConfiguration(MailProperties 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
@ConditionalOnMissingBean
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");
* you may not use this file except in compliance with the License.
......@@ -178,6 +178,36 @@ public class MailSenderAutoConfigurationTests {
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
public void connectionOnStartup() throws MessagingException {
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.
# Email ({sc-spring-boot-autoconfigure}/mail/MailProperties.{sc-ext}[MailProperties])
spring.mail.default-encoding=UTF-8 # Default MimeMessage encoding.
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.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.test-connection=false # Test that the mail server is available on startup.
spring.mail.username= # Login user of the SMTP server.
......
......@@ -5046,6 +5046,15 @@ to avoid having a thread blocked by an unresponsive mail server:
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]]
......
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