@littlebearapps/outlook-assistant 3.11.2 → 3.12.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/.env.example +20 -0
  2. package/README.md +51 -28
  3. package/advanced/index.js +319 -46
  4. package/auth/device-code.js +100 -3
  5. package/auth/token-storage.js +44 -2
  6. package/auth/tools.js +196 -14
  7. package/calendar/attendees.js +101 -0
  8. package/calendar/cancel.js +5 -4
  9. package/calendar/create.js +15 -4
  10. package/calendar/decline.js +10 -5
  11. package/calendar/index.js +51 -10
  12. package/calendar/list.js +146 -3
  13. package/calendar/update.js +65 -33
  14. package/categories/index.js +17 -3
  15. package/config.js +103 -17
  16. package/contacts/index.js +2 -1
  17. package/email/attachments.js +19 -37
  18. package/email/conversations.js +180 -91
  19. package/email/delta.js +123 -13
  20. package/email/draft.js +66 -9
  21. package/email/export.js +113 -77
  22. package/email/folder-utils.js +29 -129
  23. package/email/headers.js +5 -1
  24. package/email/index.js +76 -19
  25. package/email/list.js +8 -1
  26. package/email/mark-as-read.js +3 -1
  27. package/email/mime.js +4 -1
  28. package/email/read.js +5 -1
  29. package/email/search.js +23 -9
  30. package/folder/create.js +11 -4
  31. package/folder/delete.js +9 -1
  32. package/folder/index.js +11 -1
  33. package/folder/list.js +61 -27
  34. package/folder/move.js +32 -7
  35. package/folder/resolve.js +65 -25
  36. package/folder/stats.js +11 -5
  37. package/index.js +9 -1
  38. package/llms-install.md +28 -9
  39. package/llms.txt +13 -9
  40. package/package.json +3 -3
  41. package/rules/index.js +3 -3
  42. package/rules/rule-builder.js +61 -16
  43. package/utils/datetime.js +170 -0
  44. package/utils/graph-api.js +390 -211
  45. package/utils/mailbox.js +77 -0
  46. package/utils/mock-data.js +3 -0
  47. package/utils/odata-helpers.js +24 -0
  48. package/utils/safe-write.js +151 -0
  49. package/calendar/accept.js +0 -72
package/.env.example CHANGED
@@ -31,6 +31,14 @@ USE_TEST_MODE=false
31
31
  # receivedBefore rather than raising this if you can.
32
32
  # OUTLOOK_SEARCH_SCAN_LIMIT=500
33
33
 
34
+ # Inactivity timeout for each Graph request attempt (milliseconds): an attempt
35
+ # that receives no data for this long is abandoned with a timeout error. It is
36
+ # not an overall deadline — a slow response that keeps arriving isn't cut off.
37
+ # Throttled (429) and busy (503/504) responses are retried automatically (up to
38
+ # 3 times, honouring Retry-After); POST requests such as sending mail are only
39
+ # retried on a 429 asking for a short wait (10 s or less, 20 s in total).
40
+ # OUTLOOK_REQUEST_TIMEOUT_MS=60000
41
+
34
42
  # Optional: Default authentication method (device-code or browser)
35
43
  # device-code: No auth server needed, works remotely/headless
36
44
  # browser: Traditional OAuth redirect via localhost:3333
@@ -46,6 +54,18 @@ USE_TEST_MODE=false
46
54
  # Example: OUTLOOK_AUTH_AUDIENCE=consumers (for personal-account-only apps)
47
55
  # OUTLOOK_AUTH_AUDIENCE=common
48
56
 
