Skip to content

Commit ccc5e65

Browse files
committed
Add email support
This commit adds a new starter to auto-configure a MailSender when the necessary classes are present and when the property "spring.mail.host" is set. The auto-configuration also accepts any arbitrary properties that JavaMail might need using the "spring.mail.properties" prefix. Fixes gh-1760
1 parent 6ed2c65 commit ccc5e65

File tree

9 files changed

+351
-0
lines changed

9 files changed

+351
-0
lines changed

spring-boot-autoconfigure/pom.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,11 @@
380380
<artifactId>jms-api</artifactId>
381381
<optional>true</optional>
382382
</dependency>
383+
<dependency>
384+
<groupId>javax.mail</groupId>
385+
<artifactId>mail</artifactId>
386+
<optional>true</optional>
387+
</dependency>
383388
<dependency>
384389
<groupId>org.aspectj</groupId>
385390
<artifactId>aspectjweaver</artifactId>
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
/*
2+
* Copyright 2012-2014 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.HashMap;
20+
import java.util.Map;
21+
22+
import org.springframework.boot.context.properties.ConfigurationProperties;
23+
24+
/**
25+
* Configuration properties for email support.
26+
*
27+
* @author Oliver Gierke
28+
* @author Stephane Nicoll
29+
*/
30+
@ConfigurationProperties(prefix = "spring.mail")
31+
public class MailProperties {
32+
33+
private String host;
34+
35+
private Integer port;
36+
37+
private String username;
38+
39+
private String password;
40+
41+
private String defaultEncoding = "UTF-8";
42+
43+
private Map<String, String> properties = new HashMap<String, String>();
44+
45+
public String getHost() {
46+
return host;
47+
}
48+
49+
public void setHost(String host) {
50+
this.host = host;
51+
}
52+
53+
public Integer getPort() {
54+
return port;
55+
}
56+
57+
public void setPort(Integer port) {
58+
this.port = port;
59+
}
60+
61+
public String getUsername() {
62+
return username;
63+
}
64+
65+
public void setUsername(String username) {
66+
this.username = username;
67+
}
68+
69+
public String getPassword() {
70+
return password;
71+
}
72+
73+
public void setPassword(String password) {
74+
this.password = password;
75+
}
76+
77+
public String getDefaultEncoding() {
78+
return defaultEncoding;
79+
}
80+
81+
public void setDefaultEncoding(String defaultEncoding) {
82+
this.defaultEncoding = defaultEncoding;
83+
}
84+
85+
public Map<String, String> getProperties() {
86+
return properties;
87+
}
88+
89+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/*
2+
* Copyright 2012-2014 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+
import javax.activation.MimeType;
22+
import javax.mail.internet.MimeMessage;
23+
24+
import org.springframework.beans.factory.annotation.Autowired;
25+
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
26+
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
27+
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
28+
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
29+
import org.springframework.boot.context.properties.EnableConfigurationProperties;
30+
import org.springframework.context.annotation.Bean;
31+
import org.springframework.context.annotation.Configuration;
32+
import org.springframework.mail.MailSender;
33+
import org.springframework.mail.javamail.JavaMailSender;
34+
import org.springframework.mail.javamail.JavaMailSenderImpl;
35+
36+
/**
37+
* {@link EnableAutoConfiguration Auto configuration} for email support.
38+
*
39+
* @author Oliver Gierke
40+
* @author Stephane Nicoll
41+
*/
42+
@Configuration
43+
@ConditionalOnClass({MimeMessage.class, MimeType.class})
44+
@ConditionalOnProperty(prefix = "spring.mail", value = "host")
45+
@ConditionalOnMissingBean(MailSender.class)
46+
@EnableConfigurationProperties(MailProperties.class)
47+
public class MailSenderAutoConfiguration {
48+
49+
@Autowired MailProperties properties;
50+
51+
@Bean
52+
public JavaMailSender mailSender() {
53+
JavaMailSenderImpl sender = new JavaMailSenderImpl();
54+
sender.setHost(this.properties.getHost());
55+
if (this.properties.getPort() != null) {
56+
sender.setPort(this.properties.getPort());
57+
}
58+
sender.setUsername(this.properties.getUsername());
59+
sender.setPassword(this.properties.getPassword());
60+
sender.setDefaultEncoding(this.properties.getDefaultEncoding());
61+
Map<String,String> properties = this.properties.getProperties();
62+
if (!properties.isEmpty()) {
63+
Properties javaMailProperties= new Properties();
64+
for (Map.Entry<String, String> entry : properties.entrySet()) {
65+
javaMailProperties.setProperty(entry.getKey(), entry.getValue());
66+
}
67+
sender.setJavaMailProperties(javaMailProperties);
68+
}
69+
return sender;
70+
}
71+
72+
}

spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration,\
3838
org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAutoConfiguration,\
3939
org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration,\
4040
org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration,\
41+
org.springframework.boot.autoconfigure.mail.MailSenderAutoConfiguration,\
4142
org.springframework.boot.autoconfigure.mobile.DeviceResolverAutoConfiguration,\
4243
org.springframework.boot.autoconfigure.mobile.DeviceDelegatingViewResolverAutoConfiguration,\
4344
org.springframework.boot.autoconfigure.mobile.SitePreferenceAutoConfiguration,\
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
/*
2+
* Copyright 2012-2014 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 org.junit.After;
20+
import org.junit.Rule;
21+
import org.junit.Test;
22+
import org.junit.rules.ExpectedException;
23+
24+
import org.springframework.boot.test.EnvironmentTestUtils;
25+
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
26+
import org.springframework.context.annotation.Bean;
27+
import org.springframework.context.annotation.Configuration;
28+
import org.springframework.mail.javamail.JavaMailSender;
29+
import org.springframework.mail.javamail.JavaMailSenderImpl;
30+
31+
import static org.junit.Assert.*;
32+
33+
/**
34+
* Tests for {@link MailSenderAutoConfiguration}.
35+
*
36+
* @author Stephane Nicoll
37+
*/
38+
public class MailSenderAutoConfigurationTests {
39+
40+
@Rule
41+
public ExpectedException thrown = ExpectedException.none();
42+
43+
private AnnotationConfigApplicationContext context;
44+
45+
@After
46+
public void close() {
47+
if (this.context != null) {
48+
this.context.close();
49+
}
50+
}
51+
52+
@Test
53+
public void smtpHostSet() {
54+
String host = "192.168.1.234";
55+
load(EmptyConfig.class, "spring.mail.host:" + host);
56+
JavaMailSenderImpl bean = (JavaMailSenderImpl) context.getBean(JavaMailSender.class);
57+
assertEquals(host, bean.getHost());
58+
}
59+
60+
@Test
61+
public void smptHostWithSettings() {
62+
String host = "192.168.1.234";
63+
load(EmptyConfig.class, "spring.mail.host:" + host, "spring.mail.port:42",
64+
"spring.mail.username:john", "spring.mail.password:secret", "spring.mail.default-encoding:ISO-9");
65+
JavaMailSenderImpl bean = (JavaMailSenderImpl) context.getBean(JavaMailSender.class);
66+
assertEquals(host, bean.getHost());
67+
assertEquals(42, bean.getPort());
68+
assertEquals("john", bean.getUsername());
69+
assertEquals("secret", bean.getPassword());
70+
assertEquals("ISO-9", bean.getDefaultEncoding());
71+
}
72+
73+
@Test
74+
public void smptHostWithJavaMailProperties() {
75+
load(EmptyConfig.class, "spring.mail.host:localhost", "spring.mail.properties.mail.smtp.auth:true");
76+
JavaMailSenderImpl bean = (JavaMailSenderImpl) context.getBean(JavaMailSender.class);
77+
assertEquals("true", bean.getJavaMailProperties().get("mail.smtp.auth"));
78+
}
79+
80+
@Test
81+
public void smtpHostNotSet() {
82+
load(EmptyConfig.class);
83+
assertEquals(0, context.getBeansOfType(JavaMailSender.class).size());
84+
}
85+
86+
@Test
87+
public void mailSenderBackOff() {
88+
load(ManualMailConfiguration.class, "spring.mail.host:smtp.acme.org",
89+
"spring.mail.user:user", "spring.mail.password:secret");
90+
JavaMailSenderImpl bean = (JavaMailSenderImpl) context.getBean(JavaMailSender.class);
91+
assertNull(bean.getUsername());
92+
assertNull(bean.getPassword());
93+
}
94+
95+
96+
private void load(Class<?> config, String... environment) {
97+
this.context = doLoad(new Class<?>[] {config}, environment);
98+
}
99+
100+
private AnnotationConfigApplicationContext doLoad(Class<?>[] configs,
101+
String... environment) {
102+
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
103+
EnvironmentTestUtils.addEnvironment(applicationContext, environment);
104+
applicationContext.register(configs);
105+
applicationContext.register(MailSenderAutoConfiguration.class);
106+
applicationContext.refresh();
107+
return applicationContext;
108+
}
109+
110+
@Configuration
111+
static class EmptyConfig {
112+
113+
}
114+
115+
@Configuration
116+
static class ManualMailConfiguration {
117+
118+
@Bean
119+
JavaMailSender customMailSender() {
120+
return new JavaMailSenderImpl();
121+
}
122+
}
123+
}

spring-boot-dependencies/pom.xml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,11 @@
300300
<artifactId>spring-boot-starter-logging</artifactId>
301301
<version>1.2.0.BUILD-SNAPSHOT</version>
302302
</dependency>
303+
<dependency>
304+
<groupId>org.springframework.boot</groupId>
305+
<artifactId>spring-boot-starter-mail</artifactId>
306+
<version>1.2.0.BUILD-SNAPSHOT</version>
307+
</dependency>
303308
<dependency>
304309
<groupId>org.springframework.boot</groupId>
305310
<artifactId>spring-boot-starter-mobile</artifactId>
@@ -545,6 +550,11 @@
545550
<artifactId>jms-api</artifactId>
546551
<version>1.1-rev-1</version>
547552
</dependency>
553+
<dependency>
554+
<groupId>javax.mail</groupId>
555+
<artifactId>mail</artifactId>
556+
<version>1.5.0-b01</version>
557+
</dependency>
548558
<dependency>
549559
<groupId>javax.servlet</groupId>
550560
<artifactId>javax.servlet-api</artifactId>

spring-boot-starters/pom.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
<module>spring-boot-starter-logging</module>
4444
<module>spring-boot-starter-log4j</module>
4545
<module>spring-boot-starter-log4j2</module>
46+
<module>spring-boot-starter-mail</module>
4647
<module>spring-boot-starter-mobile</module>
4748
<module>spring-boot-starter-actuator</module>
4849
<module>spring-boot-starter-parent</module>
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4+
<modelVersion>4.0.0</modelVersion>
5+
<parent>
6+
<groupId>org.springframework.boot</groupId>
7+
<artifactId>spring-boot-starters</artifactId>
8+
<version>1.2.0.BUILD-SNAPSHOT</version>
9+
</parent>
10+
<artifactId>spring-boot-starter-mail</artifactId>
11+
<name>Spring Boot Mail Starter</name>
12+
<description>Spring Boot Mail Starter</description>
13+
<url>http://projects.spring.io/spring-boot/</url>
14+
<organization>
15+
<name>Pivotal Software, Inc.</name>
16+
<url>http://www.spring.io</url>
17+
</organization>
18+
<properties>
19+
<main.basedir>${basedir}/../..</main.basedir>
20+
</properties>
21+
<dependencies>
22+
<dependency>
23+
<groupId>org.springframework.boot</groupId>
24+
<artifactId>spring-boot-starter</artifactId>
25+
</dependency>
26+
<dependency>
27+
<groupId>org.springframework</groupId>
28+
<artifactId>spring-core</artifactId>
29+
<exclusions>
30+
<exclusion>
31+
<groupId>commons-logging</groupId>
32+
<artifactId>commons-logging</artifactId>
33+
</exclusion>
34+
</exclusions>
35+
</dependency>
36+
<dependency>
37+
<groupId>org.springframework</groupId>
38+
<artifactId>spring-context</artifactId>
39+
</dependency>
40+
<dependency>
41+
<groupId>org.springframework</groupId>
42+
<artifactId>spring-context-support</artifactId>
43+
</dependency>
44+
<dependency>
45+
<groupId>javax.mail</groupId>
46+
<artifactId>mail</artifactId>
47+
</dependency>
48+
</dependencies>
49+
</project>
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
provides: spring-context-support,mail

0 commit comments

Comments
 (0)