Spring Boot 发送邮件(Thymeleaf 模板)

开发环境

项目 版本
Spring Boot 2.2.5
Java 1.8
Gradle 6.2.2

添加依赖

1
2
implementation('org.springframework.boot:spring-boot-starter-mail')
implementation('org.springframework.boot:spring-boot-starter-thymeleaf') 

添加配置

spring.mail.host=smtp
spring.mail.port=port
spring.mail.username=邮箱的用户名
spring.mail.password=邮箱的授权码(不是登录密码)
spring.mail.test-connection=true
# qq邮箱 必须启用ssl
spring.mail.properties.mail.smtp.ssl.enable=true
spring.mail.properties.mail.smtp.auth=true
# 超时设置,防止阻塞,有些是无限时间
spring.mail.properties.mail.smtp.connectiontimeout=5000
spring.mail.properties.mail.smtp.timeout=3000
spring.mail.properties.mail.smtp.writetimeout=5000

编写邮件发送助手组件

 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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
package com.spas.backend.util;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Component;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;

import javax.annotation.Resource;
import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import java.util.Map;

@Component
@Slf4j
public class EmailHelper {

  @Resource
  private JavaMailSender javaMailSender;

  @Resource
  private TemplateEngine templateEngine;

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

  public void sendSimpleMail(Map<String, Object> valueMap){

    MimeMessage mimeMessage = null;

    try{
      mimeMessage = javaMailSender.createMimeMessage();
      MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(mimeMessage, true);  // true 表示多部分,可添加内联资源
      // 设置邮件信息
      mimeMessageHelper.setFrom(senderMailAddress);
      mimeMessageHelper.setTo((String[]) valueMap.get("to"));
      mimeMessageHelper.setSubject(valueMap.get("title").toString());
      mimeMessageHelper.setSubject(valueMap.get("content").toString());
      // 利用 Thymeleaf 引擎渲染 HTML
      Context context = new Context();
      context.setVariables(valueMap);  // 设置注入的变量
      String content = this.templateEngine.process("mail",context);  // 模板设置为 "mail"
      // 设置邮件内容
      mimeMessageHelper.setText(content,true); // true 表示开启 html
      javaMailSender.send(mimeMessage);
    }catch (MessagingException e){
      log.error("发送邮件出错:" + e.getMessage() + e.getCause());
    }
  }
}

编写HTML模板mail.html

<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org">
<!--${government}-->
<!--${title}-->
<!--${suggestion}-->
<!--${deadline}-->
<!--${secret}-->
<!--${url}-->
<!--${officeName}-->
<!--${createTime}-->
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
    <title>${title}</title>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.3.1/css/bootstrap.min.css">
    <style>
        .contact-clean {
            background: #f1f7fc;
            padding: 80px 0;
        }

        a{
            text-decoration: none;
        }

        @media (max-width:767px) {
            .contact-clean {
                padding: 20px 0;
            }
        }

        .contact-clean form {
            max-width: 480px;
            width: 90%;
            margin: 0 auto;
            background-color: #ffffff;
            padding: 40px;
            border-radius: 4px;
            color: #505e6c;
            box-shadow: 1px 1px 5px rgba(0,0,0,0.1);
        }

        @media (max-width:767px) {
            .contact-clean form {
                padding: 30px;
            }
        }

        .contact-clean h2 {
            margin-top: 5px;
            font-weight: bold;
            font-size: 28px;
            margin-bottom: 36px;
            color: inherit;
        }

        .contact-clean .form-group:last-child {
            margin-bottom: 5px;
        }

        .contact-clean form .form-control {
            background: #fff;
            border-radius: 2px;
            box-shadow: 1px 1px 1px rgba(0,0,0,0.05);
            outline: none;
            color: inherit;
            padding-left: 12px;
            height: 42px;
        }

        .contact-clean form .form-control:focus {
            border: 1px solid #b2b2b2;
        }

        .contact-clean form textarea.form-control {
            min-height: 100px;
            max-height: 260px;
            padding-top: 10px;
            resize: vertical;
        }

        .contact-clean form .btn {
            padding: 16px 32px;
            border: none;
            background: none;
            box-shadow: none;
            text-shadow: none;
            opacity: 0.9;
            text-transform: uppercase;
            font-weight: bold;
            font-size: 13px;
            letter-spacing: 0.4px;
            line-height: 1;
            outline: none !important;
        }

        .contact-clean form .btn:hover {
            opacity: 1;
        }

        .contact-clean form .btn:active {
            transform: translateY(1px);
        }

        .contact-clean form .btn-primary {
            background-color: #055ada !important;
            margin-top: 15px;
            color: #fff;
        }
    </style>
</head>

<body>
<div class="contact-clean">
    <form method="post">
        <h2 class="text-center">检察建议送达通知</h2>
        <p th:text="|${government} : |"></p>
        <p th:text="${suggestion}"></p>
        <div class="alert alert-danger" role="alert"><span th:utext="|<strong>注意</strong> 请在收到通知后,&nbsp; ${deadline} &nbsp;时限内回复。请立即访问检察建议流程辅助办案系统,注册并登录,通过密码关联案件,以获取更多有效信息。|"></span></div>
        <div class="card">
            <div class="card-body">
                <p class="card-text" th:text="|关联密码:${secret}|"></p>
                <p class="card-text">检察建议流程辅助办案系统网址:<a th:href="${url}" target="_blank" th:text="${url}"></a></p>
                <p class="card-text" th:text="${officeName} + '发布,' +  ${createTime}"></p>
            </div>
        </div>
    </form>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.3.1/js/bootstrap.bundle.min.js"></script>
</body>

</html>

特别注意引入名称空间 xmlns:th="http://www.thymeleaf.org"

编写测试类

 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
32
33
34
35
package com.spas.backend;

import com.spas.backend.util.EmailHelper;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Map;

@SpringBootTest
public class MailTests {

  @Resource
  private EmailHelper emailHelper;

  @Test
  public void sendSuggestion() {
    Map<String,Object> valueMap = new HashMap<>();
    LocalDateTime localDateTime = LocalDateTime.now();
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    valueMap.put("to", new String[]{"handy1998@qq.com"});
    valueMap.put("title","检察建议送达通知");
    valueMap.put("government","宜昌市水利水电局");
    valueMap.put("suggestion","你好,这是你的检察建议");
    valueMap.put("deadline","2020-06-05 23:38:04");
    valueMap.put("secret","7b84f9cc92fb26290efe9c60be54864e");
    valueMap.put("url","https://www.spas.com");
    valueMap.put("officeName","宜昌市人民检察院");
    valueMap.put("createTime", localDateTime.format(formatter));
    emailHelper.sendSimpleMail(valueMap);
  }
}

大功告成

taOLzD-EUoTWo


updatedupdated2020-07-122020-07-12
加载评论