如何无需管理员审批,通过Python脚本调用Graph API搜索个人Microsoft 365内容?
我完全懂你这种无奈——明明在浏览器里搜自己的M365内容毫无障碍,Graph Explorer里调用API也顺风顺水,为啥写个Python脚本就得求管理员注册应用?别急,其实有个不用管理员插手的方案,核心就是用用户委托的授权码流,让脚本以你的身份登录,权限由你自己同意,完全不需要管理员审批。
核心思路
Graph Explorer之所以能直接用,是因为它是微软官方注册的「公共客户端应用」,已经获得了大量用户可自主同意的权限。我们的脚本可以照搬这个逻辑:用公共客户端模式发起授权,让你通过浏览器登录并同意权限,之后就能像你自己操作一样调用Graph API了。
具体步骤(亲测有效)
1. 准备依赖
先装两个必要的Python库:微软官方的身份验证库msal,以及发送请求的requests:
pip install msal requests
2. 选择客户端ID(二选一)
这里有两种方式,挑适合你的:
方式一:自己注册一个桌面应用(推荐)
很多组织允许普通用户注册「桌面/移动应用」类型的应用,不需要管理员审批:- 登录你的Entra门户,找到「应用注册」→「新注册」
- 名称随便填(比如"My M365 Search Script"),支持的账户类型选「任何组织目录中的账户和个人Microsoft账户」
- 重定向URI选「公共客户端/桌面」,填
http://localhost:8000 - 注册完成后,复制「应用程序(客户端)ID」备用
方式二:用微软官方的Graph Explorer客户端ID
如果组织不让你注册应用,可以试试Graph Explorer的官方ID:d3590ed6-52b3-4102-aeff-aad2292ab01c。这是微软官方应用,大部分组织不会限制它的权限。
3. 编写Python脚本
把下面的代码保存成m365_search.py,替换CLIENT_ID为你选的ID,然后运行:
import msal import requests import webbrowser from http.server import HTTPServer, BaseHTTPRequestHandler import urllib.parse # 配置参数 CLIENT_ID = "你的客户端ID" # 替换成你自己的或官方的ID AUTHORITY = "https://login.microsoftonline.com/common" # 搜索所需的权限(都是用户可自主同意的,无需管理员审批) SCOPE = ["Mail.Read", "Files.Read.All", "Chat.Read", "User.Read", "Contacts.Read"] REDIRECT_URI = "http://localhost:8000" # 临时HTTP服务器,用来接收登录后的授权码 class AuthCallbackHandler(BaseHTTPRequestHandler): auth_code = None def do_GET(self): query_params = urllib.parse.parse_qs(urllib.parse.urlparse(self.path).query) if 'code' in query_params: self.auth_code = query_params['code'][0] self.send_response(200) self.send_header('Content-type', 'text/html') self.end_headers() self.wfile.write(b"登录成功!可以关闭这个页面了~") else: self.send_response(400) self.end_headers() self.wfile.write(b"授权失败,请重试") # 1. 打开浏览器让用户登录授权 server = HTTPServer(('localhost', 8000), AuthCallbackHandler) app = msal.PublicClientApplication(CLIENT_ID, authority=AUTHORITY) auth_url = app.get_authorization_request_url(SCOPE, redirect_uri=REDIRECT_URI) webbrowser.open(auth_url) # 等待用户完成登录,接收授权码 server.handle_request() # 2. 用授权码获取访问令牌 if server.RequestHandlerClass.auth_code: token_result = app.acquire_token_by_authorization_code( server.RequestHandlerClass.auth_code, scopes=SCOPE, redirect_uri=REDIRECT_URI ) if "access_token" in token_result: # 3. 调用Graph API搜索M365内容 search_keyword = input("请输入要搜索的关键词:") headers = {"Authorization": f"Bearer {token_result['access_token']}"} search_payload = { "requests": [ { "entityTypes": ["message", "chatMessage", "contact", "driveItem"], "query": {"queryString": search_keyword} } ] } response = requests.post( "https://graph.microsoft.com/v1.0/search/query", json=search_payload, headers=headers ) response.raise_for_status() # 打印搜索结果 print("\n搜索结果:") print(response.json()) else: print(f"获取令牌失败:{token_result.get('error_description')}") else: print("未获取到授权码,请重试")
4. 运行脚本
执行脚本后,会自动打开浏览器让你登录你的M365账户,第一次登录时会弹出权限请求页面,你只要点击「同意」,脚本就能获取到权限,然后输入关键词就能搜索你的邮件、Teams聊天、联系人、文档了。
为什么之前的尝试失败?
你之前遇到的「权限拒绝」「需要管理员审批」,大概率是因为用了「客户端凭据流」(服务端应用模式),或者请求了需要管理员同意的权限。而我们用的是「授权码流(公共客户端)」,获取的是用户委托的权限,这些权限只要你自己同意就行,完全不需要管理员插手——就像你在浏览器里操作自己的内容一样。
注意事项
- 如果用官方的Graph Explorer ID,部分严格的组织可能会限制它的权限,这时候还是建议自己注册桌面应用(大部分组织允许)
- 脚本里的权限是搜索所需的最小权限集,你可以根据需求增减,但尽量只请求必要的权限
- 这个脚本是完全离线的,不需要任何服务器,只要能访问微软的登录和Graph API即可
内容来源于stack exchange

