转载

轻松搞定 SpringBoot 的邮件服务

轻松搞定 SpringBoot 的邮件服务

轻松搞定 SpringBoot 的邮件服务

作者 | BoCong-Deng

来源 | CSDN博客

出品 | CSDN(ID:CSDNnews)

写在前面

我们都知道,如果系统出现预警,或者有一些监控需求,我们可以通过发送短信或者邮件来进行通知,本篇文章呢,我就打算来讲解一下SpringBoot的邮件服务。

我们都知道发送邮件应该是网站的必备功能之一,什么注册验证,忘记密码或者是给用户发送营销信息。以前我们会使用 JavaMail 相关 api 来写发送邮件的相关代码,后来 Spring 推出了 JavaMailSender 更加简化了邮件发送的过程,在之后 SpringBoot 对此进行了封装,就有了现在的 spring-boot-starter-mail ,如果你看了我前面的文章的话,就会知道,SpringBoot把大部分的需求封装成了一个个场景启动器,而mail也就是相应的场景启动器。

轻松搞定 SpringBoot 的邮件服务

了解邮件服务

经常出现和邮件相关的协议是SMTP、IMAP和POP3,所以在这里我们首先来认识了解这三个协议。

SMTP全称为Simple Mail Transfer Protocol(简单邮件传输协议),它是一组用于从源地址到目的地址传输邮件的规范,通过它来控制邮件的中转方式。SMTP认证要求必须提供账号和密码才能登陆服务器,其设计目的在于避免用户受到垃圾邮件的侵扰。

IMAP全称为Internet Message Access Protocol(互联网邮件访问协议),IMAP允许从邮件服务器上获取邮件的信息、下载邮件等。IMAP与POP类似,都是一种邮件获取协议。

POP3全称为Post Office Protocol 3(邮局协议),POP3支持客户端远程管理服务器端的邮件。POP3常用于“离线”邮件处理,即允许客户端下载服务器邮件,然后服务器上的邮件将会被删除。目前很多POP3的邮件服务器只提供下载邮件功能,服务器本身并不删除邮件,这种属于改进版的POP3协议。

那么问题来了,IMAP和POP3协议有什么不同呢?两者最大的区别在于,IMAP允许双向通信,即在客户端的操作会反馈到服务器上,例如在客户端收取邮件、标记已读等操作,服务器会跟着同步这些操作。而对于POP协议虽然也允许客户端下载服务器邮件,但是在客户端的操作并不会同步到服务器上面的,例如在客户端收取或标记已读邮件,服务器不会同步这些操作。

轻松搞定 SpringBoot 的邮件服务

SpringBoot相关类

SpringBoot中针对邮件服务的两个工具类是,JavaMailSender和JavaMailSenderImpl,它们是Spring官方提供的集成邮件服务的接口和实现类,以简单高效的设计著称,目前是Java后端发送邮件和集成邮件服务的主流工具。那如何通过JavaMailSenderImpl发送邮件?非常简单,直接在业务类注入JavaMailSenderImpl并调用send方法发送邮件。其中简单邮件可以通过SimpleMailMessage来发送邮件,而复杂的邮件(例如添加附件)可以借助MimeMessageHelper来构建MimeMessage发送邮件。

我们不难理解,SpringBoot对于邮件服务能做到开箱即用,其实就是基于官方内置的自动配置,翻看源码可知晓邮件自动配置类(MailSenderPropertiesConfiguration) 为上下文提供了邮件服务实例(JavaMailSenderImpl)。

轻松搞定 SpringBoot 的邮件服务

具体教程

配置

首先我们创建一个新的项目,只要包含最基本的web场景就可以了,然后我们在pom.xml中引入依赖就可以了,依赖如下:

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

接着,我们在application.properties主配置文件中对mail进行相关的配置,配置内容如下,我做了相关注释

1spring.mail.host=smtp.163.com
2spring.mail.username=amazing
3spring.mail.password=xxxxxx  #这里填的不是账号密码,是的第三方登录校验码
4spring.mail.default-encoding=UTF-8
5mail.fromMail.address=amazing@163.com

上面的邮箱服务器的地址,我这里放出一下常用有限发邮箱服务器地址

 1QQ邮箱(mail.qq.com)
 2POP3服务器地址:pop.qq.com(端口:110)
 3SMTP服务器地址:smtp.qq.com(端口:25)
 4SMTP服务器需要身份验证。
 5
 6网易邮箱(163.com):
 7POP3服务器地址:pop.163.com(端口:110)
 8SMTP服务器地址:smtp.163.com(端口:25)
 9
