springboot如何发送邮件,java如何发送邮件随机码作为验证

maven

        <dependency>
            <groupId>com.sun.mail</groupId>
            <artifactId>javax.mail</artifactId>
            <version>1.6.2</version>
        </dependency>

然后java

package com.metasoft.common.utils;



import java.util.Properties;

import javax.mail.Authenticator;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;

public final class JavaMailUntil {
    private JavaMailUntil() {}

    public static Session createSession() {

        //	账号信息
        String username = "skin_2023@qq.com";//	邮箱发送账号
        String password = "uncinojcclesurcdbb";//	邮箱授权码

        //	创建一个配置文件,并保存
        Properties props = new Properties();

        //	SMTP服务器连接信息
        //  126——smtp.126.com
        //  163——smtp.163.com
        //  qqsmtp.qq.com"
        props.put("mail.smtp.host", "smtp.qq.com");//	SMTP主机名
        props.put("mail.smtp.ssl.enable", "true");
        //  126——25
        //  163——645
        props.put("mail.smtp.port", "465");//	主机端口号
        props.put("mail.smtp.auth", "true");//	是否需要用户认证
        props.put("mail.smtp.starttls.enale", "true");//	启用TlS加密

        Session session = Session.getInstance(props,new Authenticator() {
            @Override
            protected PasswordAuthentication getPasswordAuthentication() {
                // TODO Auto-generated method stub
                return new PasswordAuthentication(username,password);
            }
        });

        //  控制台打印调试信息
        session.setDebug(true);
        return session;

    }

    //正则验证
    // 验证邮箱地址是否合法
    public static boolean isValidEmailAddress(String email) {
        String emailRegex = "^[a-zA-Z0-9_+&*-]+(?:\\.[a-zA-Z0-9_+&*-]+)*@(?:[a-zA-Z0-9-]+\\.)+[a-zA-Z]{2,7}$";
        return email.matches(emailRegex);
    }
}

