You need to enable JavaScript to run this app. 使用Node+Nodemailer开发联系表单提交时出现JSON解析错误与500内部错误
优惠活动
大模型
产品
解决方案
定价
更多

使用Node+Nodemailer开发联系表单提交时出现JSON解析错误与500内部错误

联系表单提交报错排查与修复

报错根源拆解

页面同时出现的两个报错是连锁触发的关系:

  • 前端抛出的unexpected token s in json at position 0:前端代码写死了要把接口返回值解析为JSON格式,但服务端不管请求成功还是失败,返回的都是纯文本字符串,文本首字符是s(对应"Something went wrong"或"Email successfully sent..."的首字母),根本不是合法JSON,因此解析直接失败。
  • 接口返回500 (Internal Server Error):说明服务端处理发信逻辑的环节本身抛出了错误,没有正常走完发信流程。

具体问题点与修复

  • Nodemailer传输配置错误(500报错核心原因)
    当前代码中createTransport的参数配置存在明显错误:
    const transporter = nodemailer.createTransport({
      service: 'smtp.gmail.com',
      port: 587,
      auth: {
        user: process.env.EMAIL,
        pass: process.env.PASS,
      },
    });
    
    这里service字段的取值要求是Nodemailer内置预设的邮箱服务标识,Gmail对应的预设值是'gmail',不是SMTP主机域名smtp.gmail.com。参数填错会直接导致SMTP连接建立失败,触发接口500。
  • Gmail授权规则不匹配(500高频触发原因)
    现在的auth配置里用的是普通账号登录密码,Gmail早已停止支持账号密码直接做SMTP授权校验,必须先开启账号两步验证,生成对应SMTP用的应用专用密码,把这个密码填到PASS环境变量里,直接填日常登录密码一定会认证失败。
  • 前后端返回格式不匹配(前端JSON解析报错核心原因)
    前端fetch逻辑直接写了.then(response => response.json()),但服务端返回的是纯文本,没有设置正确的JSON响应头,也没有返回合法JSON结构,因此前端拿到响应第一时间解析就会抛错。
  • 冗余配置隐患
    代码里这行静态资源配置是错误的:
    app.use('/public', express.static(`${process.cwd()}/public/index.html`));
    
    把单个HTML文件当成静态资源目录挂载了,虽然当前单独写了根路由的文件返回逻辑暂时没有崩溃,但后续加载CSS、JS等静态资源时很容易出现路径错误,直接删掉这行,保留已有的app.use(express.static('public'))即可满足静态资源加载需求。

可直接替换的修复代码

  1. 修正服务端Nodemailer配置
    const transporter = nodemailer.createTransport({
      host: 'smtp.gmail.com',
      port: 587,
      secure: false, // 587端口用STARTTLS加密规则
      auth: {
        user: process.env.EMAIL, // 完整Gmail账号
        pass: process.env.PASS, // Gmail生成的应用专用密码,非登录密码
      },
    });
    
  2. 统一前后端的JSON响应格式,避免解析报错
    把服务端的两个返回逻辑改成JSON格式:
    transporter.sendMail(mail, (err, data) => {
      if (err) {
        console.log(err);
        res.status(500).json({ message: 'Something went wrong.' });
      } else {
        res.status(200).json({ message: 'Email successfully sent to recipient!' });
      }
    });
    
    前端对应调整响应处理逻辑:
    const sendMail = mail => {
      fetch('https://coopza-testing.herokuapp.com/send', {
        method: 'post',
        body: mail,
      }).then(async response => {
        const result = await response.json();
        // 在这里根据返回结果加成功/失败的页面提示
      });
    };
    
  3. 校验部署环境变量
    确保Heroku部署的环境配置里,EMAIL和PASS的值和本地开发时用的一致,避免因为环境变量缺失导致发信失败。

内容的提问来源于stack exchange,提问作者Ricardo Moreira

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.11.08 07:36:04