Nodemailer发送邮件附件存在文件名但内容为空如何解决
问题根因
附件为空是3处代码错误共同导致的:
- 前端未正确配置文件上传规则,实际只把浏览器生成的假文件路径传到了后端,根本没传输文件二进制内容
- 后端未配置multipart格式解析逻辑,无法从请求中拿到真实文件数据
- Nodemailer附件配置缺失必填的文件内容字段,同时存在MIME类型书写错误
第一步:修复前端上传配置
当前表单默认使用application/x-www-form-urlencoded编码,文件控件也未配置匹配后端的name属性,提交时只会传递文件名的假路径(就是MIME片段里看到的C:\fakepath\前缀内容),不会携带真实文件。
修改规则:
- 给Form标签添加
encType="multipart/form-data"属性,开启文件编码传输 - 给文件选择控件添加
name="fFileMultiple"属性,和后端接收字段名对应;如果需要支持多文件选择,额外添加multiple属性 - 如果使用fetch/axios发送请求,必须用
FormData对象封装请求体,不能用JSON格式传参
修改后的前端代码片段:
<Form encType="multipart/form-data" {/* 保留原有method、onSubmit等属性 */} > {/* 保留其他原有表单项 */} <Form.Group> <Form.Label>Multiple Photos Allowed</Form.Label> <Form.Control type='file' name='fFileMultiple' multiple accept='.jpg, .png, .jpeg' /> </Form.Group> <Button type='submit' value={"submit"}> {status} </Button> </Form>
第二步:后端添加文件解析中间件
普通的请求体解析中间件(比如express.json()、express.urlencoded())无法解析multipart格式的文件内容,需要添加专门的文件处理中间件,以最常用的multer为例:
- 安装依赖:
npm install multer - 在服务入口文件引入并配置内存存储,直接把上传的文件暂存在内存中供邮件发送使用:
const multer = require('multer'); const upload = multer({ storage: multer.memoryStorage() });
- 给接收表单提交的路由添加中间件:单文件上传用
upload.single('fFileMultiple'),多文件上传用upload.array('fFileMultiple')。添加后真实文件数据会存到req.file(单文件)或req.files(多文件)对象中,不再出现在req.body里。
第三步:修正Nodemailer附件配置
原附件配置只传了文件名和错误的MIME类型,完全缺失文件内容字段,这是MIME片段里附件部分为空的直接原因。另外JPEG格式的正确MIME类型是image/jpeg,不是你写的images/jpeg。
单文件场景下修改后的邮件发送代码如下:
// 路由示例:app.post('/submit-complaint', upload.single('fFileMultiple'), (req, res) => { const cName = req.body.cName; const cAddress = req.body.cAddress; const phone = req.body.phone; const email = req.body.email; const vName = req.body.vName; const vAddress = req.body.vAddress; const violation = req.body.violation; const uploadFile = req.file; // 从req.file取真实文件数据,不要从req.body取 let mail = { from: "hello@gmail.com", to: "email@gmail.com", subject: `Complaint from ${cName} on ${vName}`, html: `The message is from ${cName} <br /> Complaint's Name: ${cName} <br /> Complaint's address: ${cAddress} <br /> Email: ${email} <br /> Phone: ${phone} <br /> Violator's Name: ${vName} <br /> Violator's Address: ${vAddress} <br /> Violation: ${violation} <br />`, attachments: [ { filename: uploadFile.originalname, // 自动取真实文件名,去掉fakepath假路径前缀 contentType: uploadFile.mimetype, // 用上传时自动识别的MIME类型,无需硬写 content: uploadFile.buffer // 传入文件二进制内容,为之前缺失的核心字段 }, ], }; contactEmail.sendMail(mail, (error) => { if (error) { console.log(error); return res.status(500).send('发送失败'); } else { console.log("Message has been sent"); return res.send('发送成功'); } }); // })
如果是多文件上传场景,遍历req.files数组生成attachments列表即可。
验证标准
修改完成后重新发送请求,导出邮件原始MIME信息,若附件的两个分隔符之间存在大段base64编码内容,说明文件已经正确携带,不会再出现空附件问题。
内容的提问来源于stack exchange,提问作者Terry Hunt
相关产品推荐
相关产品推荐

