7.SpringBoot学习(七)——Spring Boot Email发送邮件
1.简介
1.1 概述
The Spring Framework provides an easy abstraction for sending email by using the
JavaMailSender
interface, and Spring Boot provides auto-configuration for it as well as a starter module.
Spring Framework 通过使用 JavaMailSender 接口提供了用于发送电子邮件的简单抽象,Spring Boot 为它以及启动程序模块提供了自动装配。
1.2 特点
If
spring.mail.host
and the relevant libraries (as defined byspring-boot-starter-mail
) are available, a defaultJavaMailSender
is created if none exists. The sender can be further customized by configuration items from thespring.mail
namespace. SeeMailProperties
for more details.
如果有 “ spring.mail.host” 和相关的库(由“ spring-boot-starter-mail”定义)可用,那么如果不存在默认的“ JavaMailSender”,则会创建一个。可以通过 spring.mail 命名空间中的配置项进一步定制发送者。参考 MailProperties
以获取更多详细信息。
@ConfigurationProperties(prefix = "spring.mail")
public class MailProperties {
private static final Charset DEFAULT_CHARSET;
private String host;
private Integer port;
private String username;
private String password;
private String protocol = "smtp";
private Charset defaultEncoding;
private Map<String, String> properties;
private String jndiName;
// get&set
}
2.演示环境
- JDK 1.8.0_201
- Spring Boot 2.2.0.RELEASE
- 构建工具(apache maven 3.6.3)
- 开发工具(IntelliJ IDEA )
3.演示代码
3.1 代码说明
测试 spring boot 发送 email
3.2 代码结构
3.3 maven 依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
3.4 配置文件
spring.application.name=spring-boot-email
spring.mail.host=pop.qq.com
spring.mail.username=aaa@123.com
spring.mail.password=eiosdal
spring.mail.default-encoding=UTF-8
mail.from.addr=aaa@123.com
3.5 java代码
EmailSenderService.java
public interface EmailSenderService {
/**
* 发送简单邮件
* @param to 目的地
* @param subject 主题
* @param content 内容
*/
void sendSimpleEmail(String to, String subject, String content);
/**
* 发送含有html内容的邮件
* @param to 目的地
* @param subject 主题
* @param content 内容
*/
void sendHtmlEmail(String to, String subject, String content);
/**
* 发送带有附件的邮件
* @param to 目的地
* @param subject 主题
* @param content 内容
* @param filePath 附件路径
*/
void sendEmailWithAttachments(String to, String subject, String content, String filePath);
/**
* 发送带有静态资源(图片)的邮件
* @param to 目的地
* @param subject 主题
* @param content 内容
* @param resPath 资源路径
* @param resId 资源id
*/
void sendEmailWithInlineResource(String to, String subject, String content, String resPath, String resId);
}
EmailSenderServiceImpl.java
@Service
public class EmailSenderServiceImpl implements EmailSenderService {
@Resource
private JavaMailSender mailSender;
@Value("${mail.from.addr}")
private String from;
@Override
public void sendSimpleEmail(String to, String subject, String content) {
SimpleMailMessage message = new SimpleMailMessage();
message.setFrom(from);
message.setTo(to);
message.setSubject(subject);
message.setText(content);
mailSender.send(message);
}
@Override
public void sendHtmlEmail(String to, String subject, String content) {
try {
MimeMessage mimeMessage = mailSender.createMimeMessage();
MimeMessageHelper messageHelper = new MimeMessageHelper(mimeMessage, true);
messageHelper.setFrom(from);
messageHelper.setTo(to);
messageHelper.setSubject(subject);
messageHelper.setText(content, true);
mailSender.send(mimeMessage);
} catch (MessagingException e) {
e.printStackTrace();
}
}
@Override
public void sendEmailWithAttachments(String to, String subject, String content, String filePath) {
try {
MimeMessage mimeMessage = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);
helper.setFrom(from);
helper.setTo(to);
helper.setSubject(subject);
helper.setText(content, true);
FileSystemResource resource = new FileSystemResource(new File(filePath));
String fileName = filePath.substring(filePath.indexOf(File.separator));
helper.addAttachment(fileName, resource);
mailSender.send(mimeMessage);
} catch (MessagingException e) {
e.printStackTrace();
}
}
@Override
public void sendEmailWithInlineResource(String to, String subject, String content, String resPath, String resId) {
try {
MimeMessage mimeMessage = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);
helper.setFrom(from);
helper.setTo(to);
helper.setSubject(subject);
helper.setText(content, true);
FileSystemResource resource = new FileSystemResource(new File(resPath));
helper.addInline(resId, resource);
mailSender.send(mimeMessage);
} catch (MessagingException e) {
e.printStackTrace();
}
}
}
3.6 git 地址
spring-boot/spring-boot-05-basis/spring-boot-email
4.效果展示
使用测试类进行测试,测试时替换成实际的邮件地址和内容
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringBootEmailApplicationTests {
@Autowired
private EmailSenderService senderService;
@Test
public void contextLoads() {}
@Test
public void test_send_simpleEmail() {
senderService.sendSimpleEmail("bbb@324.com", "test", "test");
}
}
5.源码分析
5.1 Email 自动装配
JavaMailSender 仅有一个实现 JavaMailSenderImpl
在 Mail 的自动装配类 MailSenderAutoConfiguration 中有如下定义
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass({ MimeMessage.class, MimeType.class, MailSender.class })
@ConditionalOnMissingBean(MailSender.class)
@Conditional(MailSenderCondition.class)
@EnableConfigurationProperties(MailProperties.class)
@Import({ MailSenderJndiConfiguration.class, MailSenderPropertiesConfiguration.class })
public class MailSenderAutoConfiguration {
static class MailSenderCondition extends AnyNestedCondition {
MailSenderCondition() {
super(ConfigurationPhase.PARSE_CONFIGURATION);
}
@ConditionalOnProperty(prefix = "spring.mail", name = "host")
static class HostProperty {
}
@ConditionalOnProperty(prefix = "spring.mail", name = "jndi-name")
static class JndiNameProperty {
}
}
}
MailSenderAutoConfiguration 通过 @Import 对 MailSenderJndiConfiguration 和 MailSenderPropertiesConfiguration 进行导入,这两个类中声明了 JavaMailSenderImpl 对象
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(Session.class)
@ConditionalOnProperty(prefix = "spring.mail", name = "jndi-name")
@ConditionalOnJndi
class MailSenderJndiConfiguration {
private final MailProperties properties;
MailSenderJndiConfiguration(MailProperties properties) {
this.properties = properties;
}
@Bean
JavaMailSenderImpl mailSender(Session session) {
JavaMailSenderImpl sender = new JavaMailSenderImpl();
sender.setDefaultEncoding(this.properties.getDefaultEncoding().name());
sender.setSession(session);
return sender;
}
@Bean
@ConditionalOnMissingBean
Session session() {
String jndiName = this.properties.getJndiName();
try {
return JndiLocatorDelegate.createDefaultResourceRefLocator().lookup(jndiName, Session.class);
}
catch (NamingException ex) {
throw new IllegalStateException(String.format("Unable to find Session in JNDI location %s", jndiName), ex);
}
}
}