Node.js+Nodemailer:从表单获取发件人邮箱并解决显示异常
问题描述
我想从表单输入中获取用户的邮箱作为邮件的from字段,但现在收件人看到的发件人被替换成了SMTP认证的邮箱,导致发件人和预期不符。以下是我的前端表单代码和Node.js后端代码:
前端代码
<p class="drop">Drop A Message</p> <label for="name">Name:</label><br> <input type="text" name="" id="name" class="form-inputs" placeholder="Full Name" ><br> <label for="email">Email:</label><br> <input type="email" name="" id="email" class="form-inputs" placeholder="Email Address" ><br> <label for="subject">Subject:</label><br> <input type="text" name="" id="subject" class="form-inputs" placeholder="Subject Of The Message"><br> <label for="message">Message:</label><br> <textarea name="" id="mainMessage" cols="30" rows="10" class="message_body" ></textarea><br> <input type="submit" value="Send Message" class="submit_btn"> </form>
Node.js后端代码
app.post('/', (req,res) =>{ // console.log(req.body); const transporter = nodemailer.createTransport(smtpTransport({ service:'Gmail', // host: 'smtp.gmail.com', secure:false, auth: { user: 'horiyorrmi72@gmail.com', pass: 'password' } })) const mailOptions = { from: req.body.email, to : "horla_tech@protonmail.com", subject: `${req.body.subject}`, text : req.body.message } transporter.sendMail(mailOptions, (error, info) =>{ if(error){ console.log(error); res.send('error'); }else{ console.log('Email sent' + info.response); res.send('success'); } }) }) app.listen(PORT, ()=> { console.log(`server running on port: ${PORT}`); })
解决方案
核心问题原因
Gmail的SMTP服务有安全限制:当你用Gmail账户认证发送邮件时,from字段会被强制替换为你的认证邮箱(horiyorrmi72@gmail.com),不允许直接伪造发件人地址,这就是你看到发件人不符合预期的原因。
分步修复
- 补全前端表单的
name属性
当前表单输入框的name为空,后端无法正确获取表单字段值,必须给每个输入框添加对应的name:
<input type="text" name="name" id="name" class="form-inputs" placeholder="Full Name" ><br> <input type="email" name="email" id="email" class="form-inputs" placeholder="Email Address" ><br> <input type="text" name="subject" id="subject" class="form-inputs" placeholder="Subject Of The Message"><br> <textarea name="message" id="mainMessage" cols="30" rows="10" class="message_body" ></textarea><br>
- 调整后端邮件配置
from字段使用认证邮箱,但可以附加用户的名称和邮箱作为显示名称;- 添加
replyTo字段指向用户输入的邮箱,这样收件人回复时会直接发送给用户; - 开启
secure: true适配Gmail的SSL端口,避免连接错误。
调整后的后端代码:
app.post('/', (req,res) =>{ const transporter = nodemailer.createTransport({ service:'Gmail', secure: true, // 启用SSL连接 auth: { user: 'horiyorrmi72@gmail.com', pass: 'password' // 建议使用Gmail应用专用密码,需开启两步验证 } }) const mailOptions = { from: `${req.body.name} <horiyorrmi72@gmail.com>`, // 显示用户名称+认证邮箱 replyTo: req.body.email, // 设置回复邮箱为用户输入的地址 to : "horla_tech@protonmail.com", subject: req.body.subject, text : `来自${req.body.name}的消息:\n${req.body.message}\n联系邮箱:${req.body.email}` } transporter.sendMail(mailOptions, (error, info) =>{ if(error){ console.log(error); res.send('error'); }else{ console.log('Email sent: ' + info.response); res.send('success'); } }) })
- Gmail账户必要设置
- 若使用普通密码,需开启Gmail的"不太安全的应用访问";
- 更安全的方式是开启两步验证后,创建应用专用密码替代原账户密码;
- 确保Gmail SMTP服务未被限制。
内容的提问来源于stack exchange,提问作者horla
相关产品推荐
相关产品推荐

