Spring Boot实战(七):Spring Boot实现仿博客园发送通知邮件

1,520 阅读3分钟

邮件服务已经是基础性服务了 ,是网站的必备功能之一,当注册了某些网站的时候,邮箱里通常会收到一封注册成功通知邮件或者点击激活账号的邮件,博客园也是如此。本文使用Spring Boot,通过QQ邮箱来模仿博客园发送一封通知邮件。

博客园发送的“欢迎您加入博客园”的主题邮件如图所示。这种通知邮件,只有登录用户名在变化,其它邮件内容均不变,很适合用邮件模板来处理。

image

模板可以实现显示与数据分离,将模板文件和数据通过模板引擎生成最终的HTML代码。

Thymeleaf是一个适用于Web和独立环境的现代服务器端Java模板引擎,能够处理HTML,XML,JavaScript,CSS甚至纯文本。Thymeleaf由于使用了标签属性做为语法,模版页面直接用浏览器渲染,与其它模板引擎(比如Freemaker)相比,Thymeleaf最大的特点是能够直接在浏览器中打开并正确显示模板页面,而不需要启动整个Web应用。

Thymeleaf作为Spring官方推荐的模板引擎,Spring boot对Thymeleaf支持比较友好,配置简单,这里使用Thymeleaf作为模板引擎。

下面正式开始实现仿博客园发送通知邮件。

1. pom.xml添加邮件和模板相关依赖

        <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>

2. application.property配置邮箱和thymelea模板

我使用的是QQ邮箱,需要获得QQ邮箱的授权码。

关于QQ邮箱生成授权码:进入QQ邮箱 --> 邮箱设置 --> 账户 --> POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV服务 --> 生成授权码 --> 手机发送验证短信 -->得到授权码

spring.mail.host=smtp.qq.com
spring.mail.username=QQ邮箱
spring.mail.password=授权码
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true  
spring.mail.properties.mail.smtp.starttls.required=true  

#thymelea模板配置
spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.suffix=.html
spring.thymeleaf.mode=HTML
spring.thymeleaf.encoding=UTF-8
spring.thymeleaf.servlet.content-type:text/html
#热部署文件,页面不产生缓存,及时更新
spring.thymeleaf.cache=false
spring.resources.chain.strategy.content.enabled=true
spring.resources.chain.strategy.content.paths=/**

3. 编写Service及其实现

Service中有两个方法:

sendSimpleMail用于发送简单的文本邮件,是一个比较基础的案例。

sendHtmlMail用于发送HTML邮件,发送通知邮件用的就是这个方法。其实模板邮件也就是HTML邮件中的一个子类。

MailService:

public interface MailService {
    public void sendSimpleMail(String to, String subject, String  content);
    public void sendHtmlMail(String to, String subject, String  content);
}

MailServiceImpl:

@Component
public class MailServiceImpl implements MailService {

    private final Logger logger =  LoggerFactory.getLogger(this.getClass());

    @Autowired
    private JavaMailSender mailSender;

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

    @Override
    public void sendSimpleMail(String to, String subject, String  content) {
        SimpleMailMessage message = new SimpleMailMessage();
        message.setFrom(from);
        message.setTo(to);//邮件接收者
        message.setSubject(subject);//邮件主题
        message.setText(content);//邮件内容
        try {
            mailSender.send(message);
            logger.info("发送简单邮件成功!");
        } catch (Exception e) {
            logger.error("发送简单邮件时发生异常!", e);
        }
    }

    @Override
    public void sendHtmlMail(String to, String subject, String  content) {
        MimeMessage message = mailSender.createMimeMessage();
        try {
            //true表示需要创建一个multipart message
            MimeMessageHelper helper = new  MimeMessageHelper(message, true);
            helper.setFrom(from);
            helper.setTo(to);
            helper.setSubject(subject);
            helper.setText(content, true);
            mailSender.send(message);
            logger.info("发送HTML邮件成功!");
        } catch (MessagingException e) {
            logger.error("发送HTML邮件时发生异常!", e);
        }
    }
}

4. 创建模板

在resorces/templates下创建emailTemplate.html模板,与模板配置中的spring.thymeleaf.prefix=classpath:/templates/对应,不然会找不到模板。

关于Thymeleaf的使用这里简单介绍一下:

引入命名空间:。不同的约束文档中,可能会出现不同含义的相同标记名称,引入名称空间可以避免混淆和冲突。

访问数据:#{user.name}

访问变量:${today}

输出URL: 博客园

更多详情的说明和规则请参见:Thymeleaf官方文档

emailTemplate.html:

<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org">
    <head>
        <meta charset="UTF-8" />
        <title>欢迎您加入博客园</title>
    </head>
    <body>
        <p>您好,您在博客园的帐户激活成功,您的登录用户名是:<span  th:text="${username}"></span></p>
        <p>--</p>
        <div>博客园(
            <a th:href="@{https://www.cnblogs.com  }">www.cnblogs.com</a>
            ) - 开发者的网上家园</div>
        <p>代码改变世界!</p>
    </body>
</html>

5. JUnit单元测试

使用Junit进行单元测试,pom.xml中已经默认配置好了,需要编写测试类和测试方法。测试类以xxxTest.java命名,测试方法上面加@Test注解就可以使用了。具体代码如下:

@RunWith(SpringRunner.class)
@SpringBootTest
public class EmailTest {

    @Autowired
    private MailService mailService;

    @Autowired
    private TemplateEngine templateEngine;

    @Test
    public void testSendSimpleMail() throws Exception {
        mailService.sendSimpleMail("xxx@qq.com", "测试发送简单文本邮件", "测试发送简单文本邮件");
    }

    @Test
    public void testSendTemplateMail() {
        Context context = new Context();
        context.setVariable("username", "shangguanhao");
        String emailContent = templateEngine.process("emailTemplate", context);
        mailService.sendHtmlMail("xxx@qq.com", "欢迎您加入博客园", emailContent);
    }

}

进行Junit测试,就可以发送一个简答的文本邮件和一个HTML的模板邮件,几乎和博客园的一模一样(如下图所示):

image

完整代码:GitHub地址

参考:springboot(十):邮件服务