Search code examples
pythonazuremicrosoft-graph-apioffice365microsoft-graph-mail

Python send email using Graph API and Office365-REST-Python-Client


I am trying to send an email using Graph API and Python. I tried doing it with graph explorer and it worked. I found this example: https://github.com/vgrem/Office365-REST-Python-Client#working-with-outlook-api

from office365.graph_client import GraphClient

client = GraphClient(acquire_token_func)

client.me.send_mail(
    subject="Meet for lunch?",
    body="The new cafeteria is open.",
    to_recipients=["[email protected]"]
).execute_query()

Here's my code:

import msal

dict_ = {'client_id': 'foo', 'secret': 'bar', 'tenant_id': 'etc'}

def acquire_token():
    authority_url = f'https://login.microsoftonline.com/{dict_["tenant_id"]}'
    app = msal.ConfidentialClientApplication(
        authority=authority_url,
        client_id=dict_["client_id"],
        client_credential=dict_["secret"]
    )
    token = app.acquire_token_for_client(scopes=["https://graph.microsoft.com/.default"])
    return token


from office365.graph_client import GraphClient

client = GraphClient(acquire_token)

client.me.send_mail(
    subject="Meet for lunch?",
    body="The new cafeteria is open.",
    to_recipients=['[email protected]']
).execute_query()

Even though it's exactly like in the example I still get:

TypeError: send_mail() got an unexpected keyword argument 'subject'

Can you help me fix this or provide a different way of sending an email?


Solution

  • I agree with @user2250152, you need to change /me endpoint to client.users[<mail>].send_mail as you are using client credentials flow to get token.

    I registered one Azure AD application and granted Mail.Send permission of Application type:

    enter image description here

    In my case, I used below modified code to send an email using Graph API and Python:

    import msal
    import requests;
    
    dict_ = {'client_id': 'appId', 'secret': 'secret', 'tenant_id': 'tenantId'}
    
    def acquire_token():
        authority_url = f'https://login.microsoftonline.com/{dict_["tenant_id"]}'
        app = msal.ConfidentialClientApplication(
            authority=authority_url,
            client_id=dict_["client_id"],
            client_credential=dict_["secret"]
        )
        token = app.acquire_token_for_client(scopes=["https://graph.microsoft.com/.default"])
        return token
    
    result = acquire_token()
    
    if "access_token" in result:
        print("Access token created.",result["access_token"])
    
    if "access_token" in result:
        endpoint = f'https://graph.microsoft.com/v1.0/users/userId/sendMail'
        toUserEmail = "[email protected]"  
        email_msg = {'Message': {'Subject': "Meet for lunch?",
                                'Body': {'ContentType': 'Text', 'Content': "The new cafeteria is open."},
                                '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())
    

    Response:

    enter image description here

    To confirm that, I checked the Sent Items where email sent successfully like below:

    enter image description here

    Reference: python - Microsoft Graph API's "Access is denied. Check credentials and try again" - Stack Overflow by me