springboot发送邮件,内容使用thymeleaf模板引擎排版

springboot发送邮件,内容使用thymeleaf模板引擎排版

      • 1、导入jar包
      • 2、yml设置
      • 3、收件人以及收件信息设置
      • 4、发邮件service
      • 5、模版页面
      • 6、controller

1、导入jar包

<!--发送邮件-->
  <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-mail</artifactId>
   </dependency>
<!--使用thymeleaf 形式-->
   <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-thymeleaf</artifactId>
   </dependency>

2、yml设置

发件邮箱信息设置:


spring:
  mail:
    host: smtp.xx.cn
    port: 465
    username: 你的邮箱
    password: 你的密码
#    default-encoding: UTF-8
    protocol: smtp
    properties: # 配置以SSL的方式发送, 这个需要使用这种方式并且端口是465
      mail:
        smtp:
          auth: true
          ssl:
            enable: true
            socketFactory:
              class: com.sun.mail.util.MailSSLSocketFactory
              fallback: false
        debug: true

3、收件人以及收件信息设置

@Getter
@Setter
public class AcceptMailParam {
    //标题
    private String title;
    //接收人邮件地址
    private String receiveEmail[];
    //抄送人邮件地址
    private String chaoSongPersonEmail[];
    
    //附件,value 文件的绝对地址/动态模板数据
    private Map<String, Object> attachment;
	
	//thymeleaf模版引擎页面对象数据:邮件排版内存
    List<OperateDataResultInfoView> pageViewList;
}

页面对象数据展示
@Setter
@Getter
public class OperateDataResultInfoView {

    private Long id;

    /**
     * 存储当前年月,eg:202301
     */
    private Integer curMonth;
    /**
     * 库名
     */
    private String dbName;
    /**
     * 表名
     */
    private String tableName;

    /**
     * 计划生成数据量
     */
    private Long planGenDataCnt;

    /**
     * 实际生成数据量
     */
    private Long actualGenDataCnt;

    /**
     * 备注
     */
    private String remark;

    private String gmtCreate;

    private String gmtModified;

    /* *
     * 剩余待生成数据量
     */
    private Long remainToGenCnt;

    /* *
     * 生成数据成功率(实际生成数量/计划生成数量),单位%
     */
    private BigDecimal genDataSuccessRate;

/**模拟生成数据*/
    public OperateDataResultInfoView() {

        this.id = ThreadLocalRandom.current().nextLong(100L, 999L);
        this.curMonth = DateUtil.getPreMonth();
        String[] dbAndTableName = ("dbName" + id + ".tableName" + id).split("\\.");
        this.dbName = dbAndTableName[0];
        this.tableName = dbAndTableName[1];
        this.planGenDataCnt = id + ThreadLocalRandom.current().nextLong(10L, 99L);
        this.actualGenDataCnt = id;
        this.remark = null;
        this.gmtCreate = DateUtil.getNowStr();
        this.gmtModified = DateUtil.getNowStr();
        this.remainToGenCnt = (planGenDataCnt - actualGenDataCnt) >= 0 ? (planGenDataCnt - actualGenDataCnt) : 0;

        BigDecimal rate = new BigDecimal(actualGenDataCnt).divide(new BigDecimal(planGenDataCnt), 4, BigDecimal.ROUND_HALF_UP);
        this.genDataSuccessRate = rate.compareTo(new BigDecimal("1")) >= 0 ? new BigDecimal("100") : rate.multiply(new BigDecimal("100")).setScale(2, BigDecimal.ROUND_HALF_UP);
    }
}

4、发邮件service

public interface SendMailService {
    /**
     * 邮件内容排版调试
     */
    AcceptMailParam getMailContentAndSendMail(Integer curMonth);
}

