Search code examples
pythonazuremicrosoft-graph-api

Unable to send email from microsoft graph api


I am trying to send system generated email to users to notify them about change in inventory. But I am unable to do so with client secret login. I get the access token correctly. But email sending fails all the time

import requests
from msal import ConfidentialClientApplication

# Microsoft Graph API endpoints
graph_api_url = "https://graph.microsoft.com/v1.0"
send_mail_url = f"{graph_api_url}/users/admin@example.com/sendMail"

# Azure App credentials
client_id = "YOUR_CLIENT_ID"
client_secret = "YOUR_CLIENT_SECRET"
tenant_id = "YOUR_TENANT_ID"

# Recipient's email address
to_email = "recipient@example.com"

# Construct the email message
subject = "Test Email"
body = {
    "content": f"Hello, this is a test email sent from Python using Microsoft Graph API.",
    "contentType": "Text"
}
message = {
    "message": {
        "subject": subject,
        "body": body,
        "toRecipients": [{"emailAddress": {"address": to_email}}]
    }
}

# Authenticate using Microsoft Graph API
authority = f"https://login.microsoftonline.com/{tenant_id}"
app = ConfidentialClientApplication(client_id, authority=authority, client_credential=client_secret)

token_response = app.acquire_token_for_client(scopes=["https://graph.microsoft.com/.default"])

if "access_token" in token_response:
    access_token = token_response["access_token"]
    headers = {
        "Authorization": f"Bearer {access_token}",
        "Content-Type": "application/json"
    }

    # Send the email
    response = requests.post(send_mail_url, headers=headers, json=message)

    if response.status_code == 202:
        print("Email sent successfully.")
    else:
        print(f"Failed to send email. Status code: {response.status_code}")
else:
    print("Failed to acquire access token.")

Error that I am getting is {"error":{"code":"MailboxNotEnabledForRESTAPI","message":"The mailbox is either inactive, soft-deleted, or is hosted on-premise."}}'


Solution

  • Note that, the error usually occurs if the user does not have valid Office 365 license assigned to them, that is required to send mails.

    I have one user named Demo Sri without having any licenses assigned like below:

    enter image description here

    When I ran your code in my environment with this user mail, I too got same error as below:

    import requests
    from msal import ConfidentialClientApplication
    
    # Microsoft Graph API endpoints
    graph_api_url = "https://graph.microsoft.com/v1.0"
    send_mail_url = f"{graph_api_url}/users/demosri@example.com/sendMail"
    
    # Azure App credentials
    client_id = "YOUR_CLIENT_ID"
    client_secret = "YOUR_CLIENT_SECRET"
    tenant_id = "YOUR_TENANT_ID"
    
    # Recipient's email address
    to_email = "sri@example.com"
    
    # Construct the email message
    subject = "Test Email"
    body = {
        "content": f"Hello, this is a test email sent from Python using Microsoft Graph API.",
        "contentType": "Text"
    }
    message = {
        "message": {
            "subject": subject,
            "body": body,
            "toRecipients": [{"emailAddress": {"address": to_email}}]
        }
    }
    
    # Authenticate using Microsoft Graph API
    authority = f"https://login.microsoftonline.com/{tenant_id}"
    app = ConfidentialClientApplication(client_id, authority=authority, client_credential=client_secret)
    
    token_response = app.acquire_token_for_client(scopes=["https://graph.microsoft.com/.default"])
    
    if "access_token" in token_response:
        access_token = token_response["access_token"]
        headers = {
            "Authorization": f"Bearer {access_token}",
            "Content-Type": "application/json"
        }
    
        # Send the email
        response = requests.post(send_mail_url, headers=headers, json=message)
    
        if response.status_code == 202:
            print("Email sent successfully.")
        else:
            print(f"Failed to send email. Status Message: {response.content}.")
    else:
        print("Failed to acquire access token.")
    

    Response:

    enter image description here

    To resolve the error, you need to assign active Office 365 license to the user like this:

    enter image description here

    When I ran the same code again after assigning license, I got response without any error like this:

    import requests
    from msal import ConfidentialClientApplication
    
    # Microsoft Graph API endpoints
    graph_api_url = "https://graph.microsoft.com/v1.0"
    send_mail_url = f"{graph_api_url}/users/demosri@example.com/sendMail"
    
    # Azure App credentials
    client_id = "YOUR_CLIENT_ID"
    client_secret = "YOUR_CLIENT_SECRET"
    tenant_id = "YOUR_TENANT_ID"
    
    # Recipient's email address
    to_email = "sri@example.com"
    
    # Construct the email message
    subject = "Test Email"
    body = {
        "content": f"Hello, this is a test email sent from Python using Microsoft Graph API.",
        "contentType": "Text"
    }
    message = {
        "message": {
            "subject": subject,
            "body": body,
            "toRecipients": [{"emailAddress": {"address": to_email}}]
        }
    }
    
    # Authenticate using Microsoft Graph API
    authority = f"https://login.microsoftonline.com/{tenant_id}"
    app = ConfidentialClientApplication(client_id, authority=authority, client_credential=client_secret)
    
    token_response = app.acquire_token_for_client(scopes=["https://graph.microsoft.com/.default"])
    
    if "access_token" in token_response:
        access_token = token_response["access_token"]
        headers = {
            "Authorization": f"Bearer {access_token}",
            "Content-Type": "application/json"
        }
    
        # Send the email
        response = requests.post(send_mail_url, headers=headers, json=message)
    
        if response.status_code == 202:
            print("Email sent successfully.")
        else:
            print(f"Failed to send email.Status Message: {response.content}.")
    else:
        print("Failed to acquire access token.")
    

    Response:

    enter image description here

    To confirm that, I checked the same in Sent Items of user where mail sent successfully as below:

    enter image description here