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}` }); } }); });
验证步骤
- 重启Firebase模拟器或重新部署云函数
- 使用Postman发送POST请求时,确保请求头
Content-Type设置为application/json - 查看函数日志,确认
Form Data输出完整的JSON数据 - 检查收件邮箱,确认邮件正文包含表单提交详情
内容的提问来源于stack exchange,提问作者Seth Stitick
相关产品推荐
相关产品推荐

