简体   繁体   English

"使用 Microsoft Graph API 的 SendMail 请求时出现“BadRequest”错误"

[英]"BadRequest" error while using SendMail request of Microsoft Graph API

I am writing a python script to send a mail using the Microsoft Graph API.我正在编写一个 python 脚本来使用 Microsoft Graph API 发送邮件。 The mail is sent to only those IDs which exists in our AAD.邮件仅发送到我们 AAD 中存在的那些 ID。

I wrote the code:我写了代码:

from adal import AuthenticationContext
import adal
import string
import urllib
import json
import requests
import pprint
import base64
import mimetypes

API_VERSION = 'beta'
RESOURCE = 'https://graph.microsoft.com'
TENANT = <my tenant ID>
CLIENTID = <Client ID>
CLIENTSECRET = <sescret>
DOMAIN = <mydomain>

# AUTHENTICATION - get access token and update session header
def get_session():

    authority_host_url = 'https://login.windows.net'
    tenant = TENANT
    authority_url = authority_host_url + '/' + tenant
    service_endpoint = "https://graph.microsoft.com/"

    client_id = CLIENTID
    client_secret = CLIENTSECRET


    # Retrieves authentication tokens from Azure Active Directory and creates a new AuthenticationContext object.
    context = AuthenticationContext(authority_url, validate_authority=True, cache=None, api_version=None, timeout=300, enable_pii=False)
    # Gets a token for a given resource via client credentials.
    token_response = context.acquire_token_with_client_credentials(service_endpoint, client_id, client_secret)

    # Create a persistent session with the access token
    session = requests.Session()
    session.headers.update({'Authorization': f'Bearer {token_response["accessToken"]}', 'SdkVersion': 'python-adal', 'x-client-SKU': 'DynaAdmin'})
    #session.headers.update({'Authorization': f'Bearer {token_response["accessToken"]}'})

    return session

def build_uri(url):
    if 'https' == urllib.parse.urlparse(url).scheme:
        return url
    result = urllib.parse.urljoin(f'{RESOURCE}/{API_VERSION}/', url.lstrip('/'))

    print("\nURL:\n")
    print(result)

    return result

def sendmail(*, session, subject=None, recipients=None, body='',
             content_type='HTML', attachments=None):
    """Helper to send email from current user.

    session       = user-authenticated session for graph API
    subject      = email subject (required)
    recipients   = list of recipient email addresses (required)
    body         = body of the message
    content_type = content type (default is 'HTML')
    attachments  = list of file attachments (local filenames)

    Returns the response from the POST to the sendmail API.
    """

    # Verify that required arguments have been passed.
    if not all([session, subject, recipients]):
        raise ValueError('sendmail(): required arguments missing')

    # Create recipient list in required format.
    recipient_list = [{'EmailAddress': {'Address': address}}
                      for address in recipients]

    # Create list of attachments in required format.
    attached_files = []
    if attachments:
        for filename in attachments:
            b64_content = base64.b64encode(open(filename, 'rb').read())
            mime_type = mimetypes.guess_type(filename)[0]
            mime_type = mime_type if mime_type else ''
            attached_files.append( \
                {'@odata.type': '#microsoft.graph.fileAttachment',
                 'ContentBytes': b64_content.decode('utf-8'),
                 'ContentType': mime_type,
                 'Name': filename})

    # Create email message in required format.
    email_msg = {'Message': {'Subject': subject,
                             'Body': {'ContentType': content_type, 'Content': body},
                             'ToRecipients': recipient_list,
                             'Attachments': attached_files},
                 'SaveToSentItems': 'true'}

    print("\nBody:\n")              
    print(email_msg)    

    # Do a POST to Graph's sendMail API and return the response.
    resp = session.post(build_uri('/users/8368b7b5-b337ac267220/sendMail'), data=email_msg, stream=True, headers={'Content-Type': 'application/json'})

    return resp

# ------------ RUN CODE ------------

session = get_session()

myRecipients = "sea.chen@mydomain.com;anj.dy@mydomain.com"
response = sendmail(session=session,
                    subject= "hai",
                    recipients=myRecipients.split(';'),
                    body="hai this is a new mail")

print("\nRequest headers: \n")
print(response.request.headers)

print("\nResponse: \n")
print(response) 
print(response.text) 

Most likely the body of your POST is not properly formatted. POST正文很可能格式不正确。 When I did this with the requests library, I found I needed to set data like so: 当我使用requests库进行此操作时,我发现需要像这样设置data

data = json.dumps(email_msg)

The default for data is to form-encode, not pass as JSON. data的默认值是表单编码,而不是作为JSON传递。 Have a look at https://docs.microsoft.com/outlook/rest/python-tutorial#contents-of-tutorialoutlookservicepy 看看https://docs.microsoft.com/outlook/rest/python-tutorial#contents-of-tutorialoutlookservicepy

Thanks for sharing this.谢谢你分享这个。 I had different issue when I was trying to get Graph API to send one-on-one chat message to Microsoft Teams.当我尝试让 Graph API 向 Microsoft Teams 发送一对一聊天消息时,我遇到了不同的问题。 I could run the following code using http.client and get most of the messages posted in chat.我可以使用 http.client 运行以下代码并获取聊天中发布的大部分消息。

import http.client
headers = {'Content-type':'application/json',
            "Authorization": f"Bearer {getGraphAccessToken()}"
        }
  
body = {
       "body": {
          "contentType": "text",
         "charset" : "utf-8",
          "content": text
  }}

  connection = http.client.HTTPSConnection("graph.microsoft.com")
  connection.request("POST",f"/v1.0/chats/{chatId}/messages",headers=headers, body = str(body))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM