使用MS Graph API标记邮件为已读时遇CompactToken解析失败问题
问题描述
开发了一个基于MS Graph API的程序,用于拉取收件箱中昨日收到的、带附件且未读的邮件,请求端点为:
https://graph.microsoft.com/v1.0/me/mailFolders/inbox/messages?$expand=attachments&$search="hasAttachments:true AND received:yesterday AND isRead:false"
认证并获取数据后,将附件内容字节存储到S3桶中,核心代码如下:
result = app.acquire_token_silent(config["scope"], account=a) s3 = boto3.client('s3') bucket = config['bucket'] for email in emails: if email['hasAttachments']: attachments = email['attachments'] count = 0 for attachment in attachments: if attachment['isInline'] is False: name = attachment['name'] fileContent = base64.b64decode(attachment['contentBytes']) s3.put_object(Bucket=bucket, Key=name, Body=fileContent) count = count +1 emailid = email['id'] rp = requests.patch(f'https://graph.microsoft.com/v1.0/me/messages/{emailid}', data ={'isRead':'true'}, headers = {"Authorization": f"Bearer token= {result['access_token']}"}) print(rp) logger.info('Attachment uploaded-' + ' Attachment Size: ' + str(attachment['size']) + ' File Name: ' + attachment['name'] + ' Email Source: ' + email['from']['emailAddress']['address'] + ' Email ID: ' + email['id'] + ' Email Subject Line: ' + email['subject']) logger.info(f"Attachment count uploaded to s3: {count}") logger.info('All uploads complete')
目前附件上传功能正常,但无法标记邮件为已读,收到的报错信息为:
{"error":{"code":"InvalidAuthenticationToken","message":"CompactToken parsing failed with error code: 80049217","innerError":{"date":"2022-11-17T18:48:54","request-id":"<xxx>","client-request-id":"<xxx>"}}}
当前配置的权限仅为["Mail.ReadWrite"],请问是格式问题还是其他原因导致该错误?
问题分析与解决
直接原因:Authorization请求头格式错误
报错CompactToken parsing failed with error code: 80049217是因为Graph API无法正确解析身份令牌,问题出在请求头的写法上:
你的代码中写的是:
headers = {"Authorization": f"Bearer token= {result['access_token']}"}
正确的Bearer令牌格式应为Bearer {access_token},不需要额外添加token=字段,多余内容导致令牌解析失败。修正后的请求头应为:
headers = {"Authorization": f"Bearer {result['access_token']}"}
额外注意点:请求体格式问题
除了令牌格式,你的requests.patch使用data参数传递请求体,默认会以application/x-www-form-urlencoded格式发送,但Graph API要求请求体为JSON格式,建议改用json参数:
rp = requests.patch( f'https://graph.microsoft.com/v1.0/me/messages/{emailid}', json={'isRead': True}, # 使用json参数,且isRead应为布尔值而非字符串 headers={"Authorization": f"Bearer {result['access_token']}"} )
若坚持使用data参数,需手动设置Content-Type: application/json头,并将字典转为JSON字符串,但使用json参数更简便。
权限验证
你配置的Mail.ReadWrite权限已经足够完成标记邮件为已读的操作,权限本身无问题。
内容的提问来源于stack exchange,提问作者RunRabbit
相关产品推荐
相关产品推荐

