Found while building a personal mail-triage workflow on top of this library (rule authoring + a read-only mailbox scan). Each item below is a confirmed, reproduced gap — not speculative — that has a workaround in place today but would directly unblock or improve a downstream feature if fixed upstream.
1. rule-create cannot target nested folders
_resolve_folder_id (src/msgraph/graph.py:12) does a shallow GET /me/mailFolders (top-level only), so --move_to_folder naming a folder nested under Inbox/Archive fails with "No mail folder named …", and doesn't accept a folder id either. message-move's _resolve_destination_folder (graph.py:46) already recurses to any depth and accepts an opaque id — the two verbs are inconsistent.
Impact: blocks authoring a move-to-folder rule targeting any nested destination folder.
Fix: point rule-create's destination resolution at _resolve_destination_folder (or the recursive _folder_name_map) so rules can file into nested folders and accept ids, matching message-move.
2. rule-create hardcodes stopProcessingRules and sequence
The POST body hardcodes "stopProcessingRules": False and "sequence": 1 (src/msgraph/verbs.py ~line 240) — callers have no control over rule order or chain-stop. With overlapping predicates, the last matching rule's move silently wins over earlier, more specific rules.
Impact: forces a workaround of only ever authoring non-overlapping predicates to sidestep ordering entirely; makes it impossible to express "specific rule wins, then fall through to a broader catch-all."
Fix: expose stopProcessingRules and sequence as rule-create arguments so specific-before-broad ordering is enforceable.
3. mail-list exposes no isRead or categories field
Even in --format detailed, mail-list returns only a minimal projection (from, id, receivedDateTime, subject). Per-message read status and category tags are not obtainable from any read-only verb.
Impact: blocks any read-only client from enumerating which category-tagged items are unread — can only degrade to folder-level unread counts. Reproduced live 2026-07-23 (mail-list --folder <name> --format detailed on 500 messages returned zero usable categories/isRead fields to filter on).
Fix: add isRead and categories to the $select (and JSON output) for mail-list --format detailed.
4. searchfolder-create's documented --source_folders default doesn't appear to apply
Docs state --source_folders defaults to inbox, but a search folder created via this verb (omitting --source_folders) reports "shallow over 0 source folder(s)" when inspected via searchfolder-list --format detailed — meaning its filter can structurally never match anything, regardless of how much matching mail exists.
Impact: a category-filtered search folder created without an explicit --source_folders silently returns nothing forever. Discovered live 2026-07-23.
Fix: confirm whether the default is actually applied at creation time (vs. only documented), and either fix the default or make the omission fail loudly instead of creating a folder that can never match.
None of these are blocking outright — each has a workaround in place — but fixing them removes real workaround debt for anyone building rule-authoring or read-only scanning tools on top of this library.
Found while building a personal mail-triage workflow on top of this library (rule authoring + a read-only mailbox scan). Each item below is a confirmed, reproduced gap — not speculative — that has a workaround in place today but would directly unblock or improve a downstream feature if fixed upstream.
1.
rule-createcannot target nested folders_resolve_folder_id(src/msgraph/graph.py:12) does a shallowGET /me/mailFolders(top-level only), so--move_to_foldernaming a folder nested under Inbox/Archive fails with "No mail folder named …", and doesn't accept a folder id either.message-move's_resolve_destination_folder(graph.py:46) already recurses to any depth and accepts an opaque id — the two verbs are inconsistent.Impact: blocks authoring a move-to-folder rule targeting any nested destination folder.
Fix: point
rule-create's destination resolution at_resolve_destination_folder(or the recursive_folder_name_map) so rules can file into nested folders and accept ids, matchingmessage-move.2.
rule-createhardcodesstopProcessingRulesandsequenceThe POST body hardcodes
"stopProcessingRules": Falseand"sequence": 1(src/msgraph/verbs.py~line 240) — callers have no control over rule order or chain-stop. With overlapping predicates, the last matching rule's move silently wins over earlier, more specific rules.Impact: forces a workaround of only ever authoring non-overlapping predicates to sidestep ordering entirely; makes it impossible to express "specific rule wins, then fall through to a broader catch-all."
Fix: expose
stopProcessingRulesandsequenceasrule-createarguments so specific-before-broad ordering is enforceable.3.
mail-listexposes noisReadorcategoriesfieldEven in
--format detailed,mail-listreturns only a minimal projection (from,id,receivedDateTime,subject). Per-message read status and category tags are not obtainable from any read-only verb.Impact: blocks any read-only client from enumerating which category-tagged items are unread — can only degrade to folder-level unread counts. Reproduced live 2026-07-23 (
mail-list --folder <name> --format detailedon 500 messages returned zero usablecategories/isReadfields to filter on).Fix: add
isReadandcategoriesto the$select(and JSON output) formail-list --format detailed.4.
searchfolder-create's documented--source_foldersdefault doesn't appear to applyDocs state
--source_foldersdefaults toinbox, but a search folder created via this verb (omitting--source_folders) reports "shallow over 0 source folder(s)" when inspected viasearchfolder-list --format detailed— meaning its filter can structurally never match anything, regardless of how much matching mail exists.Impact: a category-filtered search folder created without an explicit
--source_folderssilently returns nothing forever. Discovered live 2026-07-23.Fix: confirm whether the default is actually applied at creation time (vs. only documented), and either fix the default or make the omission fail loudly instead of creating a folder that can never match.
None of these are blocking outright — each has a workaround in place — but fixing them removes real workaround debt for anyone building rule-authoring or read-only scanning tools on top of this library.