news 2026/1/14 9:13:24

通过 Gmail API 发送邮件的完整指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
通过 Gmail API 发送邮件的完整指南

本文档详细介绍了如何通过编程方式调用 Google Gmail API 来发送电子邮件。整个过程不依赖于 SMTP,而是使用现代的 OAuth 2.0 授权流程和 REST API 调用,这使得它可以在任何网络环境(包括限制了 SMTP 端口的云服务器)下工作。

目录

  1. 前置条件
  2. 第一步:启用 API 和创建 OAuth 凭据
  3. 第二步:获取授权 Token
  4. 第三步:发送邮件
  5. 附录:常见问题(FAQ)

1. 前置条件

在开始之前,请确保您拥有:

  • 一个 Google 账户:任何标准的@gmail.com账户或 Google Workspace 账户都可以。这个账户将是发送邮件的账户。
  • 一个 Google Cloud Platform (GCP) 项目:这是调用所有 Google API 的管理中心。即使您的代码不运行在 GCP 上,也必须拥有一个 GCP 项目来启用 API 和创建凭据。如果您没有,可以免费创建一个。
  • Python 环境:本地或服务器上需要安装 Python 3。

2. 第一步:启用 API 和创建 OAuth 凭据

此步骤的目标是在您的 GCP 项目中创建一个“应用身份证”,即credentials.json文件。

  1. 登录 GCP 控制台:访问 Google Cloud Console 并选择您的项目。
  2. 启用 Gmail API
    • 在顶部的搜索栏中输入Gmail API
    • 在搜索结果中选择 “Gmail API” 并点击“启用”按钮。
  3. 创建 OAuth 客户端 ID
    • 导航到 “API 和服务” > “凭据” 页面。
    • 点击“+ 创建凭据”并选择“OAuth 客户端 ID”
    • 如果系统提示您配置“OAuth 同意屏幕”,请按以下步骤操作:
      • 选择“外部”(External)。
      • 填写必要的应用信息(应用名称、用户支持电子邮件等)。
      • 在“测试用户”步骤中,添加您将要用来发邮件的那个 Gmail 账户
      • 保存并继续。
    • 返回创建凭据页面,在“应用类型”(Application type) 中选择“桌面应用”(Desktop app)。
    • 给它一个名称(例如,“Gmail Sender Script”)。
    • 点击“创建”
  4. 下载凭据文件
    • 创建成功后,会弹出一个窗口显示您的客户端 ID 和密钥。请不要复制它们
    • 点击右侧的“下载 JSON”按钮。
    • 将下载的文件重命名为credentials.json并将其保存在您的项目文件夹中。此文件非常机密,切勿泄露。

3. 第二步:获取授权 Token

此步骤的目标是让您的 Gmail 账户授权给上一步创建的应用,并生成一把“钥匙”,即token.json文件。这是一个一次性的本地操作。

  1. 创建get_token.py脚本
    在与credentials.json相同的文件夹中,创建以下 Python 脚本:

    # get_token.pyimportos.pathfromgoogle.auth.transport.requestsimportRequestfromgoogle.oauth2.credentialsimportCredentialsfromgoogle_auth_oauthlib.flowimportInstalledAppFlow# 定义需要的权限范围,https://mail.google.com/ 是最高权限SCOPES=["https://mail.google.com/"]defmain():""" 引导用户完成 OAuth 2.0 授权流程并生成 token.json。 """creds=None# 如果 token.json 已存在,则先加载它ifos.path.exists("token.json"):creds=Credentials.from_authorized_user_file("token.json",SCOPES)# 如果没有有效的凭据,则启动新的授权流程ifnotcredsornotcreds.valid:# 如果 token 已过期且有 refresh_token,则刷新它ifcredsandcreds.expiredandcreds.refresh_token:creds.refresh(Request())else:# 否则,从 credentials.json 启动新的网页授权流程flow=InstalledAppFlow.from_client_secrets_file("credentials.json",SCOPES)creds=flow.run_local_server(port=0)# 将新获取的凭据写入 token.json 文件withopen("token.json","w")astoken:token.write(creds.to_json())print("token.json 文件已成功生成或刷新。")if__name__=="__main__":main()
  2. 安装必要的库
    在终端中运行以下命令:

    pipinstall--upgradegoogle-api-python-client google-auth-httplib2 google-auth-oauthlib
  3. 运行脚本
    在终端中运行脚本:

    python get_token.py
  4. 在浏览器中完成授权

    • 脚本会自动在您的浏览器中打开一个 Google 登录页面。
    • 登录您希望用来发邮件的 Gmail 账户
    • 您可能会看到一个“此应用未经 Google 验证”的警告。这是正常的,因为这是您自己的应用。请点击“高级”>“转至…(不安全)”
    • 在下一个页面中,点击“允许”,授予权限。
    • 授权成功后,您会看到 “The authentication flow has completed” 的消息,并且终端会显示 “token.json 文件已成功生成”。

