基于Nest.js(Typescript)+Mongodb+TS定时任务实现发送邮件功能(qq邮箱)

Nest.js+Mongodb+定时任务实现发送邮件功能(qq邮箱)

  • 前置知识
    • 开始前准备
    • **项目创建**
      • **构建工具**
      • **导入依赖**
      • **项目构建完成** **可以启动项目**
    • **邮件与数据库模块的创建**
    • **用Postman调用**
    • nestjs邮件服务的链接

前置知识

了解TS语言、 Nestjs框架、 Nosql(mongodb)

开始前准备

基于Nest.js(Typescript)+Mongodb+TS定时任务实现发送邮件功能(qq邮箱)_第1张图片
找到SMTP服务开启他
基于Nest.js(Typescript)+Mongodb+TS定时任务实现发送邮件功能(qq邮箱)_第2张图片
会生成授权码,记住后面有用!(记住保存自己的操作哈)
基于Nest.js(Typescript)+Mongodb+TS定时任务实现发送邮件功能(qq邮箱)_第3张图片
我们接下来就可以开撸啦:

小提示:
Nest.js 用于构建高效且可伸缩的服务端应用程序的渐进式 Node.js 框架。
NestJS 默认使用 JavaScript 的超集 TypeScript 进行开发。

项目创建

构建工具

可以使用 npm、yarn、pnpm进行包管理,建议使用npm
建议安装nrm镜像源管理工具,可以方便切换国内镜像,提高下载速度
建议安装nvm用于切换node版本

全局安装

首先全局安装相关命令,可以使用npm 、yarm、pnpm管理包

npm add -g @nestjs/cli nodemon ts-node  //全局安装nestjs-cli  脚手架
nest new project-004   //这是构建脚手架项目

提示
项目构建完成 项目中还没有导入依赖

项目列表

导入依赖

直接在当前项目下运行 (记住有些电脑可能由于权限的问题安装失败)
直接管理员运行cmd 切到相应项目目录 执行 npm i

//package.json (这个文件是项目中配置依赖文件 (相当于java项目中的 .pom文件)(里面已经标注了需要的依赖和依赖的版本号))
npm i
会生成 node_modules 文件夹 里面存放包文件

网传项目依赖方法 (我的不好用,并没有使用这种)

进入项目目录然后安装项目依赖,包含数据库管理、表单验证、加密工具、JWT、文件上传、工具包、日期处理等

npm add prisma-binding @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

npm add -D prisma typescript @types/node @types/mockjs @nestjs/mapped-types @types/passport-local @types/passport-jwt @types/express @types/lodash @types/multer @types/node

项目构建完成 可以启动项目

执行命令是 npm run start :dev

邮件与数据库模块的创建

