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

Next.js TypeScript集成Nodemailer表单无法发送邮件报错求助

Next.js + Nodemailer 联系表单500/404异常排查方案

问题根因说明

  • 直接访问接口返回Begone.属于正常逻辑:你的handler中写了非POST请求直接返回404的判断,浏览器直接访问接口是GET请求,触发该分支符合预期,不属于故障点。
  • 500错误的核心触发点是VSCode自动补全的formidablePromise函数:你关闭Next.js默认bodyParser后,接口需要手动通过formidable解析FormData格式的请求体,但自动生成的函数默认直接抛出Function not implemented错误,请求执行到该步骤直接中断,自然返回500状态码。
  • 将APIResponse类型替换为any只是绕过了TS类型检查,不会解决任何运行时错误,反而会掩盖类型不匹配的潜在问题。

分步修复方案

  1. 替换自动生成的空formidablePromise实现,补全FormData解析逻辑:

    // /pages/api/nodemailer.ts 文件内补充对应依赖导入
    import formidable from "formidable";
    import type { NextApiRequest, NextApiResponse } from "next";
    
    // 正确的formidable解析封装
    const formidablePromise = (req: NextApiRequest) => {
      return new Promise<{fields: Record<string, string>, files: formidable.Files}>((resolve, reject) => {
        const form = formidable({ multiples: false });
        form.parse(req, (err, fields, files) => {
          if (err) return reject(err);
          // formidable默认返回字段值为数组,统一转为字符串方便后续取值
          const parsedFields: Record<string, string> = {};
          for (const key in fields) {
            parsedFields[key] = Array.isArray(fields[key]) ? fields[key][0] : fields[key];
          }
          resolve({ fields: parsedFields, files });
        });
      });
    };
    

    注意:pages路由下请安装formidable@3.x版本,v4为纯ESM包,在CommonJS模块环境的pages接口中会出现导入报错。

  2. 补全类型定义,移除any类型绕过:

    // 定义明确的响应类型替换any
    type APIResponse = {
      message: string;
      error?: string;
    };
    
    // 确认bodyParser关闭配置写法正确
    export const config = {
      api: {
        bodyParser: false,
      },
    };
    
  3. 修正handler逻辑,确保POST分支正确走解析、发信流程:

    const handler = async (req: NextApiRequest, res: NextApiResponse<APIResponse>) => {
      // 非POST请求返回404的逻辑可保留
      if (req.method !== "POST") {
        return res.status(404).send({ message: "Begone." });
      }
    
      try {
        // 解析FormData请求体
        const { fields } = await formidablePromise(req);
        // 校验必填字段
        if (!fields.email || !fields.content) {
          return res.status(400).send({ message: "Missing required fields", error: "参数不全" });
        }
        // 此处编写原有Nodemailer发信逻辑即可
        // await transporter.sendMail({...})
        return res.status(200).send({ message: "邮件发送成功" });
      } catch (err) {
        return res.status(500).send({ message: "Send failed", error: (err as Error).message });
      }
    };
    
    export default handler;
    
  4. 检查前端Form组件请求逻辑:提交FormData时不要手动设置Content-Type请求头,浏览器会自动携带正确的multipart格式头与boundary参数,手动设置反而会导致后端解析失败;同时确认前端传的字段名和后端fields中取的字段名完全一致。

验证注意事项

  • 修改完成后重启Next.js开发服务,可在解析逻辑后加console.log(fields)确认能正常拿到表单提交的内容,再测试发信流程。
  • 发信时不要使用邮箱账号的明文密码,需配置邮箱服务商提供的应用专用密码,避免账号被风控拦截导致发信失败。

内容的提问来源于stack exchange,提问作者Joaquin Palacios

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 19:48:20