57
+ # Optional: Shared-mailbox support (OPT-IN, work/school accounts only).
58
+ # Unset = off: sign-in requests the standard scopes only, exactly as before.
59
+ # read — adds Mail.Read.Shared (read/search/export shared mailboxes)
60
+ # true|readwrite — adds Mail.Read.Shared + Mail.ReadWrite.Shared (also move,
61
+ # flag, categorise, mark read, manage folders)
62
+ # After enabling it, restart the server and re-authenticate:
63
+ # auth action=authenticate force=true
64
+ # Personal Outlook.com accounts can't be granted these scopes — leave it unset.
65
+ # The browser flow (npm run auth-server) has no fallback for accounts that
66
+ # reject them; use device-code auth if you enable this.
67
+ # OUTLOOK_SHARED_MAILBOX=read
68
+
49
69
  # Optional: Default timezone for calendar events when not explicitly
50
70
  # specified by the caller. Use any IANA timezone identifier.
51
71
  # Default: Australia/Melbourne
package/README.md CHANGED
@@ -36,14 +36,14 @@ Outlook Assistant connects AI assistants to your Microsoft Outlook account throu
36
36
  - 📨 **Search and read emails** — find messages by sender, subject, date, or keywords; read full threads with conversation grouping; batch flag, move, export, or categorise multiple emails at once
37
37
  - 🛡️ **Send emails with safety controls** — dry-run preview, pre-send mail tips (out-of-office, mailbox full, delivery restrictions), session rate limiting, and recipient allowlist to prevent mistakes
38
38
  - ✏️ **Draft emails for review** — create, update, and send drafts; reply and forward as drafts; preview before saving with dry-run mode
39
- - 📅 **Manage your calendar** — view upcoming events, schedule meetings with attendees, decline or cancel invitations
39
+ - 📅 **Manage your calendar** — view upcoming events, look back at past ones or find them by date range and subject, schedule meetings with attendees, update, decline or cancel events
40
40
  - 📦 **Export emails** — save individual messages to Markdown, EML, JSON, or CSV; export full conversation threads to MBOX or HTML; bulk-export search results in one call
41
41
  - 🔍 **Investigate email headers** — full raw header access (DKIM, SPF, DMARC, delivery chain, X-Mailer, X-Originating-IP) for phishing investigation and compliance review
42
42
  - 🗂️ **Organise your inbox** — create nested folders (addressable by path), set up inbox rules, colour-code with categories, manage Focused Inbox — all work together for complete inbox automation
43
43
  - 🔄 **Track inbox changes** — delta sync detects new, modified, and deleted emails since your last check, with tokens for incremental polling
44
44
  - 👥 **Manage contacts** — search your contact book and organisational directory, create and update contact records
45
45
  - ⚙️ **Configure settings** — set out-of-office auto-replies, working hours, and time zone
46
- - 📬 **Access shared mailboxes** — read team inboxes and service accounts (Microsoft 365)
46
+ - 📬 **Access shared mailboxes** — read and organise team inboxes and service accounts, including custom subfolders and nested folder paths; enumerate, read, and search the folder tree (best-effort — listings flag any branches skipped due to depth limits or per-folder errors), move/flag/categorise messages, and manage folders (work/school Microsoft 365 accounts; opt-in via `OUTLOOK_SHARED_MAILBOX`). Sending, drafts, replies, and forwards from a shared mailbox are not supported — those operations always act on the signed-in user's own mailbox
47
47
  - 🏢 **Find meeting rooms** — search by building, floor, capacity, AV equipment, and wheelchair accessibility (Microsoft 365)
48
48
 
49
49
  ### Why Outlook Assistant?
@@ -62,15 +62,15 @@ Outlook Assistant connects AI assistants to your Microsoft Outlook account throu
62
62
 
63
63
  | Module | Tools | What You Can Do |
64
64
  |--------|------:|-----------------|
