前言
这篇文章基于一个简单的 Python 脚本,整理如何在已获得用户合法授权的前提下,使用 refresh_token 换取 access_token,再通过 Microsoft Graph API 读取 Outlook 邮件。文章重点放在实现流程与原理拆解,不展示任何真实敏感令牌。
脚本作用
这个脚本的核心逻辑其实只有两步:
调用微软 OAuth2 令牌接口,用
refresh_token换取新的access_token带上
Bearer access_token请求https://graph.microsoft.com/v1.0/me/messages,获取当前账号的邮件列表
原脚本里还做了一个最基础的输出处理:
打印邮件主题
打印发件人地址
打印正文预览
bodyPreview
从结构上看,这是一种很典型的“令牌换取 + 资源接口访问”模式。
流程拆解
1. 先用 refresh_token 换 access_token
脚本先向微软令牌端点发起 POST 请求,请求体里主要包含这些字段:
import requestsdef get_access_token(refresh_token: str, client_id: str) -> str:
data = { "client_id": client_id, "grant_type": "refresh_token", "refresh_token": refresh_token, "scope": "https://graph.microsoft.com/.default",
}
resp = requests.post( "https://login.microsoftonline.com/consumers/oauth2/v2.0/token",
data=data,
timeout=15,
)
resp.raise_for_status() return resp.json()["access_token"]这里的关键点有两个:
grant_type=refresh_token表示当前不是首次授权,而是用已有刷新令牌续期client_id用来标识这是哪个应用在请求令牌
2. 再请求 Graph 邮件接口
换到访问令牌后,脚本继续请求 Microsoft Graph 的邮件接口:
import requestsdef fetch_messages(access_token: str):
url = "https://graph.microsoft.com/v1.0/me/messages"
headers = { "Authorization": f"Bearer {access_token}",
}
resp = requests.get(url, headers=headers, timeout=15)
resp.raise_for_status() return resp.json().get("value", [])如果只是读取最近一封邮件,也可以像原脚本注释里那样配合查询参数:
/me/messages?$top=1&$orderby=receivedDateTime desc
这样可以减少返回数据量,也更适合做“拉最新邮件”场景。
原理
1. OAuth2 解决的是“你有没有权限访问邮箱”
Graph API 本身不直接认账号密码,而是认令牌。令牌体系大致分成两种:
access_token:短期使用,用来真正访问接口refresh_token:有效期相对更长,用来换取新的access_token
所以脚本的本质不是“直接登录邮箱”,而是:
应用先完成授权
拿到刷新令牌
之后靠刷新令牌不断续期访问令牌
再用访问令牌访问 Graph 邮箱资源
2. Microsoft Graph 是统一资源入口
Microsoft Graph 相当于微软生态的一层统一 API 网关。邮件、日历、联系人、OneDrive 等很多资源都能通过 Graph 访问。
在本文这个场景里,请求的是:
https://graph.microsoft.com/v1.0/me/messages
其中:
v1.0表示稳定版本接口me表示当前已授权用户messages表示当前用户邮箱下的邮件资源
3. 返回的数据为什么能直接拿到主题和发件人
因为 messages 接口返回的每一项本身就是结构化邮件对象,常见字段包括:
subject:邮件主题from.emailAddress.address:发件人地址bodyPreview:正文摘要receivedDateTime:收件时间hasAttachments:是否带附件
这也是 Graph API 相比传统协议更方便的地方:它直接给你 JSON 结构,不需要自己解析 MIME 原始报文。
对原脚本的理解
原脚本虽然短,但已经具备一个完整的读取链路:
get_accesstoken()负责换令牌Graph()负责请求/me/messages主流程遍历结果并打印主题、发件人和内容预览
它适合拿来做这些场景:
自建邮箱提醒系统
面板类项目里拉取用户收件信息
邮件通知聚合
对接 Outlook 邮箱的数据同步工具
优点
相比自己去连 IMAP / POP3,Graph API 有几个明显优势:
返回 JSON,开发体验更直接
支持筛选、排序、分页等查询能力
与微软账号体系整合度更高
更适合做 Web 服务或后台接口集成
如果业务并不依赖传统邮件协议,优先选择 Graph 通常更省事。
可改进的地方
原脚本是一个最小可运行版本,实际项目里建议补这些点:
1. 明确异常处理
原脚本使用了裸 except,这会吞掉很多真实错误。更推荐:
区分网络错误与授权失败
打印接口返回的错误码和错误描述
对超时做重试,而不是直接返回空数组
2. 控制返回结果规模
如果邮箱邮件很多,直接请求全部消息并不合适。可以配合:
$top限制数量$orderby控制排序$select只取必要字段$filter做条件筛选
例如:
/me/messages?$top=10&$select=subject,from,bodyPreview,receivedDateTime&$orderby=receivedDateTime desc
3. 不要在代码里硬编码令牌
真实项目一定不要像测试脚本那样直接把:
client_idrefresh_token访问结果日志
硬写在源码里。更合理的做法是放到:
环境变量
密钥管理服务
后端受控配置
安全提醒
邮件接口涉及明显的隐私数据,落地时必须注意:
只操作自己或已授权用户的邮箱
不要在日志中打印完整令牌
不要把敏感邮件正文直接落盘
生产环境要限制作用域和访问范围
总结
这个脚本的核心原理并不复杂:先通过 OAuth2 刷新令牌换到访问令牌,再拿访问令牌请求 Microsoft Graph 的邮件资源接口。Graph API 的优势在于数据结构清晰、调用统一、对现代应用更友好。
如果你的目标是做 Outlook 邮箱接入、邮件同步、后台提醒或自动化通知,这种实现方式会比传统协议更轻量,也更容易扩展。


留言评论
暂无留言