10谷歌邮箱(google.com):
11POP3服务器地址:pop.gmail.com(SSL启用端口:995)
12SMTP服务器地址:smtp.gmail.com(SSL启用端口:587)
13
14阿里云邮箱(mail.aliyun.com):
15POP3服务器地址:pop3.aliyun.com(SSL加密端口:995;非加密端口:110)
16SMTP服务器地址:smtp.aliyun.com(SSL加密端口:465;非加密端口:25)
17IMAP服务器地址:imap.aliyun.com(SSL加密端口:993;非加密端口:143)
18
19新浪邮箱(sina.com):
20POP3服务器地址:pop3.sina.com.cn(端口:110)
21SMTP服务器地址:smtp.sina.com.cn(端口:25)

简单使用

这样就完成了我们SpringBoot使用邮件服务的基本配置,那么接下来我们简单使用一下,首先编写Service,目录结构如下

轻松搞定 SpringBoot 的邮件服务

1public interface MailService {
2    public void sendSimpleMail(String to, String subject, String content);
3}
 1@Component
 2public class MailServiceImpl implements MailService{
 3
 4    private final Logger logger = LoggerFactory.getLogger(this.getClass());
 5
 6    @Autowired
 7    private JavaMailSender mailSender;
 8
 9    @Value("${mail.fromMail.addr}")
10    private String from;
11
12    @Override
13    public void sendSimpleMail(String to, String subject, String content) {
14        SimpleMailMessage message = new SimpleMailMessage();
15        message.setFrom(from);
16        message.setTo(to);
17        message.setSubject(subject);
18        message.setText(content);
19
20        try {
21            mailSender.send(message);
22            logger.info("简单邮件已经发送。");
23        } catch (Exception e) {
24            logger.error("发送简单邮件时发生异常!", e);
25        }
26
27    }
28}

编写 test 类进行测试,至此一个简单的文本发送就完成了。

轻松搞定 SpringBoot 的邮件服务

轻松搞定 SpringBoot 的邮件服务

丰富邮件内容

但是在正常使用的过程中,我们通常在邮件中加入图片或者附件来丰富邮件的内容,下面讲介绍如何使用 Spring Boot 来发送丰富的邮件。

发送 html 格式邮件

其它都不变在 MailService 添加 sendHtmlMail 方法

 1public void sendHtmlMail(String to, String subject, String content) {
 2    MimeMessage message = mailSender.createMimeMessage();
 3
 4    try {
 5        //true表示需要创建一个multipart message
 6        MimeMessageHelper helper = new MimeMessageHelper(message, true);
 7        helper.setFrom(from);
 8        helper.setTo(to);
 9        helper.setSubject(subject);
10        helper.setText(content, true);
11
12        mailSender.send(message);
13        logger.info("html邮件发送成功");
14    } catch (MessagingException e) {
15        logger.error("发送html邮件时发生异常!", e);
16    }
17}

在测试类中构建 html 内容,测试发送

1@Test
2public void testHtmlMail() throws Exception {
3    String content="<html>/n" +
4            "<body>/n" +
5            "    <h3>hello world ! 这是一封Html邮件!</h3>/n" +
6            "</body>/n" +
7            "</html>";
8    MailService.sendHtmlMail("xxxxxx@163.com","test simple mail",content);
9}

发送带附件的邮件

还是老样子,在 MailService 添加 sendAttachmentsMail 方法。

 1public void sendAttachmentsMail(String to, String subject, String content, String filePath){
 2    MimeMessage message = mailSender.createMimeMessage();
 3
 4    try {
 5        MimeMessageHelper helper = new MimeMessageHelper(message, true);
 6        helper.setFrom(from);
 7        helper.setTo(to);
 8        helper.setSubject(subject);
 9        helper.setText(content, true);
10
11        FileSystemResource file = new FileSystemResource(new File(filePath));
12        String fileName = filePath.substring(filePath.lastIndexOf(File.separator));
13        helper.addAttachment(fileName, file);
14
15        mailSender.send(message);
16        logger.info("带附件的邮件已经发送。");
17    } catch (MessagingException e) {
18        logger.error("发送带附件的邮件时发生异常!", e);
19    }
20}

添加多个附件可以使用多条 helper.addAttachment(fileName, file),然后在测试类中添加测试方法

1@Test
2public void sendAttachmentsMail() {
3    String filePath="e://tmp//application.log";
4    mailService.sendAttachmentsMail("xxxxx@163.com", "主题:带附件的邮件", "有附件,请查收!", filePath);
5}

