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

Firebase云函数发送邮件仅显示{},无法获取表单数据

问题:Firebase Cloud Function无法解析POST请求体,邮件正文仅显示{}

开发Firebase云函数时,使用Nodemailer发送表单提交数据到邮箱,通过模拟器测试时,Postman发送JSON格式的POST请求,但函数日志显示req.body为空对象,最终邮件正文仅显示{}。

原代码问题分析

Firebase的functions.https.onRequest默认不会自动解析JSON请求体,req.body初始为空对象,即便尝试手动解析空字符串也无法得到有效数据,这是导致邮件正文无内容的核心原因。

解决方案

方案1:使用Express处理请求(推荐)

引入Express框架,通过express.json()中间件自动解析JSON请求体,代码更简洁易维护:

import * as functions from 'firebase-functions';
import nodemailer from 'nodemailer';
import cors from 'cors';
import * as dotenv from 'dotenv';
import express from 'express';

dotenv.config();

const app = express();
const corsHandler = cors({ origin: true });

// 先处理跨域,再添加JSON解析中间件
app.use(corsHandler);
app.use(express.json());

const emailUser = process.env.EMAIL_USER || functions.config().email.user;
const emailPass = process.env.EMAIL_PASS || functions.config().email.pass;

const transporter = nodemailer.createTransport({
  service: 'gmail',
  auth: {
    user: emailUser,
    pass: emailPass,
  },
});

// 处理POST请求
app.post('/', async (req, res) => {
  try {
    const formData = req.body;
    console.log('Form Data:', formData);

    const mailOptions = {
      from: emailUser,
      to: 'my@email.co',
      subject: 'Form Submission',
      text: `Here are the details of your submission:\n\n${JSON.stringify(formData, null, 2)}`,
    };

    console.log('Mail Options:', mailOptions);

    const info = await transporter.sendMail(mailOptions);
    console.log('Email sent:', info.response);

    res.status(200).send({ message: 'Email sent successfully!' });
  } catch (error) {
    console.error('Error sending email:', error);
    res.status(500).send({ error: `An error occurred while trying to send the email: ${(error as Error).message}` });
  }
});

// 将Express app挂载为Firebase云函数
export const sendMail = functions.https.onRequest(app);

方案2:手动解析请求体(无需Express)

如果不想引入Express,可以手动读取请求流解析JSON:

import * as functions from 'firebase-functions';
import nodemailer from 'nodemailer';
import cors from 'cors';
import * as dotenv from 'dotenv';

dotenv.config();

const corsHandler = cors({ origin: true });

const emailUser = process.env.EMAIL_USER || functions.config().email.user;
const emailPass = process.env.EMAIL_PASS || functions.config().email.pass;

const transporter = nodemailer.createTransport({
  service: 'gmail',
  auth: {
    user: emailUser,
    pass: emailPass,
  },
});

export const sendMail = functions.https.onRequest((req, res) => {
  corsHandler(req, res, async () => {
    try {
      // 手动读取请求流并解析JSON
      const formData = await new Promise<any>((resolve, reject) => {
        let rawBody = '';
        req.on('data', chunk => rawBody += chunk.toString());
        req.on('end', () => {
          try {
            resolve(JSON.parse(rawBody));
          } catch (err) {
            reject(new Error('Failed to parse JSON request body'));
          }
        });
        req.on('error', reject);
      });

      console.log('Form Data:', formData);

      const mailOptions = {
        from: emailUser,
        to: 'my@email.co',
        subject: 'Form Submission',
        text: `Here are the details of your submission:\n\n${JSON.stringify(formData, null, 2)}`,
      };

      console.log('Mail Options:', mailOptions);

      const info = await transporter.sendMail(mailOptions);
      console.log('Email sent:', info.response);

      res.status(200).send({ message: 'Email sent successfully!' });
    } catch (error) {
      console.error('Error sending email:', error);
      res.status(500).send({ error: `An error occurred while trying to send the email: ${(error as Error).message}` });
    }
  });
});

验证步骤

  1. 重启Firebase模拟器或重新部署云函数
  2. 使用Postman发送POST请求时,确保请求头Content-Type设置为application/json
  3. 查看函数日志,确认Form Data输出完整的JSON数据
  4. 检查收件邮箱,确认邮件正文包含表单提交详情

内容的提问来源于stack exchange,提问作者Seth Stitick

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 05:12:48