WIP: feat(email): Microsoft 365 (Outlook) support via Microsoft Graph #334
Closed
codemonkey76 wants to merge 9 commits from
codemonkey76/feat/microsoft-graph-email into main
pull from: codemonkey76/feat/microsoft-graph-email
merge into: sleepy:main
sleepy:main
sleepy:dev
sleepy:fix/950-webhook-reminder
sleepy:fix/948-skill-import-urls
sleepy:fix/947-deepseek-provider
sleepy:fix/946-slash-autocomplete
sleepy:fix/940-google-oauth2-email
sleepy:fix/939-plan-mode
sleepy:fix/938-security-hardening-suite
sleepy:fix/937-workspace-confinement
sleepy:fix/936-edit-file-code-nav-tools
sleepy:fix/effective-mode-undefined
sleepy:fix/async-generator-500
sleepy:refactor/split-small-routes-779
sleepy:refactor/split-session-routes-778
sleepy:refactor/split-llm-core-700
sleepy:refactor/split-chat-routes-724
sleepy:refactor/split-model-routes-701
sleepy:refactor/split-skills-routes-777
sleepy:refactor/split-document-routes-769
sleepy:refactor/split-ai-interaction-722
sleepy:refactor/split-cookbook-routes-775
sleepy:refactor/split-builtin-actions-723
sleepy:refactor/split-task-scheduler-774
sleepy:refactor/tool-execution-split-667
sleepy:fix/rag-health-coordinator-756
sleepy:fix/agent-core-missing-round-loop
sleepy:fix/rag-health-check-756
sleepy:fix/missing-readmes-782
sleepy:fix/search-files-split-772
sleepy:fix/dedup-search-impl-771
sleepy:fix/mcp-integrations-split-781
sleepy:fix/cookbook-helpers-split-785
sleepy:fix/search-cross-feature-776
sleepy:fix/graceful-llm-degradation-770
sleepy:fix/dedup-research-handler-773
sleepy:fix/cross-route-coupling-780
sleepy:fix/skills-typed-request-762
sleepy:fix/chat-stream-pydantic-731
sleepy:fix/chat-handler-imports-737
sleepy:fix/public-llm-exports-730
sleepy:fix/dedup-search-content-784
sleepy:fix/dedup-stream-parse-735
sleepy:fix/stream-error-boundary-734
sleepy:fix/typed-event-names-786
sleepy:fix/dedup-js-utilities-792
sleepy:fix/skills-index-lookup-761
sleepy:fix/xss-charname-innerhtml-788
sleepy:fix/coderunner-document-write-789
sleepy:fix/ai-interaction-thread-safety-729
sleepy:fix/client-side-api-key-regex-793
sleepy:fix/dead-loadingtext-796
sleepy:fix/active-streams-eviction-736
sleepy:fix/builtin-actions-sqlite-orm-732
sleepy:fix/llm-core-thread-safety-709
sleepy:fix/singleton-thread-safety-768
sleepy:fix/video-upload-multimodal-826
sleepy:fix/mic-button-audio-825
sleepy:fix/multimodal-capabilities-827
sleepy:fix/dedup-system-msg-717
sleepy:fix/service-dead-calls-750
sleepy:fix/db-session-context-manager-757
sleepy:fix/dedup-llmconfig-710
sleepy:fix/keyword-lists-764-v2
sleepy:fix/keyword-lists-764
sleepy:fix/llm-cache-ttl-708
sleepy:fix/validate-config-711
sleepy:fix/totp-constant-time-689
sleepy:fix/admin-tools-constant-681
sleepy:fix/dedup-truncate-670
sleepy:fix/threadsafe-extractions-audit-754
sleepy:fix/dedup-json-io-767
sleepy:fix/695-deduplicate-admin-check
sleepy:fix/upload-auth-dedup-765
sleepy:fix/705-deduplicate-network-constants
sleepy:fix/deduplicate-chunking-749
sleepy:fix/760-deduplicate-embed
sleepy:fix/dedup-validation-759
sleepy:fix/748-deduplicate-tokenization
sleepy:fix/add-readmes-728-742-782
sleepy:fix/key-file-permissions-706
sleepy:fix/embedding-retry-766
sleepy:fix/deterministic-doc-ids-753
sleepy:fix/search-facade-783
sleepy:fix/remove-dead-memory-746
sleepy:fix/remove-rag-manager-747
sleepy:fix/dead-docstring-763
sleepy:refactor/split-tool-schemas-666
sleepy:refactor/split-agent-loop-664
sleepy:refactor/split-tool-implementations-665
sleepy:fix/mark-stopped-500-663
sleepy:fix/streamingtts-scope-662
sleepy:fix/code-block-tool-parsing-661
No reviewers
Labels
Clear labels
area:chat
area:core
area:llm
area:routes
area:tools
bug
Something isn't working
documentation
Improvements or additions to documentation
duplicate
This issue or pull request already exists
enhancement
New feature or request
good first issue
Good for newcomers
help wanted
Extra attention is needed
invalid
This doesn't seem right
question
Further information is requested
refactor
wontfix
This will not be worked on
No labels
area:chat
area:core
area:llm
area:routes
area:tools
bug
documentation
duplicate
enhancement
good first issue
help wanted
invalid
question
refactor
wontfix
Milestone
Clear milestone
No items
No milestone
Projects
Clear projects
No items
No project
Assignees
Clear assignees
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".
No due date set.
Dependencies
No dependencies set.
Reference
sleepy/odysseus!334
Loading…
Reference in a new issue
No description provided.
Delete branch "codemonkey76/feat/microsoft-graph-email"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Adds first-class Microsoft 365 / Outlook email support via the Microsoft Graph API. Closes #159. Microsoft has disabled Basic Auth for Exchange Online, so Office 365 work/school accounts can't connect over IMAP/SMTP today; Graph works even on tenants that disable IMAP.
A single dispatch point —
_graph_backend(account_id, owner)— returns aGraphBackendfor accounts whoseoauth_provideris"microsoft", andNoneotherwise, so every email route keeps its existing IMAP path as the default branch.GraphBackendreturns the same dict shapes as the IMAP sync helpers, so route handlers and the frontend stay backend-agnostic.What's included
/meaddress+name import. Reuses #237'soauth_*columns (no new migration).$count), read, mark-read./sendMail(Graph files it in Sent Items, so the IMAP append is skipped)..envrequired — Client ID/secret/tenant are entered in the UI (an "App credentials" panel in the account form), stored insettings.jsonwith the secret encrypted; env vars remain a fallback. Also restores #237's Google "Connect" button, which had been orphaned when the Email tab was refactored into "Manage in Integrations".tests/test_email_graph.py(14 cases, mocked HTTP, no network).Setup (operator, one-time)
Register an Azure app (Web platform), add the redirect URI shown in the UI, and grant delegated Graph permissions:
offline_access,User.Read,Mail.ReadWrite,Mail.Send. Then enter Client ID/secret in the account's OAuth panel — no rebuild needed.Test plan
tests/test_email_graph.pypassesNotes
isRead, no\Answered); common cases are mapped,\Answeredis a no-op for Graph.🤖 Generated with Claude Code
Review-order note: this PR is stacked on #237 (Google OAuth2 for email), which is still open. It reuses #237's OAuth scaffolding — the
oauth_*columns, signed OAuth state, and callback pattern — so the diff currently includes #237's commits.Suggested path:
mainso the diff is just the 4 Microsoft commits (a29c51c→3eff44b) and take it out of draft.Keeping it as a draft until then. The Microsoft-specific work is self-contained in those 4 commits if you'd like an early look. It also restores #237's "Connect with Google" button, which the earlier Email-tab → "Manage in Integrations" refactor had orphaned.
||Closing — out of scope.
Pull request closed