发送带静态资源的邮件

邮件中的静态资源一般就是指图片,在 MailService 添加 sendAttachmentsMail 方法。

 1public void sendInlineResourceMail(String to, String subject, String content, String rscPath, String rscId){
 2    MimeMessage message = mailSender.createMimeMessage();
 3
 4    try {
 5        MimeMessageHelper helper = new MimeMessageHelper(message, true);
 6        helper.setFrom(from);
 7        helper.setTo(to);
 8        helper.setSubject(subject);
 9        helper.setText(content, true);
10
11        FileSystemResource res = new FileSystemResource(new File(rscPath));
12        helper.addInline(rscId, res);
13
14        mailSender.send(message);
15        logger.info("嵌入静态资源的邮件已经发送。");
16    } catch (MessagingException e) {
17        logger.error("发送嵌入静态资源的邮件时发生异常!", e);
18    }
19}

在测试类中添加测试方法

1@Test
2public void sendInlineResourceMail() {
3    String rscId = "neo006";
4    String content="<html><body>这是有图片的邮件:<img src=/'cid:" + rscId + "/' ></body></html>";
5    String imgPath = "C://Users//summer//Pictures//favicon.png";
6
7    mailService.sendInlineResourceMail("XXXXX@163.com", "主题:这是有图片的邮件", content, imgPath, rscId);
8}

添加多个图片可以使用多条 <img src='cid:" + rscId + "' >helper.addInline(rscId, res) 来实现

轻松搞定 SpringBoot 的邮件服务

邮件系统

上面发送邮件的基础服务就这些了,但是如果我们要做成一个邮件系统的话还需要考虑以下几个问题,首先是邮件模板的问题,我们会经常收到类似这样的邮件

轻松搞定 SpringBoot 的邮件服务

其中只有 neo 这个用户名在变化,其它邮件内容均不变,如果每次发送邮件都需要手动拼接的话会不够优雅,并且每次模板的修改都需要改动代码的话也很不方便,因此对于这类邮件需求,都建议做成邮件模板来处理。模板的本质很简单,就是在模板中替换变化的参数,转换为 html 字符串即可,这里以thymeleaf为例来演示,第一步当然是导入thymeleaf的包啦。

1<dependency>
2    <groupId>org.springframework.boot</groupId>
3    <artifactId>spring-boot-starter-thymeleaf</artifactId>
4</dependency>

然后在在 resorces/templates 下创建 emailTemplate.html

 1<!DOCTYPE html>
 2<html lang="zh" xmlns:th="http://www.thymeleaf.org">
 3    <head>
 4        <meta charset="UTF-8"/>
 5        <title>Title</title>
 6    </head>
 7    <body>
 8        您好,这是验证邮件,请点击下面的链接完成验证,<br/>
 9        <a href="#" th:href="@{ http://www.xxx.com/neo/{id}(id=${id}) }">激活账号</a>
10    </body>
11</html>
1@Test
2public void sendTemplateMail() {
3    //创建邮件正文
4    Context context = new Context();
5    context.setVariable("id", "006");
6    String emailContent = templateEngine.process("emailTemplate", context);
7
8    mailService.sendHtmlMail("ityouknow@126.com","主题:这是模板邮件",emailContent);
9}

当然啦,这里要强调一点的是,我们在实现邮箱服务的时候,因为各种原因,总会有邮件发送失败的情况,比如:邮件发送过于频繁、网络异常等。在出现这种情况的时候,我们一般会考虑重新重试发送邮件,会分为以下几个步骤来实现:

  • 接收到发送邮件请求,首先记录请求并且入库。

  • 调用邮件发送接口发送邮件,并且将发送结果记录入库。

  • 启动定时系统扫描时间段内,未发送成功并且重试次数小于3次的邮件,进行再次发送

轻松搞定 SpringBoot 的邮件服务

最后

很多时候邮件发送并不是我们主业务必须关注的结果,比如通知类、提醒类的业务可以允许延时或者失败。这个时候可以采用异步的方式来发送邮件,加快主交易执行速度,在实际项目中可以采用MQ发送邮件相关参数,监听到消息队列之后启动发送邮件。

原文链接:

https://blog.csdn.net/DBC_121/article/details/104687395

推荐阅读 

原文  http://mp.weixin.qq.com/s?__biz=MjM5MjAwODM4MA==&mid=2650740549&idx=3&sn=171aa1aeb2ed09f37e46333fc06b2d3c
正文到此结束
Loading...