使用GMail API 发送邮箱
1️⃣ 准备工作
创建 Google Cloud 项目
打开 Google Cloud Console → Cloud 概览 →欢迎 → 创建新项目
启用 Gmail API
直接搜索:Gmail API
启用服务并选择相应的项目
创建 OAuth 2.0 客户端 ID,创建之前需要前置操作 ,先选择项目 点击开始配置Google Auth Platform
找到“OAuth 客户端 ID”并点击
类型选择 桌面应用程序(快捷方便)下载 client_secret_xxx.json
client_secret_xxx.json
是 Google OAuth 2.0 客户端凭证 文件,里面包含了你在 Google Cloud Console 创建的 OAuth 2.0 凭证信息,主要用于认证和授权。
安装依赖(我这里使用的是python 环境)
pip install --upgrade google-api-python-client google-auth-httplib2 google-auth-oauthlib
2️⃣ 授权流程(第一次)
下面是client_sercret_xxx.json 与token之间的关系
文件 | 作用 | 生命周期 | 使用方式 |
---|---|---|---|
client_secret_xxx.json | 应用身份 | 长期不变 | 首次授权时必须 |
token.pickle | 用户身份 + 授权 | access_token 1 小时,refresh_token 长期有效 | 发邮件、刷新 token |
为啥要进行手动授权:
阶段 | 原因/作用 | 说明 |
---|---|---|
首次手动授权 | 保护用户账户安全 | Gmail 涉及敏感数据(邮箱、邮件内容),Google 不允许应用直接用用户名/密码访问。手动授权让用户明确允许应用访问哪些权限。 |
首次获取 refresh_token | OAuth 2.0 设计中,refresh_token 只会在用户同意授权后发放一次,确保应用无法偷偷获取长期访问权限。 | |
防止滥用 | 如果每次都能自动授权,恶意应用可能会无声访问用户邮箱。手动授权是防护措施。 | |
后续自动使用 | 不需要再次手动授权 | 第一次授权后拿到 refresh_token(长期有效),后续可以用它自动刷新 access_token,无需再次登录或输入验证码。 |
手动授权如图:
代码示例:
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
import pickle
import os.path
import pickle
# 权限范围
SCOPES = ['https://www.googleapis.com/auth/gmail.send']def send_email_via_api():creds = None# 检查是否已有凭据if os.path.exists('config/new_token.pickle'):with open('new_token.pickle', 'rb') as token:creds = pickle.load(token)if not creds or not creds.valid:if creds and creds.expired and creds.refresh_token:creds.refresh(Request())else:# flow = InstalledAppFlow.from_client_secrets_file(# 'config/client_secret_2_xxx.json', SCOPES)# creds = flow.run_local_server(port=0)flow = InstalledAppFlow.from_client_secrets_file(r'config/new2.json',SCOPES)creds = flow.run_local_server(port=8080,open_browser=True,access_type='offline',prompt='consent')# 保存凭据供下次使用with open('config/token.pickle', 'wb') as token:pickle.dump(creds, token)
✅ 说明:
-
access_type='offline'
→ 获取长期refresh_token
-
prompt='consent'
→ 保证用户每次授权时都会返回refresh_token
-
第一次授权后,会弹出浏览器让用户登录 Gmail 并同意权限
-
每次使用
creds.valid
检查 access_token 是否过期 -
如果过期且有 refresh_token,调用:
creds.refresh(Request())
with open('token.pickle', 'wb') as token:pickle.dump(creds, token)
-
不需要再次输入验证码,refresh_token 是长期有效的
3️⃣ 发送邮件
使用 Gmail API 发送邮件,需要构造 MIME
消息并 Base64 编码:
# 1. 获取访问令牌(从已有的token.pickle中提取)
with open('./config/token.pickle', 'rb') as f:creds = pickle.load(f)
access_token = creds.token# 2. 手动构建邮件内容6
message = MIMEText('20250822测试')
message['to'] = 'xxx@163.com'
# message['from'] = 'a'
message['subject'] = '客户验收程序20250822测试'
raw_message = base64.urlsafe_b64encode(message.as_bytes()).decode()# 3. 配置请求参数(可手动设置代理)
url = 'https://www.googleapis.com/gmail/v1/users/me/messages/send'
headers = {'Authorization': f'Bearer {access_token}','Content-Type': 'application/json'
}
data = {'raw': raw_message}# 4. 发送请求(支持代理配置)
proxies = {# 根据VPN/代理类型设置,如SOCKS5需安装requests[socks]'https': 'socks5://127.0.0.1:1080' # 示例:本地SOCKS5代理
}try:response = requests.post(url,headers=headers,data=json.dumps(data),# proxies=proxies, # 可选:需要时启用timeout=30)response.raise_for_status() # 抛出HTTP错误print("HTTP直接调用成功:", response.json())
except requests.exceptions.RequestException as e:print(f"HTTP请求失败:{e}")if response:print("响应内容:", response.text)
注意事项
-
token.pickle
-
保存
access_token
和refresh_token
,确保刷新后更新文件
-
-
发送限制
-
Gmail API 每日免费发送上限约 500 封(G Suite 可更高)
-
-
安全性
-
不要在前端暴露
client_secret
或refresh_token
-
服务器端统一管理发送逻辑
-
-
附件邮件
-
如果要发送附件,需要构造
MIMEMultipart
并附加MIMEBase
对象
-