使用 Spring Email 和 Thymeleaf 技术,向新注册用户发送激活邮件(一)

这篇内容对应"2.1 发送邮件"小节

邮箱设置

需要去邮箱对应的官方客户端软件或网站开启IMAP/SMTP服务或POP3/SMTP服务器
在这里插入图片描述
如果不开启,就无法使用第三方用户代理,只能走第官方的电子邮件客户端软件或网站,用户代理就是电子邮件客户端软件。

开启之后,我们就可以用Spring Email技术将整合的JavaMailSender作为发送邮件的用户代理。
在这里插入图片描述

Spring Email

导入Jar包

要想使用邮件Spring整合的邮件功能,需要导入spring boot start mail Jar包

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

邮箱参数配置

不要将邮箱相关参数写死在Java程序中,而是应该写作配置文件中,方便以后修改。
邮箱相关参数:

  • host:电子邮件服务器域名,Spring Email用户代理需要向那个服务器发送邮件
  • port:端口,20 世纪 90 年代,一些电子邮件服务提供商已开始使用 SMTPS,当时使用的是 安全套接字层协议 (SSL),这是 TLS 的原始版本,现已弃用。他们为此指定了端口 465,尽管没有任何官方互联网机构批准使用该端口。
  • protocol:用户代理向电子邮件服务器发送邮件所使用的协议,注意smtp与smtps不一样
  • username:邮件发送发的邮箱
  • password:邮件发送方的密码 因为SMTP协议认证要求必须提供账户名和密码才能登录服务器,其设计目的在于避免用户受到垃圾邮件的侵扰。
  • properties.mail.smtp.ssl.enable: 是否启用安全连接

配置文件如下:

spring:
    mail:
        host: smtp.sina.com    
        port: 465
        properties:
            mail:
                smtp:
                    ssl:
                        enable: true
        protocol: smtps
        username: nowcoder@sina.com
        password: nowcoder123

使用JavaMailSender发送邮件

JavaMailSender是一个接口类,我们通过其实现类JavaMailSenderImpl来进行邮件的发送,发送邮件的逻辑最好封装一下,这样可以反复的使用,复用代码。
所以,新建一个包,包名叫util,专门用于存放工具类
在这里插入图片描述
然后,在util报下新建一个MailClient类,邮箱客户端,因为JavaMailSender在发送邮件的过程中,扮演的角色是用户代理(电子邮件客户端软件)
在这里插入图片描述
所以将这个类取名为MaillClient。

一封邮件邮件的格式:
在这里插入图片描述
JavaMailSender接口源码:

public interface JavaMailSender extends MailSender {
    MimeMessage createMimeMessage();

    MimeMessage createMimeMessage(InputStream var1) throws MailException;

    void send(MimeMessage var1) throws MailException;

    void send(MimeMessage... var1) throws MailException;

    void send(MimeMessagePreparator var1) throws MailException;

    void send(MimeMessagePreparator... var1) throws MailException;
}

可以发现JavaMailSender 接口就两类方法
在这里插入图片描述
send方法从字面既可以理解,这是用于发邮件的。

createMimeMessage 方法是干什么的呢?

要想理解这个方法,主要是要理解中间Mime的含义,Mime全称是Multipurpose Internet Mail Extension,多用途因特网邮件拓展。

那这个MIME有什么用呢?前面我们在配置时,使用的邮件传输协议时smtps,该协议与smtp一样,都支持传输ASCCII码文本数据,不可以传输其他可执行文件或者二进制对象,甚至连中文文字都传输不了。

SMTP无法满足传送多媒体邮件(带有图片、音频或视频数据)的需要,并且许多非英语国家的文字也无法使用通过SMTP传输。所以,为了解决SMTP无法传输非ASCII码文本的问题,MIME(Multipurpose Internet Mail Extension,多用途因特网邮件拓展)应运而生了。MIME最主要的作用就是定义了传送编码,可对任意内容格式进行转换,而不会被邮件系统所改变。
在这里插入图片描述
MailClient 类源码:

