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

Firebase云函数调用Google API失败,求GIS及邮件实现指南

问题解决:Firebase云函数调用Google API返回INTERNAL错误及邮件功能实现指引

一、云函数返回Google API响应失败的原因及修复

你的云函数代码存在两个核心问题,导致返回INTERNAL错误:

1. 授权头变量未正确解析

你在Authorization头中直接写了'Bearer data.accessToken',这是字符串字面量,没有实际注入传入的accessToken值,Google API会因无效令牌拒绝请求。需要用模板字符串拼接变量:

'Authorization': `Bearer ${data.accessToken}`

2. 直接返回HTTP响应流而非解析后的数据

https.get的response是可读流对象,不能直接作为云函数返回值(Firebase Callable函数要求返回可序列化的JSON数据)。需要读取响应体并解析为JSON后再返回。

修正后的云函数代码

exports.loadCalendar = functions.https.onCall(async (data, context) => {
  console.log('Manual Logging: loadCalendar started');
  console.log('Data:', data);
  const https = require('https');

  return new Promise((resolve, reject) => {
    const req = https.get({
      hostname: 'googleapis.com',
      path: '/calendar/v3/calendars/primary/events',
      headers: {
        'Authorization': `Bearer ${data.accessToken}`,
      },
    });

    req.on('response', (res) => {
      let body = '';
      // 读取响应流
      res.on('data', (chunk) => {
        body += chunk;
      });
      // 响应结束后解析JSON
      res.on('end', () => {
        try {
          const result = JSON.parse(body);
          resolve(result);
        } catch (err) {
          reject(new Error(`Failed to parse response: ${err.message}`));
        }
      });
    });

    req.on('error', (err) => {
      reject(new Error(`Request failed: ${err.message}`));
    });
  });
});

组件代码优化

httpsCallable返回的是Observable,无需同时使用await和subscribe,可以简化为:

loadCalendar() {
  this.fns.httpsCallable('loadCalendar')({ accessToken: this.access_token })
    .subscribe({
      next: (result) => console.log('result', result),
      error: (err) => console.error('error', err)
    });
}

二、邮件功能实现及新版GIS实践指引

1. 核心配置要点

要实现类似WP Mail SMTP的邮件发送,你需要:

  • 确保用户授权的OAuth2 scope包含https://www.googleapis.com/auth/gmail.send(仅发送权限,无需完全访问Gmail)
  • 在云函数中调用Gmail API的users.messages.send接口发送邮件

2. 新版GIS实践建议

  • 使用Google Identity Services客户端库获取令牌,遵循PKCE流程(适用于单页应用),确保令牌安全性和合规性
  • 处理令牌过期:GIS会自动刷新令牌(请求offline_access scope后),无需手动管理刷新流程
  • 权限最小化:仅请求邮件发送所需的gmail.send scope,避免过度授权

邮件发送云函数示例(基于Gmail API)

exports.sendEmail = functions.https.onCall(async (data, context) => {
  const { accessToken, to, subject, text } = data;
  const https = require('https');

  // 构建Gmail API请求体(需base64编码)
  const emailContent = [
    `To: ${to}`,
    `Subject: ${subject}`,
    '',
    text
  ].join('\n');
  const encodedEmail = Buffer.from(emailContent).toString('base64').replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');

  return new Promise((resolve, reject) => {
    const req = https.request({
      hostname: 'googleapis.com',
      path: '/gmail/v1/users/me/messages/send',
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${accessToken}`,
        'Content-Type': 'application/json'
      }
    }, (res) => {
      let body = '';
      res.on('data', (chunk) => body += chunk);
      res.on('end', () => {
        try {
          resolve(JSON.parse(body));
        } catch (err) {
          reject(new Error(`Failed to parse response: ${err.message}`));
        }
      });
    });

    req.on('error', (err) => reject(new Error(`Request failed: ${err.message}`)));
    req.write(JSON.stringify({ raw: encodedEmail }));
    req.end();
  });
});

内容的提问来源于stack exchange,提问作者DE-AS360

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 16:27:39