最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

python - How do I send email using client credentials flow such that sender's mail is included? - Stack Overflow

programmeradmin9浏览0评论

I created below app to send mail using Graph API

I used Client Credential flow to send mail, but I keep getting 401 error. Is there anything that needs to be changed in the API permission on Azure or in the code? Is there a way I can send mail using delegated access without an interactive session?

import requests
import msal

client_id = 'bdxxx'
tenant_id = '97xxx'
client_secret = 'Ltxxxxxx'
authority = f'/{tenant_id}'
scope = ['/.default']
graph_url = '.0'
sender_email = '[email protected]'

def get_access_token():
    try:
        client = msal.ConfidentialClientApplication(client_id, authority=authority, client_credential=client_secret)

      
        token_result = client.acquire_token_for_client(scopes=scope)
        
        if "access_token" in token_result:
            return f"Bearer {token_result['access_token']}"
        else:
            raise Exception(f"Failed to obtain access token: {token_result}")
        
    except Exception as e:
        print(f"Exception: {e}")
        return None

if __name__ == '__main__':
    access_token = get_access_token()  
    print(f'Access token: {access_token}')
    if not access_token:
        print("Access token retrieval failed. Exiting.")
        exit()

    headers = {
        'Authorization': access_token,
        'Content-Type': 'application/json'
    }

    email_message = {
        "message": {
            "subject": "Test Email",
            "body": {
                "contentType": "HTML",
                "content": "Email body"
            },
            "toRecipients": [
                {
                    "emailAddress": {
                        "address": "[email protected]"
                    }
                }
            ],
              "from": {
                "emailAddress": {
                    "address": '[email protected]'
                }
            }
            
        },
        "saveToSentItems": "false"
    }

    response = requests.post(
        f"{graph_url}/users/{sender_email}/sendMail",
        json=email_message,
        headers=headers
    )
    
    print(f'{response.status_code} {response.text}')

I created below app to send mail using Graph API

I used Client Credential flow to send mail, but I keep getting 401 error. Is there anything that needs to be changed in the API permission on Azure or in the code? Is there a way I can send mail using delegated access without an interactive session?

import requests
import msal

client_id = 'bdxxx'
tenant_id = '97xxx'
client_secret = 'Ltxxxxxx'
authority = f'https://login.microsoftonline/{tenant_id}'
scope = ['https://graph.microsoft/.default']
graph_url = 'https://graph.microsoft/v1.0'
sender_email = '[email protected]'

def get_access_token():
    try:
        client = msal.ConfidentialClientApplication(client_id, authority=authority, client_credential=client_secret)

      
        token_result = client.acquire_token_for_client(scopes=scope)
        
        if "access_token" in token_result:
            return f"Bearer {token_result['access_token']}"
        else:
            raise Exception(f"Failed to obtain access token: {token_result}")
        
    except Exception as e:
        print(f"Exception: {e}")
        return None

if __name__ == '__main__':
    access_token = get_access_token()  
    print(f'Access token: {access_token}')
    if not access_token:
        print("Access token retrieval failed. Exiting.")
        exit()

    headers = {
        'Authorization': access_token,
        'Content-Type': 'application/json'
    }

    email_message = {
        "message": {
            "subject": "Test Email",
            "body": {
                "contentType": "HTML",
                "content": "Email body"
            },
            "toRecipients": [
                {
                    "emailAddress": {
                        "address": "[email protected]"
                    }
                }
            ],
              "from": {
                "emailAddress": {
                    "address": '[email protected]'
                }
            }
            
        },
        "saveToSentItems": "false"
    }

    response = requests.post(
        f"{graph_url}/users/{sender_email}/sendMail",
        json=email_message,
        headers=headers
    )
    
    print(f'{response.status_code} {response.text}')

Share Improve this question asked Mar 27 at 12:13 Lucifer DarknightLucifer Darknight 495 bronze badges 1
  • To resolve the issue you need to assign Mail.Send application type API permission – Rukmini Commented Mar 27 at 12:24
Add a comment  | 

1 Answer 1

Reset to default 1

The error usually occurs if you using ConfidentialClientApplication to send mail and granted delegated type API permission to the Microsoft Entra ID application.

Hence to resolve the error, you need to grant application type API permission to the Microsoft Entra ID application. Refer this MsDoc

Make sure to grant admin consent:

Now I am able to send mail successfully:

import requests
import msal

client_id = 'ClientID'
tenant_id = 'TenantID'
client_secret = 'Secret'
authority = f'https://login.microsoftonline/{tenant_id}'
scope = ['https://graph.microsoft/.default']
graph_url = 'https://graph.microsoft/v1.0'
sender_email = 'xxx'

def get_access_token():
    try:
        client = msal.ConfidentialClientApplication(client_id, authority=authority, client_credential=client_secret)

      
        token_result = client.acquire_token_for_client(scopes=scope)
        
        if "access_token" in token_result:
            return f"Bearer {token_result['access_token']}"
        else:
            raise Exception(f"Failed to obtain access token: {token_result}")
        
    except Exception as e:
        print(f"Exception: {e}")
        return None

if __name__ == '__main__':
    access_token = get_access_token()  
    print(f'Access token: {access_token}')
    if not access_token:
        print("Access token retrieval failed. Exiting.")
        exit()

    headers = {
        'Authorization': access_token,
        'Content-Type': 'application/json'
    }

    email_message = {
        "message": {
            "subject": "Test Email",
            "body": {
                "contentType": "HTML",
                "content": "Email body"
            },
            "toRecipients": [
                {
                    "emailAddress": {
                        "address": "xxx"
                    }
                }
            ],
              "from": {
                "emailAddress": {
                    "address": 'xxx'
                }
            }
            
        },
        "saveToSentItems": "false"
    }

    response = requests.post(
        f"{graph_url}/users/{sender_email}/sendMail",
        json=email_message,
        headers=headers
    )
    
    print(f'{response.status_code} {response.text}')

  • Make sure to assign O365 license to the user.
  • And if you are making use of personal Microsoft user account to send mail, then it required Mail.Send delegated API permission which doesn't work with ConfidentialClientApplication
  • For personal Microsoft user account, you need to make use of /me that is https://graph.microsoft/v1.0/me/sendMail endpoint and make use of any user interactive flow.
发布评论

评论列表(0)

  1. 暂无评论