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

如何在React+Firebase应用中通过Gmail API代用户发送邮件?

嘿,我刚好做过类似的需求,这就给你拆解具体的实现步骤,保证一步步能跑通:

实现步骤

1. 扩展Google登录的授权范围

你原来的Firebase Google登录可能只请求了基础身份权限,现在需要新增gmail.send权限,让用户首次登录时授权你的应用代发邮件。修改你的Google登录逻辑:

import { getAuth, signInWithPopup, GoogleAuthProvider } from "firebase/auth";

const auth = getAuth();
const provider = new GoogleAuthProvider();

// 添加Gmail发送权限到登录请求里
provider.addScope('https://www.googleapis.com/auth/gmail.send');

const handleGoogleSignIn = async () => {
  try {
    const result = await signInWithPopup(auth, provider);
    // 从登录结果里提取带权限的accessToken,存起来后续发邮件用
    const credential = GoogleAuthProvider.credentialFromResult(result);
    const accessToken = credential.accessToken;
    localStorage.setItem('gmailAccessToken', accessToken);
  } catch (error) {
    console.error('登录/授权失败:', error);
    // 这里可以给用户显示友好提示,比如"授权失败,请重试"
  }
};

注意:用户首次登录时会看到包含"发送邮件"权限的授权弹窗,授权后再次登录就不会重复弹出了。

2. 实现表单数据转Gmail发送功能

接下来要把表单数据转换成符合Gmail API要求的格式,然后调用API发送邮件:

const sendFormToMerchant = async (formData) => {
  let accessToken = localStorage.getItem('gmailAccessToken');
  if (!accessToken) {
    alert('请先完成Gmail授权哦');
    return;
  }

  // 1. 构建邮件内容,把表单数据转成清晰的文本(也可以改成HTML格式)
  const emailContent = `
    提交人姓名: ${formData.name}
    联系邮箱: ${formData.email}
    表单内容: ${formData.content}
  `;

  // 2. 把邮件转成Gmail API要求的base64url编码格式
  const encodedEmail = btoa(
    `To: 商家邮箱@your-merchant.com
Subject: 新的表单提交 - ${formData.name}

${emailContent}`
  ).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');

  try {
    // 3. 调用Gmail API发送邮件
    const response = await fetch('https://gmail.googleapis.com/gmail/v1/users/me/messages/send', {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${accessToken}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({ raw: encodedEmail })
    });

    if (response.ok) {
      alert('表单已成功发送给商家!');
      // 这里可以重置表单
    } else {
      const errorInfo = await response.json();
      console.error('发送失败:', errorInfo);
      alert('发送出错,请稍后重试');
    }
  } catch (error) {
    console.error('网络请求出错:', error);
    alert('发送失败,请检查网络连接');
  }
};

3. 处理Token过期与授权异常

accessToken会过期(一般1小时),所以要处理过期的情况,用Firebase的refreshToken刷新新的accessToken:

import { getAuth, signInWithCredential, GoogleAuthProvider } from "firebase/auth";

const refreshGmailAccessToken = async () => {
  const auth = getAuth();
  const currentUser = auth.currentUser;
  if (!currentUser) return null;

  try {
    // 用用户的refreshToken获取新的授权凭证
    const credential = GoogleAuthProvider.credential(null, currentUser.refreshToken);
    const result = await signInWithCredential(auth, credential);
    const newToken = GoogleAuthProvider.credentialFromResult(result).accessToken;
    localStorage.setItem('gmailAccessToken', newToken);
    return newToken;
  } catch (error) {
    console.error('Token刷新失败:', error);
    return null;
  }
};

然后可以在sendFormToMerchant里优化,当返回401未授权时自动刷新token并重试:

// 在sendFormToMerchant的try块里修改:
try {
  let response = await fetch('https://gmail.googleapis.com/gmail/v1/users/me/messages/send', {
    // ... 原请求配置
  });

  // 如果token过期,尝试刷新后重试
  if (response.status === 401) {
    const newToken = await refreshGmailAccessToken();
    if (newToken) {
      response = await fetch('https://gmail.googleapis.com/gmail/v1/users/me/messages/send', {
        // 用新token重新请求
        headers: {
          'Authorization': `Bearer ${newToken}`,
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({ raw: encodedEmail })
      });
    }
  }

  // 后续的成功/失败处理...
}

4. 必要的控制台配置

最后别忘了在Google Cloud Console做两步配置:

  • 找到你的项目,搜索并启用Gmail API
  • 进入OAuth同意屏幕,确保https://www.googleapis.com/auth/gmail.send已经添加到授权范围里;如果是生产环境,记得把应用发布为"生产"状态,否则只有测试用户能授权。

内容的提问来源于stack exchange,提问作者Vinay Singh

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 08:36:35