Repository navigation
fix(outlook): find scheduled sends outside Drafts - #205
Conversation
Outlook's own Schedule send parks the deferred message wherever it likes — on a live mailbox, in Deleted Items — so scoping discovery to Drafts missed every send scheduled from the Outlook UI. Scan the mailbox instead, narrowed to `isDraft eq true`. Graph cannot filter on the proptag deferred property server-side (`any(ep: ep/id eq 'SystemTime 0x3FEF' ...)` is rejected with ErrorInvalidUrlQueryFilter for eq and ge alike), so isDraft is what keeps the scan bounded and the property is matched client-side. Page size 500, measured as the sweet spot on a 1,200-draft mailbox. Also drop past-dated matches: Outlook leaves the tagged copy behind after delivery, and a mailbox-wide scan surfaces that residue where the Drafts-scoped one did not. Fixes #204 Claude-Session: https://claude.ai/code/session_01A7i4dE7jfKMCEM5BRoTwtw
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
✅ Post-merge smoke passedMerged: Steps
Feature-path result (live mailbox, read-only) Pre-fix this returned 1 (the Drafts-resident one). The two Flake, unrelated to this PR: the first full run had Not live yet for agents: this repo publishes on Prod: n/a — repo does not deploy on merge (release workflow is tag-triggered). Cleanup
|
Releases the scheduled-send discovery fix from #205, which landed on main after the 0.3.1 tag and so is not in any published package. Agents run the installed server, not main, so list_scheduled_sends keeps missing Outlook-UI-scheduled messages until this ships. Claude-Session: https://claude.ai/code/session_01A7i4dE7jfKMCEM5BRoTwtw
Fixes #204.
The bug, confirmed live
Read-only Graph check against a real mailbox — the Drafts-scoped query the provider used found 1 pending send; a mailbox-wide scan found 4:
Outlook's own Schedule send parks the deferred message outside Drafts, so folder membership says nothing about whether a send is pending. Note the last row: a past deferred time, i.e. residue Outlook left behind after delivery.
The fix
listScheduledSendsnow scans/messagesmailbox-wide, narrowed to$filter=isDraft eq true, and matches the deferred property client-side.Server-side filtering on the property is not available — all three shapes were probed against live Graph and rejected:
svep/any(ep: ep/id eq 'SystemTime 0x3FEF')ErrorInvalidUrlQueryFilter… and ep/value gt '2026-09-07T00:00:00Z'ErrorInvalidUrlQueryFilter… and casted(ep/value, Edm.DateTimeOffset) gt …BadRequest— unknown functioncastedSo
isDraft eq trueis what keeps the scan bounded; a pending deferred send is always still a draft, and without it this would page the entire mailbox.Past-dated matches are now dropped. The Drafts-scoped scan rarely saw that residue; a mailbox-wide one sees all of it, and reporting a year-old delivered message as "pending" would be worse than the bug being fixed.
Page size 500, measured on the 1,200-draft mailbox above: 3 pages / ~7.5s, vs 13 pages / ~9.2s at 100 and 2 pages / ~8.3s at 999 — Graph's per-item cost dominates, so bigger pages stop paying off.
Verification
npm run test:run— all workspaces green (511 + 236 + 116 + 219 + 31);npm run lintclean;openspec validate add-scheduled-send --strictpasses.list_scheduled_sendsreturns the 3 pending sends (was 1), residue excluded, stable across repeat calls.Spec delta in
openspec/changes/add-scheduled-send/updated — it previously said listing happens "only from Drafts".https://claude.ai/code/session_01A7i4dE7jfKMCEM5BRoTwtw