/**
     * 获取指定月份的邮件【邮件内容:生成数据的结果集 信息】
     * 次月1日8点 发送
     */
    @Override
    public AcceptMailParam getMailContentAndSendMail(Integer curMonth) {
        AcceptMailParam acceptMailParam = new AcceptMailParam();
        List<OperateDataResultInfoView> pageViewList = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            pageViewList.add(new OperateDataResultInfoView());
        }
        Collections.sort(pageViewList, Comparator.comparing(OperateDataResultInfoView::getId).reversed());
        acceptMailParam.setPageViewList(pageViewList);

        String[] emails = {"xxx1@qq.com"};
        String[] chaoSongPerson = {"xx2@qq.com"};
        //收件人,支持多人
        acceptMailParam.setReceiveEmail(emails);
        //抄送人,支持多人
        acceptMailParam.setChaoSongPersonEmail(chaoSongPerson);
        acceptMailParam.setTitle("统计业务表生成数据结果");

        //添加附件
        Map<String, Object> map = new HashMap<>();
        //key为邮件附件文件名称,路径改为你的服务器路径即可,可添加不同类型文件
        map.put("1-test1.zip", "/Users/gina/xx/data/test2.zip");
        map.put("2-test2.xlsx", "/Users/gina/xx/data/test1.xlsx");
        acceptMailParam.setAttachment(map);
        
        //调试邮件内容排版时,此处可注释掉。
        //this.sendTemplateMail(acceptMailParam,"/mail/list");
        return acceptMailParam;
    }

5、模版页面

在resources下,在路径templates/mail/下添加文件list.html

<!DOCTYPE html>

<html xmlns:th="http://www.thymeleaf.org">

<style>
  tr.odd td {
    background-color: #f0faaa;
  }

  td.number {
    text-align: right;
  }


  table {
    width: 100%;
    border: 1px solid #000;
    border-collapse: collapse;
  }

  table > tbody > tr > td, table > thead > tr > th {
    padding: 2px 10px;
    border-left: 1px dotted #000000;
    vertical-align: top;
    line-height: 20px;
  }

  table > tbody > tr, table > thead > tr {
    border-bottom: 1px solid #000000;
  }

  table th {
    background-color: #99cc33;
  }

  table > tbody > tr > td > a, table > tbody > tr > td > a:hover {
    text-decoration: none;
    font-weight: bold;
    background-color: #352726;
    padding: 2px 10px;
    color: #f0faaa;
    margin-left: 10px;
    text-transform: uppercase;
    border: 0px;
  }

</style>
  <head>
    <title>统计业务表生成数据结果</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
  </head>
  <body>
    <h1>统计业务表生成数据结果</h1>
    <table>
      <tr>
        <th>生成月份</th>
        <th>库名</th>
        <th>表名</th>
        <th>计划生成()</th>
        <th>实际生成()</th>
        <th>成功率%</th>
        <th>未生成()</th>
        <th>创建时间</th>
        <th>更新时间</th>
        <th>备注</th>
      </tr>
      <tr th:each="o : ${pageViewList}" th:class="${o.id % 2 == 0}? 'odd'" >
        <td th:text="${o.curMonth}"   ></td>
        <td th:text="${o.dbName}" ></td>
        <td th:text="${o.tableName}" ></td>
        <td th:text="${o.planGenDataCnt}" ></td>
        <td th:text="${o.actualGenDataCnt}"></td>
        <td th:text="${o.genDataSuccessRate}"></td>
        <td th:text="${o.remainToGenCnt}"></td>
        <td th:text="${o.gmtCreate}"></td>
        <td th:text="${o.gmtModified}"></td>
        <td th:text="${o.remark}"></td>
      </tr>
    </table>
  </body>
</html>

6、controller

@Controller
@Slf4j
public class SendMailController {

    /**
     * 调试生成的页面样式,不发邮件
     * 数据处理结果集view
     */
    @Resource
    private SendMailService sendMailService;

    /** 点此可直接访问
     * http://localhost:8081/sendMail?curMonth=202311
    */
    @RequestMapping("sendMail")
    public String sendMail(Model model, @RequestParam(name = "curMonth") Integer curMonth) {
        try {
            AcceptMailParam acceptMailParam = sendMailService.getMailContentAndSendMail(curMonth);
            model.addAttribute("title", acceptMailParam.getTitle());
            model.addAttribute("pageViewList", acceptMailParam.getPageViewList());
        } catch (Exception e) {
            log.error("sendMail fail ,msg={}", e.getMessage());
        }
        return "mail/list";
    }
}