现在,您的项目文件夹中应该有credentials.jsontoken.json两个文件了。


4. 第三步:发送邮件

这是最终发送邮件的脚本。我们使用 Python 内置的urllib库,因为它在有网络代理的环境下表现更稳定。

  1. 创建send_email_raw_api.py脚本
    在同一个文件夹中,创建以下脚本:

    # send_email_raw_api.pyimportjsonimportbase64importloggingimporturllib.requestfromemail.mime.textimportMIMETextfromurllib.errorimportURLError,HTTPError# 配置日志记录logging.basicConfig(level=logging.INFO,format='%(asctime)s - %(levelname)s - %(message)s')defget_access_token(proxy_url=None):"""使用 refresh_token 获取新的 access_token"""logging.info("尝试刷新 access_token...")try:withopen('token.json','r')asf:token_data=json.load(f)withopen('credentials.json','r')asf:# 兼容从 GCP 下载的两种 JSON 格式creds_data=json.load(f).get('installed')orjson.load(f).get('web')params={'client_id':creds_data['client_id'],'client_secret':creds_data['client_secret'],'refresh_token':token_data['refresh_token'],'grant_type':'refresh_token'}data=json.dumps(params).encode('utf-8')req=urllib.request.Request(creds_data['token_uri'],data=data,headers={'Content-Type':'application/json'})# 配置代理(如果提供)ifproxy_url:proxy_handler=urllib.request.ProxyHandler({'https':proxy_url,'http':proxy_url})opener=urllib.request.build_opener(proxy_handler)else:opener=urllib.request.build_opener()withopener.open(req,timeout=30)asresponse:result=json.loads(response.read().decode('utf-8'))logging.info("成功刷新 access_token。")returnresult['access_token']exceptExceptionase:logging.error(f"刷新 access_token 失败:{e}",exc_info=True)returnNonedefsend_email_raw(access_token,to,subject,message_text,proxy_url=None):"""使用原始 HTTP 请求和 access_token 发送邮件"""logging.info("使用原始 API 请求发送邮件...")try:message=MIMEText(message_text,'plain','utf-8')message['to']=to message['from']='me'message['subject']=subject raw_message=base64.urlsafe_b64encode(message.as_bytes()).decode()api_url='https://www.googleapis.com/gmail/v1/users/me/messages/send'headers={'Authorization':f'Bearer{access_token}','Content-Type':'application/json'}body={'raw':raw_message}data=json.dumps(body).encode('utf-8')req=urllib.request.Request(api_url,data=data,headers=headers,method='POST')# 配置代理(如果提供)ifproxy_url:proxy_handler=urllib.request.ProxyHandler({'https':proxy_url,'http':proxy_url})opener=urllib.request.build_opener(proxy_handler)else:opener=urllib.request.build_opener()logging.info(f"向{api_url}发送 POST 请求...")withopener.open(req,timeout=30)asresponse:response_data=json.loads(response.read().decode('utf-8'))logging.info(f"邮件发送成功!Message ID:{response_data.get('id')}")returnresponse_dataexcept(URLError,HTTPError)ase:logging.error(f"发送邮件时发生网络错误:{e}",exc_info=True)ifhasattr(e,'read'):logging.error(f"错误详情:{e.read().decode()}")exceptExceptionase:logging.error(f"发送邮件时发生未知错误:{e}",exc_info=True)returnNoneif__name__=='__main__':# --- 配置 ---RECIPIENT_EMAIL="收件人邮箱@example.com"EMAIL_SUBJECT="来自应用的 API 调用问候"EMAIL_BODY="这是一封通过纯 Python urllib 库调用 Gmail API 发送的邮件。"# 如果需要通过代理发送,请设置代理地址,否则设为 None# PROXY_ADDRESS = "http://127.0.0.1:7890"PROXY_ADDRESS=None# --- 配置结束 ---# 1. 获取最新的 access_tokenaccess_token=get_access_token(proxy_url=PROXY_ADDRESS)# 2. 如果成功获取,则发送邮件ifaccess_token:send_email_raw(access_token=access_token,to=RECIPIENT_EMAIL,subject=EMAIL_SUBJECT,message_text=EMAIL_BODY,proxy_url=PROXY_ADDRESS)
  2. 修改配置并运行

    • 打开send_email_raw_api.py文件。
    • 在文件底部的if __name__ == '__main__':部分,修改RECIPIENT_EMAIL,EMAIL_SUBJECT, 和EMAIL_BODY的值。
    • 如果您需要通过代理发送,请修改PROXY_ADDRESS
    • 保存文件并在终端运行:
    python send_email_raw_api.py

如果一切顺利,您将在终端看到成功发送的日志,并且收件人会收到邮件。


