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

基于Microsoft Graph OAuth2迁移邮件脚本遇连接错误求助

问题描述

原本有一个基于IMAP的后台脚本,负责持续查询邮件并处理内容与附件。现在使用的邮箱要迁移至Office365并停用IMAP,需改为使用Microsoft Graph与OAuth2。管理员提供了测试账号信息(包含Application (client) ID、Directory (tenant) ID、Secret、共享邮箱等)及授权、令牌端点,但直接访问端点时分别出现AADSTS900144和AADSTS900561错误。

编写的测试脚本执行时出现连接超时错误:

requests.exceptions.ConnectionError: HTTPSConnectionPool(host='login.microsoftonline.com', port=443): Max retries exceeded with url: /********/oauth2/authorize/v2.0/.well-known/openid-configuration (Caused by NewConnectionError('<urllib3.connection.HTTPSConnection object at 0x000001DAB297C880>: Failed to establish a new connection: [WinError 10060] A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond'))

已知ConfidentialClientApplication会自动添加/v2.0/,也尝试过其他方案,但始终无法完成令牌/认证请求,卡壳数日。测试脚本如下:

import msal
import requests

# Define the Azure OAuth 2.0 SSO endpoint URLs
TENANT_ID = ''
AUTHORITY_URL = 'https://login.microsoftonline.com/' + TENANT_ID + "/oauth2/authorize"
CLIENT_ID = ''
CLIENT_SECRET = ''

# Define the Azure Graph API endpoint URLs
GRAPH_API_URL = 'https://graph.microsoft.com/v1.0'
EMAILS_ENDPOINT = GRAPH_API_URL + '/me/messages'


def save_attachment(attachment_url, headers, file_path):
    attachment_response = requests.get(attachment_url, headers=headers)
    if attachment_response.status_code == requests.codes.ok:
        with open(file_path, 'wb') as f:
            f.write(attachment_response.content)
        print(f'Saved attachment to {file_path}')
    else:
        print(f'Failed to retrieve attachment. Status code: {attachment_response.status_code}')


# Create a `ConfidentialClientApplication` instance to authenticate the user
app = msal.ConfidentialClientApplication(
    CLIENT_ID,
    client_credential=CLIENT_SECRET,
    authority=AUTHORITY_URL
)
# Obtain an access token using the `acquire_token_for_client` method
# result = app.acquire_token_for_client(scopes=[GRAPH_API_URL + '/.default'], proxies=proxy_options)
result = app.acquire_token_for_client(scopes=[GRAPH_API_URL + '/.default'])

# Check if the access token was obtained successfully
if "access_token" in result:
    # Call the Azure Graph API to retrieve emails using the `requests` library with the appropriate headers and proxy
    headers = {
        'Authorization': 'Bearer ' + result['access_token']
    }
    # response = requests.get(EMAILS_ENDPOINT, headers=headers)
    response = requests.get(EMAILS_ENDPOINT, headers=headers)

    # Parse the response and print the subject lines of the emails
    if response.status_code == requests.codes.ok:
        emails = response.json()['value']
        count = 0
        for email in emails:
            print('Subject:', email['subject'])

            # Retrieve attachments if they exist
            if 'attachments' in email:
                for attachment in email['attachments']:
                    # Call the Azure Graph API to retrieve the attachment content
                    attachment_id = attachment['id']
                    attachment_url = f"{EMAILS_ENDPOINT}/{email['id']}/attachments/{attachment_id}"
                    attachment_name = attachment['name']

                    # Define a file path to save the attachment
                    file_path = f"{attachment_name}"

                    # Save the attachment to the local file system
                    save_attachment(attachment_url, headers, file_path)

            else:
                print('No attachments found.')
            count += 1
            if count >= 5:
                break
    else:
        print('Failed to retrieve emails. Status code:', response.status_code)
else:
    print(result.get("error_description"))
解决方案

1. 修正Authority URL配置错误

当前的AUTHORITY_URL错误使用了授权端点/oauth2/authorize,ConfidentialClientApplication需要的是租户基础权限地址,正确格式应为:

AUTHORITY_URL = f'https://login.microsoftonline.com/{TENANT_ID}'

MSAL库会自动拼接正确的令牌和发现端点,无需手动添加/oauth2/authorize,这是引发AADSTS900144错误的核心原因之一。

2. 解决连接超时问题

超时错误说明脚本无法访问login.microsoftonline.com,需做以下检查:

  • 网络环境是否需要代理:取消注释代码中proxies=proxy_options部分,配置正确的代理地址(如proxy_options = {"https": "http://your-proxy:port"}),并在acquire_token_for_client和requests.get中传入proxies参数。
  • 确认防火墙/安全组是否放行login.microsoftonline.com和graph.microsoft.com的443端口。

3. 适配共享邮箱访问

脚本中使用/me/messages,但后台服务(客户端凭证模式)无法使用/me,需直接指定共享邮箱的邮箱地址或ID,修改邮件端点:

SHARED_MAILBOX_EMAIL = "shared@yourdomain.com"
EMAILS_ENDPOINT = f"{GRAPH_API_URL}/users/{SHARED_MAILBOX_EMAIL}/messages"

4. 确认应用权限配置

使用客户端凭证模式(acquire_token_for_client)需要在Azure AD中给应用配置应用权限(而非委托权限),并确保已授予管理员同意:

  • 所需权限:Mail.Read、Mail.ReadWrite(根据需求选择),权限类型为"应用权限"。
  • 未授予管理员同意会导致AADSTS900561错误。

5. 修正附件请求端点

当前附件URL拼接错误,正确格式应为:

attachment_url = f"{GRAPH_API_URL}/users/{SHARED_MAILBOX_EMAIL}/messages/{email['id']}/attachments/{attachment_id}/$value"

直接请求/$value端点可获取附件二进制内容,无需额外处理。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 02:52:10