springboot+thymeleaf实现发Html邮件自由

news2024/11/16 19:49:21

2019年,我刚接触测试架构和测试开发类的工作时,经常会有自动化发邮件的功能,大都是从各个平台自动化统计一些数据出来,每周定时发一封邮件给领导交差,回过头来再看看我发的邮件,不美观,不专业。这2年,也有想过不要再费劲去拼样式+变量字符串了,但由于我打工仔繁忙的属性,一直拖到现在。这周项目有空闲时间,我研究了一下,弄了个模板出来,业务代码一套,就成了!!!!!

技术选型

springboot+thymeleaf

基础配置

配置

#application.properties
spring.mail.host=192.168.19.232    
spring.mail.username=bug@hookweb.com.cn   #发件人邮箱
spring.mail.password=emailqa              #发件人邮箱授权码,不是密码,如果有些企业邮箱本身不存在授权,直接用密码试试
spring.mail.protocol=smtp
spring.mail.default-encoding=UTF-8
spring.mail.port=25
spring.thymeleaf.prefix=classpath:/templates/

POM依赖

		<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-mail</artifactId>
            <version>2.1.5.RELEASE</version>
        </dependency>

HTML邮箱模板

最炫酷,最自由的方式,HTML模板任意定制,直接从网上下载最方便

<!DOCTYPE html>
<!--suppress ALL-->
<html xmlns:th="http://www.thymeleaf.org" xmlns:background-color="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="description" content="email code">
    <meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<!--邮箱验证码模板-->
<body>
<div style="background-color:#ECECEC; padding: 35px;">
    <table cellpadding="0" align="center"
           style="width: 800px;height: 100%; margin: 0px auto; text-align: left; position: relative; border-top-left-radius: 5px; border-top-right-radius: 5px; border-bottom-right-radius: 5px; border-bottom-left-radius: 5px; font-size: 14px; font-family:微软雅黑, 黑体; line-height: 1.5; box-shadow: rgb(153, 153, 153) 0px 0px 5px; border-collapse: collapse; background-position: initial initial; background-repeat: initial initial;background:#fff;">
        <tbody>
        <tr>
            <th valign="middle"
                style="height: 25px; line-height: 25px; padding: 15px 35px; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: RGB(148,0,211); background-color: RGB(148,0,211); border-top-left-radius: 5px; border-top-right-radius: 5px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px;">
                <font face="微软雅黑" size="5" style="color: rgb(255, 255, 255); " th:text="${content}">    <!--/*@thymesVar id="msg" type="java"*/-->

                </font>
            </th>
        </tr>
        <tr>
            <td style="word-break:break-all">
                <div style="padding:25px 35px 40px; background-color:#fff;opacity:0.8;">

                    <h2 style="margin: 5px 0px; ">
                        <font color="#333333" style="line-height: 20px; ">
                            <font style="line-height: 22px; " size="4">
                                尊敬的用户:</font>
                        </font>
                    </h2>
                    <!-- 中文 -->
                    <p >您好!感谢您使用****,您的账号正在进行邮箱验证,验证码为:<font color="#ff8c00"><!--/*@thymesVar id="recipienttype" type="java"*/-->


                        <div th:object="${bodyEntity}">
                            <p th:text="*{recipienttype}"></p>
                            <p th:text="*{address}"></p>
                        </div>

                    <p th:text="${code}"></p>
                    </font>,有效期30分钟,请尽快填写验证码完成验证!</p><br>

                    <div style="width:100%;margin:0 auto;">
                        <div style="padding:10px 10px 0;border-top:1px solid #ccc;color:#747474;margin-bottom:20px;line-height:1.3em;font-size:12px;">
                            <p>****团队</p>
                            <p>联系我们:********</p>
                            <br>
                            <p>此为系统邮件,请勿回复<br>
                                Please do not reply to this system email
                            </p>
                            <!--<p>©***</p>-->
                        </div>
                    </div>
                </div>
            </td>
        </tr>
        </tbody>
    </table>
</div>
</body>
</html>

基础发邮件服务

package com.send.mail.services;
import java.util.Map;
public interface MailService {
    void sendHtmlMailOne(String to, String subject, String content);
    void sendHtmlMailMulti(String[] to, String subject, String content);
}

基础发邮件服务实现

