簡體   English   中英

如何使用 Microsoft Graph API 發送 python email.message.EmailMessage

[英]How to send python email.message.EmailMessage with Microsoft Graph API

我們的 web 應用程序通過 python 的 smtplib 發送格式良好的消息(包括一些嵌入的圖像)。 消息是用python的email.message.EmailMessage class生成的,如下代碼所示。

10 月初, Microsoft 在其 Office365 Email 帳戶中棄用了對 Basic Auth的支持。 我們一直在使用 Basic Auth,現在需要找到一個新的解決方案。 努力讓 OAuth2 工作一段時間后,我們決定重構並改用Microsoft Graph API

奇怪的是,盡管 Graph API 站點上的大多數示例都包含多語言(HTTP / C# / Javascript / PHP 等)示例,但用於發送 email 的 MIME 格式(示例 4)只有 8217518 示例 821718

我們想知道是否可以使用圖表 API 發送我們使用 python.email.EmailMessage 構建的 email,如果可以,如何發送。

下面是一些示例代碼,顯示了我們之前所做的以及我們現在正在嘗試獲得的內容。

當我們運行代碼時,我們得到錯誤

'{"error":{"code":"RequestBodyRead","message":"Requested value \'text/plain\' was not found."}}'

import smtplib
from email.utils import formatdate
from email.message import EmailMessage
import requests


server = 'smtp.office365.com'  # for exampler
port = 587  # for example
from_mail = 'levrai@ninjane.er'
to_mail = 'desti@nati.on'
subject = 'Demo sending the old way!'
password = 'not_so_Secur3!'

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

# the below function builds up the nice message based on an html template
text_msg, html_msg, cids, locs = doc_mail_from_template(message_parts)  

msg = EmailMessage()
msg.set_content(text_message)
msg.add_alternative(html_msg, subtype='html')
msg['From'] = from_mail
msg['To'] = to_mail
msg['Date'] = formatdate(localtime=True)
msg['Subject'] = subject

# now embed images to the email
for loc, cid in zip(locs, cids):
    with open(loc, 'rb') as img:
        maintype, subtype = guess_type(img.name)[0].split('/')  # know the Content-Type of the image
        msg.get_payload()[1].add_related(img.read(), maintype=maintype, subtype=subtype, cid=cid) # attach it


if date_now < '2022-10-01':   # before, we could do this
    with smtplib.SMTP(server, port) as smtp:
        smtp.starttls(context=context)
        smtp.login(from_mail, password)
        smtp.sendmail(from_mail, [to_mail, ], msg.as_string())
        
else:  # now we must do this
    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)
    
    # setup message:
    email_msg = {'Message': {'Subject': subject,
                             'Body': {
                                 'ContentType': 'text/plain', 'Content': e_message.as_string() },   # what do i put here?
                             'ToRecipients': [{'EmailAddress': {'Address': to_mail}}]
                             },
                'SaveToSentItems': 'true'}
    endpoint = f'https://graph.microsoft.com/v1.0/users/{from_user}/sendMail'
    r = requests.post(endpoint, json=email_msg,
                      headers={'Authorization': 'Bearer ' + result['access_token'], "Content-Type": "application/json"})

您似乎在使用 Graph 作為 JSON 消息發送的示例與作為 MIME 消息發送混合在一起。 作為 MIME 發送有一些限制,例如您的 email 必須小於 4 mb(或者因為 MIME 膨脹 2.5-3 mb)。 您需要確保對消息進行正確編碼,但在從 EmailMessage 構建的 phython 中,以下內容對我來說沒問題。 (微軟方面的解析器可能有點限制,所以從簡單的格式開始,看看是否有效,然后增加消息的復雜性)。

例如

 from email.message import EmailMessage import base64 import sys import json import logging import msal import requests config = { "authority": "https://login.microsoftonline.com/eb8db77e-65e0-4fc3-b967-.......", "client_id": "18bb3888-dad0-4997-96b1-.........", "scope": ["https://graph.microsoft.com/.default"], "secret": ".............", "tenant-id": "eb8db77e-65e0-4fc3-b967-........" } app = msal.ConfidentialClientApplication(config['client_id'], authority=config['authority'], client_credential=config['secret']) result = app.acquire_token_silent(config["scope"], account=None) if not result: logging.info("No suitable token exists in cache. Let's get a new one from AAD.") result = app.acquire_token_for_client(scopes=config["scope"]) sender_email = "gscales@gbbbbb.onmicrosoft.com" receiver_email = "gscales@ccccc.onmicrosoft.com" def create_message(sender, to, subject, message_text): message = EmailMessage() message.set_content(message_text) message['to'] = to message['from'] = sender message['subject'] = subject raw = base64.urlsafe_b64encode(message.as_bytes()) return raw.decode() messageToSend = create_message(sender_email,receiver_email,"test subject","test 123") print(messageToSend) endpoint = f'https://graph.microsoft.com/v1.0/users/{sender_email}/sendMail' r = requests.post(endpoint, data=messageToSend, headers={'Authorization': 'Bearer ' + result['access_token'], "Content-Type": "text/plain"}) print(r.status_code) print(r.text)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM