Phuriwaj

O365 Python — OAuth2 Email Summary to Microsoft Teams

Script pattern for reading Microsoft 365 emails via OAuth2 (O365 library) and posting a Claude-summarised digest to a Teams channel as an Adaptive Card.

Why / When to Use

  • Daily email digest automation without Basic Auth (deprecated by Microsoft in 2022)
  • Summarise inbox to Teams channel on a schedule
  • Works with any M365 account using OAuth2 / Azure App registration

Core Concept / Commands

Install dependencies:

pip install O365 anthropic requests

Azure App registration (one-time):

  1. Go to portal.azure.com → Azure Active Directory → App registrations → New registration
  2. Copy Client ID and Tenant ID → paste into script
  3. Go to Certificates & secrets → create secret → paste into script
  4. Go to API permissions → Add → Microsoft Graph → Delegated:
    • Mail.Read
    • offline_access
  5. Click Grant admin consent

Script skeleton:

from O365 import Account
 
credentials = ('CLIENT_ID', 'CLIENT_SECRET')
account = Account(credentials, tenant_id='TENANT_ID')
 
if not account.is_authenticated:
    account.authenticate(scopes=['basic', 'message_all'])
 
mailbox = account.mailbox()
inbox = mailbox.inbox_folder()
messages = inbox.get_messages(limit=50)
 
# Pass messages to Claude API for summarisation
# Post result to Teams webhook

Schedule with cron (Linux/Mac):

# Run every weekday at 8:00 AM
0 8 * * 1-5 /usr/bin/python3 /path/to/email_summary_teams.py

Schedule with Task Scheduler (Windows):

  • Open Task Scheduler → Create Basic Task → Daily at 8:00 AM
  • Action: python C:\path\to\email_summary_teams.py

Key Options / Variants

  • Filter by sender, skip newsletters, group by priority — all possible via O365 query params
  • Teams card can include urgent flags, bullet points per email, total count
  • Token refresh is handled automatically by O365 library after first auth

Gotchas

  • Basic Auth was disabled by Microsoft for M365 in 2022 — O365 library is the correct replacement
  • First run requires interactive browser auth to generate OAuth token; subsequent runs use cached refresh token
  • offline_access scope is required for non-interactive token refresh

Source

Conversation “Power Automate workflow URL explanation” — 2026-05-20