65
- | **Email** | 8 | `search-emails` (list/search/delta/conversations), `read-email` (content + forensic headers), `send-email` (with dry-run + mail tips), `draft` (create/update/send/delete/reply/forward), `update-email` (read status, flags), `attachments`, `export`, `get-mail-tips` |
66
- | **Calendar** | 3 | `list-events`, `create-event`, `manage-event` (update/decline/cancel/delete) |
65
+ | **Email** | 8 | `search-emails` (list/search/delta/conversations), `read-email` (content + forensic headers), `send-email` (with dry-run + mail tips), `draft` (create/update/send/delete/reply/reply-all/forward), `update-email` (read status, flags), `attachments`, `export`, `get-mail-tips` |
66
+ | **Calendar** | 3 | `list-events` (upcoming by default; `startAfter`/`startBefore`/`subject` filters), `create-event`, `manage-event` (update/decline/cancel/delete) |
67
67
  | **Contacts** | 2 | `manage-contact` (list/search/get/create/update/delete), `search-people` |
68
68
  | **Categories** | 3 | `manage-category` (CRUD), `apply-category`, `manage-focused-inbox` |
69
69
  | **Settings** | 1 | `mailbox-settings` (get/set auto-replies/set working hours) |
70
70
  | **Folder** | 1 | `folders` (list/create/move/stats/delete) — nested folders addressable by path (`Parent/Child`) or ID |
71
71
  | **Rules** | 1 | `manage-rules` (list/create/update/reorder/delete) |
72
- | **Advanced** | 2 | `access-shared-mailbox`, `find-meeting-rooms` |
73
- | **Auth** | 1 | `auth` (status/authenticate/about) |
72
+ | **Advanced** | 2 | `access-shared-mailbox` (messages or folder tree), `find-meeting-rooms` |
73
+ | **Auth** | 1 | `auth` (status/authenticate/device-code-complete/about) |
74
74
 
75
75
  **22 tools total** — consolidated from 55 for optimal AI performance. See the [Tools Reference](docs/quickrefs/tools-reference.md) for complete parameter details.
76
76
 
@@ -104,7 +104,7 @@ Outlook Assistant works with both personal and work/school Microsoft accounts, b
104
104
  | Categories | Full support | Full support |
105
105
  | Mailbox settings | Full support | Full support |
106
106
  | Focused Inbox | API works (overrides stored) but mail routing not affected | Full support |
107
- | Shared mailboxes | Not available | Requires `Mail.Read.Shared` |
107
+ | Shared mailboxes | Not available | Opt-in (`OUTLOOK_SHARED_MAILBOX`). Read + organise only. Read: `Mail.Read.Shared`; organise (move/categorise/flag/create folders): `Mail.ReadWrite.Shared`. No sending/drafts/replies/forwards |
108
108
  | Meeting room search | Not available | Requires `Place.Read.All` + admin consent |
109
109
 
110
110
  > **Note**: On personal accounts, Microsoft's `$search` API has limited support for free-text queries. Outlook Assistant handles this automatically with progressive search — if your query returns no results, it falls back through OData filters, boolean filters, and recent message listing to find your emails. For the most direct results on personal accounts, use the structured filter parameters (`from`, `subject`, `to`, `receivedAfter`).
@@ -141,7 +141,9 @@ Outlook Assistant is designed with safety-first principles for AI-driven email a
141
141
  > }
142
142
  > ```
143
143
 
144
- **Draft protections** — The `draft` tool shares `send-email` safety controls: dry-run preview, recipient allowlist, mail-tips validation, and rate limiting. The `send` action shares the `send-email` rate limit counter, preventing circumvention via the draft-then-send pathway.
144
+ **Input and file hardening** — IDs containing `.` or `..` path segments are refused before any request is made, continuation links (`deltaToken`) must point at `graph.microsoft.com`, and attachment downloads and exports write sanitised filenames inside the output directory without overwriting existing files or following symlinks.
145
+
146
+ **Draft protections** — The `draft` tool shares `send-email` safety controls: dry-run preview, recipient allowlist, mail-tips validation, and rate limiting. The `send` action shares the `send-email` rate limit counter, preventing circumvention via the draft-then-send pathway. `update`, `send` and `delete` refuse any ID that is not an unsent draft, so a received or sent message is never edited, deleted or re-sent.
145
147
 
146
148
  **Token-optimised architecture** — Tools are consolidated using the STRAP (Single Tool, Resource, Action Pattern) approach. 22 tools instead of 55 reduces per-turn overhead by ~11,000 tokens (~64%), keeping more of the AI's context window available for your actual conversation. Fewer tools also means the AI selects the right tool more accurately — research shows tool selection degrades beyond ~40 tools.
147
149
 
@@ -164,7 +166,7 @@ npx @littlebearapps/outlook-assistant
164
166
  To check which version you have, or to see the available options:
165
167
 
166
168
  ```bash