5. 附录:常见问题(FAQ)

  • Q: 为什么必须要有 GCP 项目?

    • A: GCP 项目是您作为“开发者”的身份标识。所有 Google API 的启用、凭据创建和用量管理都必须依托于一个 GCP 项目。
  • Q:credentials.jsontoken.json有什么区别?请用通俗的比喻解释。

    • A: 当然,这是一个核心概念。我们可以用一个“机器人管家”的例子来理解:
      • credentials.json是什么?—— 机器人的“出厂说明书 & 身份证”

        • 这个文件是在您的 GCP 工厂里生成的,它定义了您的机器人管家是谁。
        • 它包含了客户端 ID(相当于机器人的身份证号,是公开的)和客户端密钥(相当于机器人的出厂机密代码,是绝对私密的)。
        • 这份“说明书”是永久有效的,它只代表机器人的身份,但本身没有任何权力。任何不认识这个机器人的家庭都不会让它进门。
      • token.json是什么?—— 特定家庭的“门禁卡”

        • 这个文件是在您(家庭主人)亲自“面试”过机器人,并同意授权后,才颁发给这个特定机器人的“门禁卡”。
        • 它包含了access_token(一张临时通行证,可能一小时就过期)和refresh_token(一张长期身份卡)。
        • 当机器人需要进门工作时,它会出示“临时通行证” (access_token)。如果通行证过期了,它就会出示它的“长期身份卡” (refresh_token) 和自己的“身份证” (credentials.json),去物业处(Google)换一张新的“临时通行证”。
      • 它们如何协同工作?

        • 您的代码(机器人)在工作时,必须同时携带自己的“身份证” (credentials.json) 和您家颁发的“门禁卡” (token.json)。
        • 如果门禁卡里的临时通行证过期了,它就需要用门禁卡里的长期身份卡加上自己身份证上的机密代码,才能换到新的临时通行证。
        • 总结:credentials.json是“我是谁”,token.json是“我被谁授权可以做什么”。两者缺一不可。
  • Q: 我可以把这两个 JSON 文件提交到 Git 仓库吗?

    • A:绝对不能!这两个文件都是高度机密的,泄露它们等同于泄露了您应用乃至用户邮箱的控制权。请务必将它们添加到.gitignore文件中。
  • Q:token.json会过期吗?

    • A: 是的,token.json里的access_token通常只有1小时的有效期。但它包含的refresh_token有效期很长。我们提供的脚本会自动使用refresh_token去换取新的access_token,所以您几乎无感。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/1/4 23:14:22

老Mac升级终极解决方案:OpenCore Legacy Patcher深度指南

你的2013款MacBook Pro还在运行High Sierra吗?那个曾经引以为傲的Retina屏幕如今只能显示模糊的界面,每次系统更新都提示"不兼容",这种感觉就像开着老爷车在高速公路上被超车。别担心,今天的技术教练将带你用OpenCore L…

作者头像 李华
网站建设 2026/1/4 23:14:18

WorkshopDL完整指南:零基础玩转Steam创意工坊模组

WorkshopDL完整指南:零基础玩转Steam创意工坊模组 【免费下载链接】WorkshopDL WorkshopDL - The Best Steam Workshop Downloader 项目地址: https://gitcode.com/gh_mirrors/wo/WorkshopDL 还在为Epic、GOG等平台无法体验Steam创意工坊的精彩内容而苦恼吗&…

作者头像 李华
网站建设 2026/1/4 23:14:12

城通网盘解析工具:免费高速下载的完整解决方案

还在为城通网盘的下载速度而烦恼吗?想要轻松获取高速直连下载地址?这款完全免费的城通网盘解析工具将彻底改变你的下载体验,让你享受前所未有的下载便利! 【免费下载链接】ctfileGet 获取城通网盘一次性直连地址 项目地址: http…

作者头像 李华
网站建设 2026/1/4 23:14:09

3分钟掌握TwitCasting直播录制:零基础极速配置指南

想要轻松录制TwitCasting平台的精彩直播内容吗?无论你是想要保存喜欢的音乐表演、游戏直播还是生活分享,DouyinLiveRecorder都能帮你实现跨平台直播存档的梦想。本教程将带你从零开始,快速掌握这款强大的录制工具。 【免费下载链接】DouyinLi…

作者头像 李华
网站建设 2026/1/4 23:13:53

Jellyfin Android TV终极指南:让大屏娱乐回归纯粹

Jellyfin Android TV终极指南:让大屏娱乐回归纯粹 【免费下载链接】jellyfin-androidtv Android TV Client for Jellyfin 项目地址: https://gitcode.com/gh_mirrors/je/jellyfin-androidtv 还在为不同设备间的媒体文件同步而烦恼吗?每次想在电视…

作者头像 李华
网站建设 2026/1/4 23:13:02

网盘直链解析技术深度解析:八大平台下载链路优化方案

网盘直链解析技术深度解析:八大平台下载链路优化方案 【免费下载链接】Online-disk-direct-link-download-assistant 可以获取网盘文件真实下载地址。基于【网盘直链下载助手】修改(改自6.1.4版本) ,自用,去推广&#…

作者头像 李华