React Native调用Firebase云函数发邮件出现Unhandled Promise Rejection错误
后端云函数修改方案
核心修改点:
- 移除多余的cors配置:可调用云函数(
https.onCall)原生支持跨域,cors是给onRequest类型的HTTP函数使用的,错误调用cors会导致函数返回异常,触发NOT FOUND错误 - 把nodemailer的回调逻辑改为async/await形式,保证云函数可以等待邮件发送完成再返回结果,避免函数提前终止
- 增加参数校验和标准错误抛出逻辑,方便前端识别错误类型,也便于在Firebase日志中排查问题
修改后完整代码:
const functions = require("firebase-functions"); const admin = require('firebase-admin') const nodemailer = require('nodemailer') admin.initializeApp(); let transporter = nodemailer.createTransport({ service: 'gmail', auth: { user: 'MyEmail@gmail.com', pass: 'MyPass' } }); exports.sendMail = functions.https.onCall(async (data) => { const dest = data.dest; // 先校验入参合法性 if (!dest) { throw new functions.https.HttpsError('invalid-argument', '缺少收件人邮箱参数'); } const mailOptions = { from: 'Test Email <MyEmail@gmail.com>', to: dest, subject: 'I am squash', html: `<p style="font-size: 16px;">Squash Richard</p> <br /> <img src="https://i.etsystatic.com/6129578/r/il/858dbc/703555889/il_570xN.703555889_14z1.jpg" />` }; try { await transporter.sendMail(mailOptions); return { status: 'success', message: '邮件发送成功' }; } catch (err) { // 错误打印到云函数日志,方便排查 console.error('邮件发送失败:', err); throw new functions.https.HttpsError('internal', '邮件发送失败', err.toString()); } });
前端代码修改方案
核心修改点:
- 给云函数调用返回的Promise增加错误捕获,避免未处理的Promise拒绝警告
- 给useEffect增加空依赖数组,避免组件渲染时重复触发云函数调用
修改后完整代码:
import React, {useEffect} from 'react'; import { View, Text } from 'react-native'; import functions from '@react-native-firebase/functions'; function EmailScreen() { useEffect(() => { const sendTestMail = async () => { try { const result = await functions().httpsCallable('sendMail')({dest: 'MyOtherEmail@gmail.com'}); console.log('调用成功:', result.data); } catch (err) { // 打印错误详情,方便排查 console.error('调用失败:', err.code, err.message, err.details); } } sendTestMail(); }, []) return( <View> <Text>This is the email screen.</Text> </View> ) } export default EmailScreen;
额外排查注意事项
- 云函数修改后需要重新部署,等待2-3分钟部署完全生效后再测试,避免缓存导致的NOT FOUND问题
- Gmail已经停止支持低安全性应用访问,若使用Gmail发信需要先开启账号两步验证,再生成应用专用密码填入
auth.pass字段,否则会被Gmail拦截发信请求 - 可以先在Firebase控制台的云函数测试页直接调用
sendMail函数,确认后端逻辑正常后再调试前端调用
内容的提问来源于stack exchange,提问作者velkoon
相关产品推荐
相关产品推荐