167
- outlook-assistant --version # prints e.g. 3.11.2
169
+ outlook-assistant --version # prints e.g. 3.12.1
168
170
  outlook-assistant --help # usage, options and key environment variables
169
171
  ```
170
172
 
@@ -210,10 +212,13 @@ Add to your MCP client config:
210
212
  <summary><strong>Claude Code</strong> (CLI)</summary>
211
213
 
212
214
  ```bash
213
- claude mcp add outlook -- npx @littlebearapps/outlook-assistant
215
+ claude mcp add outlook \
216
+ -e OUTLOOK_CLIENT_ID=your-application-client-id \
217
+ -e OUTLOOK_CLIENT_SECRET=your-client-secret-VALUE \
218
+ -- npx -y @littlebearapps/outlook-assistant
214
219
  ```
215
220
 
216
- Then set environment variables in your `.env` or shell.
221
+ The MCP server reads its settings from the environment your client passes it; it doesn't load a `.env` file.
217
222
  </details>
218
223
 
219
224
  <details>
@@ -260,18 +265,18 @@ Or add manually to `.cursor/mcp.json`:
260
265
 
261
266
  ### 4. Authenticate
262
267
 
263
- 1. Start the auth server: `outlook-assistant-auth` (or `npx @littlebearapps/outlook-assistant-auth`)
264
- 2. In your AI assistant, use the `auth` tool with `action=authenticate` to get an OAuth URL
265
- 3. Open the URL, sign in with your Microsoft account, and grant permissions
268
+ 1. Ask your AI assistant to connect to Outlook — it calls the `auth` tool with `action=authenticate` and returns a short code and the URL `microsoft.com/devicelogin`
269
+ 2. Open the URL on any device (a private/incognito window avoids cached sessions), enter the code, sign in and grant permissions
270
+ 3. Tell your assistant you're done — it calls `auth` with `action=device-code-complete`
266
271
  4. Tokens are saved locally and refresh automatically
267
272
 
268
- > **Note**: The auth server needs `OUTLOOK_CLIENT_ID` and `OUTLOOK_CLIENT_SECRET` environment variables. Your MCP client's `"env"` config only applies to the MCP server process — when running the auth server separately, ensure these are set in a `.env` file or exported in your shell.
273
+ No auth server is needed for this default device-code flow. If you'd rather use the browser redirect flow, see [Authentication Flow](#authentication-flow) below.
269
274
 
270
275
  ## Installation
271
276
 
272
277
  ### Prerequisites
273
278
 
274
- - **Node.js** 18.0.0 or higher
279
+ - **Node.js** 18.18.0 or higher (contributors: the dev tooling needs 22.22.1 or higher)
275
280
  - **npm** (included with Node.js)
276
281
  - **Azure account** for app registration ([free tier works](https://azure.microsoft.com/free/))
277
282
 
@@ -327,7 +332,8 @@ a server that would ignore it.
327
332
  - `MailboxSettings.ReadWrite` — settings, auto-replies, categories
328
333
  - `People.Read` — people search
329
334
  3. Optionally add **org-only** permissions (work/school accounts only):
330
- - `Mail.Read.Shared` — shared mailbox access
335
+ - `Mail.Read.Shared` — shared mailbox read access (requested only when `OUTLOOK_SHARED_MAILBOX=read` or `=true`)
336
+ - `Mail.ReadWrite.Shared` — shared mailbox writes (move/categorise/flag/mark-read; requested only when `OUTLOOK_SHARED_MAILBOX=true`)
331
337
  - `Place.Read.All` — meeting room search (requires admin consent)
332
338
  4. Click **Add permissions**
333
339
 
@@ -342,7 +348,7 @@ a server that would ignore it.
342
348
 
343
349
  ### Environment Variables
344
350
 
345
- Create a `.env` file from the example:
351
+ Set these in your MCP client's `"env"` block (see [Quick Start](#3-configure-your-mcp-client)). The MCP server doesn't load `.env` files; the browser-flow auth server (`npm run auth-server`) does, so when running from source you can also keep a `.env` for it:
346
352
 
347
353
  ```bash