package com.nowcoder.community.util;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.Component;

import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;

/*
 * 表示说我这个bean需要有spring容器来管理,
 * 而且使用@Component注解表示说是一个比较通用的bean,
 * 在哪些层次都可以使用。
 * */
@Component
public class MailClient {

    private static final Logger logger = LoggerFactory.getLogger(MailClient.class);

    /*
     * 要使用的核心组件是JavaMailSender,这个注解已经由spring来管理了
     * 我们直接注入即可获取JavaMailSenderImpl实现类对象
     * */
    @Autowired
    private JavaMailSender mailSender;

    /*
     * 发送邮件需要几个条件:
     * 1、邮件发送方(由于是服务器发送邮件,所以这个是固定的)
     * 2、邮件接收方
     * 3、邮件主题
     * 4、邮件内容
     * */
    @Value("${spring.mail.username}")
    private String from;

    public void sendMail(String to, String subject, String content) {
        try {
            MimeMessage message = mailSender.createMimeMessage();

            /*
             * 这里通过message也可以实现setFrom,setTo等。
             * 但是MimeMessageHelper帮助我们进行一些基础功能的实现比如:
             * 邮箱地址检查是否满足格式、字符串是不是为空等等
             * */
            MimeMessageHelper helper = new MimeMessageHelper(message);

            helper.setFrom(from);
            helper.setTo(to);
            helper.setSubject(subject);
            /*
            * 表示运行支持html文本,将html转成字符传进来它也支持
            * */
            helper.setText(content, true);
            mailSender.send(helper.getMimeMessage());
        } catch (MessagingException e) {
            logger.error("发送邮件失败:" + e.getMessage());
        }
    }

}

            /*
            * 表示运行支持html文本,将html转成字符传进来它也支持
            * */
            helper.setText(content, true);

这里为什么要将传入true,因为我们要把html转成字符串设置从content,让MIME去解析。如果不设置为true,它就会当作不同字符串。
在这里插入图片描述

模板引擎

为什么要用模板引擎?

  1. 我们要发送HTML邮件(不用模板引擎也可以做到),HTML是静态页面。更美观的页面
  2. HTML里面有动态生成的激活码(根本原因)更丰富的信息

在这里插入图片描述

测试HTML页面发送

在templates/mail目录下,新建demo.html模板。demo.html内容如下:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>邮件示例</title>
</head>
<body>
    <p>欢迎你, <span style="color:red;" th:text="${username}"></span>!</p>
</body>
</html>

如何生成模板渲染后端html页面?

如果是在Spring MVC的情况下,非常简单。 在controller中,某个方法,直接return 模板的路径名称,让后Spring MVC会自动找到改模板,并将Model中的数据渲染到视图中。

如果不是在Spring MVC的情况下,需要程序员手动去调用代码实现这个过程。主动的去调用Thymeleaf模板引擎:

  1. 注入thymeleaf模板引擎对象,TemplateEngine
  2. 利用thymeleaf的上下文对象 Context,设置username的值
  3. 调用模板引擎TemplateEngine对象,将数据渲染到html,生成动态网页TemplateEngine中有一个process方法,传入视图的路径名称,和上下文对象。

在这里插入图片描述

如图所示,相当于我们是直接从红色部分区域开始的。
建立MailTests类,代码如下:

package com.nowcoder.community;

import com.nowcoder.community.util.MailClient;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;

@RunWith(SpringRunner.class)
@SpringBootTest
@ContextConfiguration(classes = CommunityApplication.class)
public class MailTests {

    @Autowired
    private MailClient mailClient;

    @Autowired
    private TemplateEngine templateEngine;

    @Test
    public void testTextMail() {
        mailClient.sendMail("lihonghe@nowcoder.com", "TEST", "Welcome.");
    }

    @Test
    public void testHtmlMail() {
        Context context = new Context();
        context.setVariable("username", "sunday");

        String content = templateEngine.process("/mail/demo", context);
        System.out.println(content);

        mailClient.sendMail("lihonghe@nowcoder.com", "HTML", content);
    }

}

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

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

相关文章

Redis持久化 RDB AOF

前言 redis的十大类型终于告一段落了,下面我们开始redis持久化新篇章 为啥需要持久化呢? 我们知道redis是挡在mysql前面的带刀侍卫 是在内存中的,假如我们的redis宕机了,难道数据直接冲入mysql??? 这显然是不可能的,mysql肯定扛不住这样的场景,所以我们有了redis持久化策略…

Decoupled Multimodal Distilling for Emotion Recognition 论文阅读

Decoupled Multimodal Distilling for Emotion Recognition 论文阅读 Abstract1. Introduction2. Related Works2.1. Multimodal emotion recognition2.2. Knowledge distillation3. The Proposed Method3.1. Multimodal feature decoupling3.2. GD with Decoupled Multimodal …

JUC:ReentrantLock(可打断、锁超时、多条件变量)

文章目录 ReentrantLock特点基本语法可重入可打断&#xff08;避免死等、被动&#xff09;锁超时&#xff08;避免死等、主动&#xff09;公平锁多个条件变量 ReentrantLock 翻译&#xff1a;可重入锁 特点 可中断可设置超时时间&#xff08;不会一直等待锁&#xff09;可设…

算法学习——LeetCode力扣动态规划篇10(583. 两个字符串的删除操作、72. 编辑距离、647. 回文子串、516. 最长回文子序列)

算法学习——LeetCode力扣动态规划篇10 583. 两个字符串的删除操作 583. 两个字符串的删除操作 - 力扣&#xff08;LeetCode&#xff09; 描述 给定两个单词 word1 和 word2 &#xff0c;返回使得 word1 和 word2 相同所需的最小步数。 每步 可以删除任意一个字符串中的一个…

Last-Modified:HTTP缓存控制机制解析

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

nodejs下载安装以及npm、yarn安装及配置教程

1、nodejs下载安装 ​ 1.1、使用nodejs版本管理工具下载安装&#xff0c;可一键安装、切换不同nodejs版本&#xff0c; nvm-setup.zip&#xff1a;安装版&#xff0c;推荐使用 本次演示的是安装版。 1、双击安装文件 nvm-setup.exe 选择nvm安装路径 例如&#xff1a;E:\Soft…

蓝桥杯算法题-图形排版

题目描述 小明需要在一篇文档中加入 N 张图片&#xff0c;其中第 i 张图片的宽度是 Wi&#xff0c;高度是 Hi。   假设纸张的宽度是 M&#xff0c;小明使用的文档编辑工具会用以下方式对图片进行自动排版&#xff1a; 1. 该工具会按照图片顺序&#xff0c;在宽度 M 以内&…

Mysql数据库:MHA高可用架构

目录 前言 一、MHA概述 1、什么是MHA 2、MHA的特点 3、MHA的组成 4、MHA的工作原理 5、故障切换备选主库的算法 二、部署MHA高可用架构 1、环境部署 2、部署主从同步 2.1 修改主配置文件并创建软链接 2.1.1 master 修改主配置文件并创建软连接 2.1.2 slave1 修改主…

【JavaSE】类和对象详解(下)

前言 面向对象程序的三大特性&#xff1a;封装、继承、多态~ 书接上回 类和对象&#xff08;上&#xff09;~ 欢迎关注个人主页&#xff1a;逸狼 创造不易&#xff0c;可以点点赞吗~ 如有错误&#xff0c;欢迎指出~ 目录 前言 封装 private public 快速生成可访问封装的方法 包…

ubuntu16.04 不支持 gcc-11,g++11

总结 ubuntu16.04 不支持 gcc-11&#xff0c;需要升级 18.04 或更高的版本。 背景 最近需要在我的 ubuntu16.04 电脑上安装 gcc-11&#xff0c;g-11&#xff0c;使用更高的版本来编译代码。根据网上查到的方式是添加以下的源并进行安装 sudo add-apt-repository ppa:ubuntu…

