nodemailer实现的邮件发送功能仅移动端失效,是什么原因?
问题修复方案
核心问题出在异步逻辑执行顺序,以及部分移动端浏览器的请求规则适配问题,具体修复点如下:
- 提前关闭了smtp传输通道:
sendMail是异步方法,你写在回调外的smtpTransport.close()会在发信请求还没处理完成就直接切断连接,PC端网络延迟低大概率能赶在关闭前完成发信,移动端网络波动大就会触发提前断连导致失败,需要把关闭逻辑挪到sendMail的回调函数内部。 - 当前的CORS配置没有适配OPTIONS预检请求:部分移动端浏览器(比如Safari、微信内置浏览器)发POST跨域请求前会先发送OPTIONS预检请求,默认的cors配置没有明确处理该类请求,会导致接口请求被拦截。
- 代码存在笔误:根路径GET路由中响应对象拼写错误,把
res拼成了resizeBy,虽然不影响发信接口,但会导致根路径访问报错。 - Gmail发信鉴权优化:直接使用账号密码发信后续会被谷歌的安全策略拦截,建议开启谷歌账号的两步验证后,生成应用专用密码代替普通账号密码使用。
修复后参考代码:
const express = require('express'); const bodyParser = require('body-parser'); const nodemailer = require('nodemailer'); const cors = require('cors'); const app = express(); app.use(bodyParser.json()); app.use(bodyParser.urlencoded({extended: true})); // 明确配置CORS规则,建议把origin替换为你的个人站点实际域名,避免被恶意调用 const corsOptions = { origin: '*', methods: ['GET', 'POST', 'OPTIONS'], allowedHeaders: ['Content-Type'] } app.use(cors(corsOptions)); // 手动处理OPTIONS预检请求 app.options('/api/form', cors(corsOptions)); app.get('/', (req, res)=> { res.send('welcome to my form') }) app.post('/api/form', (req, res)=>{ let data = req.body let smtpTransport = nodemailer.createTransport({ service: 'gmail', port:465, secure: true, // 465端口需显式开启安全传输配置 auth:{ user:"xxxxxx@gmail.com", pass:'xxxxxx' // 替换为谷歌账号生成的应用专用密码 } }); let mailOptions={ from:data.email, to:'xxxxxxxx@gmail.com', subject:`from BLOG`, html:` <h3 style="text-decoration:underline;">Informations</h3> <p style="padding: 10px 10px"> ${data.message}</p> ` }; smtpTransport.sendMail(mailOptions, (error,response)=>{ // 发信完成后再关闭传输通道 smtpTransport.close(); if(error){ res.status(500).send(error) } else{ res.send('Success') } }) }) const PORT = process.env.PORT||3001; app.listen(PORT,()=>{ console.log(`Server starting at port ${PORT}`); })
内容的提问来源于stack exchange,提问作者jesuismert
相关产品推荐
相关产品推荐

