You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实例化module.exports导出的邮件模块?遇Email类构造函数报错

解决TypeError: Class constructor Email cannot be invoked without new问题

这个错误的核心原因是:你使用的**email-templates是v3及以上的新版本**,但教程里的代码是针对v2及更早的旧版本编写的——新版本的API已经从回调式的函数改成了需要实例化的类,直接像旧代码那样调用就会触发这个错误。

修复步骤

1. 理解版本差异

旧版本(v2)的用法是直接调用emailTemplates()传目录和回调:

// 旧版本(v2)的写法
emailTemplates('./templates', (err, template) => { ... })

而新版本(v3+)要求你先通过new实例化EmailTemplates类,再使用它的API:

// 新版本(v3+)的写法
const EmailTemplates = require('email-templates');
const template = new EmailTemplates({
  views: { root: './templates' }
});

2. 重写你的邮件模块

下面是适配新版本email-templates的修正代码,同时优化了初始化逻辑(避免每次调用sendMail都重复初始化):

const nodemailer = require('nodemailer');
const EmailTemplates = require('email-templates');
const path = require('path');

class MailSender {
  constructor() {
    // 只初始化一次transport和template实例
    this._transport = null;
    this._template = null;
  }

  async init(config) {
    if (this._transport && this._template) return;

    // 初始化模板引擎
    this._template = new EmailTemplates({
      views: {
        root: path.resolve(config.emailTplsDir)
      }
    });

    // 初始化邮件传输器
    this._transport = nodemailer.createTransport({
      service: 'Sendgrid',
      auth: {
        user: process.env.SENDGRID_USERNAME,
        pass: process.env.SENDGRID_PASSWORD
      }
    });
  }

  async send(from, to, subject, text, html) {
    const params = { from, to, subject, text };
    if (html) params.html = html;
    return this._transport.sendMail(params);
  }

  async sendMail(from, to, subject, tplName, locals) {
    // 确保初始化完成
    await this.init({ emailTplsDir: "email-templates" });
    
    // 渲染模板(新版本返回的是包含html和text的对象)
    const { html, text } = await this._template.render(tplName, locals);
    
    // 发送邮件
    return this.send(from, to, subject, text, html);
  }
}

// 导出单例实例,避免重复创建
module.exports = new MailSender();

3. 调用方式保持不变

你的调用代码不需要修改,依然可以像之前那样使用:

var mailer = require('../../utils/mailSender');
var locals = { name: "New User", siteName: "Takwinland" };

mailer.sendMail('contact@takwinland.com', "dhaker.odesk@gmail.com", 'Welcome!', 'signup', locals)
  .then(function () {
    res.status(200).send('A welcome email has been sent to ' + "dhaker.odesk@gmail.com" + '.');
  })
  .catch(function (err) {
    return res.status(500).send({ msg: err.message });
  });

额外优化建议

  • 移除对Q的依赖:新版本的nodemailer和email-templates都原生支持Promise,用async/await会让代码更简洁易读。
  • 把模板目录路径配置到环境变量或单独的配置文件里,不要硬编码在代码中。

内容的提问来源于stack exchange,提问作者Med Dhaker Abdeljawed

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:52:08