数据库之MyBatisPlus详解

MyBatisPlus MyBatis-Plus (opens new window)&#xff08;简称 MP&#xff09;是一个 MyBatis (opens new window) 的增强工具&#xff0c;在 MyBatis 的基础上只做增强不做改变&#xff0c;为简化开发、提高效率而生。 官网地址&#xff1a;https://baomidou.com/ 一、入门案…

微信公众号迁移公证书在哪?

公众号迁移有什么作用&#xff1f;只能变更主体吗&#xff1f;很多小伙伴想做公众号迁移&#xff0c;但是不知道公众号迁移有什么作用&#xff0c;今天跟大家具体讲解一下。首先公众号迁移最主要的就是修改公众号的主体了&#xff0c;比如我们公众号原来是A公司的&#xff0c;现…

Ruoyi-Cloud-Plus_使用Docker部署分布式微服务系统_环境准备_001---SpringCloud工作笔记200

1.首先安装docker: 如果以前安装过首先执行: yum remove docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-selinux docker-engine-selinux docker-engine 去卸载docker 2.安装dokcer需要的工具包…

linux下minio部署和nginx配置

1 下载minio wget https://dl.min.io/server/minio/release/linux-amd64/minio chmod x minio #启动minio&#xff0c;文件数据存放在/data目录 ./minio server /data2 部署minio 下载minio后赋予可执行权限就可以运行了&#xff0c;这里我整理了遇到的坑和解决问题的最终配置…

大模型面试准备(九):简单透彻理解MoE

节前&#xff0c;我们组织了一场算法岗技术&面试讨论会&#xff0c;邀请了一些互联网大厂朋友、参加社招和校招面试的同学&#xff0c;针对大模型技术趋势、大模型落地项目经验分享、新手如何入门算法岗、该如何备战、面试常考点分享等热门话题进行了深入的讨论。 合集在这…

【洛谷】P9241 [蓝桥杯 2023 省 B] 飞机降落

挺有意思的一道题&#xff0c;分享给大家 题目链接 P9241 [蓝桥杯 2023 省 B] 飞机降落 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 题目描述 输入格式 输出格式 输入输出样例 说明/提示 思路 一开始尝试贪心能不能做&#xff0c;但是不好确定飞机的顺序 因为这题的数…

第5篇:挖矿病毒(一)

0x00 前言 ​ 随着虚拟货币的疯狂炒作&#xff0c;挖矿病毒已经成为不法分子利用最为频繁的攻击方式之一。病毒传播者可以利用个人电脑或服务器进行挖矿&#xff0c;具体现象为电脑CPU占用率高&#xff0c;C盘可使用空间骤降&#xff0c;电脑温度升高&#xff0c;风扇噪声增大…

金融衍生品市场

金融衍生品市场 衍生金融品的作用衍生金融工具远期合约期货合约期权 衍生金融品的作用 套期保值&#xff08;Hedging&#xff09; 组合多头头寸(long position)与空头头寸(short position)例&#xff1a;股票与股指期货 投机 衍生金融工具 远期合约 定义&#xff1a;在将来…

C语言数组详解

一维数组 创建和初始化 数组就是一组相同元素的集合。 他的创建&#xff1a; char arr[10]; int arr1[5]; 数组创建中 [] 里不能是变量&#xff0c;但是在c99标准之后就可以了被称为变长数组&#xff0c;但是不常用&#xff0c;而且变长数组不能初始化。 初始化&#xff…

这两个比较经典的LVS问题怎么解?

今日景芯SoC VIP学员遇到的LVS问题&#xff0c;比较经典&#xff0c;大家先思考下。然后本文末尾分享下2.5GHz A72训练营的LVS解法&#xff1a; 问题1&#xff1a; 问题2&#xff1a; 修改后&#xff1a; 具体修改方案参见知识星球&#xff0c;接下来分享下2.5GHz A72项目的LV…