MCPcopy
hub / github.com/O365/python-o365

github.com/O365/python-o365 @v2.1 sqlite

repository ↗ · DeepWiki ↗ · release v2.1 ↗
1,679 symbols 5,010 edges 58 files 859 documented · 51%
README

Downloads PyPI PyPI pyversions Build Status

O365 - Microsoft Graph and Office 365 API made easy

Detailed usage documentation is still in progress

[!IMPORTANT] With version 2.1 old access tokens will not work and the library will require a new authentication flow to get new access and refresh tokens.

This project aims to make interacting with Microsoft Graph and Office 365 easy to do in a Pythonic way. Access to Email, Calendar, Contacts, OneDrive, etc. Are easy to do in a way that feel easy and straight forward to beginners and feels just right to seasoned python programmer.

The project is currently developed and maintained by alejcas.

Core developers

We are always open to new pull requests!

Rebuilding HTML Docs

  • Install sphinx python library

    pip install sphinx==2.2.2

  • Run the shell script build_docs.sh, or copy the command from the file when using on windows

Quick example on sending a message:

from O365 import Account

credentials = ('client_id', 'client_secret')

account = Account(credentials)
m = account.new_message()
m.to.add('to_example@example.com')
m.subject = 'Testing!'
m.body = "George Best quote: I've stopped drinking, but only while I'm asleep."
m.send()

Why choose O365?

  • Almost Full Support for MsGraph and Office 365 Rest Api.
  • Good Abstraction layer between each Api. Change the api (Graph vs Office365) and don't worry about the api internal implementation.
  • Full oauth support with automatic handling of refresh tokens.
  • Automatic handling between local datetimes and server datetimes. Work with your local datetime and let this library do the rest.
  • Change between different resource with ease: access shared mailboxes, other users resources, SharePoint resources, etc.
  • Pagination support through a custom iterator that handles future requests automatically. Request Infinite items!
  • A query helper to help you build custom OData queries (filter, order, select and search).
  • Modular ApiComponents can be created and built to achieve further functionality.

This project was also a learning resource for us. This is a list of not so common python idioms used in this project: - New unpacking technics: def method(argument, *, with_name=None, **other_params): - Enums: from enum import Enum - Factory paradigm - Package organization - Timezone conversion and timezone aware datetimes - Etc. (see the code!)

What follows is kind of a wiki...

Table of contents

Install

O365 is available on pypi.org. Simply run pip install O365 to install it.

Requirements: >= Python 3.9

Project dependencies installed by pip: - requests - msal - beatifulsoup4 - python-dateutil - tzlocal - tzdata

Usage

The first step to be able to work with this library is to register an application and retrieve the auth token. See Authentication.

With the access token retrieved and stored you will be able to perform api calls to the service.

A common pattern to check for authentication and use the library is this one:

scopes = ['my_required_scopes']  # you can use scope helpers here (see Permissions and Scopes section)

account = Account(credentials)

if not account.is_authenticated:  # will check if there is a token and has not expired
    # ask for a login using console based authentication. See Authentication for other flows
    if account.authenticate(scopes=scopes) is False:
        raise RuntimeError('Authentication Failed')

# now we are authenticated
# use the library from now on

# ...

Authentication

You can only authenticate using oauth authentication because Microsoft deprecated basic auth on November 1st 2018.

[!IMPORTANT] Until version 2.1 this library was using a custom authentication mechanism. On 2.1 we moved to using msal to achieve the authentication.

There are currently three authentication methods:

  • Authenticate on behalf of a user: Any user will give consent to the app to access its resources. This oauth flow is called authorization code grant flow. This is the default authentication method used by this library.
  • Authenticate on behalf of a user (public): Same as the former but for public apps where the client secret can't be secured. Client secret is not required.
  • Authenticate with your own identity: This will use your own identity (the app identity). This oauth flow is called client credentials grant flow.

    [!NOTE] 'Authenticate with your own identity' is not an allowed method for Microsoft Personal accounts.

When to use one or the other and requirements:

Topic On behalf of a user (auth_flow_type=='authorization') On behalf of a user (public) (auth_flow_type=='public') With your own identity (auth_flow_type=='credentials')
Register the App Required Required Required
Requires Admin Consent Only on certain advanced permissions Only on certain advanced permissions Yes, for everything
App Permission Type Delegated Permissions (on behalf of the user) Delegated Permissions (on behalf of the user) Application Permissions
Auth requirements Client Id, Client Secret, Authorization Code Client Id, Authorization Code Client Id, Client Secret
Authentication 2 step authentication with user consent 2 step authentication with user consent 1 step authentication
Auth Scopes Required Required None
Token Expiration 60 Minutes without refresh token or 90 days* 60 Minutes without refresh token or 90 days* 60 Minutes*
Login Expiration Unlimited if there is a refresh token and as long as a refresh is done within the 90 days Unlimited if there is a refresh token and as long as a refresh is done within the 90 days Unlimited
Resources Access the user resources, and any shared resources Access the user resources, and any shared resources All Azure AD users the app has access to
Microsoft Account Type Any Any Not Allowed for Personal Accounts
Tenant ID Required Defaults to "common" Defaults to "common" Required (can't be "common")

*O365 will automatically refresh the token for you on either authentication method. The refresh token lasts 90 days but it's refreshed on each connection so as long as you connect within 90 days you can have unlimited access.

The Connection Class handles the authentication.

With auth_flow_type 'credentials' you can authenticate using a certificate based authentication by just passing the client_secret like so:

client_secret = {
    "thumbprint": <thumbprint of cert file>,
    "private_key": <private key from the private_key_file>
 }
credentials = client_id, client_secret
account = Account(credentials)

Oauth Authentication

This section is explained using Microsoft Graph Protocol, almost the same applies to the Office 365 REST API.

Authentication Steps
  1. Log in to the Microsoft Entra Admin Center
  2. Visit https://entra.microsoft.com/ and sign in.

  3. Create a new application and note its App (client) ID

  4. In the left navigation bar, select Applications > App registrations.
  5. Click + New registration.
  6. Provide a Name for the application and keep all defaults.
  7. From the Overview of your new application, copy the (client_id) Application (client) ID for later reference.

  8. Generate a new password (client_secret)

  9. In the Overview window, select Certificates & secrets.
  10. Click New client secret.
  11. In the Add a client secret window, provide a Description and Expiration, then click Add.
  12. Save the (client_secret) Value for later reference.

  13. Add redirect URIs and set Multitenant Account Type

  14. In the Overview window, click Add a redirect URI.
  15. Click + Add a platform, then select Web.
  16. Add https://login.microsoftonline.com/common/oauth2/nativeclient as the redirect URI.
  17. Scroll down to Supported account types
  18. Select the radio button in front of Accounts in any organizational directory (Any Microsoft Entra ID tenant - Multitenant)
  19. Click Save.

  20. Add required permissions

  21. In the left navigation bar, select API permissions.
  22. Click + Add a permission.
  23. Under Microsoft Graph, select Delegated permissions.
  24. Add the delegated permissions you plan to use (for example):
    • Mail.Read
    • Mail.ReadWrite
    • Mail.Send
    • User.Read
    • User.ReadBasic.All
    • offline_access
  25. Click Add permissions.

[!IMPORTANT] The offline_access permission is required for the refresh token to work.

  1. Then you need to log in for the first time to get the access token that will grant access to the user resources.

    To authenticate (login) you can use different authentication interfaces. On the following examples we will be using the Console Based Interface, but you can use any one.

    • When authenticating on behalf of a user:

[!IMPORTANT] In case you can't secure the client secret you can use the auth flow type 'public' which only requires the client id.

    1. Instantiate an `Account` object with the credentials (client id and client secret).
    1. Call `account.authenticate` and pass the scopes you want (the ones you previously added on the app registration portal).

        > Note: when using the "on behalf of a user" authentication, you can pass the scopes to either the `Account` init or to the authenticate method. Either way is correct.

        You can pass "protocol scopes" (like: "https://graph.microsoft.com/Calendars.ReadWrite") to the method or use "[scope helpers](https://github.com/O365/python-o365/blob/master/O365/connection.py#L34)" like ("message_all").
        If you pass protocol scopes, then the `account` instance must be initialized with the same protocol used by the scopes. By using scope helpers you can abstract the protocol from the scopes and let this library work for you.
        Finally, you can mix and match "protocol scopes" with "scope helpers".
        Go to the [procotol section](#protocols) to know more about them.

        For Example (following the previous permissions added):

        ```python
        from O365 import Account
        credentials = ('my_client_id', 'my_client_secret')

        # the default protocol will be Microsoft Graph
        # the default authentication method will be "on behalf of a user"

        account = Account(credentials)
        if account.authenticate(scopes=['basic', 'message_all']):
           print('Authenticated!')

        # 'basic' adds: 'https://graph.microsoft.com/User.Read'
        # 'message_all' adds: 'https://graph.microsoft.com/Mail.ReadWrite' and 'https://graph.microsoft.com/Mail.Send'
        ```
        When using the "on behalf of the user" authentication method, this method call will print an url that the user must visit to give consent to the app on the required permissions.

        The user must then visit this url and give consent to the application. When consent is given, the page will rediret to: "https://login.microsoftonline.com/common/oauth2/nativeclient" by default (you can change this) with an url query param called 'code'.

        Then the user must copy the resulting page url and paste it back on the console.
        The method will then return True if the login attempt was succesful.

- When authenticating

Core symbols most depended-on inside this repo

get
called by 1188
O365/connection.py
_cc
called by 397
O365/utils/utils.py
build_url
called by 291
O365/utils/utils.py
get
called by 189
O365/excel.py
add
called by 141
O365/calendar.py
$
called by 50
docs/latest/_static/jquery.js
jQuery
called by 46
docs/latest/_static/jquery-3.4.1.js
m
called by 41
docs/latest/_static/jquery.js

Shape

Method 1,104
Function 424
Class 146
Route 5

Languages

Python77%
TypeScript23%

Modules by API surface

O365/excel.py175 symbols
O365/calendar.py120 symbols
docs/latest/_static/jquery-3.5.1.js112 symbols
docs/latest/_static/jquery-3.4.1.js112 symbols
O365/utils/utils.py104 symbols
O365/drive.py84 symbols
docs/latest/_static/jquery.js83 symbols
O365/utils/token.py77 symbols
O365/message.py73 symbols
O365/teams.py65 symbols
O365/address_book.py54 symbols
O365/mailbox.py53 symbols

Dependencies from manifests, versioned

Click7.0 · 1×
beautifulsoup44.0.0 · 1×
msal1.31.1 · 1×
pytest3.9.0 · 1×
python-dateutil2.7 · 1×
requests2.32.0 · 1×
twine1.12.0 · 1×
tzdata2023.4 · 1×
tzlocal5.0 · 1×
wheel0.32.0 · 1×

For agents

$ claude mcp add python-o365 \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact