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

需要身份验证令牌时从Python发送Exchange邮件的最佳方式

实现方案

推荐两种可行的实现方式,可根据业务场景选择:

方案1:使用smtplib配合OAuth2认证(你之前误以为smtplib不支持,实际可以通过自定义认证逻辑实现)

前置要求

  • 应用注册时已添加Office 365 Exchange Online的SMTP.SendAsApp应用权限,且已获得租户管理员同意
  • 获取令牌时的scopes参数填写为["https://outlook.office365.com/.default"]

代码示例

import msal
import smtplib
import base64
from email.mime.text import MIMEText

# 1. 获取令牌(和你现有逻辑一致,注意scope正确)
param_client_id = "你的客户端ID"
param_client_credential = "你的客户端凭证"
param_tenant_name = "你的租户ID/域名"
scopes = ["https://outlook.office365.com/.default"]
sender_email = "发件人邮箱地址"

app = msal.ConfidentialClientApplication(
        client_id=param_client_id,
        client_credential=param_client_credential,
        authority=f"https://login.microsoftonline.com/{param_tenant_name}"
    )
result = app.acquire_token_for_client(scopes=scopes)
mytoken = result['access_token']

# 2. 构造XOAuth2认证字符串
auth_string = f"user={sender_email}\x01auth=Bearer {mytoken}\x01\x01"
auth_string_b64 = base64.b64encode(auth_string.encode('utf-8')).decode('utf-8')

# 3. 构造邮件内容
msg = MIMEText("邮件正文内容", "plain", "utf-8")
msg['From'] = sender_email
msg['To'] = "收件人邮箱地址"
msg['Subject'] = "邮件主题"

# 4. SMTP连接发送
with smtplib.SMTP("smtp.office365.com", 587) as server:
    server.starttls()
    # 不用默认的login方法,手动发送XOAuth2认证命令
    server.docmd("AUTH", f"XOAUTH2 {auth_string_b64}")
    server.sendmail(sender_email, ["收件人邮箱地址"], msg.as_string())

方案2:调用Microsoft Graph API发送邮件(官方推荐,无需维护SMTP连接逻辑)

前置要求

  • 应用注册时已添加Microsoft Graph的Mail.Send应用权限,且已获得租户管理员同意
  • 获取令牌时的scopes参数填写为["https://graph.microsoft.com/.default"]

代码示例

import msal
import requests

# 1. 获取令牌
param_client_id = "你的客户端ID"
param_client_credential = "你的客户端凭证"
param_tenant_name = "你的租户ID/域名"
scopes = ["https://graph.microsoft.com/.default"]
sender_email = "发件人邮箱地址"

app = msal.ConfidentialClientApplication(
        client_id=param_client_id,
        client_credential=param_client_credential,
        authority=f"https://login.microsoftonline.com/{param_tenant_name}"
    )
result = app.acquire_token_for_client(scopes=scopes)
mytoken = result['access_token']

# 2. 构造发邮件请求参数
url = f"https://graph.microsoft.com/v1.0/users/{sender_email}/sendMail"
headers = {
    "Authorization": f"Bearer {mytoken}",
    "Content-Type": "application/json"
}
payload = {
    "message": {
        "subject": "邮件主题",
        "body": {
            "contentType": "Text",
            "content": "邮件正文内容"
        },
        "toRecipients": [
            {
                "emailAddress": {
                    "address": "收件人邮箱地址"
                }
            }
        ]
    },
    "saveToSentItems": True # 是否保存到发件箱
}

# 3. 发送请求
response = requests.post(url, headers=headers, json=payload)
response.raise_for_status() # 异常校验

常见问题排查

  • 确认应用注册的权限类型为应用权限而非委托权限,且已经过管理员同意
  • 确认获取的令牌权限正确,可解析令牌查看roles声明是否包含对应权限
  • 若使用SMTP方案,确认发件人账户已开启Authenticated SMTP选项(你已配置可忽略)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 11:30:06