跳转至

NestJS

适用于 NestJS(Node.js 18+)应用的集成指南。Mailexam 通过 Nodemailer@nestjs-modules/mailer 模块作为 SMTP 接入。

前置条件

  • Mailexam 账户,以及已创建并具备 SMTP 凭据的项目
  • Nest 应用(CLI:nest new)。

从项目的欢迎邮件(或控制台)中复制:

  • YOUR_LOGIN — SMTP 登录名(例如 xxxxx);
  • YOUR_PASSWORD — SMTP 密码(与登录名成对的唯一凭据);
  • 主机 — YOUR_LOGIN.mailexam.cn登录名一致)。

1. 依赖

npm install @nestjs-modules/mailer nodemailer
npm install -D @types/nodemailer

.env 可选依赖:

npm install @nestjs/config

2. 环境变量

项目根目录的 .env 文件(勿将密码提交到 git):

MAILEXAM_LOGIN=YOUR_LOGIN
MAILEXAM_PASSWORD=YOUR_PASSWORD
MAILEXAM_PORT=587
MAIL_FROM=noreply@example.test

SMTP 主机:YOUR_LOGIN.mailexam.cn

发件人地址

MAIL_FROM 可以是任意测试地址——邮件进入 Mailexam,而非真实收件人。

备选端口

MAILEXAM_PORT=587

传输配置中:secure: false(587 上 STARTTLS)。

MAILEXAM_PORT=2525
MAILEXAM_PORT=465

传输配置中设置 secure: true

3. Mailer 模块

app.module.ts

import { Module } from '@nestjs/common';
import { MailerModule } from '@nestjs-modules/mailer';
import { ConfigModule } from '@nestjs/config';
import { MailController } from './mail.controller';

@Module({
  imports: [
    ConfigModule.forRoot({ isGlobal: true }),
    MailerModule.forRootAsync({
      useFactory: () => {
        const login = process.env.MAILEXAM_LOGIN!;
        const port = Number(process.env.MAILEXAM_PORT ?? 587);

        return {
          transport: {
            host: `${login}.mailexam.cn`,
            port,
            secure: port === 465,
            auth: {
              user: login,
              pass: process.env.MAILEXAM_PASSWORD,
            },
          },
          defaults: {
            from: process.env.MAIL_FROM ?? 'noreply@example.test',
          },
        };
      },
    }),
  ],
  controllers: [MailController],
})
export class AppModule {}

不使用 @nestjs/config 时移除 ConfigModule,并确保变量已在进程环境中设置。

4. 测试路由

// mail.controller.ts
import { Body, Controller, Post } from '@nestjs/common';
import { MailerService } from '@nestjs-modules/mailer';

class SendMailDto {
  to?: string;
  subject?: string;
  text?: string;
}

@Controller('mail')
export class MailController {
  constructor(private readonly mailer: MailerService) {}

  @Post('test')
  async test(@Body() body: SendMailDto) {
    await this.mailer.sendMail({
      to: body.to ?? 'user@example.test',
      subject: body.subject ?? 'Nest + Mailexam',
      text: body.text ?? '来自 NestJS 的 Mailexam 测试',
    });

    return { status: 'ok' };
  }
}

启动并验证:

npm run start:dev
curl -X POST http://127.0.0.1:3000/mail/test \
  -H 'Content-Type: application/json' \
  -d '{"to":"user@example.test","subject":"测试","text":"你好"}'

邮件将出现在 Mailexam 控制台 → 您的项目 → 收件箱。

5. 本地开发与 CI

环境 建议
local .env + ConfigModule.forRoot()
CI GitLab CI/CD Variables 中的密钥 MAILEXAM_LOGINMAILEXAM_PASSWORD

.gitlab-ci.yml 示例:

variables:
  MAILEXAM_LOGIN: $MAILEXAM_LOGIN
  MAILEXAM_PASSWORD: $MAILEXAM_PASSWORD
  MAILEXAM_PORT: "587"
  MAIL_FROM: "noreply@example.test"

单元测试可 mock MailerService,或在测试模块中使用 transport: { jsonTransport: true }

集成测试后,通过 Mailexam API 验证投递。

6. 常见问题

连接超时 / 认证失败

  • host 须为 {login}.mailexam.cnauth.user — 邮件中的同一登录名。
  • 登录名和密码为同一项目的邮件成对凭据

587 端口与 TLS

  • 587 使用 secure: false(STARTTLS)。465 使用 secure: true

变量为 undefined

  • 添加 ConfigModule.forRoot() 或在 CI 中 export .env

控制台中看不到邮件

  • 查看同一 Mailexam 项目的收件箱。
  • 检查 Nest 日志中 sendMail 的 SMTP 错误。

参见