Python SDK for Microsoft Graph API — Mail and SharePoint made simple
Project description
apigraph
Python SDK for Microsoft Graph API — interact with Mail and SharePoint using a clean, simple interface.
Features
- Mail: list folders & subfolders, fetch messages, read content, mark as read, move between folders, create folders.
- SharePoint: list drives, browse items, download files, move items.
- Context manager support (
withstatement handles connect/disconnect automatically). - Structured exceptions (
HttpConnectionError,MailBoxException) for predictable error handling. - Certificate-based authentication via MSAL.
Requirements
- Python ≥ 3.10
- An Azure AD App Registration with:
Mail.Read,Mail.ReadWrite(and/orSites.Read.All,Sites.ReadWrite.Allfor SharePoint) application permissions.- A certificate uploaded to the App Registration.
Installation
pip install apigraph
Or from source:
git clone https://github.com/YOUR_USERNAME/apigraph.git
cd apigraph
pip install -e .
Configuration
Set the following environment variables (copy .env.example as a starting point):
| Variable | Description |
|---|---|
APIGRAPH_CLIENT_ID |
Azure App Registration client ID |
APIGRAPH_TENANT_ID |
Azure tenant ID |
APIGRAPH_CERT_PATH |
Path to the private key PEM file |
APIGRAPH_CERT_THUMBPRINT |
Certificate thumbprint (hex, no colons) |
cp .env.example .env
# edit .env with your values
Quick start
from apigraph import Graphapi
with Graphapi("user@company.com") as api:
# List mail folders
folders = api.fetch_mail_folders()
for f in folders["value"]:
print(f["displayName"], "—", f["id"])
# Fetch unread emails
mails = api.fetch_mails(filter_read_status="unread")
for m in mails["value"]:
print(m["subject"])
# Get full content of an email
content = api.get_mail_content(api.mailbox_email, mails["value"][0]["id"])
# Mark as read
api.mark_as_read(mails["value"][0]["id"])
# Move email to a folder by name
api.move_to_folder_by_name(mails["value"][0]["id"], "Archive")
SharePoint example
from apigraph import Graphapi
SITE_ID = "your-site-id"
DRIVE_ID = "your-drive-id"
with Graphapi("user@company.com") as api:
drives = api.list_sharepoint_drives(SITE_ID)
folder_id = api.get_drive_folder_by_name(DRIVE_ID, "Reports")
items = api.list_drive_items(DRIVE_ID, folder_id)
for item in items:
print(item["name"])
content = api.download_drive_item(DRIVE_ID, items[0]["id"])
API reference
| Method | Description |
|---|---|
fetch_mail_folders() |
List all mail folders |
fetch_mail_subfolders(folder_id) |
List subfolders of a folder |
fetch_all_folders_and_subfolders() |
Full folder tree with IDs |
fetch_mails(filter_read_status) |
Fetch messages (None/"read"/"unread") |
fetch_mails_from_folder(mailbox, folder_id) |
Messages by folder ID |
fetch_mails_from_folder_by_name(folder_name) |
Messages by folder name |
mark_as_read(mail_id) |
Mark a message as read |
move_to_folder_by_name(email_id, folder_name) |
Move message by folder name |
move_to_folder_by_id(email_id, folder_id) |
Move message by folder ID |
create_folder(folder_name) |
Create a mail folder |
create_subfolder(parent_id, name) |
Create a subfolder |
get_mail_content(mailbox, email_id, filter_query) |
Retrieve message content |
get_mail_content_from_folder(folder, field, value) |
Find message by arbitrary field |
get_mail_by_subject(folder_name, subject_text) |
Find message by subject |
fetch_paginated(url) |
Generic paginated Graph request |
list_sharepoint_drives(site_id) |
List drives in a site |
list_sharepoint_drive_items(site_id, drive_id) |
Root items of a drive |
list_drive_items_by_path(site_id, drive_id, path) |
Items at a path |
list_drive_items(drive_id, folder_id) |
Items in a folder (paginated) |
download_drive_item(drive_id, item_id) |
Download file bytes |
get_drive_folder_by_name(drive_id, folder_name) |
Folder ID by name |
move_drive_item(drive_id, item_id, target_folder_id) |
Move a drive item |
Error handling
from apigraph import Graphapi, HttpConnectionError, MailBoxException
try:
with Graphapi("user@company.com") as api:
api.mark_as_read("bad-id")
except MailBoxException as e:
print("Config error:", e.message, e.details)
except HttpConnectionError as e:
print("HTTP error:", e.message, e.status_code, e.details)
Development
pip install -e ".[dev]"
pytest tests/
ruff check src/
License
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
No source distribution files available for this release.See tutorial on generating distribution archives.
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
apigraph-0.1.0-py3-none-any.whl
(39.0 kB
view details)
File details
Details for the file apigraph-0.1.0-py3-none-any.whl.
File metadata
- Download URL: apigraph-0.1.0-py3-none-any.whl
- Upload date:
- Size: 39.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
039cf7e497be1538755b88f1dcdb6dcaa9aa1b6d3e4c89dd7ebf7fd759f02e1c
|
|
| MD5 |
6c908af24ed42db4ba7cb991c512a1de
|
|
| BLAKE2b-256 |
32a7cbd912bd172481d11f740830746962233848fc504ba21639af0ca680c9fc
|