Firebase免费套餐下使用Nodemailer+Gmail OAuth2发送邮件失败
我帮你梳理下免费Firebase套餐下用Nodemailer+Gmail发邮件的常见坑和解决办法哈:
免费Firebase套餐下Nodemailer+Gmail发邮件的问题排查与解决
首先得明确一个关键点:Firebase免费套餐(Spark Plan)对出站网络请求有严格限制——哪怕是Google自家服务,也只有Firestore、Storage这类Firebase原生服务在允许列表里,Gmail的SMTP/API属于外部服务范畴,直接调用会被拦截,这是很多人踩的第一个坑!
常见问题&解决步骤
1. 先搞定套餐限制问题
如果想继续用Gmail发邮件,要么升级到Blaze套餐(按需付费,小流量场景几乎没成本),要么换用其他支持免费额度的邮件服务(比如SendGrid的免费 tier)。
2. 升级套餐后,处理Gmail的认证问题
Google已经禁用了“不太安全的应用”访问权限,所以不能直接用邮箱密码登录,推荐两种方式:
- App Password:前提是你的Gmail账号开启了两步验证,在Google账号设置里生成专门的应用密码,用来替代普通密码
- OAuth2认证:更安全的方式,需要在Google Cloud Console创建OAuth客户端ID,生成refresh token后配置到Nodemailer里
3. 给你的TypeScript代码补全优化示例
你的代码片段没写完,这里给你一个完整的可运行示例(基于App Password方式):
import * as functions from 'firebase-functions'; import * as nodemailer from 'nodemailer'; import { DocumentSnapshot } from 'firebase-functions/lib/providers/firestore'; // 从Firebase环境变量读取邮箱配置,避免硬编码 const gmailConfig = functions.config().gmail; // 配置Nodemailer传输器 const transporter = nodemailer.createTransport({ service: 'gmail', auth: { user: gmailConfig.user, pass: gmailConfig.app_password // 这里用生成的App Password,不是普通邮箱密码 } }); export const sendMessage = functions.firestore.document('/messages/{messageId}') .onCreate(async (snap: DocumentSnapshot) => { const messageData = snap.data(); if (!messageData?.email || !messageData?.content) { console.log('缺少必要的邮件数据'); return; } const mailOptions = { from: `网站联系表单 <${gmailConfig.user}>`, to: '你的接收邮箱@example.com', subject: `新消息:${messageData.subject || '无主题'}`, text: ` 发件人:${messageData.name || '匿名'} 邮箱:${messageData.email} 内容:${messageData.content} ` }; try { await transporter.sendMail(mailOptions); console.log('邮件发送成功'); return snap.ref.update({ sent: true }); } catch (error) { console.error('邮件发送失败:', error); return snap.ref.update({ sent: false, errorMsg: (error as Error).message }); } });
4. 环境变量配置(重要!别硬编码密码)
用Firebase CLI设置环境变量,避免把敏感信息提交到代码仓库:
firebase functions:config:set gmail.user="你的gmail邮箱@gmail.com" gmail.app_password="你生成的App Password"
5. 本地测试小技巧
本地运行Functions时,需要先把环境变量同步到本地:
firebase functions:config:get > .runtimeconfig.json
总结
- 免费套餐无法调用Gmail服务,必须升级到Blaze套餐
- Gmail认证优先用App Password(需两步验证)或OAuth2,别用普通密码
- 代码里一定要加错误处理和日志,方便排查发送失败的问题
内容的提问来源于stack exchange,提问作者Murhaf Sousli




