SvelteKit中Nodemailer结合FormData发送带附件邮件的问题
在SvelteKit中通过Nodemailer发送FormData中的文件附件
问题描述
我在SvelteKit的+page.server.ts中尝试用Nodemailer发送邮件,通过FormData接收用户上传的文件,但处理附件时遇到了类型错误。
我的+page.server.ts代码如下:
import type { Actions } from './$types'; import nodemailer from 'nodemailer'; export const actions = { default: async ({ request }) => { const data = await request.formData(); const newfile = data.get('file') as File; const transporter = nodemailer.createTransport({ ...... // 此处省略邮箱配置 }); // 发送邮件 const info = await transporter.sendMail({ from: 'xxx@xxx.net', to: 'xxx@xxx.net', subject: 'WEB Message: ', html: 'testing', attachments: [ { filename: 'new_file.svg', content: await newfile.arrayBuffer() } ] }); console.log('Message sent: %s', info.messageId); } } satisfies Actions;
我尝试过以下几种处理文件的方式:
content: newfile content: newfile.stream content: newfile.text content: await newfile.arrayBuffer()
但都报错,错误信息如下:
TypeError [ERR_INVALID_ARG_TYPE]: The "chunk" argument must be of type string or an instance of Buffer or Uint8Array. Received an instance of ArrayBuffer at new NodeError (node:internal/errors:399:5) at _write (node:internal/streams/writable:315:13) at Writable.end (node:internal/streams/writable:612:17) at Immediate.<anonymous> (/Users/ben/Development/Sites/outsourcing/node_modules/.pnpm/nodemailer@6.9.1/node_modules/nodemailer/lib/mime-node/index.js:977:46) at process.processImmediate (node:internal/timers:471:21) { code: 'ERR_INVALID_ARG_TYPE' }
核心问题:如何正确处理newfile变量,并通过Nodemailer成功发送该附件?
解决方案
错误原因很明确:Nodemailer的attachments.content不接受ArrayBuffer类型,只支持字符串、Buffer或Uint8Array。你需要把ArrayBuffer转换成Node.js的Buffer或者Uint8Array。
修改后的完整代码
import type { Actions } from './$types'; import nodemailer from 'nodemailer'; export const actions = { default: async ({ request }) => { const data = await request.formData(); const newfile = data.get('file') as File | null; // 先判断是否上传了文件 if (!newfile) { return { error: '未上传任何文件' }; } const transporter = nodemailer.createTransport({ // 替换成你的SMTP配置 host: 'smtp.your-email-provider.com', port: 587, secure: false, auth: { user: 'your-account@example.com', pass: 'your-password' } }); // 将ArrayBuffer转为Node.js Buffer const arrayBuffer = await newfile.arrayBuffer(); const fileBuffer = Buffer.from(arrayBuffer); try { const info = await transporter.sendMail({ from: 'xxx@xxx.net', to: 'xxx@xxx.net', subject: 'WEB Message: ', html: 'testing', attachments: [ { filename: newfile.name, // 使用原文件名更合理 content: fileBuffer, contentType: newfile.type // 指定文件MIME类型,提升兼容性 } ] }); console.log('Message sent: %s', info.messageId); return { success: true }; } catch (error) { console.error('发送邮件失败:', error); return { error: '邮件发送失败,请稍后重试' }; } } } satisfies Actions;
关键要点
- 类型转换:通过
Buffer.from(arrayBuffer)把ArrayBuffer转换成Node.js原生的Buffer,这是Nodemailer支持的合法类型。 - 空值校验:增加
newfile的空判断,避免用户未上传文件时触发后续错误。 - 保留原文件信息:用
newfile.name作为附件名,newfile.type指定MIME类型,让邮件客户端能正确识别文件类型。 - 错误处理:用
try/catch包裹邮件发送逻辑,捕获异常并返回友好提示,同时便于排查问题。
另外,你之前尝试的newfile.stream也可以使用,但需要将其转换为Node.js可读流,相对来说Buffer的方式更直接易维护。
内容的提问来源于stack exchange,提问作者Ben Quan
相关产品推荐
相关产品推荐

