nest.js发送验证码
创建一个项目
-
创建一个项目
-
pnpm add -g @nestjs/cli nodemon ts-node
-
进入项目目录然后安装项目依赖,包含prisma、表单验证、加密工具、JWT、文件上传、工具包、日期处理等
pnpm add prisma-binding ts-node @prisma/client mockjs @nestjs/config class-validator class-transformer argon2 @nestjs/passport passport passport-local @nestjs/jwt passport-jwt lodash multer dayjs express redis @nestjs/throttler mockjs @nestjs/cache-manager cache-manager md5 @casl/prisma @casl/ability
-
通过nest g res sendemail --no-spec创建一整个模块
-
在发送邮件模块中开启导入模式
@Module({ //这里开启 imports: [ CacheModule.register({ isGlobal: true, }), ], controllers: [SendemailController], providers: [SendemailService], })
-
导入必须用到的包
import { BadRequestException, Inject, Injectable } from '@nestjs/common'; import { CreateSendemailDto } from './dto/create-sendemail.dto'; import { UpdateSendemailDto } from './dto/update-sendemail.dto'; import * as nodemailer from 'nodemailer'; import { CACHE_MANAGER } from '@nestjs/cache-manager'; import { Cache } from 'cache-manager'; import { now } from 'lodash'; import md5 from 'md5';
-
//这里是对于邮箱的配置 private transporter; constructor( @Inject(CACHE_MANAGER) private cache: Cache, private prisma: PrismaService, ) { this.transporter = nodemailer.createTransport({ host: 'smtp.qq.com', // QQ 邮箱的 SMTP 服务器地址--------默认不需要更改 port: 465, // QQ 邮箱的 SMTP 服务器端口号 secure: true, auth: { user: 'XXXXXXX',//发送方邮箱号 pass: 'XXXXXX',//授权码 //下面是qq中获取授权码的方法 在 QQ 邮箱中获取授权码(也称为“客户端密码”或“第三方授权码”),你需要进入 QQ 邮箱的设置,并按照以下步骤操作: 登录 QQ 邮箱:打开 QQ 邮箱的网页或使用 QQ 邮箱的移动应用,并使用你的账号和密码登录。 进入账户设置:登录后,在 QQ 邮箱页面中,点击右上角的设置图标(通常是齿轮状图标),然后选择“设置”或“账户设置”。 寻找授权码选项:在账户设置页面中,寻找类似“POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV服务”的选项。这通常是关于邮件客户端和第三方应用程序的设置。 生成授权码:在该选项下,你应该能够找到“生成授权码”或类似的按钮或链接。点击这个按钮,系统会要求你输入你的登录密码以确认身份。 获取授权码:完成身份验证后,系统将为你生成一个授权码。这个授权码就是用于在第三方应用程序(如 Nodemailer)中代替密码来发送邮件的密钥。 复制授权码:将生成的授权码复制下来,并保存在安全的地方。请务必妥善保管授权码,不要将它公开或分享给他人,以防止账户被滥用。 一旦你获得了 QQ 邮箱的授权码,就可以将其用于 Nodemailer 配置中的 pass 属性,以便在 NestJS 应用程序中使用 QQ 邮箱发送电子邮件。 }, }); }
-
接下来就可以使用控制器来接受http请求了
//这个用来对验证码是否正确时候的判断 import { IsNotEmpty } from 'class-validator'; export class CreateSendemailDto { @IsNotEmpty({ message: '验证的key不能为空' }) key: string; @IsNotEmpty({ message: '验证的值不能为空' }) value: string; } //UpdateSendemailDto用来验证邮箱号不能为空 import { IsEmail, IsNotEmpty } from 'class-validator'; export class UpdateSendemailDto { @IsNotEmpty({ message: '输入的邮箱号不能为空' }) @IsEmail() emil: string; } @Post('notlogin') setCode(@Body() dto: UpdateSendemailDto, @Ip() ip: any) { return this.sendemailService.setcode(dto, ip); }
-
转到service中进行对内容的发送
async setcode(dto: UpdateSendemailDto, ip: any) { //这里就是生成了一个六位数的随机数 let code = String(Math.floor(Math.random() * 1000000)).padStart(6, '0'); //这里为了使得key加密性能更好,取到了一个随机数和ip地址把他们进行拼接用于当nest缓存中的key const key = md5('captcha' + now() + ip); //将验证码保存下来 //将内容缓存起来 //第一个值代表的是缓存的key,第二个值是value,第三个是保存多长时间(这里保存了5分钟,1就是1秒) await this.cache.set(key, code, 1000 * 60 * 5); const content = `<div><h1>XXXX</h1></div> <p>你的短信验证码为${code},用于修改或者找回密码做的身份验证,5分钟内有效,请勿泄露和转发,如非本人操作,请忽略此邮箱</p> `; try { const mailOptions = { from: '发送方的邮箱号', // 发送方邮箱地址,一般和上面的邮箱一致 //to.emil代表的是给谁发送,发送方是谁 to: user.emil, subject: '发送验证码修改密码和找回密码', //content代表的是发送内容 text: content, }; await this.transporter.sendMail(mailOptions); return { //这里将key一并返回出去因为缓存验证的时候还会用到 message: '邮箱发送成功', key, }; } catch (error) { throw new Error('Failed to send email.'); } } } //这个方法用来验证验证码是否正确 async notgetcode(dto: CreateSendemailDto) { //这里的code就是根据缓存key来得到的值 const code = await this.cache.get(dto.key); //判断 if (code != dto.value) { throw new BadRequestException('验证码输入错误'); } else { return { message: '验证码验证成功', code: 200, }; }