使用Nodemailer发验证链接遇阻:开发正常,Cyclic.sh部署后Gmail拦截邮件
部署到Cyclic.sh后Nodemailer发送Gmail验证邮件失败且被拦截
我用Nodemailer给用户发邮箱验证链接,本地开发模式下邮件能正常送到用户邮箱,但部署到Cyclic.sh之后,邮件发不出去,还会被Gmail拦截。
拦截提示截图:
相关代码:
const nodemailer = require('nodemailer'); const jwt = require("jsonwebtoken"); const path = require("path"); if(process.env.NODE_ENV !== "production") { require('dotenv').config({ path: path.join(__dirname, "..", ".env") }); } const transporter = nodemailer.createTransport({ service: 'gmail', auth: { user: process.env.MAIL_ID, pass: process.env.MAIL_PASSWORD } }); module.exports = { sendVerificationLink: async (id, email, name) => { const token = jwt.sign({ data: { userid: id, name: name, email: email }, exp: Math.floor(Date.now() / 1000) + (60 * 60) }, process.env.ACCESS_TOKEN_SECRET); const mailOptions = { from: process.env.MAIL_ID, to: `${email}`, subject: "Verify your email", html: ` <p>Hi ${name}, please click on the following link to verify your email</p> <a href = "http://${process.env.DOMAIN}/auth/verify/${token}">Verify your email</a> ` }; await transporter.sendMail(mailOptions); return; } }
问题原因及解决办法
1. 修复Gmail账户权限问题
本地能用是因为开发机器IP在Gmail信任列表里,但Cyclic.sh的服务器IP属于陌生地址,Gmail会判定为风险登录直接拦截。按以下步骤操作:
- 登录Gmail账户进入「安全」设置,开启两步验证。
- 两步验证开启后,在同页面找到「应用专用密码」,生成一个仅用于Nodemailer的密码,替换.env里的
MAIL_PASSWORD。 - 确保「不太安全的应用访问」处于关闭状态(该选项已被两步验证替代,无需开启)。
2. 优化邮件内容降低垃圾邮件判定概率
Gmail的反垃圾机制会严格检查邮件属性:
- 给发件人添加友好名称:把
from字段改成"你的应用名称" <${process.env.MAIL_ID}>,比如from: "MyApp <myapp@gmail.com>",提升邮件辨识度。 - 替换HTTP链接为HTTPS:部署后的
DOMAIN要使用HTTPS开头,HTTP链接会被标记为不安全,触发拦截。 - 可选:在邮件底部添加退订提示,符合邮件发送规范,减少被判定为垃圾邮件的可能。
3. 调整Nodemailer的SMTP配置
使用service: 'gmail'偶尔会有兼容性问题,换成明确的SMTP配置更稳定:
const transporter = nodemailer.createTransport({ host: 'smtp.gmail.com', port: 465, secure: true, // 启用SSL加密 auth: { user: process.env.MAIL_ID, pass: process.env.APP_SPECIFIC_PASSWORD // 这里填应用专用密码 } });
4. 检查Cyclic.sh环境变量配置
确保Cyclic.sh后台的环境变量里,MAIL_ID、APP_SPECIFIC_PASSWORD、DOMAIN都配置正确,没有拼写错误,同时NODE_ENV设置为production,避免本地dotenv的影响。
5. 捕获错误日志排查问题
在sendMail代码中添加错误捕获,方便查看具体失败原因:
try { await transporter.sendMail(mailOptions); } catch (error) { console.error('邮件发送失败:', error); throw error; // 根据业务需求处理错误 }
然后在Cyclic.sh的控制台查看日志,能精准定位是认证失败、连接超时还是其他问题。
内容的提问来源于stack exchange,提问作者Daniel Vanum
相关产品推荐
相关产品推荐

