无需邀请批量获取外部联合用户活动状态的技术咨询
问题描述
我希望通过API批量获取外部企业联合用户的活动状态,无需邀请用户并等待其接受邀请。是否可以通过非Microsoft Graph API的其他方式,获取与Teams搜索栏一致的活动状态响应?当前使用Graph API仅能返回所有联合用户的“离线”或“状态未知”结果,恳请提供相关帮助或建议。
当前使用的Graph API代码
import requests import json import os # 补充缺失的导入 from dotenv import load_dotenv from msal import ConfidentialClientApplication load_dotenv(dotenv_path=r'....') CLIENT_ID = os.getenv('CLIENT_ID') CLIENT_SECRET = os.getenv('CLIENT_SECRET') TENANT_ID = os.getenv('TENANT_ID') app = ConfidentialClientApplication( CLIENT_ID, authority=f"https://login.microsoftonline.com/{TENANT_ID}", client_credential=CLIENT_SECRET, ) result = app.acquire_token_for_client(scopes=["https://graph.microsoft.com/.default"]) if "access_token" in result: access_token = result["access_token"] else: print("Error acquiring token:", result.get("error"), result.get("error_description")) exit(1) user_id = "..." presence_url = f'https://graph.microsoft.com/beta/communications/presences/{user_id}' presence_headers = { 'Authorization': f'Bearer {access_token}', 'Content-Type': 'application/json' } response = requests.get(presence_url, headers=presence_headers) if response.status_code == 200: presence_info = response.json() print("Presence Info:", json.dumps(presence_info, indent=2)) else: print("Failed to retrieve presence info:", response.status_code, response.text)
解决方案与建议
核心限制说明
你遇到的问题是Graph API的应用权限模式导致的:应用权限下,出于跨租户隐私保护和数据安全限制,无法获取外部联合用户的真实活动状态,返回“离线”或“状态未知”是预期行为。而Teams客户端能显示准确状态,是因为基于当前登录用户的委托权限,且用户与外部联系人存在互动关系(如发起过聊天、在搜索栏中发起过沟通等)。
非Graph API的可行方向
- Teams JavaScript客户端SDK:在Teams Tab应用中使用
microsoftTeams.user.getPresence方法,基于当前登录用户的上下文获取外部用户状态。但该方式仅能在Teams客户端内运行,且要求当前用户与目标外部用户有过互动。 - 切换到委托权限的Graph API:放弃客户端凭证流,改用用户上下文的授权码流,申请
Presence.Read.All委托权限。这种模式下,若当前用户已与外部用户存在互动(无需正式邀请,只要在Teams中搜索并发起过沟通),就能获取到和客户端一致的状态。但此方式无法完全实现无交互的批量获取,仍依赖用户间的互动关系。
委托权限模式代码示例
如果考虑切换到委托权限,可参考以下代码框架:
import requests import json import os from dotenv import load_dotenv from msal import PublicClientApplication load_dotenv(dotenv_path=r'....') CLIENT_ID = os.getenv('CLIENT_ID') TENANT_ID = os.getenv('TENANT_ID') REDIRECT_URI = "http://localhost:8000" # 需提前在Azure AD应用中配置该重定向URI app = PublicClientApplication( CLIENT_ID, authority=f'https://login.microsoftonline.com/{TENANT_ID}' ) # 初始化授权码流 flow = app.initiate_auth_code_flow( scopes=["Presence.Read.All"], redirect_uri=REDIRECT_URI ) print("请访问以下链接完成授权:", flow["auth_uri"]) auth_code = input("输入页面返回的授权码: ") # 换取访问令牌 result = app.acquire_token_by_auth_code_flow(flow, {"code": auth_code}) if "access_token" in result: access_token = result["access_token"] target_user_id = "目标外部用户ID" presence_url = f'https://graph.microsoft.com/beta/communications/presences/{target_user_id}' presence_headers = { 'Authorization': f'Bearer {access_token}', 'Content-Type': 'application/json' } response = requests.get(presence_url, headers=presence_headers) if response.status_code == 200: print("活动状态信息:", json.dumps(response.json(), indent=2, ensure_ascii=False)) else: print("请求失败:", response.status_code, response.text) else: print("获取令牌失败:", result.get("error"), result.get("error_description"))
关键注意事项
- 无论采用哪种方式,都无法绕过“用户间需存在互动关系”的限制,这是Teams的隐私规则决定的,目的是保护外部用户的状态隐私。
- Teams客户端SDK方式只能在前端场景中使用,无法实现纯后台的批量状态获取。
内容的提问来源于stack exchange,提问作者Loco2343
相关产品推荐
相关产品推荐

