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

无需邀请批量获取外部联合用户活动状态的技术咨询

问题描述

我希望通过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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 05:27:03