(九)Spring Boot整合Mail邮件服务

整理学习spring boot常见案例,

仓库地址:spring-boot-learn
欢迎star、fork,给作者一些鼓励

Spring Boot整合邮件服务

Spring Boot也对JavaMail进行了封装简化。以前学JavaWeb的时候学习过调用JavaMail进行邮件,那时候需要配置的选项还是蛮多的,今天看到 纯洁的微笑 大佬关于SpringBoot邮件服务的文章,如今也可以愉快的玩一下邮件发送。

准备

导入依赖

1
2
3
4
5
6
7
8
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

修改application.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
spring:
mail:
#邮件服务器地址
host: smtp.163.com
#用户名
username: tycoding_tumo@163.com
#密码
password: 客户端授权密码
default-encoding: UTF-8
properties:
mail:
smtp.auth: true

thymeleaf:
mode: LEGACYHTML5
cache: false

#发件人邮箱
mail.from: tycoding_tumo@163.com

注意

spring.mail.host是邮件服务器的地址

可以登录自己的163邮箱查看(其他邮箱雷同):

1
2
3
4
服务器地址:
POP3服务器: pop.163.com
SMTP服务器: smtp.163.com
IMAP服务器: imap.163.com

username是邮箱登录名

这里我全以163邮箱为例

password是客户端授权密码不是登录密码

因为需要使用smtp服务,需要在163邮箱设置中开启smtp服务(其他邮箱也是),而在163邮箱中开启smtp服务需要设置客户端授权码,这个密码就是我们第三方API请求163服务的验证密码

mail.from是发件人邮箱

名字是自定义的。一般情况下,spring.mail.usernamemail.from是一样的

邮件服务

基础邮件

创建一个服务层方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
@Component
public class MailService {
private Logger logger = LoggerFactory.getLogger(this.getClass());

@Autowired
private JavaMailSender mailSender;

@Value("${mail.from}")
private String from;

/**
* 发送普通邮件
*
* @param to 收件人邮箱
* @param subject 邮件主题
* @param content 邮件内容
*/
public void sendMail(String to, String subject, String content) {
SimpleMailMessage mailMessage = new SimpleMailMessage();
mailMessage.setFrom(from);
mailMessage.setTo(to);
mailMessage.setSubject(subject);
mailMessage.setText(content);

try {
mailSender.send(mailMessage);
} catch (Exception e) {
e.printStackTrace();
}
}
}

测试方法:

1
2
3
4
5
6
7
8
9
10
11
12
@SpringBootTest
@RunWith(SpringRunner.class)
public class MailServiceTest {

@Autowired
private MailService mailService;

@Test
public void sendMail() {
mailService.sendMail("tycoding_tumo@163.com", "测试邮件", "hello this test email");
}
}

HTML格式邮件

Service服务层方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/**
* 发送HTML格式的邮件
*
* @param to 收件人邮箱
* @param subject 邮件主题
* @param content 邮件内容
*/
public void sendHtmlMail(String to, String subject, String content) {
MimeMessage mimeMessage = mailSender.createMimeMessage();
try {
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);
helper.setFrom(from);
helper.setTo(to);
helper.setSubject(subject);
helper.setText(content, true);
mailSender.send(mimeMessage);
} catch (MessagingException e) {
e.printStackTrace();
}
}

测试方法:

1
2
3
4
5
6
7
8
9
@Test
public void sendHtmlMail() {
String html = "<html>\n" +
"<body>\n" +
"<h2>this a html email</h2>\n" +
"</body>\n" +
"</html>";
mailService.sendHtmlMail("tycoding_tumo@163.com", "测试HTML邮件", html);
}

携带附件的邮件

Service服务层方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/**
* 发送携带附件的邮件
*
* @param to 收件人邮箱
* @param subject 邮件主题
* @param content 邮件内容
* @param filePath 文件地址
*/
public void sendAttachmentsMail(String to, String subject, String content, String filePath) {
MimeMessage mimeMessage = mailSender.createMimeMessage();
try {
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);
helper.setFrom(from);
helper.setTo(to);
helper.setSubject(subject);
helper.setText(content, true);

FileSystemResource file = new FileSystemResource(new File(filePath));
String fileName = filePath.substring(filePath.lastIndexOf(File.separator));
helper.addAttachment(fileName, file);

mailSender.send(mimeMessage);
} catch (MessagingException e) {
e.printStackTrace();
}
}

