Microsoft Teams¶
Practical, operationally-named examples for the Teams lifecycle — administration, governance, management, cleanup, and bulk export/import. All scripts are flat in this folder and follow console-print style.
Note: team creation in Graph is asynchronous. Use
client.teams.create_and_wait(name).execute_query()(waits and loads the team) orclient.teams.create(name).execute_query()and poll the returnedTeamsAsyncOperationyourself.
Administration & lifecycle¶
| Script | What it does |
|---|---|
teams_lifecycle.py |
Create, update settings, archive/unarchive, and delete a team |
prune_inactive_teams.py |
Report, archive, or delete teams idle >= --days (default 180); dry-run by default (--apply) |
import_teams.py |
Bulk-provision teams from a CSV (name,description?,template?) via create_and_wait |
export_teams.py |
Export the tenant Teams inventory to CSV/JSON (owners/members/guests counts) |
members_lifecycle.py |
Add/remove team members and owners |
teams_export_membership.py |
Export all team memberships to CSV |
python prune_inactive_teams.py # candidates idle >= 180 days
python prune_inactive_teams.py --days 90 --action archive --apply
python import_teams.py --file teams.csv
python export_teams.py --output /tmp
Migration (export)¶
| Script | What it does |
|---|---|
migration/migrate/export_team.py |
Resumable team archive via MigrationJob adapters: structure, members, channels, tabs, apps, messages, inline images (--files adds channel files) |
migration/migrate/export_messages.py |
Compliance message export via deferred collection adapters (to_ndjson + download_hosted_contents) |
See migration/README.md for the archive layout and permissions.
Audit & governance¶
| Script | What it does |
|---|---|
teams_inventory.py |
Tenant-wide report: owners, member/guest counts, visibility, archive state |
teams_settings_audit.py |
Scan team settings for policy compliance |
teams_guest_audit.py |
Find all teams with external guest users |
teams_lifecycle_audit.py |
Lifecycle report: archived and recently deleted teams |
teams_orphan_owners.py |
Teams without owners (orphaned) |
find_empty_teams.py |
Cleanup candidates: teams with no channels or no messages |
find_excessive_admins.py |
Security risk: teams with too many owners |
archive_inactive_teams.py |
Report archiving candidates (inactive teams) |
channels_inactive.py |
Inactive channels based on last message date |
restore_deleted_team.py |
List, restore, or permanently delete deleted groups/teams |
Apps & tags¶
| Script | What it does |
|---|---|
apps_catalog.py |
Inventory of the tenant Teams app catalog |
apps_installed.py |
App adoption across all teams |
apps_lifecycle.py |
Install, uninstall, and inspect apps in a team |
apps_tabs.py |
Pinned apps/tabs across all teams |
tags_lifecycle.py |
Create, update, and delete teamwork tags |
tags_report.py |
All tags across teams (member counts, teams without tags) |
Channels & chats¶
| Script | What it does |
|---|---|
channels_inventory.py |
Cross-team channel inventory and audit |
channels_lifecycle.py |
Channel lifecycle: create, update, delete, channel email |
channels_messages.py |
Channel messaging: send, reply, list, team-wide activity digest |
channels_shared.py |
Shared channels: create, share with another team, verify access |
chats_inventory.py |
A user's chats (list/pagination) |
chats_lifecycle.py |
Create and manage chats |
chats_messages.py |
Chat messaging: send, reply, list, export, digest |
Meetings & analytics¶
| Script | What it does |
|---|---|
online_meetings.py |
Create online meetings with join links |
usage_report.py |
Team counts and user activity over periods |
call_records.py |
Teams call quality analytics |
Typical workflow (bulk onboarding → governance → cleanup)¶
from office365.graph_client import GraphClient
from tests.settings import client_id, client_secret, tenant
client = GraphClient(tenant=tenant).with_client_secret(client_id, client_secret)
# provision (async + wait for readiness)
team = client.teams.create_and_wait("Finance", "Budgeting and reporting").execute_query()
print(team.id, team.display_name)
# ...later, governance...
# prune_inactive_teams.py --days 180 --action archive --apply
# export_teams.py --output /tmp