348
354
  cp .env.example .env
@@ -366,7 +372,9 @@ USE_TEST_MODE=false
366
372
  | `OUTLOOK_DEFAULT_TIMEZONE` | IANA timezone applied to calendar events when callers don't pass one (e.g. `Europe/London`, `America/New_York`). | `Australia/Melbourne` |
367
373
  | `OUTLOOK_MAX_EMAILS_PER_SESSION` | Cap on `send-email` + `draft send` per MCP server lifetime. | unlimited |
368
374
  | `OUTLOOK_ALLOWED_RECIPIENTS` | Comma-separated allowlist of domains/addresses for sends, drafts, and rule forwards. | unrestricted |
375
+ | `OUTLOOK_SHARED_MAILBOX` | Opt-in shared-mailbox support (work/school only). `read` requests `Mail.Read.Shared`; `true` (or `readwrite`/`1`) also requests `Mail.ReadWrite.Shared`. Unset leaves sign-in unchanged. After enabling, restart and run `auth action=authenticate force=true`. | unset (off) |
369
376
  | `OUTLOOK_SEARCH_SCAN_LIMIT` | How many recent messages the client-side search fallback scans. Personal accounts match `to` locally within this window, so the default caps how far back a `to` search reaches. Max 5000. | `500` |
377
+ | `OUTLOOK_REQUEST_TIMEOUT_MS` | Inactivity timeout for each Graph request attempt, in milliseconds: an attempt that receives no data for this long is abandoned with a timeout error. It isn't an overall deadline, so a slow response that keeps arriving isn't cut off. Throttled (`429`) and busy (`503`/`504`) responses are retried automatically, honouring `Retry-After`. | `60000` |
370
378
 
371
379
  ### MCP Client Configuration
372
380
 
@@ -407,19 +415,27 @@ No auth server needed. Works everywhere, including remote/headless environments.
407
415
 
408
416
  ### Browser Redirect Flow (Alternative)
409
417
 
410
- For localhost development or if you prefer the traditional OAuth flow:
418
+ For localhost development or if you prefer the traditional OAuth flow, start the auth server. From a source checkout:
411
419
 
412
420
  ```bash
413
421
  npm run auth-server
414
422
  ```
415
423
 
416
- This starts a local server on port 3333 to handle the OAuth callback.
424
+ From a global npm install:
425
+
426
+ ```bash
427
+ node "$(npm root -g)/@littlebearapps/outlook-assistant/outlook-auth-server.js"
428
+ ```
429
+
430
+ This starts a local server on port 3333 to handle the OAuth callback. (The `outlook-assistant` command itself only accepts `--version` and `--help`; any other argument exits with an error.)
417
431
 
418
432
  1. In your AI assistant, use the `auth` tool with `action=authenticate, method=browser`
419
433
  2. Open the provided URL in your browser
420
434
  3. Sign in and grant permissions — tokens are saved automatically
421
435
 