package com.send.mail.services.impl;

import com.send.mail.services.MailService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;
import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
@Service
public class MailServiceImpl implements MailService {
    @Value("${spring.mail.username}") //直接从配置文件获取username的值
    private String from;
    @Autowired
    private JavaMailSender javaMailSender;
    @Override
    public void sendHtmlMailOne(String to, String subject, String content) {
        try {
            MimeMessage message = javaMailSender.createMimeMessage();
            MimeMessageHelper helper = new MimeMessageHelper(message, true);
            helper.setTo(to);//收件者
            helper.setFrom(from);//发送者
            helper.setSubject(subject);//主题
            helper.setText(content, true);//第二个参数true表示邮件正文是HTML格式的,该参数不传默认为false。
            javaMailSender.send(message);
        } catch (MessagingException e) {
            System.out.println("发送失败");
        }
    }
    @Override
    public void sendHtmlMailMulti(String[] to, String subject, String content) {
        try {
            MimeMessage message = javaMailSender.createMimeMessage();
            MimeMessageHelper helper = new MimeMessageHelper(message, true);
            helper.setTo(to);//收件者
            helper.setFrom(from);//发送者
            helper.setSubject(subject);//主题
            helper.setText(content, true);//第二个参数true表示邮件正文是HTML格式的,该参数不传默认为false。
            javaMailSender.send(message);
        }catch (Exception e) {
            e.printStackTrace();
        }
    }
}

使用JavaMailSender发送邮件
注入JavaMailSender(由Spring容器管理)
使用MimeMessageHelper消息助手,可自定义设置发件人、收件人、抄送人等邮件信息

动态值

变量值

package com.send.mail.util;
import org.springframework.stereotype.Service;
@Service
public class GetCode {
    public String getCode() {
        String str = "123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; // no zero
        StringBuilder code = new StringBuilder();
        for (int i = 0; i < 6; i++) {
            int index = (int) (Math.random() * str.length());
            code.append(str.charAt(index));
        }
        return code.toString();
    }
}

对象传给HTML解析

package com.send.mail.util;
public class BodyEntity {
    private String recipienttype;
    private String address;
    public BodyEntity() {
    }
    public BodyEntity(String recipienttype, String address) {
        this.recipienttype = recipienttype;
        this.address = address;
    }
    public void setRecipienttype(String recipienttype) {
        this.recipienttype = recipienttype;
    }
    public void setAddress(String address) {
        this.address = address;
    }
    public String getRecipienttype() {
        return recipienttype;
    }
    public String getAddress() {
        return address;
    }
}

controller解析发送邮件

package com.send.mail.controller;
import com.send.mail.services.impl.MailServiceImpl;
import com.send.mail.util.BodyEntity;
import com.send.mail.util.GetCode;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;
import javax.mail.MessagingException;
import java.util.HashMap;
import java.util.Map;
@RestController
public class IndexController {
    @Autowired
    private MailServiceImpl mailService;
    @Autowired
    private TemplateEngine templateEngine;
    @Autowired
    private GetCode getCode;
    @GetMapping("/sendmail/{to}")
    public String sendmail(@PathVariable String to) throws MessagingException {
        //Thymeleaf提供了TemplateEngine来对模板进行渲染,通过Context构造模板中变量需要的值
        Context context = new Context();
        context.setVariable("title", "自定义的HTML内容标题");//设置templates模板里的title变量值
        context.setVariable("content","自定义的HTML内容标题");
        String mail = templateEngine.process("index.html", context);
        mailService.sendHtmlMailOne(to, "邮件标题", mail);
        return "sucess";
    }
    @GetMapping("/sendmailm/{to}")
    public String sendmailm(@PathVariable String[] to) throws MessagingException {
        //Thymeleaf提供了TemplateEngine来对模板进行渲染,通过Context构造模板中变量需要的值
        BodyEntity bodyEntity=new BodyEntity();
        bodyEntity.setRecipienttype("recipient's");
        bodyEntity.setAddress("danae@hookweb.com.cn");
        Context context = new Context();
        context.setVariable("title", "自定义的HTML内容标题");//设置templates模板里的title变量值
        context.setVariable("content","自定义的HTML内容标题");
        context.setVariable("code",getCode.getCode());
        context.setVariable("bodyEntity",bodyEntity);
        String mail = templateEngine.process("index.html", context);
        mailService.sendHtmlMailMulti(to, "邮件标题", mail);
        return "sucess";
    }
}

