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

如何通过Microsoft Graph API发送Python email.message.EmailMessage邮件

如何通过Microsoft Graph API发送Python EmailMessage构建的带嵌入图片的邮件

你的错误源于误用了Graph API的普通邮件发送格式——EmailMessage生成的是完整的多部分MIME邮件内容,不能直接塞进Body.Content字段,需要使用Graph API的MIME邮件发送能力来处理。

错误原因解析

你当前代码将EmailMessage转成字符串后,试图以text/plain的类型传递给Graph API,但这个字符串包含了HTML、嵌入图片等多部分MIME结构,Graph API无法识别这种格式,因此抛出"Requested value 'text/plain' was not found"错误。

解决方案步骤

要发送用EmailMessage构建的邮件,需按以下步骤操作:

  • 将EmailMessage对象序列化为RFC 822格式的字节流
  • 对字节流进行Base64编码
  • 调用Graph API的sendMail接口,将编码后的内容放在MimeContent字段中,替代原来的Body字段

修正后的完整代码

import smtplib
from email.utils import formatdate
from email.message import EmailMessage
from email.mime.guess_type import guess_type
import requests
import msal
import base64

server = 'smtp.office365.com'
port = 587
from_mail = 'levrai@ninjane.er'
to_mail = 'desti@nati.on'
subject = 'Demo sending via Graph API!'
password = 'not_so_Secur3!'

message_parts = ['Hi sir', 'This is a demo message.', 'It could help others to help me, and possibly others too.']

# 假设doc_mail_from_template是已实现的函数,返回文本、HTML内容、图片CID和本地路径
text_msg, html_msg, cids, locs = doc_mail_from_template(message_parts)  

msg = EmailMessage()
msg.set_content(text_msg)  # 修正原代码变量名错误:text_message -> text_msg
msg.add_alternative(html_msg, subtype='html')
msg['From'] = from_mail
msg['To'] = to_mail
msg['Date'] = formatdate(localtime=True)
msg['Subject'] = subject

# 嵌入图片到邮件
for loc, cid in zip(locs, cids):
    with open(loc, 'rb') as img:
        maintype, subtype = guess_type(img.name)[0].split('/')
        msg.get_payload()[1].add_related(img.read(), maintype=maintype, subtype=subtype, cid=cid)

# 使用Graph API发送邮件
client_id = 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxx8c5'
client_secret = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-xxb96'
tenant_id = 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxx973'
userId = "levrai@ninjane.er"        
authority = f"https://login.microsoftonline.com/{tenant_id}"
scopes = ["https://graph.microsoft.com/.default"]

app = msal.ConfidentialClientApplication(client_id=client_id, client_credential=client_secret, authority=authority)
result = app.acquire_token_silent(scopes, account=None)
if not result:
    result = app.acquire_token_for_client(scopes=scopes)

# 将EmailMessage转为RFC 822格式字节流,再Base64编码
mime_content = msg.as_bytes()
base64_mime = base64.b64encode(mime_content).decode('utf-8')

# 构造Graph API请求体:使用MimeContent替代Body
email_msg = {
    'Message': {
        'MimeContent': {
            'ContentType': 'message/rfc822',
            'Content': base64_mime
        },
        'ToRecipients': [{'EmailAddress': {'Address': to_mail}}]
    },
    'SaveToSentItems': 'true'
}

endpoint = f"https://graph.microsoft.com/v1.0/users/{userId}/sendMail"  # 修正原代码变量名:from_user -> userId
r = requests.post(
    endpoint,
    json=email_msg,
    headers={'Authorization': 'Bearer ' + result['access_token'], "Content-Type": "application/json"}
)

# 检查请求结果
if r.status_code == 202:
    print("邮件发送成功")
else:
    print(f"发送失败,错误信息:{r.text}")

关键注意事项

  • 权限配置:确保你的Azure AD应用已添加Mail.Send应用权限,并完成管理员同意
  • 变量修正:原代码中存在text_message、e_message、from_user等变量名错误,需修正为正确的变量
  • Base64编码:必须使用标准Base64编码(无换行符),base64.b64encode默认符合要求

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 16:30:58