7、启动服务后,访问页面展示:
在这里插入图片描述

邮箱内容样式为:
在这里插入图片描述

有对thymeleaf感兴趣的同学可通过中文官网去了解:thymeleaf中文官网

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/248882.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

lv12 linux内核的安装与加载

目录 1 tftp加载Linux内核及rootfs 1.1 uboot内核启动命令 1.2 uboot自启动参数环境变量 1.3 实验 2 EMMC加载Linux 内核及rootfs ​编辑 2.1 emmc中写入uimage ​编辑 2.2 emmc中写入dtb 2.3 emmc中写入根文件系统 2.4 设置环境变量 3 tftp加载Linux内核nfs挂载ro…

Tomcat-安装部署(源码包安装)

一、简介 Tomcat 是由 Apache 开发的一个 Servlet 容器&#xff0c;实现了对 Servlet 和 JSP 的支持&#xff0c;并提供了作为Web服务器的一些特有功能&#xff0c;如Tomcat管理和控制平台、安全域管理和Tomcat阀等。 简单来说&#xff0c;Tomcat是一个WEB应用程序的托管平台…

设计模式-策略(Strategy)模式

又被称为政策&#xff08;方针&#xff09;模式策略模式(Strategy Design Pattern)&#xff1a;封装可以互换的行为&#xff0c;并使用委托来决定要使用哪一个策略模式是一种行为设计模式&#xff0c;它能让你定义一系列算法&#xff0c;并将每种算法分别放入独立的类中&#x…

【从零开始学习--设计模式--装饰者模式】

返回首页 前言 感谢各位同学的关注与支持&#xff0c;我会一直更新此专题&#xff0c;竭尽所能整理出更为详细的内容分享给大家&#xff0c;但碍于时间及精力有限&#xff0c;代码分享较少&#xff0c;后续会把所有代码示例整理到github&#xff0c;敬请期待。 此章节介绍装…

【Jmeter】Jmeter基础5-Jmeter元件介绍之线程(用户)

2.5.1、线程组 一个线程组即一个虚拟用户组&#xff0c;线程组中的每个线程即为1个虚拟用户&#xff0c;每个线程互相隔离&#xff0c;互不影响参数说明&#xff1a; 在取样器错误后要执行的动作 继续&#xff1a;忽略错误&#xff0c;继续执行启动下一进程循环&#xff1a; 终…

12G全国30米高程DEM原始数据

但可能大部分朋友更关注国内范围的30米高程DEM原始数据有多大&#xff0c;以及数据的具体覆盖情况。 我们在这里&#xff0c;再为大家分享全国30米高程DEM原始数据的基本情况。 全国30米高程DEM原始数据 全国30米高程DEM原始数据共分1159个文件块&#xff0c;每个文件块在经…

Go delve调试工具的简单应用

Delve是个啥 Delve is a debugger for the Go programming language. The goal of the project is to provide a simple, full featured debugging tool for Go. Delve should be easy to invoke and easy to use. Chances are if you’re using a debugger, things aren’t go…

机器学习练习题

例1: 解&#xff1a; 最大似然估计&#xff1a; P &#xff08;男&#xff09; 8 / 20 0.4 &#xff0c; P &#xff08;女&#xff09; 12 / 20 0.6 P&#xff08;男&#xff09; 8/200.4&#xff0c;P&#xff08;女&#xff09; 12/20 0.6 P&#xff08;男&#xff0…

three.js模拟太阳系

地球的旋转轨迹目前设置为了圆形&#xff0c;效果&#xff1a; <template><div><el-container><el-main><div class"box-card-left"><div id"threejs" style"border: 1px solid red"></div><div c…

服务器被攻击宕机的一些小建议

