Microsoft Graph Python SDK

repository·main·Indexed 20 days ago

https://github.com/microsoftgraph/msgraph-sdk-python

A high-level, asynchronous interface for interacting with the Microsoft Graph API to manage users, groups, and other Microsoft 365 data. The SDK supports Python 3.10+ and integrates with azure.identity for application and delegated authentication flows, including ClientSecretCredential, DeviceCodeCredential, and InteractiveBrowserCredential. It provides a GraphServiceClient for making requests, handling pagination via odata_next_link, and managing API errors with APIError.

Tokens
12.4K
Snippets
43
Records
46
Agent score
70%

What's inside msgraph-sdk

  1. Select an authentication provider

    main

    The SDK supports both sync and async credential classes from azure.identity. Your choice depends on the permission type required:

    Application Permissions

    Used for daemon apps or background tasks without a signed-in user. Use azure.identity.aio.ClientSecretCredential for async application access.

    Delegated Permissions (Scopes)

    Used when an app requires a user to log in and interact with their own data. Common libraries include:

    • DeviceCodeCredential: For environments where authentication is triggered on one machine and completed on another (e.g., cloud servers).
    • InteractiveBrowserCredential: For environments with a browser where the user enters credentials manually.
    • AuthorizationCodeCredentials: For custom client applications where the frontend calls the backend.
  2. Use the Fluent Request Builder Pattern

    main

    The msgraph-sdk replaces raw URL strings used in msgraph-core with a fluent interface. This allows for method chaining and IDE autocomplete to navigate the Microsoft Graph resource hierarchy. Note that all requests return a coroutine and must be awaited or run in an async loop.

    # msgraph-core (Legacy)
    resp = client.get('/users/userId/messages')
    
    # msgraph-sdk (New)
    req = client.users.by_user_id('userId').messages.get()
    resp = asyncio.run(req)
  3. Initialize the GraphServiceClient

    main

    To use the Microsoft Graph SDK, you must first create a credential object using azure.identity and then pass it to the GraphServiceClient.

    For application-level access (daemon services), use ClientSecretCredential. For user-level access or local development, you can use AzureCliCredential (requires az login to be performed beforehand).

    import asyncio
    from azure.identity import ClientSecretCredential
    from msgraph import GraphServiceClient
    
    # Create a credential object
    credential = ClientSecretCredential(
        tenant_id='TENANT_ID',
        client_id='CLIENT_ID',
        client_secret='CLIENT_SECRET'
    )
    scopes = ['https://graph.microsoft.com/.default']
    
    # Create the API client
    client = GraphServiceClient(credentials=credential, scopes=scopes)
  4. Upgrade from msgraph-core to msgraph-sdk

    main

    If you are migrating from the legacy msgraph-core package to the modern msgraph-sdk, note that the SDK introduces a fluent request builder pattern, strongly typed model classes, and requires an asynchronous execution environment. The SDK is built on the Kiota client generator and targets the Microsoft Graph v1.0 API.

    # msgraph-core
    pip install msgraph-core
    
    # msgraph-sdk
    pip install msgraph-sdk
  5. Send Mail with User Delegation

    main

    To send an email as the signed-in user, construct a SendMailPostRequestBody containing a Message object. The Message object requires fields like subject, from_, to_recipients, and body (an ItemBody).

    Setup Requirements:

    1. App Registration: Platform: Mobile and desktop applications with redirect_uri (e.g., http://localhost) and public client flow enabled.
    2. API Permissions: Mail.Send.
    import asyncio
    from msgraph import GraphServiceClient
    from msgraph.generated.users.item.send_mail.send_mail_post_request_body import SendMailPostRequestBody
    from msgraph.generated.models.body_type import BodyType
    from msgraph.generated.models.message import Message
    from msgraph.generated.models.email_address import EmailAddress
    from msgraph.generated.models.item_body import ItemBody
    from msgraph.generated.models.recipient import Recipient
    from azure.identity import InteractiveBrowserCredential
    
    # Setup credentials
    credential = InteractiveBrowserCredential(client_id='...', authority='...', tenant_id='...', redirect_uri='...')
    scopes = ['Mail.Send']
    client = GraphServiceClient(credentials=credential, scopes=scopes)
    
    async def send_mail():
        sender = EmailAddress(address='john.doe@outlook.com', name='John Doe')
        
        from_recipient = Recipient(email_address=sender)
        recipients = []
    
        recipient_email = EmailAddress(address='jane.doe@outlook.com', name='Jane Doe')
        recipients.append(Recipient(email_address=recipient_email))
    
        email_body = ItemBody(content='Dummy content', content_type=BodyType.Text)
        
        message = Message(
            subject='Test Email',
            from_escaped=from_recipient,
            to_recipients=recipients,
            body=email_body
        )
        
        request_body = SendMailPostRequestBody(message=message)
        await client.me.send_mail.post(request_body)
    
    asyncio.run(send_mail())
  6. Handle pagination with odata_next_link

    main

    By default, the SDK returns a maximum of 100 rows. If more data is available, the response will contain an odata_next_link. Use the .with_url() method to fetch subsequent batches.

    # Initial request
    members = await client.groups.by_group_id(group_id).members.get()
    
    # Iterate over result batches using odata_next_link
    while members is not None and members.odata_next_link is not None:
        members = await client.groups.by_group_id(group_id).members.with_url(members.odata_next_link).get()
        if members:
            for member in members.value:
                print(member.display_name)
  7. Initialize the GraphServiceClient with ClientSecretCredential

    main

    To use the Microsoft Graph SDK, you must first create a credential object using azure.identity and then initialize the GraphServiceClient. For application-level access (client credentials flow), use ClientSecretCredential with your tenant_id, client_id, and client_secret. You must also define the scopes, typically using the default Graph scope: ['https://graph.microsoft.com/.default'].

    import asyncio
    from azure.identity import ClientSecretCredential
    from msgraph import GraphServiceClient
    
    # Create a credential object. Used to authenticate requests
    credential = ClientSecretCredential(
        tenant_id='TENANT_ID',
        client_id='CLIENT_ID',
        client_secret='CLIENT_SECRET',
    )
    scopes = ['https://graph.microsoft.com/.default']
    
    # Create an API client with the credentials and scopes
    client = GraphServiceClient(credentials=credential, scopes=scopes)
  8. Create a default GraphServiceClient

    main

    To create a default Microsoft Graph client, provide an authentication credential (from azure.identity) and the required scopes to the GraphServiceClient constructor. This client uses https://graph.microsoft.com as the base URL and a default HTTPX client.

    from azure.identity import AuthorizationCodeCredential
    from msgraph import GraphServiceClient
    
    credentials = AuthorizationCodeCredential(
        tenant_id='your_tenant_id',
        client_id='your_client_id',
        authorization_code='your_auth_code',
        redirect_uri='your_redirect_uri'
    )
    scopes = ['User.Read', 'Mail.ReadWrite']
    client = GraphServiceClient(credentials=credentials, scopes=scopes)
  9. Configure Authentication with AzureIdentityAuthenticationProvider

    main

    The msgraph-sdk uses an AuthenticationProvider to manage token lifecycle (fetching, caching, and refreshing). You should use the AzureIdentityAuthenticationProvider from the kiota-authentication-azure package, which requires an asynchronous credential from azure.identity.aio.

    # msgraph-sdk approach
    from azure.identity.aio import ClientSecretCredential
    from kiota_authentication_azure.azure_identity_authentication_provider import AzureIdentityAuthenticationProvider
    
    credential = ClientSecretCredential(tenant_id='...', client_id='...', client_secret='...')
    auth_provider = AzureIdentityAuthenticationProvider(credential)
  10. Create a Graph client with a custom httpx.AsyncClient

    main

    If you need to provide a custom HTTP client (e.g., for custom proxy settings or timeouts), use GraphClientFactory to create an adapter and pass it to the GraphServiceClient.

    import httpx
    from msgraph import GraphRequestAdapter
    from msgraph_core import GraphClientFactory
    
    # Assuming auth_provider is already defined
    http_client = GraphClientFactory.create_with_default_middleware(client=httpx.AsyncClient())
    request_adapter = GraphRequestAdapter(auth_provider, http_client)
    client = GraphServiceClient(request_adapter=request_adapter)
  11. Send Mail from a Shared Mailbox

    main

    To send an email from a shared mailbox using the user's delegation, you must set the from_ property of the Message to the shared mailbox address and include the sender in the sender property.

    Setup Requirements:

    1. API Permissions: Mail.Send.Shared.
    2. The user must have access to the shared mailbox.
    import asyncio
    from msgraph import GraphServiceClient
    from msgraph.generated.models.body_type import BodyType
    from msgraph.generated.models.message import Message
    from msgraph.generated.models.email_address import EmailAddress
    from msgraph.generated.models.item_body import ItemBody
    from msgraph.generated.models.recipient import Recipient
    from msgraph.generated.users.item.send_mail.send_mail_post_request_body import SendMailPostRequestBody
    from azure.identity import InteractiveBrowserCredential
    
    credential = InteractiveBrowserCredential(client_id='...', authority='...', tenant_id='...', redirect_uri='...')
    scopes = ["Mail.Send.Shared"]
    client = GraphServiceClient(credentials=credential, scopes=scopes)
    
    async def send_mail():
        sender = EmailAddress(address='john.doe@outlook.com')
        sender_recipient = Recipient(email_address=sender)
    
        from_mailbox = EmailAddress(address='your-shared-mailbox@outlook.com')
        from_recipient = Recipient(email_address=from_mailbox)
    
        recipients = [Recipient(email_address=EmailAddress(address='jane.doe@outlook.com', name='Jane Doe'))]
    
        email_body = ItemBody(content='Dummy content', content_type=BodyType.Text)
        
        message = Message(
            subject='Test Email',
            sender=sender_recipient,
            from_=from_recipient,
            to_recipients=recipients,
            body=email_body
        )
    
        request_body = SendMailPostRequestBody(message=message)
        await client.me.send_mail.post(request_body)
    
    asyncio.run(send_mail())