通过 API 连接 Gmail
Google API 客户端库、OAuth2 授权以及 Gmail scope 选择。
通过 API 连接 Gmail 是 CoddyKit 上的免费 AI Agents 课时。 这是第 1 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 AI Agents 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 AI Agents 课程共包含 4 节课。
为什么使用 Gmail API 而不是 SMTP?
传统的邮件自动化使用 SMTP/IMAP,但 Gmail API 提供了更多功能:读取会话、按查询条件搜索、管理标签,以及通过完整身份验证发送邮件。它还支持 OAuth 2.0,因此您的智能体无需存储密码,只需使用权限范围受限的访问令牌即可。
Gmail API 是 Google Workspace APIs 的一部分,通过 google-api-python-client 库访问。
# Install required libraries:
# pip install google-api-python-client google-auth google-auth-oauthlib
# The Gmail API lets agents:
# - List and search messages (labels, queries)
# - Read full message content and attachments
# - Send messages via OAuth (no password needed)
# - Manage labels and threads
# - Watch for new messages via push notifications
print('Gmail API is part of Google Workspace APIs')身份验证:服务账号与用户身份验证
Gmail API 有两种身份验证方式:
- 服务账号:最适合通过全域委派进行工作区或组织级使用;无需用户交互
- 用户 OAuth(带同意屏幕的 OAuth2):个人 Gmail 账号必须使用此方式;用户授予一次访问权限,智能体使用刷新令牌
对于大多数智能体自动化任务,服务账号因可靠性更高而更受推荐。
# Service Account approach:
# 1. Go to Google Cloud Console -> APIs & Services -> Credentials
# 2. Create a Service Account
# 3. Download the JSON key file
# 4. In Google Workspace Admin: enable domain-wide delegation
# 5. Grant required scopes to the service account
# User OAuth approach:
# 1. Create OAuth 2.0 Client ID (Desktop or Web App type)
# 2. Download credentials.json
# 3. First run: user sees consent screen and grants access
# 4. Agent stores token.json with refresh token for subsequent runs
print('Choose service account for org automation, OAuth for personal Gmail')OAuth2 凭据 JSON 结构
Google 会在 JSON 文件中提供凭据,您的智能体会加载该文件进行身份验证。对于用户 OAuth,这是从 Google Cloud Console 下载的 credentials.json 文件。该文件包含您的客户端 ID、密钥和重定向 URI——切勿将其提交到版本控制系统。
# credentials.json structure (User OAuth — Desktop app type):
# {
# "installed": {
# "client_id": "123456789.apps.googleusercontent.com",
# "client_secret": "GOCSPX-abc123xyz",
# "redirect_uris": ["urn:ietf:wg:oauth:2.0:oob", "http://localhost"],
# "auth_uri": "https://accounts.google.com/o/oauth2/auth",
# "token_uri": "https://oauth2.googleapis.com/token"
# }
# }
# service-account.json structure:
# {
# "type": "service_account",
# "project_id": "my-project",
# "private_key_id": "abc123",
# "private_key": "-----BEGIN PRIVATE KEY-----\n...",
# "client_email": "agent@my-project.iam.gserviceaccount.com",
# "client_id": "..."
# }
print('Store credential files outside your git repository')Gmail API 作用域
OAuth 作用域准确规定了您的智能体可以访问的内容。请只请求所需的作用域,这是最小权限原则。Gmail 作用域的范围从只读到完全访问。
gmail.readonly— 读取所有邮件gmail.send— 仅发送邮件,不能读取gmail.modify— 读取、发送邮件并修改标签gmail.compose— 仅创建草稿
# Gmail API scope constants
SCOPE_READONLY = 'https://www.googleapis.com/auth/gmail.readonly'
SCOPE_SEND = 'https://www.googleapis.com/auth/gmail.send'
SCOPE_MODIFY = 'https://www.googleapis.com/auth/gmail.modify'
SCOPE_COMPOSE = 'https://www.googleapis.com/auth/gmail.compose'
# Calendar scopes (often used alongside Gmail)
SCOPE_CALENDAR_READ = 'https://www.googleapis.com/auth/calendar.readonly'
SCOPE_CALENDAR_EVENTS = 'https://www.googleapis.com/auth/calendar.events'
# Combine scopes your agent actually needs
AGENT_SCOPES = [
SCOPE_READONLY,
SCOPE_SEND,
SCOPE_CALENDAR_EVENTS
]
print(f'Using {len(AGENT_SCOPES)} scopes')用户 OAuth:首次身份验证流程
用户首次运行智能体时,智能体会打开浏览器,让用户授予权限。智能体会将生成的令牌存储在 token.json 中。后续运行时,智能体会加载存储的令牌并自动刷新,无需再次使用浏览器。
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
from google.oauth2.credentials import Credentials
import os
SCOPES = ['https://www.googleapis.com/auth/gmail.readonly']
def get_credentials(token_file='token.json', creds_file='credentials.json'):
creds = None
# Load existing token if available
if os.path.exists(token_file):
creds = Credentials.from_authorized_user_file(token_file, SCOPES)
# Refresh or re-authenticate if needed
if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request()) # auto-refresh
else:
# Opens browser for user consent (first time only)
flow = InstalledAppFlow.from_client_secrets_file(
creds_file, SCOPES
)
creds = flow.run_local_server(port=0)
# Save token for next run
with open(token_file, 'w') as f:
f.write(creds.to_json())
return creds服务账号身份验证
对于无需用户交互即可运行的自动化智能体,服务账号非常理想。智能体使用私钥进行身份验证,然后通过全域委派模拟 Google Workspace 用户的身份。无需同意屏幕,也无需浏览器,只需一个 JSON 密钥文件即可。
from google.oauth2 import service_account
import os
SCOPES = [
'https://www.googleapis.com/auth/gmail.readonly',
'https://www.googleapis.com/auth/gmail.send'
]
def get_service_account_credentials(impersonate_user):
service_account_file = os.environ.get(
'GOOGLE_SERVICE_ACCOUNT_JSON',
'service-account.json'
)
credentials = service_account.Credentials.from_service_account_file(
service_account_file,
scopes=SCOPES
)
# Impersonate a real user (requires domain-wide delegation in Admin)
delegated = credentials.with_subject(impersonate_user)
return delegated
creds = get_service_account_credentials('agent@yourcompany.com')
print('Service account credentials ready')构建 Gmail 服务对象
获得凭据后,请使用 googleapiclient.discovery.build() 创建 Gmail 服务对象。这是所有 Gmail API 调用的主要接口。请传入服务名称 'gmail' 和版本 'v1'。
from googleapiclient.discovery import build
def build_gmail_service(credentials):
service = build(
'gmail',
'v1',
credentials=credentials,
cache_discovery=False # avoid file warnings in some environments
)
return service
# Full setup: credentials -> service
creds = get_credentials() # or get_service_account_credentials()
gmail = build_gmail_service(creds)
# Test: get user profile
profile = gmail.users().getProfile(userId='me').execute()
print('Email:', profile['emailAddress'])
print('Total messages:', profile['messagesTotal'])构建 Calendar 服务对象
同样的凭据设置也适用于 Google Calendar。只需使用 'calendar' 和 'v3' 进行构建即可。如果一个智能体同时需要 Gmail 和 Calendar,请使用同一个凭据对象构建这两个服务。
from googleapiclient.discovery import build
def build_google_services(credentials):
gmail = build(
'gmail', 'v1',
credentials=credentials,
cache_discovery=False
)
calendar = build(
'calendar', 'v3',
credentials=credentials,
cache_discovery=False
)
return gmail, calendar
# Use both in one agent
creds = get_credentials()
gmail_service, calendar_service = build_google_services(creds)
# Test calendar access
cal_list = calendar_service.calendarList().list().execute()
for cal in cal_list.get('items', []):
print(f'Calendar: {cal["summary"]}')处理 Google API 错误
Google API 错误会以 googleapiclient.errors.HttpError 的形式引发。错误中包含 HTTP 状态码和带有错误详细信息的 JSON 正文。请始终捕获该错误,并记录状态和消息,以便调试。
from googleapiclient.errors import HttpError
import json
def safe_gmail_call(service, user_id='me'):
try:
profile = service.users().getProfile(userId=user_id).execute()
return profile
except HttpError as e:
status = e.resp.status
try:
error_body = json.loads(e.content.decode())
message = error_body.get('error', {}).get('message', str(e))
except Exception:
message = str(e)
if status == 401:
print('AUTH ERROR: Credentials invalid or expired')
elif status == 403:
print(f'PERMISSION ERROR: {message}')
print('Check scopes and domain-wide delegation settings')
elif status == 429:
print('QUOTA EXCEEDED: Gmail API rate limit hit')
else:
print(f'Gmail API error {status}: {message}')
return NoneGoogle API 配额和速率限制
Gmail API 有使用配额:默认每天 10 亿个配额单位,每次调用根据操作不同消耗 1 到 100 个单位。读取邮件的成本高于列出邮件。请使用批量请求,并在遇到 429/503 错误时采用指数退避,以保持在限制范围内。
import time
from googleapiclient.errors import HttpError
def gmail_call_with_retry(func, max_retries=5):
for attempt in range(max_retries):
try:
return func()
except HttpError as e:
if e.resp.status in (429, 500, 503):
wait = (2 ** attempt) + 1
print(f'Quota/server error. Waiting {wait}s (attempt {attempt+1})')
time.sleep(wait)
elif e.resp.status == 403:
# Check if it's a quota exceeded vs permission error
import json
body = json.loads(e.content.decode())
reason = body.get('error', {}).get('errors', [{}])[0].get('reason', '')
if reason == 'rateLimitExceeded':
time.sleep(2 ** attempt)
else:
raise # real permission error, don't retry
else:
raise
raise Exception(f'Gmail API call failed after {max_retries} attempts')安全存储凭据
切勿将 token.json、credentials.json 或 service-account.json 提交到版本控制系统。请将它们加入 .gitignore。在生产环境中,请将服务账号 JSON 存储在环境变量或密钥管理器中,并在运行时加载。
import json
import os
from google.oauth2 import service_account
SCOPES = ['https://www.googleapis.com/auth/gmail.readonly']
def get_credentials_from_env():
# Load service account JSON from environment variable
sa_json = os.environ.get('GOOGLE_SERVICE_ACCOUNT_JSON')
if not sa_json:
raise EnvironmentError(
'GOOGLE_SERVICE_ACCOUNT_JSON env var not set. '
'Set it to the contents of your service-account.json'
)
sa_info = json.loads(sa_json)
credentials = service_account.Credentials.from_service_account_info(
sa_info,
scopes=SCOPES
)
return credentials
# In production: export GOOGLE_SERVICE_ACCOUNT_JSON=$(cat service-account.json)
creds = get_credentials_from_env()
print('Service account loaded from env var')快速检查:服务账号与用户 OAuth
检验您对 Gmail API 身份验证方式的理解。
Gmail API 连接回顾
现在,您已经可以将智能体连接到 Gmail:
- 用户 OAuth:使用
InstalledAppFlow,并存储token.json;后续运行时自动刷新 - 服务账号:加载 JSON 密钥,并调用
.with_subject(user_email)进行委派 - 作用域:请求所需的最小范围(
gmail.readonly、gmail.send、calendar.events) - 使用
build('gmail', 'v1', credentials=creds)构建服务 - 捕获
HttpError处理 API 错误;在 429/503 错误时重试 - 切勿提交凭据文件——在生产环境中使用环境变量
常见问题解答
「通过 API 连接 Gmail」课时是免费的吗?
是的 — 「通过 API 连接 Gmail」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 AI Agents 课程的其余内容,请升级到 CoddyKit PRO。 AI Agents 课程共包含 4 节课。
「通过 API 连接 Gmail」这节课中我会学到什么?
Google API 客户端库、OAuth2 授权以及 Gmail scope 选择。 你通过在浏览器中直接运行的动手代码来练习 AI Agents,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 AI Agents 需要有经验吗?
无需任何先前经验。CoddyKit 上的 AI Agents 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 1 节课,共 4 节。
「通过 API 连接 Gmail」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 AI Agents 课中编写并运行代码吗?
能。每节 AI Agents 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- 通过 API 连接 Gmail
- 以编程方式读取和发送电子邮件
- 创建与查询日历事件
- 构建简单的电子邮件助手代理