You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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;

关键要点

  1. 类型转换:通过Buffer.from(arrayBuffer)把ArrayBuffer转换成Node.js原生的Buffer,这是Nodemailer支持的合法类型。
  2. 空值校验:增加newfile的空判断,避免用户未上传文件时触发后续错误。
  3. 保留原文件信息:用newfile.name作为附件名,newfile.type指定MIME类型,让邮件客户端能正确识别文件类型。
  4. 错误处理:用try/catch包裹邮件发送逻辑,捕获异常并返回友好提示,同时便于排查问题。

另外,你之前尝试的newfile.stream也可以使用,但需要将其转换为Node.js可读流,相对来说Buffer的方式更直接易维护。

内容的提问来源于stack exchange,提问作者Ben Quan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 05:28:07