接口请求

在这里插入图片描述

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Android Jetpack:现代化Android开发的利器

Android Jetpack&#xff1a;现代化Android开发的利器 引言 随着移动应用的快速发展和用户体验的不断提升&#xff0c;现代化的Android应用开发变得愈发复杂和多样化。为了提高开发效率、简化代码、加速应用迭代&#xff0c;Google推出了Android Jetpack组件&#xff0c;成为现…

springboot零基础到项目实战

推荐教程&#xff1a; springboot零基础到项目实战 SpringBoot这门技术课程所包含的技术点其实并不是很多&#xff0c;但是围绕着SpringBoot的周边知识&#xff0c;也就是SpringBoot整合其他技术&#xff0c;这样的知识量很大&#xff0c;例如SpringBoot整合MyBatis等等。因此…

gitlab-ce升级方法

Centos7升级gitlab-ce&#xff1a; 1、记录当前版本 在升级前一定要做好备份&#xff0c;记录自己当前的gitlab-ce的版本&#xff1a; yum list | grep gitlab-ce 2、编辑/etc/gitlab/gitlab.rb文件&#xff1a; 1&#xff09;将下面几行注释取消。 说明&#xff1a; 1&am…

pytorch进阶学习(二):使用DataLoader读取自己的数据集

上一节使用的是官方数据集fashionminist进行训练&#xff0c;这节课使用自己搜集的数据集来进行数据的获取和训练。所需资源教学视频&#xff1a;https://www.bilibili.com/video/BV1by4y1b7hX/?spm_id_from333.1007.top_right_bar_window_history.content.click&vd_sourc…

建立数据驱动,关键字驱动和混合Selenium框架这些你了解吗

一、什么是Selenium框架&#xff1f; Selenium框架是一种代码结构&#xff0c;用于简化代码维护和提高代码可读性。框架涉及将整个代码分成较小的代码段&#xff0c;以测试特定的功能。 该代码的结构使得“数据集”与实际的“测试用例”分开&#xff0c;后者将测试Web应用程序…

【PyTorch】第八节:数据的预处理

作者&#x1f575;️‍♂️&#xff1a;让机器理解语言か 专栏&#x1f387;&#xff1a;PyTorch 描述&#x1f3a8;&#xff1a;PyTorch 是一个基于 Torch 的 Python 开源机器学习库。 寄语&#x1f493;&#xff1a;&#x1f43e;没有白走的路&#xff0c;每一步都算数&#…

【NVIDIA GPU 入门】综述

系列文章目录 文章目录系列文章目录前言一、概述二、GPU架构基础2.1 GPU概述2.2 GPU的架构2.3 自主查询GPU相关信息三、CUDA编程概念3.1 CUDA线程模型3.1 线程层次结构1.引入库2.读入数据总结参考文献前言 GPU作为机器学习的基础运算设备&#xff0c;基本上是无人不知无人不晓。…

【bsauce读论文】PSPRAY-基于时序侧信道的Linux内核堆利用技术

会议&#xff1a;USENIX Security’23 作者&#xff1a;来自 Seoul National University 的 Yoochan Lee、Byoungyoung Lee 等人。 主要内容&#xff1a;由于Linux内核的堆分配器SLUB开启的freelist随机化保护&#xff0c;所以堆相关的内核漏洞利用成功率较低&#xff08;平均…

BEV(一)---lift splat shoot

1. 算法原理 1.1 2D坐标与3D坐标的关系 如图&#xff0c;已知世界坐标系上的某点P&#xff08;Xc&#xff0c; Yc&#xff0c; Zc&#xff09;经过相机的内参矩阵可以获得唯一的图像坐标p&#xff08;x&#xff0c; y&#xff09;&#xff0c;但是反过来已知图像上某点p&…

软考初级程序员--学习

1、十进制 转 二进制 1.1、整数十进制87 转换为 二进制为 1010111 1.2 、小数十进制0.125 转为 二进制 为 0.001 使用乘2取整法&#xff0c;一直乘到没有小数 2、二进制 转 十进制 2.1、二进制1010111 转换为 十进制 2.2、 二进制小数0.001 转 十进制 3、循环队列 计算长度通用…

