Skip to content

Nest 发送邮件

邮件协议

  • SMTP:发送邮件协议
  • IMAP:接收邮件协议
  • POP3:接收邮件协议

邮件使用场景

注意

  • 验证码
  • 邮箱注册
  • 邮箱找回密码
  • 验证码流程

先去查看验证码对不对,再去查看用户名有没有 最后返回

接受发送用的插件

  • nodemailer:发送邮件
  • node-imap:接收邮件

开启协议

我这里就用 QQ 邮箱举例

  • 获取授权码

发送邮件

安装包

ts
pnpm add --save nodemailer

pnpm add --save-dev @types/nodemailer

发送邮件第一步

创建邮件模块和服务

ts
nest g  module emial
nest g service emial

email.module.ts

ts
import { Module } from "@nestjs/common";
import { EmailService } from "./email.service";

@Module({
  providers: [EmailService],
  exports: [EmailService],
})
export class EmailModule {}

email.service.ts

ts
import { Injectable } from "@nestjs/common";
import { createTransport, Transporter } from "nodemailer";
@Injectable()
export class EmailService {
  transporter: Transporter;
  // 不同的邮箱 不同的设置
  /*
   host: 'smtp-mail.outlook.com',
   port: 587,
   secure: false
   */
  // QQ邮箱
  /*
   host: 'smtp.qq.com',
   port: 465,
   secure: true
  */
  // 网易163邮箱
  /*
host: 'smtp.163.com',
port: 465,
secure: true
 */
  constructor() {
    this.transporter = createTransport({
      host: "smtp.qq.com",
      port: 587,
      secure: false,
      auth: {
        user: "xxx@qq.com", // 发送邮箱的账号
        pass: "xxxx", // 获取发送邮箱的授权码
      },
    });
  }
  // 发送邮件
  async sendEmail({ to, subject, html }) {
    const result = await this.transporter.sendMail({
      from: {
        name: "验证发送邮件请勿回复", // 这个就是右下脚提示的语言
        address: "xxx@qq.com", // 发送邮箱的账号
      },
      to,
      subject,
      html,
    });
    return result;
  }

  // 发送带附件的
  async sendEmailfujian({ to, subject, html, attachments }) {
    const result = await this.transporter.sendMail({
      from: {
        name: "验证发送邮件请勿回复", // 这个就是右下脚提示的语言
        address: "xxxx@qq.com", // 发送邮箱的账号
      },
      to,
      subject,
      html,
      attachments,
    });
    return result;
  }
}

发送邮件第二步

基础版本

  • 发送邮件的 service.ts
ts
  async sendemail() {
    const result = await this.emailService.sendEmail({
      to: 'xxxx5@qq.com', // 你要发送的邮件账号
      subject: '测试邮件', // 标题
      html: '测试邮件内容', // 邮件内容
    });
  if (result.messageId) {
      return {
        data: {
          message: '发送成功',
        },
      };
    } else {
      return {
        data: {
          message: '发送失败',
        },
      };
    }
  }
  • 发送邮件的 controller
ts
  // 发送邮件
  @Post('sendemail')
  async sendemail() {
    const result = await this.userService.sendemail();
    return {
      data: result,
    };
  }

读取 html 版本

  • 使用场景广泛

注意

  1. 重置密码 (里面有个连接.连接上有个 token24 小时失效)

  2. 验证邮箱 (验证邮箱)

  3. 订单确认 (只能点击一次)

  4. 验证码 等等

  • 发送邮件的 service.ts
ts
  // 发送电子邮件html版本
  async sendemailhtml() {
    const readdir = './src/modules/user/emailhtml/index.html'; // 文件目录
    const result = await this.emailService.sendEmail({
      to: 'xxxxx@qq.com', // 你要发送的邮件账号
      subject: '我个人的邮件', // 邮件标题
      html: fs.readFileSync(readdir, 'utf-8'), // 读取文件内容
    });
    if (result.messageId) {
      return {
        data: {
          message: '发送成功',
        },
      };
    } else {
      return {
        data: {
          message: '发送失败',
        },
      };
    }
  }
  • 发送邮件的 controller
ts
  // 发送邮件html
  @Post('sendemailhtml')
  async sendemailhtml() {
    const result = await this.userService.sendemailhtml();
    return {
      data: result,
    };
  }

带附件版本

  • 发送邮件的 service.ts
ts
  // 发送电子邮件附件版本
  async sendemailfujian() {
    const filedir = './src/modules/user/emailhtml/功率元器件产品目录.pdf';
    const result = await this.emailService.sendEmailfujian({
      to: 'xxxxx@qq.com',
      subject: '文件邮件',
      html: '文件邮件内容',
      attachments: [
        // 多个就继续写
        {
          filename: '文档.pdf',
          path: filedir,
        },
      ],
    });
    if (result.messageId) {
      return {
        data: {
          message: '发送成功',
        },
      };
    } else {
      return {
        data: {
          message: '发送失败',
        },
      };
    }
  }
  • 发送邮件的 controller
ts
  // 发送邮件html附件版本
  @Post('sendemailfujian')
  async sendemailfujian() {
    const result = await this.userService.sendemailfujian();
    return {
      data: result,
    };
  }

群发邮件

  • 发送邮件的 service.ts

仅仅需要在 to 的后面加上你自己的邮箱用逗号分隔

ts
  // 发送电子邮件
  async sendemail() {
    const result = await this.emailService.sendEmail({
      to: 'xxxx1@qq.com,xxxx2@gmail.com',
      subject: '测试邮件',
      html: '测试邮件内容',
    });
    console.log(result);
    return {
      data: result,
    };
  }
  • 发送邮件的 controller
ts

  // 发送邮件
@Post('sendemail')
  async sendemail() {
    const result = await this.userService.sendemail();
    return {
      data: result,
    };
  }

邮件被标记为垃圾邮件

注意

  1. 使用 SPF 和 DKIM 验证(需要域名 DNS 配置)

  2. 避免使用过多的感叹号和全大写单词

  3. 确保 HTML 和文本内容都存在

  4. 不要发送未经请求的邮件

  5. 提供明确的退订选项