然后就是业务层了,包含发送普通邮件,发送附件,发送图片邮件


	/**
	 * 发送邮件
	 */
	@PostMapping("/sendEmail")
	@ApiOperationSupport(order = 18)
	@ApiOperation(value = "发送激活邮件", notes = "传入id")
	public R sendEmail(String userIds) throws MessagingException {
		if (StringUtil.isBlank(userIds)) {
			return R.fail("请至少选择一个用户");
		}
		List<User> userList = userService.list(Wrappers.<User>lambdaQuery().in(User::getId, Func.toLongList(userIds)));

		//	创建Session会话
		Session session = JavaMailUntil.createSession();

		for (User user : userList) {
			String targetEmail = "";
			//优先判断user的account是不是邮箱地址,如果不是判断user的email是不是邮箱地址,如果也不是,直接抛出异常

			// 优先判断user的account是不是邮箱地址
			if (JavaMailUntil.isValidEmailAddress(user.getAccount())) {
				targetEmail = user.getAccount();
			} else {
				// 如果user的account不是邮箱地址,则判断user的email是不是邮箱地址
				if (JavaMailUntil.isValidEmailAddress(user.getEmail())) {
					targetEmail = user.getEmail();
				} else {
					// 如果都不是邮箱地址,直接跳过
					log.info("用户{}的email和account都不是邮箱地址", user.getId());
					continue;
				}
			}


			MimeMessage message = new MimeMessage(session);
			message.setSubject("邀请您激活账号");
			String activationLink = "http://localhost:2888/register?activationCode=" + UUID.randomUUID().toString();
			String emailContent = "" +
					"\n" +
					"感谢您的注册。\n" +
					"\n" +
					"您目前处于已完成临时注册的状态。\n" +
					"\n" +
					"如需完成注册,请点击以下URL。" + activationLink;//todo 后续改成线上地址
			message.setText(emailContent);
			message.setFrom(new InternetAddress("skins_2023@qq.com"));
			message.setRecipient(MimeMessage.RecipientType.TO, new InternetAddress(targetEmail));

			Transport.send(message);
		}

		return R.success("操作成功");
	}
	/**
	 * 发送邮件带附件
	 */
	@GetMapping("/sendEmailForFile")
	@ApiOperationSupport(order = 18)
	@ApiOperation(value = "发送邮件带附件", notes = "传入id")
	public R sendEmailForFile(String userIds) throws MessagingException {

		try {
			//	创建会话
			Session session = JavaMailUntil.createSession();

			//	创建邮件
			MimeMessage message = new MimeMessage(session);
			message.setFrom("发送的邮箱");
			message.setRecipient(MimeMessage.RecipientType.TO, new InternetAddress("主要发送人邮箱"));
			message.setRecipients(MimeMessage.RecipientType.CC, new InternetAddress[] {new  InternetAddress("抄送人邮箱"),new InternetAddress("抄送人邮箱")});
			message.setSubject("主题");

			//	邮件主体
			BodyPart textPart = new MimeBodyPart();
			textPart.setContent("文件内容","text/html;charset=utf-8");

			//	邮件附件
			BodyPart filePart = new MimeBodyPart();
			filePart.setFileName("附件显示名字.类型名");

			//	提交附件文件

			filePart.setDataHandler(new DataHandler(new ByteArrayDataSource(Files.readAllBytes(Paths.get("本地文件路径")),"application/octet-stream")));

			Multipart multipart = new MimeMultipart();
			multipart.addBodyPart(textPart);
			multipart.addBodyPart(filePart);

			//	将邮件装入信封
			message.setContent(multipart);

			Transport.send(message);
		} catch (AddressException e) {
			e.printStackTrace();
		} catch (MessagingException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}

		return R.success("操作成功");
	}/**
	 * 发送邮件带图片
	 */
	@GetMapping("/sendEmailForPhoto")
	@ApiOperationSupport(order = 18)
	@ApiOperation(value = "发送邮件带图片", notes = "传入id")
	public R sendEmailForPhoto(String userIds) throws MessagingException {

		try {
			//	创建会话
			Session session = JavaMailUntil.createSession();
			//	创建邮件
			MimeMessage message = new MimeMessage(session);
			message.setFrom("发送的邮箱");
			message.setRecipient(MimeMessage.RecipientType.TO, new InternetAddress("主要发送人邮箱"));
			message.setRecipients(MimeMessage.RecipientType.CC, new InternetAddress[] {new  InternetAddress("抄送人邮箱"),new InternetAddress("抄送人邮箱")});
			message.setSubject("主题");

			//	邮件主体
			BodyPart textPart = new MimeBodyPart();
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.append("文字");
			stringBuilder.append("文字");
			stringBuilder.append("<img src=\"cid:自定义id\"/>");
			textPart.setContent(stringBuilder.toString(),"text/html;charset=utf-8");


			//	邮件附件
			BodyPart filePart = new MimeBodyPart();
			filePart.setFileName("图片名称.jpg");

			//	提交附件文件
			filePart.setDataHandler(
					new DataHandler(
							new ByteArrayDataSource(
									Files.readAllBytes(
											Paths.get("本地路径")),
									"application/octet-stream")));

			filePart.setHeader("Content-ID","自定义id");

			Multipart multipart = new MimeMultipart();
			multipart.addBodyPart(textPart);
			multipart.addBodyPart(filePart);

			//	将邮件装入信封
			message.setContent(multipart);

			Transport.send(message);
		} catch (AddressException e) {
			e.printStackTrace();
		} catch (MessagingException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}

		return R.success("操作成功");
	}

	/**
	 * 生成六位数随机验证码
	 */
	public String generateRandomCode() {
		Random random = new Random();
		int code = 100000 + random.nextInt(900000);
		return String.valueOf(code);
	}

	/**
	 * 发送包含验证码的邮件
	 */
	@GetMapping("/sendVerificationCode")
	public R sendVerificationCode(@RequestParam("emailAddress") String emailAddress) throws MessagingException {
		//验证邮箱地址是否正确
		boolean isValid = JavaMailUntil.isValidEmailAddress(emailAddress);

		if (!isValid) {
			return R.fail("邮箱地址不正确");
		}
		String verificationCode = generateRandomCode();

		// 创建邮件内容
		String emailContent = "您的验证码是:" + verificationCode+"。请在注册或登录时使用。有效期为10分钟。";

		// 创建Session会话
		Session session = JavaMailUntil.createSession();

		// 创建邮件对象
		MimeMessage message = new MimeMessage(session);
		message.setSubject("密码重置验证码");
		message.setText(emailContent);
		message.setFrom(new InternetAddress("skins_2023@qq.com"));
		message.setRecipient(MimeMessage.RecipientType.TO, new InternetAddress(emailAddress));

		// 发送
		Transport.send(message);
		//验证码存入redis中方便后续读取,有效期为十分钟
		bladeRedis.getRedisTemplate().opsForValue().set("verificationCode:" + emailAddress, verificationCode, 10, TimeUnit.MINUTES);

		return R.success("验证码已发送到您的邮箱,请查收!");
	}

	/**
	 * 账号激活
	 */
	@PostMapping("/activateAccount")
	public R activateAccount(@RequestBody RegisterUserVO userVO) throws MessagingException {
		log.info(userVO.toString());

		return R.success("账号激活");
	}
	/**
	 * 忘记密码-修改密码
	 */
	@PostMapping("/changePassword")
	public R changePassword(@RequestBody RegisterUserVO userVO) throws MessagingException {
		log.info(userVO.toString());
		//查询是否存在此邮箱的账号
		User user = userService.getOne(new QueryWrapper<User>().lambda().eq(User::getAccount, userVO.getUsername()));
		//如果查询不到用户,则返回错误信息
		if (user == null) {
			return R.fail("用户不存在");
		}
		//判断两次输入的密码是否一致
		if (!userVO.getPassword().equals(userVO.getPassword2())) {
			return R.fail("两次输入的密码不一致");
		}
		//判断验证码是否正确
		String verificationCode = (String)bladeRedis.getRedisTemplate().opsForValue().get("verificationCode:" + userVO.getUsername());
		if (!verificationCode.equals(userVO.getEmailCode())) {
			return R.fail("邮箱验证码错误");
		}

		// 修改密码
		userService.update(Wrappers.<User>update().lambda().set(User::getPassword, DigestUtil.hex(userVO.getPassword())).eq(User::getId, user.getId()));

		return R.success("密码修改成功");
	}

}

