如何实例化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
相关产品推荐
相关产品推荐