422
- > **Note**: The auth server reads `OUTLOOK_CLIENT_ID` and `OUTLOOK_CLIENT_SECRET` from environment variables. Your MCP client's `"env"` config only applies to the MCP server process, not a separately-started auth server.
436
+ > **Note**: The auth server reads `OUTLOOK_CLIENT_ID` and `OUTLOOK_CLIENT_SECRET` from environment variables or a `.env` file in the directory you start it from. Your MCP client's `"env"` config only applies to the MCP server process, not a separately-started auth server.
437
+ >
438
+ > **Shared mailboxes**: the browser flow requests the configured scopes with no fallback. If you enable `OUTLOOK_SHARED_MAILBOX`, sign in with the device-code flow.
423
439
 
424
440
  ## Directory Structure
425
441
 
@@ -429,7 +445,7 @@ outlook-assistant/
429
445
  ├── config.js # Configuration settings
430
446
  ├── outlook-auth-server.js # OAuth server (port 3333)
431
447
  ├── auth/ # Authentication module (1 tool)
432
- ├── email/ # Email module (7 tools)
448
+ ├── email/ # Email module (8 tools)
433
449
  │ ├── mail-tips.js # Pre-send recipient validation
434
450
  │ ├── headers.js # Email header retrieval
435
451
  │ ├── mime.js # Raw MIME/EML content
@@ -437,15 +453,20 @@ outlook-assistant/
437
453
  │ ├── attachments.js # Attachment operations
438
454
  │ └── ...
439
455
  ├── calendar/ # Calendar module (3 tools)
456
+ │ ├── attendees.js # Attendee builder (email or {email, type})
457
+ │ └── list.js # list-events filters
440
458
  ├── contacts/ # Contacts module (2 tools)
441
459
  ├── categories/ # Categories module (3 tools)
442
460
  ├── settings/ # Settings module (1 tool)
443
- ├── folder/ # Folder module (1 tool)
461
+ ├── folder/ # Folder module (1 tool; resolve.js resolves paths/IDs)
444
462
  ├── rules/ # Rules module (1 tool)
445
463
  ├── advanced/ # Advanced module (2 tools)
446
464
  └── utils/
447
- ├── graph-api.js # Microsoft Graph API client (includes $batch)
465
+ ├── graph-api.js # Microsoft Graph API client (includes $batch, path guards)
466
+ ├── mailbox.js # me vs users/{sharedMailbox} prefix, shared-mailbox opt-in
448
467
  ├── safety.js # Rate limiting, recipient allowlist, dry-run
468
+ ├── safe-write.js # Exclusive, outputDir-confined file writes
469
+ ├── datetime.js # ISO 8601 parsing and timezone conversion
449
470
  ├── odata-helpers.js # OData query building
450
471
  ├── field-presets.js # Token-efficient field selections
451
472
  ├── response-formatter.js # Verbosity levels
@@ -524,8 +545,9 @@ USE_TEST_MODE=true npm start
524
545
  | [Getting Started](docs/how-to/getting-started/connect-outlook-to-claude.md) | Install, configure, and authenticate — start here |
525
546
  | [Azure Setup Guide](docs/guides/azure-setup.md) | Azure account creation, app registration, permissions, and secrets |
526
547
  | [How-To Guides](docs/how-to/index.md) | 29 practical guides for email, calendar, contacts, and settings |
