使用 Python 和 Graph API 从 Outlook 发送邮件 - 身份验证问题

问题描述 投票:0回答:1

我编写了一个 Python 脚本,该脚本使用 office365 库并将 Excel 文件从 SharePoint 加载到我的本地系统。从那里,我通过 SQL Alchemy 将选定的内容推送到 SQL 服务器。

此流程每天运行,作为收集报告数据的例行程序。然而,Excel 的问题在于人们使用它。因此,我预计有时会出现问题。例如,文件不可用或只是名称稍有偏差(并且未被我的正则表达式捕获)。

幸运的是,报告的使用者也是文件的提供者。因此,我想在我的脚本中实现检查,如果脚本无法完成其工作,则自动将问题发送给文件提供者(和我)。

首先,我想从我的 Outlook 帐户发送一封邮件。为此,我想使用 Microsoft Graph API。

我已找到我的租户 ID,并前往 entra.microsoft.com 创建应用程序。我向应用程序授予了 Mail.Send 和 Mail.Send.Shared 权限,并创建了一个客户端密钥。

这样,我就可以编写以下代码了。

import msal
import requests
import json

TENANT_ID = 'Tenant ID'
AUTHORITY_URL = 'https://login.microsoftonline.com/' + TENANT_ID
CLIENT_ID = 'Client ID'
CLIENT_SECRET = 'Client Secret'
SCOPES = ["https://graph.microsoft.com/.default"]

app = msal.ConfidentialClientApplication(
    client_id=CLIENT_ID,
    client_credential=CLIENT_SECRET,
    authority=AUTHORITY_URL)

result = app.acquire_token_for_client(scopes=SCOPES)

userId = "My Outlook Mail Adress"
endpoint = f'https://graph.microsoft.com/v1.0/users/{userId}/sendMail'
toUserEmail = "My Outlook Mail Adress"
email_msg = {'Message': {'Subject': "Test Sending Email from Python",
                         'Body': {'ContentType': 'Text', 'Content': "This is a test email."},
                         'ToRecipients': [{'EmailAddress': {'Address': toUserEmail}}]
                         },
             'SaveToSentItems': 'true'}
r = requests.post(endpoint,
                  headers={'Authorization': 'Bearer ' + result['access_token']},
                  json=email_msg)
if r.ok:
    print('Sent email successfully')
else:
    print(r.json())

但是,Graph API 回复:

{'error': {'code': 'ErrorAccessDenied', 'message': '访问被拒绝。 检查凭据并重试。'}}

所以我想,在将用户权限委托给应用程序时我做错了什么。 这里是我找到的有关此主题的 Microsoft 文档。

你知道我必须如何更改我的代码才能获得发送邮件的许可吗?

据我所知,我所做的事情与this问题的答案中描述的完全一样。但对他们有效的方法对我来说却不起作用。

这个问题也密切相关。我能发现的唯一区别是,回答者在应用程序级别上向应用程序授予了 Mail.Send 权限,而我希望使用委派级别,因为我们的组织未启用另一个级别。

python api outlook microsoft-graph-api office365
1个回答
0
投票

我最近投入了大量工作来使用 Graph API 与我的驱动器和电子邮件进行交互,但最初却陷入了困境。

看起来您已经为您的应用程序提供了与您的组织交互所需的一切,但没有为您的应用程序提供访问/与您的实际帐户交互所需的一切。

来自他们的 文档

Confidential Client App

获取客户端的令牌: 获取当前机密的令牌 客户端,而不是最终用户。

你想要

acquire_token_on_behalf_of:使用代表(OBO)获取令牌 流量。

当前应用程序是一个中间层服务,使用令牌调用 代表最终用户。当前应用程序可以使用此类令牌(又称为 用户断言)请求另一个令牌来访问下游 Web API, 代表该用户。

© www.soinside.com 2019 - 2024. All rights reserved.