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

如何在Django中实现OAuth2授权读取用户Gmail?替代已废弃oauth2client

在Django中实现Google OAuth2授权读取用户邮件

前置准备

  1. Google Cloud Console配置

    • 创建新项目,启用Gmail API
    • 配置OAuth同意屏幕(根据用户群体选择外部/内部类型,填写必要信息并添加测试用户)
    • 创建OAuth 2.0客户端ID,选择Web应用类型,设置授权回调URL(如http://localhost:8000/oauth2callback)
    • 记录生成的客户端ID和客户端密钥
  2. 安装依赖库
    在Django项目中安装现代Google OAuth相关依赖:

    pip install django google-auth google-auth-oauthlib google-auth-httplib2 google-api-python-client
    

Django项目配置

在settings.py中添加Google OAuth参数:

# settings.py
GOOGLE_CLIENT_ID = "你的客户端ID"
GOOGLE_CLIENT_SECRET = "你的客户端密钥"
GOOGLE_REDIRECT_URI = "http://localhost:8000/oauth2callback"
# 授权范围:仅申请邮件只读权限,遵循最小权限原则
GOOGLE_SCOPES = ["https://www.googleapis.com/auth/gmail.readonly"]

核心视图实现

1. 授权发起视图

创建视图引导用户跳转至Google授权页面:

# views.py
from django.shortcuts import redirect
from google_auth_oauthlib.flow import Flow
from django.conf import settings

def google_auth(request):
    # 构建授权流程
    flow = Flow.from_client_config(
        client_config={
            "web": {
                "client_id": settings.GOOGLE_CLIENT_ID,
                "client_secret": settings.GOOGLE_CLIENT_SECRET,
                "redirect_uris": [settings.GOOGLE_REDIRECT_URI],
                "auth_uri": "https://accounts.google.com/o/oauth2/auth",
                "token_uri": "https://oauth2.googleapis.com/token",
            }
        },
        scopes=settings.GOOGLE_SCOPES,
        redirect_uri=settings.GOOGLE_REDIRECT_URI,
    )

    # 生成授权URL,请求离线访问以获取刷新令牌
    authorization_url, state = flow.authorization_url(
        access_type="offline",
        include_granted_scopes="true"
    )

    # 存储state到session用于回调验证,防止CSRF攻击
    request.session["state"] = state
    return redirect(authorization_url)

2. 授权回调视图

处理Google返回的授权码,获取并存储访问令牌:

# views.py
from django.http import HttpResponseBadRequest
from googleapiclient.discovery import build

def oauth2callback(request):
    # 验证state参数一致性
    if request.GET.get("state") != request.session.get("state"):
        return HttpResponseBadRequest("无效的state参数")

    flow = Flow.from_client_config(
        client_config={
            "web": {
                "client_id": settings.GOOGLE_CLIENT_ID,
                "client_secret": settings.GOOGLE_CLIENT_SECRET,
                "redirect_uris": [settings.GOOGLE_REDIRECT_URI],
                "auth_uri": "https://accounts.google.com/o/oauth2/auth",
                "token_uri": "https://oauth2.googleapis.com/token",
            }
        },
        scopes=settings.GOOGLE_SCOPES,
        state=request.session.get("state"),
        redirect_uri=settings.GOOGLE_REDIRECT_URI,
    )

    # 用授权码交换令牌
    flow.fetch_token(code=request.GET.get("code"))

    # 将凭证信息存入session(生产环境建议扩展用户模型,存储到数据库)
    credentials = flow.credentials
    request.session["credentials"] = {
        "token": credentials.token,
        "refresh_token": credentials.refresh_token,
        "token_uri": credentials.token_uri,
        "client_id": credentials.client_id,
        "client_secret": credentials.client_secret,
        "scopes": credentials.scopes,
    }

    return redirect("read_emails")

3. 读取邮件视图

使用存储的凭证调用Gmail API读取用户邮件:

# views.py
from google.oauth2.credentials import Credentials
from django.shortcuts import render

def read_emails(request):
    # 从session获取凭证信息
    credentials_data = request.session.get("credentials")
    if not credentials_data:
        return redirect("google_auth")

    # 构建Credentials对象,库会自动处理令牌刷新
    credentials = Credentials(**credentials_data)

    # 创建Gmail API客户端
    service = build("gmail", "v1", credentials=credentials)

    # 获取用户最近10封邮件的基础信息
    results = service.users().messages().list(userId="me", maxResults=10).execute()
    messages = results.get("messages", [])

    email_list = []
    for msg in messages:
        msg_data = service.users().messages().get(userId="me", id=msg["id"], format="metadata").execute()
        headers = msg_data.get("payload", {}).get("headers", [])
        # 提取邮件主题和发件人信息
        subject = next((h["value"] for h in headers if h["name"] == "Subject"), "无主题")
        sender = next((h["value"] for h in headers if h["name"] == "From"), "未知发件人")
        email_list.append({"subject": subject, "sender": sender, "id": msg["id"]})

    return render(request, "emails.html", {"emails": email_list})

URL配置

在项目urls.py中添加路由:

# urls.py
from django.urls import path
from . import views

urlpatterns = [
    path("google-auth/", views.google_auth, name="google_auth"),
    path("oauth2callback/", views.oauth2callback, name="oauth2callback"),
    path("read-emails/", views.read_emails, name="read_emails"),
]

模板示例(emails.html)

<!DOCTYPE html>
<html>
<head>
    <title>我的邮件</title>
</head>
<body>
    <h1>最近邮件</h1>
    <ul>
        {% for email in emails %}
        <li>
            <strong>主题:</strong> {{ email.subject }}<br>
            <strong>发件人:</strong> {{ email.sender }}
        </li>
        {% empty %}
        <li>暂无邮件</li>
        {% endfor %}
    </ul>
    <a href="{% url 'google_auth' %}">重新授权</a>
</body>
</html>

关键注意事项

  • 令牌存储:生产环境禁止将令牌存在session中,建议扩展Django用户模型,添加字段存储refresh_token、token等信息
  • HTTPS要求:生产环境必须使用HTTPS,否则Google OAuth服务会拒绝回调请求
  • 错误处理:需添加异常捕获逻辑(如令牌过期、API调用失败等),提升用户体验
  • 权限范围:始终遵循最小权限原则,仅申请业务必需的权限

内容的提问来源于stack exchange,提问作者Kovy Jacob

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 14:05:15