graph API could only access message but not attachments

Yang Liu 20 Reputation points
2025-01-07T19:43:54.7533333+00:00

I am trying to download outlook email attachments through the graph API, I followed the instruction and get a working token:

Step1:

AUTHORITY = f'https://login.microsoftonline.com/{TENANT_ID}'
SCOPES = ['https://graph.microsoft.com/.default']
GRAPH_API_BASE_URL = 'https://graph.microsoft.com/v1.0/'
def authenticate():
    # Authenticate using MSAL
    app = msal.ConfidentialClientApplication(
        client_id=CLIENT_ID,
        client_credential=CLIENT_SECRET,
        authority=AUTHORITY
    )
    result = app.acquire_token_silent(SCOPES, account=None)
    if not result:
        result = app.acquire_token_for_client(scopes=SCOPES)
    #print('success authenticating')
    return result['access_token']

This token allows me to access the emails:

step 2:

query = f"hasAttachments eq true"
response = requests.get(
f'{GRAPH_API_BASE_URL}users/{USER_ID}/mailFolders/{FOLDER_ID}/messages?$filter={query}'
, headers=headers)
data = response.json()

I could get email details as expected.

Step 3:

However, if I try to download or access the attachments, I got 403 error:

headers = {
        'Authorization': f'Bearer {access_token}',
        'Content-Type': 'application/json'
    }
    email_id = email['id']
    response = requests.get(f'{GRAPH_API_BASE_URL}users/{USER_ID}/messages/' + email_id + '/attachments', headers=headers)
    print(response)

The system administrator already grant me all credentials for mail. Any help please? 

Microsoft Graph
Microsoft Graph
A Microsoft programmability model that exposes REST APIs and client libraries to access data on Microsoft 365 services.
12,849 questions
{count} votes

Accepted answer
  1. Yakun Huang-MSFT 9,300 Reputation points Microsoft Vendor
    2025-01-08T06:41:07.5033333+00:00

    Hello Yang Liu,

    Thank you for reaching out to Microsoft Support!

    After our tests, the endpoint works well, and the test results are as follows:

    Screenshot 2025-01-08 063633

    For your error code 403, it may be the lack of token permissions, but what you show in the screenshot is not the permissions that have been granted to the application, the permissions that have been granted to the application are as follows:

    User's image

    To use get Mail attachments, the permission you must add is Mail.Read. Check if you have this permission in the token. You can parse the token using jwt.ms to check if Mail.Read is in the roles attribute.

    Screenshot 2025-01-08 063942

    Reference document:

    https://learn.microsoft.com/en-us/graph/api/message-list-attachments?view=graph-rest-1.0&tabs=http

    Hope this helps.

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

    1 person found this answer helpful.
    0 comments No comments

1 additional answer

Sort by: Most helpful
  1. Saranya Madhu-MSFT 1,160 Reputation points Microsoft Vendor
    2025-01-08T05:32:00.69+00:00

    Hi Yang Liu,

    Thanks for reaching out to Microsoft!

    I tested from my end and am able to get the attachments using the Graph API -GET https://graph.microsoft.com/v1.0/{userid}/messages/{messageid}/attachments

    User's image

    Also getting the raw contents of the attachment if the attachment is a file or Outlook item by appending the path segment /$value to the request URL.

    GET /me/messages/{id}/attachments/{id}/$value

    From the code:

    response = requests.get(f'{GRAPH_API_BASE_URL}users/{USER_ID}/messages/' + email_id + '/attachments', headers=headers)

    Please make sure the endpoint URL is correctly formatted and passed the valid messageId to get the attachment.

    Retrieve a list of attachment objects attached to a message.

    Hope this helps.

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

    0 comments No comments

Your answer

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