Microsoft Teams
msgvault can archive Microsoft Teams chats and channel messages into the same
local archive as email, calendar events, and text-message imports. Teams
messages are stored with message_type = teams, so they can be searched,
queried, and embedded without mixing them into ordinary email-only workflows.
Teams sync is read-only: msgvault reads messages through Microsoft Graph and does not send messages, edit Teams content, or modify channel membership.
Prerequisites¶
Teams ingestion uses Microsoft Graph delegated OAuth, not IMAP. It requires the
same [microsoft] client_id config block used by add-o365, but it stores a
separate Graph token under tokens/teams_<email>.json. An Outlook IMAP token
created by add-o365 does not authorize Teams sync.
Register a Microsoft Entra app as described in OAuth Setup, with:
- Redirect URI:
http://localhost:8089/callback/microsoft - Public client flows enabled
- Delegated Microsoft Graph permissions:
Chat.Read,ChannelMessage.Read.All,Team.ReadBasic.All,Channel.ReadBasic.All,User.Read, andUser.ReadBasic.All
Some tenants require an administrator to grant consent for channel-message permissions before users can authorize the app.
Configure msgvault:
[microsoft]
client_id = "your-azure-app-client-id"
# tenant_id = "your-org-tenant-id" # optional; default is "common"
Authorize Teams¶
msgvault add-teams [email protected]
The command opens a browser, requests the Graph scopes above, verifies the
returned identity, stores the token as [email protected], creates a
teams source, and confirms the account email as the default "me" identity.
| Flag | Description |
|---|---|
--tenant |
Azure AD tenant ID for this authorization; defaults to common |
--no-default-identity |
Do not auto-confirm the email address as this source's "me" identity |
Sync Teams¶
# Full first run or incremental later runs are auto-detected.
msgvault sync-teams [email protected]
# Chats only
msgvault sync-teams [email protected] --no-channels
# Test with a per-conversation limit
msgvault sync-teams [email protected] --limit 100
# Re-fetch all messages and upsert them in place
msgvault sync-teams [email protected] --full
The first run walks chats, joined teams, channels, root channel messages, and
replies. Later runs resume from stored cursors and checkpoints. If a run is
interrupted, re-run sync-teams; completed conversations are skipped and
incomplete ones continue.
| Flag | Description |
|---|---|
--no-channels |
Sync chats only and skip team channels |
--limit |
Maximum messages per conversation (0 means no limit) |
--full |
Ignore stored cursors and re-fetch every message, repairing/backfilling rows in place |
What Gets Archived¶
- One-on-one chats, group chats, meeting chats, team channels, and channel replies.
- Plain-text body text derived from Graph HTML bodies, plus the original HTML body when present.
- Sender and conversation members as participants, so Teams contacts can appear in the same contact graph as email and text-message contacts.
- The original Graph message JSON in raw-message storage with format
teams_json. - Link attachments as attachment references.
- Inline hosted-content images downloaded into msgvault's attachment store.
- Call-recording event links in the searchable body text.
Deleted Teams messages are marked deleted in the archive when Graph reports a
deletedDateTime; existing rows are not silently left active.
Inline Media Backfill¶
If you imported Teams messages before inline hosted-content downloads were available, or a transient Graph error left some inline images missing, run:
msgvault backfill-teams-media [email protected]
msgvault backfill-teams-media [email protected] --only-incomplete
The backfill scans stored Teams HTML bodies for hostedContents URLs and
downloads those images into the attachment store. It is idempotent because
attachment storage is content-addressed.
Scheduled Sync¶
msgvault serve can schedule Teams syncs through the normal [[accounts]]
block after add-teams creates the source and token:
[[accounts]]
email = "[email protected]"
schedule = "*/30 * * * *"
enabled = true
The scheduler resolves the entry to the teams source when that account has a
Teams source. Scheduled Teams syncs include channels.
Search and Query¶
Teams messages use message_type = teams:
msgvault search "incident review" --message-type teams
msgvault search "message_type:teams incident review"
msgvault query --format table "
SELECT sent_at, from_email, subject, snippet
FROM v_messages
WHERE message_type = 'teams'
ORDER BY sent_at DESC
LIMIT 20
"
Manual sync-teams does not run the embedding worker immediately. If vector
search is enabled and you want newly synced Teams messages in semantic/hybrid
results, run msgvault embeddings build after the sync, or configure
[vector.embed.schedule].run_after_sync = true for scheduled daemon syncs.
In the Web UI, Teams direct chats, group chats, and channel
conversations appear as conversation rows in Everything and can be combined
with the same search, filters, and grouping as other archive modalities. In
the TUI, press m to switch from Email mode to Texts mode.