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

Outlook Graph API调用PATCH方法返回访问被拒绝错误求助

Outlook Graph API PATCH请求标记邮件已读返回权限拒绝排查

问题现象

  • 调用Outlook Graph API读取邮件时凭证、相关配置运行正常,调用PATCH方法接口时返回错误:Access is denied. Check credentials and try again.
  • 当前使用的权限范围配置为:OFFICE365_SCOPES='https://graph.microsoft.com/.default'
  • 现有实现代码如下:
public function setMessageAsSeen($userName, $msgId){
    try{    
        if( ! $this->msLogin()){
            return [];
        }
        $ch = curl_init();
        $url = "https://graph.microsoft.com/v1.0/users/".$userName."/messages/".$msgId;
        $request_headers = array();
        $request_headers[] = 'Content-type: application/json';
        $request_headers[] = 'Authorization: Bearer '.$this->accessToken;
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PATCH');
        curl_setopt($ch, CURLOPT_HTTPHEADER, $request_headers);
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode(['isRead' => true]));
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
        $response = curl_exec($ch);
        dd($response);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);
        if($httpCode != 200) {
            return false;
        }
        return true;
    }catch(Exception $e){
        Log::error('setMessageAsSeen() error : '.$e->getMessage());
        return false;
    }
}

排查步骤

  1. 优先核对Azure AD应用权限配置
    读取邮件正常仅代表应用已被授予读类权限(如Mail.Read、Mail.ReadBasic.All),修改邮件状态(包括标记isRead为true)属于写操作,必须匹配对应写权限:
    • 如果是委托权限场景(用户登录后操作自己的邮箱),需要添加Mail.ReadWrite委托权限
    • 你当前调用的是/users/{userName}/messages接口,属于应用身份访问指定用户邮箱的场景,必须添加Mail.ReadWrite.All应用权限,且该权限需要完成管理员同意,普通用户授权不生效
    • 权限配置完成后必须重新获取access_token,旧token不会自动同步新权限,哪怕没过期也会持续返回权限不足
  2. 校验当前access_token的实际权限
    不要仅以代码中配置的scope值为准,将实际拿到的$this->accessToken解码,查看payload中的字段:
    • 应用身份场景看roles字段,确认是否包含Mail.ReadWrite.All
    • 委托身份场景看scp字段,确认是否包含Mail.ReadWrite
      如果字段中没有对应权限,说明权限授予流程、token获取环节存在问题,和代码逻辑无关
  3. 排除代码逻辑干扰
    先将拿到的access_token放到接口测试工具中,手动发起PATCH请求:
    • 请求地址和你代码中拼接的地址一致
    • 请求头携带Content-type: application/json和Authorization: Bearer <你的token>
    • 请求体为{"isRead": true}
      如果手动请求仍然返回403,可完全排除代码问题,继续排查权限和策略配置;如果手动请求正常,再检查curl配置是否存在异常(比如当前代码重复设置了CURLOPT_RETURNTRANSFER,虽不影响权限但属于冗余配置;生产环境需要将CURLOPT_SSL_VERIFYHOST、CURLOPT_SSL_VERIFYPEER改回启用状态,避免安全风险)
  4. 特殊策略排查
    如果权限配置正确、token也携带了对应权限仍然报错,检查目标邮箱的Exchange策略:
    • 确认邮箱没有开启针对第三方应用的MAPI访问限制
    • 确认Azure AD条件访问策略没有拦截该应用对目标邮箱的写操作
    • 确认目标邮箱没有配置专属的应用访问权限白名单,将你使用的Azure AD应用加入允许列表

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 23:27:35