周赛341(模拟、双指针、树上DP)

文章目录周赛341[6376. 一最多的行](https://leetcode.cn/problems/row-with-maximum-ones/)暴力模拟[6350. 找出可整除性得分最大的整数](https://leetcode.cn/problems/find-the-maximum-divisibility-score/)暴力模拟[6375. 构造有效字符串的最少插入数](https://leetcode.c…

JVM系统优化实践(15):GC可视化工具实践

您好&#xff0c;我是湘王&#xff0c;这是我的CSDN博客&#xff0c;欢迎您来&#xff0c;欢迎您再来&#xff5e; 线上系统的JVM监测要么使用jstat、jmap、jhat等工具查看JVM状态&#xff0c;或者使用监控系统&#xff0c;如Zabbix、Prometheus、Open-FaIcon、Ganglia等。作为…

pyg的NeighborLoader和LinkNeighborLoader

NeighborLoader 1 数据格式要求 需要传入加载的属性值&#xff1a; class NeighborLoader(data: Union[Data, HeteroData, Tuple[FeatureStore, GraphStore]], num_neighbors: Union[List[int], Dict[Tuple[str, str, str], List[int]]], input_nodes: Union[Tensor, None…

进程调度的基本过程

进程调度的基本过程&#x1f50e; 进程是什么&#x1f50e; 进程管理&#x1f50e; 进程中结构体的属性进程标识符(PID)内存指针文件描述符表结构体中与进程调度相关的属性进程的状态进程的优先级进程的上下文进程的记账信息&#x1f50e; 总结&#x1f50e; 结尾&#x1f50e;…

(第十四届蓝桥真题) 整数删除(线段树+二分)

样例输入&#xff1a; 5 3 1 4 2 8 7 样例输出&#xff1a; 17 分析&#xff1a;这道题我想的比较复杂&#xff0c;不过复杂度还是够用的&#xff0c;我是用线段树二分来做的。 我们用线段树维护所有位置的最小值&#xff0c;那么我们每次删除一个数之前先求一遍最小值&a…

停车场管理系统文件录入(C++版)

❤️作者主页&#xff1a;微凉秋意 ✅作者简介&#xff1a;后端领域优质创作者&#x1f3c6;&#xff0c;CSDN内容合伙人&#x1f3c6;&#xff0c;阿里云专家博主&#x1f3c6; 文章目录一、案例需求描述1.1、汽车信息模块1.2、普通用户模块1.3、管理员用户模块二、案例分析三…

mysql:使用终端操作数据库

登录进入终端&#xff1a; mysql -u root -p 展示数据库 SHOW DATABASES; 创建数据库&#xff1a; CREATE DATABASE IF NOT EXISTS RUNOOB_TEST DEFAULT CHARSET utf8 COLLATE utf8_general_ci; 1. 如果数据库不存在则创建&#xff0c;存在则不创建。 2. 创建RUNOOB_TEST数据库…

ElasticSearch安装、启动、操作及概念简介

ElasticSearch快速入门 文件链接&#xff1a;https://pan.baidu.com/s/15kJtcHY-RAY3wzpJZIn4-w?pwd0k5a 提取码&#xff1a;0k5a 有些软件对于安装路径有一定的要求&#xff0c;例如&#xff1a;路径中不能有空格&#xff0c;不能有中文&#xff0c;不能有特殊符号&#xf…

JUC并发编程之ReentrantLock

1. 非公平锁实现原理 加锁解锁流程 构造器默认实现的是非公平锁 public ReentrantLock() {sync new NonfairSync();}NonfairSync 继承 Sync&#xff0c; Sync 继承 AbstractQueuedSynchronizer 没有竞争时 第一个竞争出现时 Thread-1 执行了 CAS 尝试将state 由 0 改为 1&…

Stable Diffusion免费(三个月)通过阿里云轻松部署服务

温馨提示&#xff1a;划重点&#xff0c;活动入口在这里喔&#xff0c;不要迷路了。 其实我就在AIGC_有没有一种可能&#xff0c;其实你早就在AIGC了&#xff1f;阿里云邀请你&#xff0c;体验一把AIGC级的毕加索、达芬奇、梵高等大师作画的快感。阿里云将提供免费云产品资源&…