现在网络攻击屡有发生&#xff0c;任何网站服务器都面临这样的危险&#xff0c;服务器被攻击造成的崩溃宕机是损失是我们无法估量的。网络攻击我们无法预测&#xff0c;但做好防御措施是必须的&#xff0c;建议所有的网站都要做好防范措施&#xff0c;准备相应的防护预案&#…

RT-DETR 目标过线计数

使用 Ultralytics RT-DETR 进行目标计数 🚀 实际应用场景 物流水产养殖使用 Ultralytics RT-DETR 进行传送带包裹计数使用 Ultralytics RT-DETR 在海中进行鱼类计数请使用最新代码(2023年12月8日后),旧版本不支持! 示例 “目标计数示例” 目标计数 from ultralytics

高并发如何实现单用户信息查询接口

高并发如何实现单用户信息查询接口 故事情节 产品&#xff1a;小李&#xff0c;有个单用户信息查询的功能&#xff0c;需要你实现一下小李&#xff1a;这还不简单&#xff0c;两分钟我给你实现两分钟过去…小李&#xff1a;欧克了&#xff0c;部署上线了运维&#xff1a;哪个…

git checkout进行更改分支

git clone https://gitee.com/yaleguo1/minit-learning-demo.git下载代码。 cd minit-learning-demo/进入目录里边。 ls -l看一下当前分支的内容。 git checkout geek_chapter02更改分支到geek_chapter02。 ls -l看一下目录里边的内容。

Python 自动化之收发邮件(二)

发邮件之Windows进程监控 文章目录 发邮件之Windows进程监控前言一、基本内容二、基本结构三、库模块四、函数模块1.进程监控2.邮件发送 五、程序运行模块1.获取时间2.用户输入3.进程监控3.1进程启动发邮件3.2进程停止发邮件 总结 前言 上一篇简单写了一下如何进行邮件的收发操…

NXP应用随记(四):eMios阅读随记-整体功能概述

目录 1、eMios IP介绍 2、时钟结构 3、通道类型 4、功能介绍 5、中断与DMA 6、EMIOS -通道分配建议(针对S32K312) 1、eMios IP介绍 Emios是什么&#xff1f;eMIOS提供了独立的通道(UCs)&#xff0c;您可以配置这些通道来为不同的功能生成或测量时间事件。 每个eMIOS实例最…

智能插座是什么

智能插座 电工电气百科 文章目录 智能插座前言一、智能插座是什么二、智能插座的类别三、智能插座的原理总结 前言 智能插座的应用广泛&#xff0c;可以用于智能家居系统中的电器控制&#xff0c;也可以应用在办公室、商业场所和工业控制中&#xff0c;方便快捷地实现电器的远…

锁--07_2---- index merge(索引合并)引起的死锁

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 案例分析生产背景死锁日志表结构执行计划 EXPLAN为什么会用 index_merge&#xff08;索引合并&#xff09;为什么用了 index_merge就死锁了解决方案注&#xff1a;M…

算法训练营Day14

#Java #二叉树层次遍历 #反转二叉树 开源学习资料 二叉树的层次遍历&#xff1a;力扣题目链接 二叉树的层次遍历很好理解&#xff1a; 就是从根结点一层一层地往下遍历&#xff08;同一层&#xff0c;从左到右&#xff09;&#xff1a; 迭代的方式很好理解&#xff1a;就是…

Netty常见的设计模式

简介 设计模式在软件开发中起着至关重要的作用&#xff0c;它们是解决常见问题的经过验证的解决方案。而Netty作为一个优秀的网络应用程序框架&#xff0c;同样也采用了许多设计模式来提供高性能和可扩展性。在本文中&#xff0c;我们将探讨Netty中使用的一些关键设计模式&…

TS系列-keyof的妙用

案例1 1、如果&#xff0c;有一个接口&#xff0c;某个变量的类型&#xff0c;是这个接口的 key &#xff1f; keyof 后面可以跟 一个对象类型或者一个接口类型keyof 是把后面 对象或者接口 的 键 都提取出来&#xff0c;组成一个联合类型 interface IStudentAttr {name: stri…
最新文章