测试方法:

1
2
3
4
5
@Test
public void sendAttachmentsMail() {
String filePath = "/tycoding/learn-plan.md";
mailService.sendAttachmentsMail("tycoding_tumo@163.com", "测试携带附件的邮件", "这是携带附件的邮件,请注意查收", filePath);
}

HTML内联资源邮件

Service服务层方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/**
* 发送HTML标签内携带资源的邮件
*
* @param to 收件人邮箱
* @param subject 邮件主题
* @param content 邮件内容
* @param resPath 资源路径
* @param resId 资源ID
*/
public void sendInlineResourceMail(String to, String subject, String content, String resPath, String resId) {
MimeMessage mimeMessage = mailSender.createMimeMessage();
try {
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 (Exception e) {
e.printStackTrace();
}
}

测试方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
@Test
public void sendInlineResourceMail() {
String to = "tycoding_tumo@163.com";
String subject = "这是携带内联资源的邮件";
String resId = "001";
String resPath = "/tycoding/totoro.png";
String content = "<html>\n" +
"<body>\n" +
"这是带图片的邮件<img src=\'resId:" + resId + "\'>" +
"</body>\n" +
"</html>";
mailService.sendInlineResourceMail(to, subject, content, resPath, resId);
}

模板邮件

比如一些网站常用发送发送验证码到邮箱,通常这是用一个模板的,比如这样:

resources/下创建模板emailTemplate.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>邮件模板</title>
</head>
<body>

您好,欢迎注册本系统,您的验证码是: <b th:text="${code}"></b>

-- TyCoding

</body>
</html>

Service层方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Autowired
private TemplateEngine templateEngine;

/**
* 发送模板邮件
*
* @param to 收件人邮箱
* @param subject 邮件主题
* @param code 邮件验证码
*/
public void sendTemplateMail(String to, String subject, String code) {
Context context = new Context();
context.setVariable("code", code);
String emailContent = templateEngine.process("emailTemplate", context);
sendHtmlMail(to, subject, emailContent);
}

测试方法:

1
2
3
4
5
@Test
public void sendTemplateMail() {
int code = (int) (Math.random() * 9 + 1) * 100000;
mailService.sendTemplateMail("tycoding_tumo@163.com", "这是模板邮件", String.valueOf(code));
}

常见错误

在实际测试中遇到了很多错误,比如:

550 User has no permission

解释

一般是因为你的163邮箱没有开启客户端授权,导致第三方API调用163服务被拒绝

解决办法

登录163邮箱,配置客户端授权,并且开启设置POP3/SMTP/IMAP服务

535 Error: authentication failed

解释

显然是说身份验证失败,一般是因为在application.yml中配置的spring.mail.password是你的邮箱登录密码

解决办法

这个spring.mail.password不能填写你的邮箱密码,要写客户端授权密码,具体要登录163邮箱查看并设置

553 Mail from must equal authorized user

解释

一般是因为application.yml中配置的spring.mail.passwordmail.from(发件人邮箱)不一致导致的

解决办法

对比application.yml中配置的spring.mail.passwordmail.from

DT:SPM 163 smtp11,D8CowADX

1
com.sun.mail.smtp.SMTPSendFailedException: 554 DT:SPM 163 smtp14,EsCowAB3K92VD3ZcPZPeHQ--.26803S2 1551241110

解释

出现这一串代码,一般是说明,你的配置中 发件人邮箱是163邮箱,收件人邮箱是其他邮箱(比如QQ邮箱)。

解决办法

经过查百度,163官方是说其不允许发送垃圾邮件,但是这种错误是时不时出现的。在我的测试中,之前几封邮件是从163发送给QQ邮箱是可以的,但是莫名后几次就开始报这个错误了。暂时也不清楚如何解决。只要是163邮箱发送给163邮箱(比如自己发送给自己)就不会报这个错。


交流

以上仅是个人的见解,可能有些地方是错误的,深知自己的菜鸡技术,欢迎大佬指出。

个人建了一个Java交流群:671017003。 欢迎大佬或是新人入驻一起交流学习Java技术。


联系

If you have some questions after you see this article, you can contact me or you can find some info by clicking these links.

如果你觉得这篇文章帮助到了你,你可以帮作者买一杯果汁表示鼓励