527
- | [Roadmap](ROADMAP.md) | Active milestones (v3.11.2, v3.8.x, v3.12.0+) and recent releases |
528
- | [Troubleshooting & FAQ](docs/how-to/getting-started/verify-your-connection.md#common-connection-problems) | Common problems, re-authentication, and frequently asked questions |
548
+ | [Roadmap](ROADMAP.md) | Active milestones (v3.12.x, v3.8.x, v3.13.0+) and recent releases |
549
+ | [Troubleshooting](docs/troubleshooting.md) | Known errors and fixes, including auth, search, export and shared mailboxes |
550
+ | [FAQ](docs/faq/faq.md) | Install, accounts, permissions, tokens, updates, uninstall |
529
551
  | [Tools Reference](docs/quickrefs/tools-reference.md) | All 22 tools with parameters |
530
552
  | [AI Agent Guide](docs/how-to/ai-agents/using-outlook-assistant-in-agents.md) | Tool selection and workflow patterns for AI agents |
531
553
 
@@ -536,9 +558,10 @@ Full documentation: [docs/](docs/README.md)
536
558
  - **Personal account search**: Free-text `query` and the raw `searchExpression` (formerly `kqlQuery`) rely on Microsoft's `$search` API, which has limited support on personal Outlook.com accounts. `query` mitigates this with progressive fallback (OData filters, boolean filters, then a client-side scan). Field-scoped `$search` (e.g. `subject:"…"`) is rejected outright there; since v3.10.0 `from:`/`to:`/`subject:` expressions are translated into the closest equivalent OData filters and retried, but boolean operators, grouping, wildcards and other field prefixes are not — those still terminate with an explicit no-results rather than a silent broader search. Structured filters (`from`, `subject`, `to`, `receivedAfter`) remain the most direct route. Cross-folder search (`searchAllFolders: true`) returns a superset of inbox-only results. Note that `query` and `searchExpression` are not interchangeable there: `searchExpression` goes to `$search`, which matches the whole message including the body and ranks by relevance rather than date, while `query` falls back to a subject substring match that never reads bodies.
537
559
  - **`to` search depth on personal accounts**: the server-side recipient filter is rejected, so `to` is matched locally over the 500 most recent messages (`OUTLOOK_SEARCH_SCAN_LIMIT`, max 5000). On a large archive that excludes older mail — pair `to` with `receivedAfter`/`receivedBefore`. Since v3.11.1 the response says so whenever the scan was truncated, whether or not it matched.
538
560
  - **Focused Inbox**: Only available on work/school Microsoft 365 accounts.
539
- - **Shared mailboxes**: Require `Mail.Read.Shared` permission and a work/school account.
561
+ - **Shared mailboxes**: Require a work/school account and are **opt-in**: set `OUTLOOK_SHARED_MAILBOX=read` (read) or `=true` (read and organise), restart the server, then re-authenticate with `auth action=authenticate force=true`. Until then, `sharedMailbox` calls are refused with setup guidance (`access-shared-mailbox` keeps its previous well-known-folder behaviour). `auth action=about` shows whether the shared scopes were actually granted. Support covers reading and organising only. Reading needs `Mail.Read.Shared`; organising (move/categorise/flag/mark-read/create folders via `sharedMailbox`) needs `Mail.ReadWrite.Shared` — add it in Azure and re-authenticate (until then, shared-scoped writes fail with 403; they never fall back to your own mailbox). Custom subfolders are supported — pass `folder` as a display name or nested path (e.g. `Inbox/Vendors/Acme`), a raw `folderId`, or use `listFolders: true` (or `folders action=list, sharedMailbox: …`) to discover them. **Sending, drafts, replies, and forwards from a shared mailbox are not supported** — `send-email` and `draft` (including reply/reply-all/forward) always act on the signed-in user's own mailbox, and `Mail.Send.Shared` is not requested.
540
562
  - **Meeting room search**: Requires `Place.Read.All` permission with admin consent (work/school accounts only).
541
- - **Export default path**: Exports save to the system temp directory by default. Use `savePath` or `outputDir` to specify a different location.
563
+ - **Export default path**: Exports and attachment downloads save to the system temp directory by default. Use `outputDir` (or `savePath`) to choose a different location.
564
+ - **`list-events` date filters**: `startAfter`/`startBefore` must include `Z` or a ±hh:mm offset; zone-less and date-only values are rejected rather than guessed.
542
565
 
543
566
  ## Contributing
544
567