Python code using MSAL is failing to recognise my free Outlook email account

Grant Rule 20 Reputation points
2024-07-11T08:09:57.2333333+00:00

I'm using Python code with MSAL to read emails from my free Outlook account. I have set up Apps in Azure and correctly added permissions and granted admin access, etc. When I use the App that has delegated permissions using app.acquire_token_for_client it works as expected. However, when I use the App with application permissions using ConfidentialClientApplication, authentication fails. What could be the problem? Is it because I am using free Outlook and Azure accounts. All my research on-line indicates it should be possible.

The App permissions are as follows

User's image

My Python code is below. When I run it I get:

Access token acquired successfully.

Failed to retrieve emails.

Status Code: 404

Response: {'error': {'code': 'ErrorInvalidUser', 'message': "The requested user '####@hotmail.com' is invalid."}}

from msal import ConfidentialClientApplication

import requests

# Replace with your own email address
user_email = "####@hotmail.com"

client_id = '#####################################'
client_secret = '###############################'
tenant_id = '###################################'

authority = f"https://login.microsoftonline.com/{tenant_id}"

# Acquire the access token
app = ConfidentialClientApplication(
    client_id,
    authority=authority,
    client_credential=client_secret
)

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

if "access_token" in result:
    access_token = result["access_token"]
    print("Access token acquired successfully.")
else:
    print("Failed to acquire token.")
    print(result.get("error"))
    print(result.get("error_description"))
    print(result.get("correlation_id"))  # You might need this when reporting a bug
    exit()

# Make a request to the Microsoft Graph API to get the user's emails
headers = {
    'Authorization': f'Bearer {access_token}',
    'Content-Type': 'application/json'
}

# Correct the endpoint URL by using /users/{user_email}/mailFolders/inbox/messages
endpoint = f'https://graph.microsoft.com/v1.0/users/{user_email}/mailFolders/inbox/messages'

response = requests.get(endpoint, headers=headers)

if response.status_code == 200:
    emails = response.json().get('value', [])
    print(f"Found {len(emails)} emails in the inbox.")
    for email in emails:
        print(f"Subject: {email['subject']}")
        print(f"From: {email['from']['emailAddress']['address']}")
        print(f"Received: {email['receivedDateTime']}")
        print("----")
else:
    print("Failed to retrieve emails.")
    print(f"Status Code: {response.status_code}")
    print(f"Response: {response.json()}")
Outlook | Windows | Classic Outlook for Windows | For business
Microsoft Security | Microsoft Entra | Microsoft Entra ID
Microsoft Security | Microsoft Graph
{count} votes

Answer accepted by question author
  1. CarlZhao-MSFT 46,406 Reputation points
    2024-07-12T06:49:03.5866667+00:00

    Hi @Grant Rule

    You cannot use application permissions to retrieve emails for personal or guest users because these users do not have mailboxes available in your tenant, their mailboxes exist in their home tenant. Therefore, you can only log these users into your multi-tenant application and call the /me/mailFolders/inbox/messages endpoint to retrieve emails in their home tenant.

    Hope this helps.

    If the reply is helpful, please click Accept Answer and kindly upvote it. If you have additional questions about this answer, please click Comment.


0 additional answers

Sort by: Most helpful

Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.