如何在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
相关产品推荐
相关产品推荐