安装邮件模块 (https://nest-modules.github.io/mailer/docs/mailer).
npm install --save @nestjs-modules/mailer nodemailer

安装数据库模块
//定义模型
npm i --save @typegoose/typegoose
//安装定义文件,用于提示
npm i --save mongoose  @types/mongoose
//连接mongdb
npm i --save nestjs-typegoose

安装定时任务(https://docs.nestjs.com/techniques/task-scheduling)
npm install --save @nestjs/schedule

安装模板引擎  安装一个就可
npm i handlebars
#or
npm i pug
#or
npm i add ejs

新建邮件模块、控制器、服务
nest g mo modules/email
nest g co modules/email 
nest g s modules/email 

新建数据库模块、控制器、服务
nest g mo service/email
nest g co service/email 
nest g s service/email

在根模块 导入这些模块
app.module.ts

import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { UserModule } from './server/user/user.module';
import { MongooseModule } from '@nestjs/mongoose';
import { ScheduleModule } from '@nestjs/schedule';
import { EmailModule } from './modules/email/email.module';
import { MailerModule } from '@nestjs-modules/mailer';
import { PugAdapter } from '@nestjs-modules/mailer/dist/adapters/pug.adapter';
// import path from 'path';


@Module({
  imports: [
  MongooseModule.forRoot('mongodb://127.0.0.1:27017/database'),//连接数据库的
  ScheduleModule.forRoot(),//数据表对象
  UserModule,  //数据库的模块
  EmailModule,  //邮件的模块
  MailerModule.forRoot({   //连接邮件的
      transport: {
          host: 'smtp.qq.com', //邮箱服务器地址
          port: 465, //服务器端口 默认 465
          auth: {
              user: '[email protected]',//你的邮箱地址
              pass: 'bsdakfsjfdffdssfdfssdsdfasdgsakjlfskjlaf'//授权码  我这个不是真的
          }
      },
      preview: true,//是否开启预览,开启了这个属性,在调试模式下会自动打开一个网页,预览邮件
      defaults: {
          from: '[email protected]' //发送人 你的邮箱地址
      },
      template: {
          // dir: path.join(process.cwd(), './src/template'),//这里就是你的模板文件夹路径
          //dir: __dirname + '/template',   //
          adapter: new PugAdapter(),  //模板的
          options: {
              strict: true //严格模式
          }
      }
  })

],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

缕清需求(我们先创建邮件模块 调用我的接口我直接发送一个邮件(里面内容写死了),调用接口传入账号信息,我给他发送邮件)

配置邮件控制器

    import { Controller, Get, Post,Body } from '@nestjs/common';
    import { EmailService } from './email.service';
    // import { NoAuth } from '@decorators/no.auth.decorator';

    @Controller('email')
    export class EmailController {
        
        constructor(private readonly emailService: EmailService) {}
        /**
         * emaii.controller.ts
         * @returns 请求之后直接发送一个邮件
         */
        @Get()
        sendEmail() {
            this.emailService.example();
            return 'ok';
        }
        // @NoAuth()
        @Post('/sendCode')
        async sendEmailCode(@Body("email") email:string) {
            return this.emailService.sendEmailCode(email);
        }
        @Post('/sendCode-ing')
        async senEmailCodes(@Body() data){
            //先将信息存入数据库
        }

    }

配置邮件服务器

import { Injectable } from '@nestjs/common';
import { ISendMailOptions, MailerService } from '@nestjs-modules/mailer';
import path from 'path';

@Injectable()
export class EmailService {

    constructor(private readonly mailerService: MailerService) {}
    /**
     * email.sercice.ts
     */
    public example(): void {

        console.log("执行之前")
        this.mailerService
            .sendMail({
            to: '[email protected]', // list of receivers
            from: '[email protected]', // sender address
            subject: '主题是键盘敲烂,月薪过万!!!', // Subject line
            text:'dsadhsahdashdsahdosahdi',//没用邮件中没有体现
            html:'welcome'
            // template: __dirname + '/email', // The `.pug`, `.ejs` or `.hbs` extension is appended automatically.      
            }).then(() => {})
            .catch(() => {});
        console.log("执行之后")
    }
     
     async sendEmailCode(email:string) {
      try {
          console.log('进入');
          console.log('准备发送');  
          await this.mailerService.sendMail(
            {
                to: email, // list of receivers
                from: '[email protected]', // sender address
                subject: '主题是键盘敲烂,月薪过万!!!', // Subject line
                text:'dsadhsahdashdsahdosahdi',
                html:'welcome'                
            }         
          ).then(()=>{}).catch(()=>{});
          return { code: 200, message: '发送成功' };
      } catch (error) {
          console.error('发送邮件出错:', error);
          return { error };
      }
  }
}

现在就已经实现了发送邮件的功能
需求2:我们将前台传入的数据存入数据库, 定时任务执行发送邮件的接口

提示:我们需要导入邮件模块 所以我们需要将邮件的Module.ts文件写上exports:[EmailService]

配置邮件Module

import { Global, Module } from '@nestjs/common';
import { EmailController } from './email.controller';
import { EmailService } from './email.service';

@Module({
  imports:[],
  controllers: [EmailController],
  providers: [EmailService],
  exports:[EmailService] //输出这个
})
export class EmailModule {}


配置数据库控制器

import { Body, Controller, Get, Post } from '@nestjs/common';
import { UserService } from './user.service';
import { User } from './user.schema';
import { EmailService } from 'src/modules/email/email.service';

@Controller('user')
export class UserController {
    constructor(private readonly userService : UserService){}
 
    @Get("/select")
    async selectAll() {
      return await this.userService.select();
    }
    @Post("/addemail")
    async addEmail(@Body() userDto:User){//USer 是我数据库的表(就是实体类)
      return await this.userService.addEmail(userDto);
    }
    @Get("selectemail")
    async selectemail(){
      return await this.userService.selectemail();///查询
  }

}

配置数据库服务器

import { Injectable, Logger } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { User, UserDocument } from './user.schema';
import { Model, Schema } from 'mongoose';
import { Cron } from '@nestjs/schedule';
import { EmailService } from 'src/modules/email/email.service';
import { prototype } from 'events';
import { verify } from 'crypto';

@Injectable()
export class UserService {

    private readonly logger = new Logger(UserService.name);//定时任务
    constructor(@InjectModel('User') private readonly userModel: Model<UserDocument>,
    private readonly emailService:EmailService) {}  //用构造函数去注入  邮件功能
   
    // @Cron('0 15 10 ? * MON')//定时查询,发送邮件 .每周一上午10点15分执行任务
     @Cron('45 * * * * *')//定时查询,发送邮件
     async handleCron() {
        this.logger.debug('该方法将在45秒标记处每分钟运行一次');
        let list: User[] =  await this.selectemail()//查询数据库返回数组信息
        const emails = list.map(u => u.email).join(",")  //emails = 账号,账号,账号
        console.log(emails);
        console.log("定时任务查询了数据库");
        //展示数据库邮箱信息
        console.log("准被发送邮件");
        this.emailService.sendEmailCode(emails);
    } 
    async select(){
        return await this.userModel.find().exec();///查询
    }
    async selectemail(){
        return await this.userModel.find({},{email:1,name:1});///查询 给定的文档 返回    
    }
    async addEmail(userDto){
        return await this.userModel.create(userDto);//想调用添加方法
    }     
}

配置数据库Module

import { Module } from '@nestjs/common';
import { UserController } from './user.controller';
import { UserService } from './user.service';
import { MongooseModule } from '@nestjs/mongoose';
import { User, UserSchema } from './user.schema';
import { EmailModule } from 'src/modules/email/email.module';
import { EmailService } from 'src/modules/email/email.service';

@Module({
  imports: [
    MongooseModule.forFeature([{   //数据库的配置
     name: User.name,
     schema: UserSchema,
    }]),
    EmailModule    //将邮件模块引入进来
    
  ],
  controllers: [UserController],
  providers: [UserService]
})
export class UserModule {
  // constructor(private readonly emailService:EmailService){}
}

配置数据库user.Schema.ts 这个是我们自己创建的

// user.schema.ts
import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
import { Document } from 'mongoose';

export type UserDocument = User & Document;
@Schema({collection:"userandemail"}) // userandemail  是我数据库的表(集合)
export class User {
  @Prop()
  name: string;

  @Prop()
  age: number;

  @Prop()
  email: string;
}
export const UserSchema = SchemaFactory.createForClass(User);

就可以启动运行了

用Postman调用

http://localhost:3000/email //直接固定的发送(发送到我自己这里了)
http://localhost:3000/email/sendCode //传入一个账号发送
http://localhost:3000/user/addemail //存入数据库定时发送

nestjs邮件服务的链接

链接: nestjs官网定时.
链接: nestjs官网邮件.

你可能感兴趣的:(前端学习,mongodb,javascript,typescript)