顺便也发出我写的前端代码,vue

<template>
  <div class="register-container" ref="register">
    <p style="line-height:150%; margin:50pt 0pt 20pt 50pt; text-align:center;">
      <span style="font-family:FZXiaoBiaoSong-B05S; font-size:26pt; display:inline-block;">重置密码</span>
    </p>
    <div class="register-form">
      <el-form :model="form" ref="form" :rules="rules" label-width="100px">
        <el-form-item label="登录邮箱" prop="username">
          <el-input v-model="form.username" placeholder="请输入邮箱"></el-input>
        </el-form-item>
        <el-form-item label="邮箱验证码" prop="emailCode">
          <el-input v-model="form.emailCode" placeholder="请输入邮箱验证码"></el-input>
          <el-button type="primary" @click="sendEmailCode" :disabled="countDown > 0">{{ countDown > 0 ? countDown + '秒后重新发送' : '发送验证码' }}</el-button>
        </el-form-item>
        <el-form-item label="新密码" prop="password">
          <el-input type="password" v-model="form.password" placeholder="请输入新密码"></el-input>
        </el-form-item>
        <el-form-item label="确认新密码" prop="password2">
          <el-input type="password" v-model="form.password2" placeholder="请再次输入新密码"></el-input>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" @click="submitForm">提交</el-button>
        </el-form-item>
      </el-form>
    </div>
  </div>
</template>

<script>
import {changePassword, sendVerificationCode} from "@/api/register/register";
import md5 from 'js-md5';

export default {
  data() {
    return {
      form: {
        username: '',
        emailCode: '',
        password: '',
        password2: '',
      },
      rules: {
        username: [
          { required: true, message: '请输入邮箱', trigger: 'blur' },
        ],
        emailCode: [
          { required: true, message: '请输入邮箱验证码', trigger: 'blur' },
        ],
        password: [
          { required: true, message: '请输入密码', trigger: 'blur' },
        ],
        password2: [
          { required: true, message: '请再次输入密码', trigger: 'blur' },
        ],
      },
      countDown: 0,
    };
  },
  methods: {
    sendEmailCode() {
      // 编写发送邮箱验证码的逻辑
      if (this.countDown === 0) {
        // 模拟发送验证码,实际开发中调用后端接口
        console.log('发送验证码');
        sendVerificationCode(this.form.username).then(res => {
          //如果res的状态码为200,表示发送成功
          if (res.status === 200) {
            this.$message.success('验证码发送成功');
          } else {
            this.$message.error('验证码发送失败');
          }
        });
        this.countDown = 60;
        const timer = setInterval(() => {
          if (this.countDown > 0) {
            this.countDown--;
          } else {
            clearInterval(timer);
          }
        }, 1000);
      }
    },
    submitForm() {
      console.log("要发送的信息====", this.form);
      //todo 后续对密码的安全性做处理
      this.form.password = md5(this.form.password);
      this.form.password2 = md5(this.form.password2);

      changePassword(this.form).then(res => {
        this.$message({ type: "success", message: "提交成功!" });
        this.resetForm();
      }, error => {
        this.$message({ type: "error", message: "提交失败,请重试!" });
      });
    },
    resetForm() {
      this.form = {
        username: '',
        emailCode: '',
        password: '',
        password2: '',
      };
    },
  },
};
</script>

