express + mongoose + nodemailer实现发送qq邮件

1,337 阅读2分钟

准备工作

依赖包

dependencies: {
    "@types/body-parser": "^1.17.1",
    "@types/chalk": "^2.2.0",
    "@types/dotenv": "^6.1.1",
    "@types/express": "^4.17.1",
    "@types/mongoose": "^5.5.18",
    "@types/nodemailer": "^6.2.1",
    "body-parser": "^1.19.0",
    "chalk": "^2.4.2",
    "dotenv": "^8.1.0",
    "express": "^4.17.1",
    "mongoose": "^5.7.1",
    "nodemailer": "^6.3.0"
}

目录结构

语言根据自己选择,我选用Typescript,因为自己习惯用Typescript。

在这里插入图片描述

config

config.ts主要是一些常量和接口的定义

import chalk from 'chalk'
import {Document} from 'mongoose'
// 返回数据的接口
export interface Res {
  state: string,
  msg: string,
}
// 扩展上面的接口
export interface UserRes extends Res {
  user: Document
}
// 端口
export const port: number = +process.env.PORT || 3000;
// 主机名
export const hostname: string = '127.0.0.1';
// 回调函数
export const callback: Function = () => console.log(`server is running on ${chalk.green(hostname)}:${chalk.green(port + '')}`);

mongoose连接mongo

import {createConnection} from 'mongoose'
// 导出一个connection
export default createConnection('mongodb://127.0.0.1:27017/testUser',
    {
      useNewUrlParser: true,
      useUnifiedTopology: true
    });

创建model

import db from './db'
import {Schema} from "mongoose";
// 创建userSchema模式
const userSchema: Schema = new Schema({
  username: {
    type: String,
    required: true
  },
  pwd: {
    type: String,
    required: true
  },
  email: {
    type: String,
    required: true
  },
  date: {
    type: Date,
    default: Date.now,
  }
});
// db.model(Model, schema, collection)
// 创建User模型并导出
const User = db.model('User', userSchema, 'user');
export default User

定义接口

初始化服务器

import {hostname, port, callback, Res, UserRes} from './config'
import {Request, Response} from 'express'

const express = require('express');
const bodyParser = require('body-parser');
const app = express();

// parse for application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({extended: false}));

// parse for application/json
app.use(bodyParser.json());
// 监听端口
app.listen(port, hostname, callback);

addUser接口

import {Request, Response} from 'express'
import {Document} from "mongoose";
import User from './models/User'
app.post('/addUser', async (req: Request, res: Response) => {
  try {
    // 查询有无username为传过来的username的user
    let user: Document = await User.findOne({username: req.body['username']});
    if (user) {
      // 返回的数据
      const data: Res = {
        state: 'failed',
        msg: '该用户已存在'
      };
      res.status(400).json(data)
    } else {
      // 如果用户并不存在在数据库则添加该用户
      const {username, password, email} = req.body;
      const newUser: Document = new User({
        username,
        pwd: password,
        email
      });
      let savedUser: Document = await newUser.save();
      const data: UserRes = {
        state: 'success',
        msg: '添加用户成功',
        user: savedUser
      };
      res.status(200).json(data)
    }
  } catch (e) {
    console.log(e)
  }
});

发送邮件findPwd接口

import {SentMessageInfo, Transporter, SendMailOptions} from "nodemailer";
const nodeMailer = require('nodemailer');
app.post('/findPwd', async (req: Request, res: Response) => {
  try {
    // 取得post参数的email和username
    const {email, username} = req.body;
    // 在mongo中查询user为username的user
    let user: Document = await User.findOne({username});
    if (user) {
      // 以下代码是发送qq邮件的主要代码
      // step1: 创建一个transporter
      let transporter: Transporter = nodeMailer.createTransport({
      	// 选择邮箱的服务类型
        service: 'qq',
        // 安全发送
        secure: true,
        // 验证用户名或密码
        auth: {
          user: 发送方的邮箱地址,
          pass: 发送方的邮箱密码或开启qq邮箱的IMAP/SMTP服务器时的密文
        }
      });
      // step2 设置邮箱选项
      let mailOptions: SendMailOptions = {
        // 从from发送到to邮箱
        from: 发送方的邮箱,
        to: email,
        // 发送邮件的标题
        subject: '找回密码',
        // 发送邮件的内容
        text: `您的用户名:${user.username},密码${user.pwd}`
      };
      // step 3 发送邮件
      transporter.sendMail(mailOptions, (err: Error | null, data: SentMessageInfo) => {
        if (err) {
          const data: Res = {
            state: 'failed',
            msg: '发送失败'
          };
          res.status(400).json(data);
        } else {
          const data: Res = {
            state: 'success',
            msg: `密码已发送至您的邮箱${email}`
          };
          res.status(200).json(data)
        }
      })
    } else {
      const data: Res = {
        state: 'failed',
        msg: '该用户不存在',
      };
      res.status(400).json(data)
    }
  } catch (e) {
    console.log(e)
  }
});