使用Nodemailer+Ethereal测试账户时遇Greeting never received错误
Nodemailer + Ethereal测试邮箱触发「Greeting never received」错误的解决方案
先还原你的问题场景:在Node 8.11.2环境下使用Nodemailer 4.6.4,通过Ethereal测试邮箱发送邮件时,不管用回调还是async/await模式,调用sendMail都会触发「Greeting never received」错误,代码完全参照官方示例,错误栈显示是连接超时(ETIMEDOUT)。
你的报错代码(回调模式)
it('can send email with a dynamic test account', done => { nodemailer.createTestAccount((err, account) => { const transporter = nodemailer.createTransport({ host: 'smtp.ethereal.email', port: 587, auth: { user: account.user, // generated ethereal user pass: account.pass // generated ethereal password } }); const mailOptions = { from: '"Fred Foo 👻" <foo@example.com>', // sender address to: 'bar@example.com, baz@example.com', // list of receivers subject: 'Hello ✔', // Subject line text: 'Hello world?', // plain text body html: '<b>Hello world?</b>' // html body }; // send mail with defined transport object transporter.sendMail(mailOptions, (error, info) => { if (error) { return console.log(error); } console.log('Message sent: %s', info.messageId); console.log('Preview URL: %s', nodemailer.getTestMessageUrl(info)); done(); }); }); }).timeout(10000);
错误堆栈信息
{ Error: Greeting never received at SMTPConnection._formatError (/Users/<username>/projects/personal/learning-tests/javascript/nodemailer/node_modules/nodemailer/lib/smtp-connection/index.js:606:19) at SMTPConnection._onError (/Users/<username>/projects/personal/learning-tests/javascript/nodemailer/node_modules/nodemailer/lib/smtp-connection/index.js:579:20) at Timeout._greetingTimeout.setTimeout (/Users/<username>/projects/personal/learning-tests/javascript/nodemailer/node_modules/nodemailer/lib/smtp-connection/index.js:520:22) at ontimeout (timers.js:498:11) at tryOnTimeout (timers.js:323:5) at Timer.listOnTimeout (timers.js:290:5) code: 'ETIMEDOUT', command: 'CONN' }
环境信息
- Node版本:8.11.2
- Nodemailer版本:4.6.4
- 操作系统:OSX 10.12.6
问题根源分析
这个错误本质是SMTP连接超时,Greeting never received意味着Nodemailer无法从Ethereal的SMTP服务器收到初始问候报文,结合ETIMEDOUT代码,大概率是以下几个原因:
- 网络限制:你的网络(比如公司内网、校园网)屏蔽了对
smtp.ethereal.email的587端口访问,或者需要走代理才能连接外部SMTP服务器; - Node版本过旧:Node 8.x已经停止维护多年,对现代TLS协议的支持不完善,和Ethereal的SMTP服务器握手失败;
- 默认连接超时设置过短:官方示例的超时可能不足以应对网络波动;
- TLS证书验证问题:老Node版本可能无法正确验证Ethereal的SSL证书,导致连接中断。
具体解决方案
1. 先排查网络连通性
在终端执行以下命令,测试能否连接到Ethereal的SMTP服务器:
telnet smtp.ethereal.email 587
如果连接失败(提示Connection refused或超时),说明网络有问题:
- 如果你用的是代理网络,需要在Nodemailer的transporter中配置代理:
const transporter = nodemailer.createTransport({ host: 'smtp.ethereal.email', port: 587, auth: { /* ...你的账户信息... */ }, proxy: 'http://your-proxy-address:port' // 替换成你的代理地址 }); - 如果是防火墙限制,需要临时关闭防火墙或者添加规则允许访问该地址和端口。
2. 调整Nodemailer的连接配置
修改transporter的配置,增加超时时间、开启调试日志、调整TLS选项:
it('can send email with a dynamic test account', done => { nodemailer.createTestAccount((err, account) => { const transporter = nodemailer.createTransport({ host: 'smtp.ethereal.email', port: 587, secure: false, // 587端口用STARTTLS,必须设为false auth: { user: account.user, pass: account.pass }, debug: true, // 开启调试日志,方便查看连接细节 tls: { rejectUnauthorized: false, // 跳过证书验证(老Node版本必备) minVersion: 'TLSv1.2' // 指定TLS版本,避免握手失败 }, connectionTimeout: 15000, // 延长连接超时到15秒 greetingTimeout: 15000 // 延长问候超时到15秒 }); const mailOptions = { /* ...你的邮件配置... */ }; transporter.sendMail(mailOptions, (error, info) => { if (error) { return console.log(error); } console.log('Message sent: %s', info.messageId); console.log('Preview URL: %s', nodemailer.getTestMessageUrl(info)); done(); }); }); }).timeout(15000); // 把测试超时也延长到15秒
开启debug: true后,你能在终端看到详细的SMTP连接日志,方便定位到底是握手失败还是真的超时。
3. 升级Node版本(最推荐的长期解决方案)
Node 8.x已经是淘汰版本,不仅安全漏洞多,而且很多现代网络协议支持不完善。建议升级到Node 14.x或更高的LTS版本(比如当前的Node 20.x),升级后很多TLS相关的兼容性问题会自动解决。
4. 重新生成Ethereal测试账户
偶尔createTestAccount生成的临时账户可能有异常,你可以手动创建一个固定测试账户,替换代码中的account.user和account.pass试试。
内容的提问来源于stack exchange,提问作者Derek Hubbard
相关产品推荐
相关产品推荐