<style scoped>
.register-container {
  text-align: center;
}

.register-form {
  width: 400px;
  margin: 0 auto;
}

.el-button {
  margin-left: 10px;
}

.el-form-item__content {
  display: flex;
}

.el-input {
  flex: 1;
}
</style>

这个就是重置密码 利用邮箱验证60秒的功能

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

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

相关文章

【半夜学习MySQL】数据库概念详解探索数据库到底是如何存储的?

&#x1f3e0;关于专栏&#xff1a;半夜学习MySQL专栏用于记录MySQL数据相关内容。 &#x1f3af;每天努力一点点&#xff0c;技术变化看得见 文章目录 什么是数据库主流数据库与数据库分类数据库的基本使用数据库的启动及关闭查看配置文件与数据库存储位置连接数据库服务器服务…

微型显示器可以实时监测大脑活动

美国团队开发基于LED的设备&#xff0c;以可视化大脑活动&#xff0c;在脑外科手术中指导神经外科医生 来自加州大学圣地亚哥分校和马萨诸塞州总医院的工程师和医生开发了一种薄膜显示设备&#xff0c;该设备结合了电极网格和特殊的GaN LED&#xff0c;可以在手术过程中实时跟…

5月9日作业

1&#xff0c;创建一对父子进程&#xff1a;父进程负责向文件中写入 长方形的长和宽子进程负责读取文件中的长宽信息后&#xff0c;计算长方形的面积。 1 #include <stdio.h> 2 #include <string.h> 3 #include <unistd.h> 4 #include <stdlib.h> 5 #…

中国4月进口以美元计同比增长8.4%,出口同比增长1.5%

中国按美元计4月进出口同比增速均转负为正&#xff0c;双双超预期。 5月9日周四&#xff0c;海关总署公布数据显示&#xff0c;以美元计价&#xff0c;中国2024年4月进口同比增长8.4%至2201亿美元&#xff0c;前值同比下降1.9%&#xff0c;出口同比增长1.5%至2924.5亿美元&…

基于Spring Boot的公司OA系统设计与实现

基于Spring Boot的银行OA系统设计与实现 开发语言&#xff1a;Java 框架&#xff1a;springboot JDK版本&#xff1a;JDK1.8 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;eclipse/myeclipse/idea 系统部分展示 用户登录界面&#xff0c;在银行OA系统运行后&#x…

ThingsBoard如何接受设备通过TCP发送的报文

1、概述 2、案例 2.1、阐述 2.2、导入依赖 2.3、构建Netty服务链接&#xff0c;接受的端口为8092 2.4、对数据进行相应的处理发送到ThingsBoard客户端 2.5、通过TCP链接工具 ​2.6、查看遥测数据 1、概述 TCP&#xff08;Transmission Control Protocol&#xff0c;传输…

【备战软考(嵌入式系统设计师)】11 - 硬件电路基础

逻辑门电路 首先我们需要先了解三个最基础的门电路&#xff0c;可以说我们一切的电子产品的基石就是这哥仨&#xff0c;它们就与&#xff0c;或&#xff0c;非。 与门和或门有两个输入端&#xff0c;一个输出端&#xff1b;非门有一个输入端一个输出端。 在我们数字电路中&a…

IOS Xcode证书配置和ipa打包流程(附详细图文教程)

IOS Xcode证书配置和ipa打包流程&#xff08;附图文教程&#xff09; 前言ipa文件简介证书文件简介Provisioning Profile描述文件简介当前环境版本Xcode证书配置和ipa打包流程生成Apple Distribution Certificates证书创建描述文件&#xff08;Provisioning Profiles&#xff0…

车载测试系列:车载以太网测试(一)

汽车行业对可靠性和安全性要求越来越高&#xff0c;车载以太网在应用过程中&#xff0c;为了保证其可靠性与安全性&#xff0c;需要对其开展测试工作。 传统的以太网测试和车载以太网测试存在一定差异&#xff0c;传统以太网测试方法并不适用汽车以太网测试。 汽车行业对测试…

代码随想录第四十三天|最后一块石头的重量 II 、目标和

