重学Springboot系列之邮件发送的整合与使用
基础协议及邮件配置整合
名词概念解释
- 什么是POP3、SMTP和IMAP?
简单的说:POP3和IMAP是用来从服务器上下载邮件的。SMTP适用于发送或中转信件时找到下一个目的地。所以我们发送邮件应该使用SMTP协议。
- 什么是免费邮箱客户端授权码功能?
邮箱客户端授权码是为了避免您的邮箱密码被盗后,盗号者通过客户端登录邮箱而独特设计的安防功能。可以理解为客户端授权码为邮件发送的二次密码。
整合邮件发送功能
引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
邮箱配置
QQ系邮箱配置
官方配置说明:参考官方帮助中心
获取客户端授权码:参考官方帮助中心
详细的配置如下:
spring:
mail:
host: smtp.qq.com #发送邮件服务器
username: xx@qq.com #QQ邮箱
password: xxxxxxxxxxx #客户端授权码
protocol: smtp #发送邮件协议
properties.mail.smtp.auth: true
properties.mail.smtp.port: 465 #端口号465或587
properties.mail.display.sendmail: Javen #可以任意
properties.mail.display.sendname: Spring Boot Guide Email #可以任意
properties.mail.smtp.starttls.enable: true
properties.mail.smtp.starttls.required: true
properties.mail.smtp.ssl.enable: true
default-encoding: utf-8
说明:开启SSL时使用587端口时无法连接QQ邮件服务器
网易系(126/163/yeah)邮箱配置
网易邮箱客户端授码:参考官方帮助中心
客户端端口配置说明:参考官方帮助中心
详细的配置如下:
spring:
mail:
host: smtp.126.com
username: xx@126.com
password: xxxxxxxx
protocol: smtp
properties.mail.smtp.auth: true
properties.mail.smtp.port: 994 #465或者994
properties.mail.display.sendmail: Javen
properties.mail.display.sendname: Spring Boot Guide Email
properties.mail.smtp.starttls.enable: true
properties.mail.smtp.starttls.required: true
properties.mail.smtp.ssl.enable: true
default-encoding: utf-8
from: xx@126.com
特别说明:
- 126邮箱SMTP服务器地址:smtp.126.com,端口号:465或者994
- 163邮箱SMTP服务器地址:smtp.163.com,端口号:465或者994
- yeah邮箱SMTP服务器地址:smtp.yeah.net,端口号:465或者994
有的邮件服务器接受使用客户端授权码发邮件,有的邮件服务器接受使用邮箱密码来发送邮件,所以password的配置不能一概而论。客户端授权码不行,就试试用邮箱密码;邮箱密码不行,就试试客户端授权码。
发送简单邮件
这里的简单邮件就是指邮件的内容只是普通文字的这种邮件。
@Service
public class MailService {
@Resource
private JavaMailSender mailSender;
@Value("${spring.mail.username}")
private String fromEmail;
/**
* 发送文本邮件
*/
public void sendSimpleMail(String to, String subject, String content) {
SimpleMailMessage message = new SimpleMailMessage();
message.setFrom(fromEmail);
message.setTo(to);
message.setSubject(subject);
message.setText(content);
mailSender.send(message);
}
}
sendSimpleMail的三个参数依次是:邮件的发送目标,邮件的标题,邮件的内容。
测试代码:
//用配置文件的指定端口DEFINED_PORT作为启动端口运行测试用例
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
public class MailServiceTest {
@Resource
MailService mailService;
@Test
public void sendSimpleMail() {
mailService.sendSimpleMail("431899405@qq.com",
"普通文本邮件",
"普通文本邮件内容测试");
}
}
测试结果
附录:QQ邮箱发邮件设置
1.开启SMTP服务
2.在配置开启SMTP之后,会返回给我们一个客户端授权码。这个授权码就是上文中用来发邮件的password,所以记下来。
发送html和基于模板的邮件
发送html邮件服务
sendHtmlMail函数的第一个参数是发送目标邮箱,第二个参数是邮件标题,第三个参数是邮件的正文(html)。
- 上一节中发送普通的文本文件邮件,使用的是SimpleMailMessage
- 下文代码中发送的正文是HTML的邮件,使用的是MimeMessage
/**
* 发送html邮件
*/
public void sendHtmlMail(String to, String subject, String content) throws MessagingException {
//注意这里使用的是MimeMessage
MimeMessage message = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true);
helper.setFrom(fromEmail);
helper.setTo(to);
helper.setSubject(subject);
//第二个参数是否是html,true表示发送的邮件正文是html文本
helper.setText(content, true);
mailSender.send(message);
}
测试用例,大家看到使用这种方式发送html邮件,我们将HTML以字符串拼接的方式写在Java代码里面,这样对于开发者而言非常的不友好。后文中我们会向大家介绍使用Java模板引擎来发送HTML邮件的方法,HTML书写更加友好。
@Test
public void sendHtmlMail() throws MessagingException {
mailService.sendHtmlMail("431899405@qq.com","一封html测试邮件","<body style=\"text-align: center;margin-left: auto;margin-right: auto;\">\n"
+ " <div id=\"welcome\" style=\"text-align: center;position: absolute;\" >\n"
+" <h3>\"一封html测试邮件\"</h3>\n"
+" <span>http://www.zimug.com</span>"
+ " <div style=\"text-align: center; padding: 10px\"><a style=\"text-decoration: none;\" href=\"https://zimug.com\" target=\"_bank\" >"
+ " <strong>我很用心,希望你有所收获</strong></a></div>\n"
+ " </div>\n" + "</body>");
}
邮件发送成功截图
基于freemarker模板的邮件
使用下面的方法发送邮件的前提是,你的项目里面已经正确的集成了freemarker模板引擎
基于freemarker模板邮件本质上,还是发送html邮件,只不过是有一个把模板转换成html字符串的过程。
@Autowired
private FreeMarkerConfigurer freeMarkerConfigurer;
@Test
public void sendTemplateMail() throws IOException, TemplateException, MessagingException {
//添加动态数据,替换模板里面的占位符
List<ArticleVO> articles = new ArrayList<>();
articles.add(new ArticleVO(1L,"dhy","spring boot1","内容一",new Date(),null));
articles.add(new ArticleVO(2L,"xpy","spring boot2","内容二",new Date(),null));
Template template = freeMarkerConfigurer.getConfiguration().getTemplate("freemarker-temp.html");
//将模板文件及数据渲染完成之后,转换为html字符串
Map<String,Object> model = new HashMap<>();
model.put("articles",articles);
String templateHtml = FreeMarkerTemplateUtils.processTemplateIntoString(template,model);
//发送邮件
mailService.sendHtmlMail("123456@qq.com","一封freemarker模板的html测试邮件",templateHtml);
}
模板文件freemarker-temp.html,使用freemarker语法编写,可以实现动态赋值。
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8" />
<title>freemarker简单示例</title>
</head>
<body>
<h1>Hello Freemarker</h1>
<table class="">
<tr>
<td>作者</td>
<td>教程名称</td>
<td>内容</td>
</tr>
<#list articles as article>
<tr>
<td>${article.author}</td>
<td>${article.title}</td>
<td>${article.content}</td>
</tr>
</#list>
</table>
</body>
</html>
ArticleVO
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class ArticleVO {
private Long id;
private String author;
private String title;
private String content;
private Date createTime;
private List<Reader> reader;
}
thymeleaf也可以实现,不妨试一试。
发送带附件和内联附件邮件
发送带附件的邮件
/**
* 发送带附件的邮件
*/
public void sendAttachmentsMail(String to, String subject, String content, String filePath) throws MessagingException {
MimeMessage message = mailSender.createMimeMessage();
//带附件第二个参数true
MimeMessageHelper helper = new MimeMessageHelper(message, true);
helper.setFrom(fromEmail);
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(message);
}
sendAttachmentsMail的第一个参数是发送目标邮箱,第二个参数是邮件的内容,第三个参数是邮件的附件。
运行如下的测试用例进行测试:
@Test
public void sendAttachmentsMailTest() throws MessagingException {
String filePath = "D:\\courseview\\springboot\\template.png";
mailService.sendAttachmentsMail("431899405@qq.com",
"这是一封带附件的邮件", "邮件中有附件,请注意查收!",
filePath);
}
邮件结果展示
发送内联附件的邮件
所谓的内联附件就是附件文件在邮件正文内显示,通常是一图片资源。
/**
* 发送正文中有静态资源的邮件
*/
public void sendResourceMail(String to, String subject, String content, String rscPath, String rscId) throws MessagingException {
MimeMessage message = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true);
helper.setFrom(fromEmail);
helper.setTo(to);
helper.setSubject(subject);
helper.setText(content, true);
//添加内联附件,指定一个资源id:rscId
FileSystemResource res = new FileSystemResource(new File(rscPath));
helper.addInline(rscId, res);
mailSender.send(message);
}
sendResourceMail方法的参数说明:
[ ] 参数一:发送邮件的目标邮箱
[ ] 参数二:文件的标题
[ ] 参数三:邮件的正文:html(含图片资源id:rscId)
[ ] 参数四:图片资源文件本地磁盘路径res
[ ] 参数五:图片资源文件的资源Id:rscId
参数三HTML文本发现正文中包含<img src=cid: rscId>
,就会根据参数五helper.addInline(rscId, res);
,找到参数四对应的资源文件res
,并渲染到HTML
里面。
下面的代码是测试用例,执行之后看结果
@Test
public void sendResourceMail() throws MessagingException {
String rscId = "dhy";
String content = "<html><body>这是有图片的邮件<br/><img src=\'cid:" + rscId + "\' ></body></html>";
String imgPath = "D:\\courseview\\springboot\\template.png";
mailService.sendResourceMail("431899405@qq.com",
"这邮件中含有图片",
content,
imgPath,
rscId);
}
邮件结果展示:
可参考文章
【SpringBoot总结】7. SpringBoot整合JavaMailSender实现邮件发送
注意连接超时的问题: 对应的邮箱不存在…