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

使用Graph API向Teams频道发消息遇401权限问题求助

问题描述

我尝试使用Microsoft Graph API向Teams频道发送消息,已在Microsoft Azure中注册应用,配置了委派权限ChannelMessage.Send和应用权限Teamwork.Migrate.All。通过客户端凭证模式成功获取应用令牌,但调用发送消息接口时返回401未授权错误,提示仅导入场景允许应用上下文POST消息。

相关代码

获取令牌代码

def get_access_token():
    url =f"https://login.microsoftonline.com/{tenant_id}/oauth2/v2.0/token"
    payload = {
        "grant_type": "client_credentials",
        "client_id": client_id,
        "client_secret": client_secret,
        "scope": "https://graph.microsoft.com/.default"
    }
    response = requests.post(url, data=payload)
    response_data = response.json()
    print(response_data)
    access_token = response_data['access_token']
    return access_token

发送消息代码

def send_message():
    endpoint_url = f"https://graph.microsoft.com/v1.0/teams/{team_id}/channels/{channel_id}/messages"
    access_token = get_access_token()
    headers = {
        'Authorization': f'Bearer {access_token}',
        'Content-Type': 'application/json'
    }
    request_body= {
        "body": {
            "content": "Hello world"
        }
    }
    response = requests.post(endpoint_url, headers=headers, data=json.dumps(request_body))
    print(response.status_code)
    print(response.json())

错误响应

401
{'error': {'code': 'Unauthorized', 'message': 'Message POST is allowed in application-only context only for import purposes. Refer to https://docs.microsoft.com/microsoftteams/platform/graph-api/import-messages/import-external-messages-to-teams for more details.', 'innerError': {'date': '2024-09-12T13:57:54', 'request-id': '60bd5cfb-xxxx-4bea-ba58-xxxxxxxxx', 'client-request-id': '60bd5cfb-xxxx-4bea-ba58-xxxxxxxx'}}}
问题原因
  1. 权限与模式不匹配:ChannelMessage.Send是委派权限,需要用户参与的授权模式(如授权码模式)才能生效,无法在客户端凭证(应用权限)模式下使用。
  2. 应用权限的限制:客户端凭证模式下,/teams/{teamId}/channels/{channelId}/messages接口仅支持导入历史消息的场景,需配合Teamwork.Migrate.All权限和特定请求参数,不能直接发送普通实时消息。
解决方案

方案1:切换到授权码模式发送普通消息

如果要发送实时普通消息,需改用用户授权的授权码模式,利用ChannelMessage.Send委派权限:

  1. 确保Azure应用中ChannelMessage.Send委派权限已获得管理员同意。
  2. 修改令牌获取逻辑为授权码模式(需先引导用户完成登录授权,获取授权码):
def get_access_token_auth_code():
    # 注意:实际需先引导用户访问授权地址获取code,此处仅展示令牌交换步骤
    url = f"https://login.microsoftonline.com/{tenant_id}/oauth2/v2.0/token"
    payload = {
        "grant_type": "authorization_code",
        "client_id": client_id,
        "client_secret": client_secret,
        "code": "用户授权后返回的授权码",
        "redirect_uri": "你的应用注册时配置的重定向URI",
        "scope": "ChannelMessage.Send"
    }
    response = requests.post(url, data=payload)
    response_data = response.json()
    access_token = response_data['access_token']
    return access_token
  1. 发送消息的接口和请求体保持原代码不变,使用上述方法获取的令牌即可正常发送。

方案2:使用应用权限导入历史消息

如果你的需求是导入历史消息,需在请求体中添加导入场景必填的字段,配合Teamwork.Migrate.All权限使用:

def send_import_message():
    endpoint_url = f"https://graph.microsoft.com/v1.0/teams/{team_id}/channels/{channel_id}/messages"
    access_token = get_access_token()
    headers = {
        'Authorization': f'Bearer {access_token}',
        'Content-Type': 'application/json'
    }
    request_body= {
        "body": {
            "content": "Hello world"
        },
        # 导入场景必须添加的字段
        "createdDateTime": "2024-09-10T10:00:00Z",  # 需为过去的时间
        "from": {
            "user": {
                "id": "消息发送者的用户ID",
                "displayName": "发送者名称"
            }
        }
    }
    response = requests.post(endpoint_url, headers=headers, json=request_body)
    print(response.status_code)
    print(response.json())

注意:导入的消息会被标记为历史消息,不会触发Teams实时通知,且createdDateTime必须设置为消息实际产生的过去时间。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 12:46:23