题目链接&#xff1a;. - 力扣&#xff08;LeetCode&#xff09; 代码如下&#xff1a; 题目链接&#xff1a;. - 力扣&#xff08;LeetCode&#xff09; 代码如下&#xff1a;

986: 哈夫曼译码

解法&#xff1a;先把代码粘贴到编译器&#xff08;vs&#xff09;上&#xff0c;分享一个一键去除空白行的操作&#xff0c;ctrlf调出查找窗口&#xff0c;输入查找(?<\r\n)\r\n&#xff0c;选择正则表达式&#xff0c;替换就可以发现会去掉一百多行空白行。 本题只需要利…

通用型产品发布解决方案(基础环境搭建)

文章目录 1.项目技术栈和前置技术2.创建Linux平台1.需求分析2.安装Virtual Box1.BIOS里修改设置开启虚拟化设备支持&#xff08;f2 或f10&#xff09;2.任务管理器 -> cpu 查看虚拟化是否开启3.卸载方式4.安装6.1.265.管理员身份运行&#xff0c;选择安装位置6.一直下一步&a…

我的Transformer专栏来啦

五一节前吹的牛&#xff0c;五一期间没完成&#xff0c;今天忙里偷闲&#xff0c;给完成了。 那就是初步拟定了一个《Transformer最后一公里》的写作大纲。 之前一直想写一系列Transformer架构的算法解析文章&#xff0c;但因为一直在忙&#xff08;虽然不知道在忙啥&#xf…

银行职员向媒体投稿发文章我找到了好方法

作为一名基层银行的媒体联络专员,我的日常工作中有一项至关重要的任务,那就是代表我所在的支行向各大媒体投稿,传播我们的金融服务、产品动态以及社会责任实践。起初,这项看似简单的工作却成了我职业生涯中的一大挑战。传统的邮件投稿方式,不仅耗时费力,而且审核流程严格,稿件从…

【DSIN】深度 Session 兴趣网络

一、提出动机 这个模型依然是研究如何更好地从用户的历史行为中捕捉到用户的动态兴趣演化规律。 1.1、序列本身的特点&#xff1a; 其实用户点击序列有他自己本身的特点&#xff1a;用户过去可能有很多历史点击行为&#xff0c;按照用户的点击时间排好序&#xff0c;比如[it…

【Linux】yum与vim

文章目录 软件包管理器&#xff1a;yumLinux安装和卸载软件包Linux中的编辑器&#xff1a;vimvim下的底行模式vim下的正常模式vim下的替换模式vim下的视图模式vim下的多线程 软件包管理器&#xff1a;yum yum其实就是一个软件,也可以叫商店 和你手机上的应用商店或app store一…

【FreeRTOS 快速入门】-- 1、STM32工程移植FreeRTOS

目录 一、新建STM32工程 为了示范完整的移植过程&#xff0c;我们从0开始&#xff0c;新建一个标准的STM32点灯工程。 &#xff08;本篇以CubeMX作示范&#xff0c;CubeIDE操作近同&#xff0c;可作对比参考&#xff09; 1、新建工程 选择 芯片型号 新建工程 2、搜索芯片型号…

计算方法实验9:Romberg积分求解速度、位移

任务 输出质点的轨迹 ( x ( t ) , y ( t ) ) , t ∈ { 0.1 , 0.2 , 0.3 , . . . , 10 } (x(t), y(t)), t\in \{0.1, 0.2, 0.3, ..., 10\} (x(t),y(t)),t∈{0.1,0.2,0.3,...,10}&#xff0c;并在二维平面中画出该轨迹.请比较M分别取4, 8, 12, 16, 20 时&#xff0c;Romberg积分达…

MTK平台ATE tool

一、校准测试环境搭建 ① 仪器端一个端口直接连接功分器。 ② 功分器输出端外接3dbm的衰减器。 ③功分器空出来的端口需要外接50 Ω的负载。 ④功分器与手机端口的连接没有顺序之分。 二、ATE设置介绍 ATE所支持的无线通信系统 — GSM — WCDMA — TDSCDMA — LTE — WI…

Redis持久化策略——Java全栈知识(17)

Redis持久化 1、Redis 持久化的三种方式 1、RDB&#xff1a; 以快照的方式将此刻 Redis 中的数据以二进制的文件形式保存在磁盘中。 RDB 的优点是&#xff1a;快照文件小、恢复速度快&#xff0c;适合做备份和灾难恢复。 RDB 的缺点是&#xff1a;定期更新可能会丢数据&#…
最新文章