apple-mail-mcp 1.6.0 → 1.6.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.
package/README.md CHANGED
@@ -149,6 +149,27 @@ Search for messages matching criteria. Searches all accounts by default.
149
149
  | `dateTo` | string | No | End date filter (e.g., "March 1, 2026") |
150
150
  | `limit` | number | No | Max results (default: 50) |
151
151
 
152
+ **Large mailboxes & partial results.** Apple Mail's AppleScript bridge cannot
153
+ search very large IMAP/Gmail mailboxes (tens of thousands of messages) before
154
+ the Apple Event times out — empirically even reading the newest 20 messages of
155
+ a 44k-message mailbox takes ~45s. To avoid burning minutes only to return a
156
+ misleading empty result, an unscoped (all-mailboxes) search **skips** mailboxes
157
+ whose message count exceeds a threshold (default **5000**), enforces a
158
+ per-account time budget, and **reports** anything it skipped or that timed out
159
+ rather than silently returning nothing. When coverage is incomplete the result
160
+ includes an explicit warning, e.g.:
161
+
162
+ ```
163
+ ⚠️ Partial results — this is NOT a confirmed "no such mail":
164
+ - skipped mailbox(es) too large to search via AppleScript: Gmail / All Mail (44287) — scope the search with `mailbox` + a `dateFrom`/`dateTo` window to target them
165
+ ```
166
+
167
+ To search inside a large mailbox, scope the call with `mailbox` (and ideally a
168
+ `dateFrom`/`dateTo` window). Tune or disable the skip threshold with the
169
+ `APPLE_MAIL_MAX_SEARCH_MAILBOX` environment variable (default `5000`; set to `0`
170
+ to disable the guard and attempt every mailbox regardless of size).
171
+ ([#24](https://github.com/sweetrb/apple-mail-mcp/issues/24))
172
+
152
173
  ---
153
174
 
154
175
  #### `get-message`
@@ -778,6 +799,7 @@ The entrypoint is written as:
778
799
  | No sending HTML email | Emails are sent as plain text; reading HTML content is supported |
779
800
  | Attachments require absolute paths | File attachments must use full absolute paths (e.g., `/Users/me/file.pdf`) |
780
801
  | No smart mailboxes | Cannot access Smart Mailboxes via AppleScript |
802
+ | Very large mailboxes not searchable | Apple Mail's AppleScript bridge times out on mailboxes with tens of thousands of messages, so unscoped `search-messages` skips mailboxes above `APPLE_MAIL_MAX_SEARCH_MAILBOX` (default 5000) and reports them as a partial result. Scope with `mailbox` + a date window to search inside one. ([#24](https://github.com/sweetrb/apple-mail-mcp/issues/24)) |
781
803
  | In-memory templates | Email templates are not persisted across server restarts |
782
804
  | Numeric-only message IDs | Message IDs must contain only digits (validated by schema) |
783
805
  | Batch size cap | Batch operations are limited to 100 messages per request |
@@ -849,6 +871,12 @@ The `\\\\` in JSON becomes `\\` in the actual string, which represents a single
849
871
  - Message IDs change if the message is moved between mailboxes
850
872
  - Use `search-messages` to find the current message ID
851
873
 
874
+ ### `search-messages` says "Partial results" or skips a mailbox
875
+ - This is expected for very large IMAP/Gmail mailboxes (e.g. Gmail's `All Mail`, `Important`): Apple Mail can't scan them via AppleScript before timing out, so they're skipped and named in the result rather than silently returning empty.
876
+ - To search inside one, scope the call with `mailbox` **and** a `dateFrom`/`dateTo` window.
877
+ - Raise or disable the threshold with `APPLE_MAIL_MAX_SEARCH_MAILBOX` (default `5000`; `0` disables the guard) — note that disabling it can make a single search take minutes.
878
+ - A `Partial results` warning means coverage was incomplete; it is **not** a confirmed "no such mail."
879
+
852
880
  ### "Account not found"
853
881
  - Account names must match exactly (case-sensitive)
854
882
  - Use `list-accounts` to see exact account names
package/build/index.js CHANGED
@@ -136,14 +136,35 @@ server.tool("search-messages", {
136
136
  dateTo: DATE_FILTER_SCHEMA.describe("End date filter (e.g., 'March 1, 2026')"),
137
137
  limit: z.number().optional().describe("Maximum number of results (default: 50)"),
138
138
  }, withErrorHandling(({ query, mailbox, account, limit = 50, dateFrom, dateTo, from, subject, isRead, isFlagged, }) => {
139
- const messages = mailManager.searchMessages(query, mailbox, account, limit, dateFrom, dateTo, from, subject, isRead, isFlagged);
139
+ const { messages, diagnostics } = mailManager.searchMessagesWithDiagnostics(query, mailbox, account, limit, dateFrom, dateTo, from, subject, isRead, isFlagged);
140
+ // Build a coverage note when the search couldn't reach everything, so a
141
+ // caller never mistakes an incomplete search for a confirmed "no matches"
142
+ // (issue #24).
143
+ const coverageNotes = [];
144
+ if (diagnostics.timedOutAccounts.length > 0) {
145
+ coverageNotes.push(`timed out (no results) for account(s): ${diagnostics.timedOutAccounts.join(", ")}`);
146
+ }
147
+ if (diagnostics.skippedLargeMailboxes.length > 0) {
148
+ coverageNotes.push(`skipped mailbox(es) too large to search via AppleScript: ${diagnostics.skippedLargeMailboxes.join(", ")} — scope the search with \`mailbox\` + a \`dateFrom\`/\`dateTo\` window to target them`);
149
+ }
150
+ if (diagnostics.notSearchedMailboxes.length > 0) {
151
+ coverageNotes.push(`could not finish searching mailbox(es): ${diagnostics.notSearchedMailboxes.join(", ")}`);
152
+ }
153
+ const coverageBlock = coverageNotes.length > 0
154
+ ? `\n\n⚠️ Partial results — this is NOT a confirmed "no such mail":\n${coverageNotes
155
+ .map((n) => ` - ${n}`)
156
+ .join("\n")}`
157
+ : "";
140
158
  if (messages.length === 0) {
141
- return successResponse("No messages found matching criteria");
159
+ const base = diagnostics.partial
160
+ ? "No messages found in the portions that were searched."
161
+ : "No messages found matching criteria";
162
+ return successResponse(`${base}${coverageBlock}`);
142
163
  }
143
164
  const messageList = messages
144
165
  .map((m) => ` - ID: ${m.id} | ${m.dateReceived.toLocaleDateString()} | ${m.subject} (from: ${m.sender}) [${m.isRead ? "read" : "unread"}]`)
145
166
  .join("\n");
146
- return successResponse(`Found ${messages.length} message(s):\n${messageList}`);
167
+ return successResponse(`Found ${messages.length} message(s):\n${messageList}${coverageBlock}`);
147
168
  }, "Error searching messages"));
148
169
  // --- get-message ---
149
170
  server.tool("get-message", {
@@ -12,7 +12,29 @@
12
12
  *
13
13
  * @module services/appleMailManager
14
14
  */
15
- import type { Message, MessageContent, Mailbox, Account, Attachment, HealthCheckResult, MailStats, BatchOperationResult, SyncStatus, RecentlyReceivedStats, MailRule, Contact, EmailTemplate, SerialEmailRecipient, SerialEmailResult } from "../types.js";
15
+ import type { Message, MessageContent, Mailbox, Account, Attachment, HealthCheckResult, MailStats, BatchOperationResult, SyncStatus, RecentlyReceivedStats, MailRule, Contact, EmailTemplate, SerialEmailRecipient, SerialEmailResult, SearchDiagnostics, SearchResult } from "../types.js";
16
+ /**
17
+ * Merge a per-account SearchDiagnostics into an aggregate (all-accounts) one.
18
+ *
19
+ * Exported for unit testing.
20
+ */
21
+ export declare function mergeSearchDiagnostics(into: SearchDiagnostics, from: SearchDiagnostics): void;
22
+ /**
23
+ * Split a per-account search payload into its message-list portion and parsed
24
+ * diagnostics. The AppleScript appends a trailer of the form:
25
+ *
26
+ * <messages>|||DIAG|||timedOut=true|||F|||skipped=Foo (9000)|||M||||||F|||notSearched=Bar|||M|||
27
+ *
28
+ * `skipped`/`notSearched` are `|||M|||`-separated mailbox names, each prefixed
29
+ * with the account name on the way out so the aggregate result is unambiguous.
30
+ *
31
+ * Exported (pure, no Mail.app dependency) for unit testing — this is the logic
32
+ * that turns a swallowed timeout into a visible partial result (issue #24).
33
+ */
34
+ export declare function splitSearchDiagnostics(output: string, account: string): {
35
+ payload: string;
36
+ diagnostics: SearchDiagnostics;
37
+ };
16
38
  /**
17
39
  * Emits AppleScript that builds a date into the variable `varName` from numeric
18
40
  * components.
@@ -127,6 +149,30 @@ export declare class AppleMailManager {
127
149
  * @returns Array of matching messages
128
150
  */
129
151
  searchMessages(query?: string, mailbox?: string, account?: string, limit?: number, dateFrom?: string, dateTo?: string, from?: string, subject?: string, isRead?: boolean, isFlagged?: boolean): Message[];
152
+ /**
153
+ * Search for messages, returning both the matches and diagnostics describing
154
+ * how complete the search was.
155
+ *
156
+ * This is the correctness fix for issue #24. The previous implementation ran
157
+ * an unbounded `messages of mb whose <predicate>` over every mailbox in an
158
+ * account; on large IMAP/Gmail mailboxes (tens of thousands of messages) that
159
+ * single Apple Event exceeded the timeout, the error was swallowed by a `try`,
160
+ * and the function returned a clean — but wrong — empty result. Callers/agents
161
+ * then confidently reported "no such mail."
162
+ *
163
+ * Two changes fix that:
164
+ * 1. Cheap count-guard: mailboxes larger than the scan threshold are skipped
165
+ * (Apple Mail can't search them before timing out anyway) and reported.
166
+ * 2. Honest diagnostics: per-account/per-mailbox timeouts are surfaced as a
167
+ * `partial` result with the affected scopes named, instead of an empty
168
+ * "success."
169
+ */
170
+ searchMessagesWithDiagnostics(query?: string, mailbox?: string, account?: string, limit?: number, dateFrom?: string, dateTo?: string, from?: string, subject?: string, isRead?: boolean, isFlagged?: boolean): SearchResult;
171
+ /**
172
+ * Split a per-account search payload into its message list and the DIAG
173
+ * trailer, parse both, and return a SearchResult. See searchMessagesWithDiagnostics.
174
+ */
175
+ private parseSearchResult;
130
176
  /**
131
177
  * Get a message by ID.
132
178
  *
@@ -1 +1 @@
1
- {"version":3,"file":"appleMailManager.d.ts","sourceRoot":"","sources":["../../src/services/appleMailManager.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"appleMailManager.d.ts","sourceRoot":"","sources":["../../src/services/appleMailManager.ts"],"names":[],"mappings":"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"}
@@ -19,6 +19,94 @@ import { homedir } from "os";
19
19
  import { executeAppleScript } from "../utils/applescript.js";
20
20
  import { parseMimeAttachments, extractMimeAttachment } from "../utils/mimeParse.js";
21
21
  // =============================================================================
22
+ // Search Tuning (issue #24)
23
+ // =============================================================================
24
+ /**
25
+ * Mailboxes larger than this are skipped during an unscoped (all-mailboxes)
26
+ * search rather than scanned. Apple Mail's AppleScript bridge cannot search a
27
+ * mailbox of this size before the Apple Event timeout fires — empirically even
28
+ * reading the newest 20 messages of a 44k-message Gmail mailbox took ~47s — so
29
+ * attempting it only burns the time budget and yields a misleading empty
30
+ * result. `count of messages` is cheap (Mail keeps it cached), so the guard is
31
+ * effectively free. The skipped mailboxes are reported back to the caller.
32
+ *
33
+ * Override with APPLE_MAIL_MAX_SEARCH_MAILBOX (set to 0 to disable the guard).
34
+ */
35
+ function getMailboxScanThreshold() {
36
+ const raw = process.env.APPLE_MAIL_MAX_SEARCH_MAILBOX;
37
+ if (raw !== undefined) {
38
+ const n = Number(raw);
39
+ if (Number.isFinite(n) && n >= 0)
40
+ return n;
41
+ }
42
+ return 5000;
43
+ }
44
+ /**
45
+ * Per-account wall-clock budget (seconds) enforced *inside* the AppleScript so
46
+ * a single account can't consume minutes. Kept comfortably below the osascript
47
+ * process timeout (see searchMessages) so the script exits and reports a
48
+ * partial result rather than being SIGKILLed with no diagnostics.
49
+ */
50
+ const SEARCH_ACCOUNT_BUDGET_SECONDS = 30;
51
+ /** osascript process timeout for a per-account search (ms). */
52
+ const SEARCH_ACCOUNT_TIMEOUT_MS = 45000;
53
+ /** Separator between the message payload and the diagnostics trailer. */
54
+ const DIAG_MARKER = "|||DIAG|||";
55
+ /**
56
+ * Merge a per-account SearchDiagnostics into an aggregate (all-accounts) one.
57
+ *
58
+ * Exported for unit testing.
59
+ */
60
+ export function mergeSearchDiagnostics(into, from) {
61
+ into.timedOutAccounts.push(...from.timedOutAccounts);
62
+ into.skippedLargeMailboxes.push(...from.skippedLargeMailboxes);
63
+ into.notSearchedMailboxes.push(...from.notSearchedMailboxes);
64
+ if (from.partial)
65
+ into.partial = true;
66
+ }
67
+ /**
68
+ * Split a per-account search payload into its message-list portion and parsed
69
+ * diagnostics. The AppleScript appends a trailer of the form:
70
+ *
71
+ * <messages>|||DIAG|||timedOut=true|||F|||skipped=Foo (9000)|||M||||||F|||notSearched=Bar|||M|||
72
+ *
73
+ * `skipped`/`notSearched` are `|||M|||`-separated mailbox names, each prefixed
74
+ * with the account name on the way out so the aggregate result is unambiguous.
75
+ *
76
+ * Exported (pure, no Mail.app dependency) for unit testing — this is the logic
77
+ * that turns a swallowed timeout into a visible partial result (issue #24).
78
+ */
79
+ export function splitSearchDiagnostics(output, account) {
80
+ const markerIdx = output.lastIndexOf(DIAG_MARKER);
81
+ const payload = markerIdx >= 0 ? output.slice(0, markerIdx) : output;
82
+ const trailer = markerIdx >= 0 ? output.slice(markerIdx + DIAG_MARKER.length) : "";
83
+ const diagnostics = {
84
+ partial: false,
85
+ timedOutAccounts: [],
86
+ skippedLargeMailboxes: [],
87
+ notSearchedMailboxes: [],
88
+ };
89
+ if (trailer) {
90
+ const fields = trailer.split("|||F|||");
91
+ const getField = (key) => {
92
+ const f = fields.find((x) => x.startsWith(`${key}=`));
93
+ return f ? f.slice(key.length + 1) : "";
94
+ };
95
+ const splitList = (raw) => raw
96
+ .split("|||M|||")
97
+ .map((s) => s.trim())
98
+ .filter((s) => s.length > 0);
99
+ diagnostics.skippedLargeMailboxes = splitList(getField("skipped")).map((mb) => `${account} / ${mb}`);
100
+ diagnostics.notSearchedMailboxes = splitList(getField("notSearched")).map((mb) => `${account} / ${mb}`);
101
+ if (getField("timedOut") === "true")
102
+ diagnostics.partial = true;
103
+ }
104
+ if (diagnostics.skippedLargeMailboxes.length > 0 || diagnostics.notSearchedMailboxes.length > 0) {
105
+ diagnostics.partial = true;
106
+ }
107
+ return { payload, diagnostics };
108
+ }
109
+ // =============================================================================
22
110
  // Text Processing Utilities
23
111
  // =============================================================================
24
112
  /**
@@ -336,18 +424,46 @@ export class AppleMailManager {
336
424
  * @returns Array of matching messages
337
425
  */
338
426
  searchMessages(query, mailbox, account, limit = 50, dateFrom, dateTo, from, subject, isRead, isFlagged) {
339
- // If no account specified, search across all accounts
427
+ return this.searchMessagesWithDiagnostics(query, mailbox, account, limit, dateFrom, dateTo, from, subject, isRead, isFlagged).messages;
428
+ }
429
+ /**
430
+ * Search for messages, returning both the matches and diagnostics describing
431
+ * how complete the search was.
432
+ *
433
+ * This is the correctness fix for issue #24. The previous implementation ran
434
+ * an unbounded `messages of mb whose <predicate>` over every mailbox in an
435
+ * account; on large IMAP/Gmail mailboxes (tens of thousands of messages) that
436
+ * single Apple Event exceeded the timeout, the error was swallowed by a `try`,
437
+ * and the function returned a clean — but wrong — empty result. Callers/agents
438
+ * then confidently reported "no such mail."
439
+ *
440
+ * Two changes fix that:
441
+ * 1. Cheap count-guard: mailboxes larger than the scan threshold are skipped
442
+ * (Apple Mail can't search them before timing out anyway) and reported.
443
+ * 2. Honest diagnostics: per-account/per-mailbox timeouts are surfaced as a
444
+ * `partial` result with the affected scopes named, instead of an empty
445
+ * "success."
446
+ */
447
+ searchMessagesWithDiagnostics(query, mailbox, account, limit = 50, dateFrom, dateTo, from, subject, isRead, isFlagged) {
448
+ // If no account specified, search across all accounts and merge diagnostics.
340
449
  if (!account) {
341
450
  const accounts = this.listAccounts();
342
451
  const allMessages = [];
452
+ const diagnostics = {
453
+ partial: false,
454
+ timedOutAccounts: [],
455
+ skippedLargeMailboxes: [],
456
+ notSearchedMailboxes: [],
457
+ };
343
458
  for (const acct of accounts) {
344
459
  if (allMessages.length >= limit)
345
460
  break;
346
461
  const remaining = limit - allMessages.length;
347
- const msgs = this.searchMessages(query, mailbox, acct.name, remaining, dateFrom, dateTo, from, subject, isRead, isFlagged);
348
- allMessages.push(...msgs);
462
+ const res = this.searchMessagesWithDiagnostics(query, mailbox, acct.name, remaining, dateFrom, dateTo, from, subject, isRead, isFlagged);
463
+ allMessages.push(...res.messages);
464
+ mergeSearchDiagnostics(diagnostics, res.diagnostics);
349
465
  }
350
- return allMessages.slice(0, limit);
466
+ return { messages: allMessages.slice(0, limit), diagnostics };
351
467
  }
352
468
  const targetAccount = this.resolveAccount(account);
353
469
  // `query` is a subject-OR-sender substring match; from/subject/isRead/isFlagged
@@ -379,79 +495,136 @@ export class AppleMailManager {
379
495
  }
380
496
  dateFilter = dateChecks.join(" and ");
381
497
  }
498
+ const scanThreshold = getMailboxScanThreshold();
382
499
  let searchCommand;
383
500
  if (mailbox) {
384
- // Search a specific mailbox
501
+ // Search a specific mailbox. The caller explicitly chose this mailbox, so
502
+ // we don't apply the count-guard skip — but we still wrap the scan so a
503
+ // timeout is reported as a partial result rather than a false empty.
385
504
  const targetMailbox = this.resolveMailbox(mailbox, targetAccount);
386
505
  searchCommand = `
387
506
  ${dateSetup}set outputText to ""
507
+ set _timedOut to false
508
+ set _notSearched to ""
388
509
  set theMailbox to mailbox "${escapeForAppleScript(targetMailbox)}"
389
- set allMessages to messages of theMailbox ${searchCondition}
390
510
  set msgCount to 0
391
- repeat with msg in allMessages
392
- if msgCount >= ${limit} then exit repeat
393
- try
394
- ${dateFilter ? `set msgDate to date received of msg\n if not (${dateFilter}) then\n -- skip message outside date range\n else` : ""}
395
- set msgId to id of msg as string
396
- set msgSubject to subject of msg
397
- set msgSender to sender of msg
398
- set d to date received of msg
399
- set msgDateStr to ${AS_DATE_TO_STRING}
400
- set msgRead to read status of msg as string
401
- set msgFlagged to flagged status of msg as string
402
- if msgCount > 0 then set outputText to outputText & "|||ITEM|||"
403
- set outputText to outputText & msgId & "|||" & msgSubject & "|||" & msgSender & "|||" & msgDateStr & "|||" & msgRead & "|||" & msgFlagged
404
- set msgCount to msgCount + 1
405
- ${dateFilter ? "end if" : ""}
406
- end try
407
- end repeat
408
- return outputText
511
+ try
512
+ set allMessages to messages of theMailbox ${searchCondition}
513
+ repeat with msg in allMessages
514
+ if msgCount >= ${limit} then exit repeat
515
+ try
516
+ ${dateFilter ? `set msgDate to date received of msg\n if not (${dateFilter}) then\n -- skip message outside date range\n else` : ""}
517
+ set msgId to id of msg as string
518
+ set msgSubject to subject of msg
519
+ set msgSender to sender of msg
520
+ set d to date received of msg
521
+ set msgDateStr to ${AS_DATE_TO_STRING}
522
+ set msgRead to read status of msg as string
523
+ set msgFlagged to flagged status of msg as string
524
+ if msgCount > 0 then set outputText to outputText & "|||ITEM|||"
525
+ set outputText to outputText & msgId & "|||" & msgSubject & "|||" & msgSender & "|||" & msgDateStr & "|||" & msgRead & "|||" & msgFlagged
526
+ set msgCount to msgCount + 1
527
+ ${dateFilter ? "end if" : ""}
528
+ end try
529
+ end repeat
530
+ on error _errMsg number _errNum
531
+ set _timedOut to true
532
+ set _notSearched to "${escapeForAppleScript(targetMailbox)}|||M|||"
533
+ end try
534
+ return outputText & "${DIAG_MARKER}timedOut=" & (_timedOut as string) & "|||F|||skipped=|||F|||notSearched=" & _notSearched
409
535
  `;
410
536
  }
411
537
  else {
412
- // Search ALL mailboxes — iterate every mailbox in the account, dedup by message ID
538
+ // Search ALL mailboxes — iterate every mailbox in the account, dedup by
539
+ // message ID. Skip mailboxes that exceed the scan threshold (they can't be
540
+ // searched before timing out), enforce a per-account wall-clock budget, and
541
+ // capture per-mailbox timeouts. All three are reported via the DIAG trailer.
542
+ const scanGuard = scanThreshold > 0 ? `mbCount > ${scanThreshold}` : "false";
413
543
  searchCommand = `
414
544
  ${dateSetup}set outputText to ""
415
545
  set msgCount to 0
416
546
  set seenIds to {}
547
+ set _timedOut to false
548
+ set _skipped to ""
549
+ set _notSearched to ""
550
+ set _startedAt to current date
417
551
  repeat with mb in mailboxes
418
552
  if msgCount >= ${limit} then exit repeat
553
+ set mbName to ""
419
554
  try
420
- set allMessages to messages of mb ${searchCondition}
421
- repeat with msg in allMessages
422
- if msgCount >= ${limit} then exit repeat
555
+ set mbName to name of mb
556
+ end try
557
+ if ((current date) - _startedAt) > ${SEARCH_ACCOUNT_BUDGET_SECONDS} then
558
+ set _timedOut to true
559
+ set _notSearched to _notSearched & mbName & "|||M|||"
560
+ else
561
+ set mbCount to 0
562
+ try
563
+ set mbCount to count of messages of mb
564
+ end try
565
+ if (${scanGuard}) then
566
+ set _timedOut to true
567
+ set _skipped to _skipped & mbName & " (" & (mbCount as string) & ")|||M|||"
568
+ else
423
569
  try
424
- set msgId to id of msg as string
425
- if seenIds does not contain msgId then
426
- set end of seenIds to msgId
427
- ${dateFilter ? `set msgDate to date received of msg\n if not (${dateFilter}) then\n -- skip message outside date range\n else` : ""}
428
- set msgSubject to subject of msg
429
- set msgSender to sender of msg
430
- set d to date received of msg
431
- set msgDateStr to ${AS_DATE_TO_STRING}
432
- set msgRead to read status of msg as string
433
- set msgFlagged to flagged status of msg as string
434
- if msgCount > 0 then set outputText to outputText & "|||ITEM|||"
435
- set outputText to outputText & msgId & "|||" & msgSubject & "|||" & msgSender & "|||" & msgDateStr & "|||" & msgRead & "|||" & msgFlagged & "|||" & name of mb
436
- set msgCount to msgCount + 1
437
- ${dateFilter ? "end if" : ""}
438
- end if
570
+ set allMessages to messages of mb ${searchCondition}
571
+ repeat with msg in allMessages
572
+ if msgCount >= ${limit} then exit repeat
573
+ try
574
+ set msgId to id of msg as string
575
+ if seenIds does not contain msgId then
576
+ set end of seenIds to msgId
577
+ ${dateFilter ? `set msgDate to date received of msg\n if not (${dateFilter}) then\n -- skip message outside date range\n else` : ""}
578
+ set msgSubject to subject of msg
579
+ set msgSender to sender of msg
580
+ set d to date received of msg
581
+ set msgDateStr to ${AS_DATE_TO_STRING}
582
+ set msgRead to read status of msg as string
583
+ set msgFlagged to flagged status of msg as string
584
+ if msgCount > 0 then set outputText to outputText & "|||ITEM|||"
585
+ set outputText to outputText & msgId & "|||" & msgSubject & "|||" & msgSender & "|||" & msgDateStr & "|||" & msgRead & "|||" & msgFlagged & "|||" & mbName
586
+ set msgCount to msgCount + 1
587
+ ${dateFilter ? "end if" : ""}
588
+ end if
589
+ end try
590
+ end repeat
591
+ on error _errMsg number _errNum
592
+ set _timedOut to true
593
+ set _notSearched to _notSearched & mbName & "|||M|||"
439
594
  end try
440
- end repeat
441
- end try
595
+ end if
596
+ end if
442
597
  end repeat
443
- return outputText
598
+ return outputText & "${DIAG_MARKER}timedOut=" & (_timedOut as string) & "|||F|||skipped=" & _skipped & "|||F|||notSearched=" & _notSearched
444
599
  `;
445
600
  }
446
601
  const script = buildAccountScopedScript(targetAccount, searchCommand);
447
- const result = executeAppleScript(script, { timeoutMs: 60000 });
602
+ const result = executeAppleScript(script, { timeoutMs: SEARCH_ACCOUNT_TIMEOUT_MS });
448
603
  if (!result.success) {
449
- console.error(`Failed to search messages: ${result.error}`);
450
- return [];
604
+ // Whole-account script failed (most often the osascript process timeout /
605
+ // SIGKILL on an unresponsive account). Surface it as a timeout rather than
606
+ // a false empty result — that confusion is the heart of issue #24.
607
+ console.error(`Failed to search messages in "${targetAccount}": ${result.error}`);
608
+ return {
609
+ messages: [],
610
+ diagnostics: {
611
+ partial: true,
612
+ timedOutAccounts: [targetAccount],
613
+ skippedLargeMailboxes: [],
614
+ notSearchedMailboxes: [],
615
+ },
616
+ };
451
617
  }
452
- if (!result.output.trim())
453
- return [];
454
- return this.parseMessageList(result.output, mailbox || "INBOX", targetAccount);
618
+ return this.parseSearchResult(result.output, mailbox || "INBOX", targetAccount);
619
+ }
620
+ /**
621
+ * Split a per-account search payload into its message list and the DIAG
622
+ * trailer, parse both, and return a SearchResult. See searchMessagesWithDiagnostics.
623
+ */
624
+ parseSearchResult(output, mailbox, account) {
625
+ const { payload, diagnostics } = splitSearchDiagnostics(output, account);
626
+ const messages = payload.trim() ? this.parseMessageList(payload, mailbox, account) : [];
627
+ return { messages, diagnostics };
455
628
  }
456
629
  /**
457
630
  * Get a message by ID.
package/build/types.d.ts CHANGED
@@ -47,6 +47,39 @@ export interface Message {
47
47
  /** Whether the message has attachments */
48
48
  hasAttachments: boolean;
49
49
  }
50
+ /**
51
+ * Per-account / per-mailbox diagnostics for a search, so callers can tell a
52
+ * genuine "no matches" apart from "we couldn't finish searching."
53
+ *
54
+ * Apple Mail's AppleScript bridge is pathologically slow on large IMAP/Gmail
55
+ * mailboxes (tens of thousands of messages): a single `whose` predicate — or
56
+ * even reading the newest 20 messages by index — can blow past the Apple Event
57
+ * timeout. Before this was tracked, those timeouts were swallowed and the
58
+ * search returned a clean (but wrong) empty result. See issue #24.
59
+ */
60
+ export interface SearchDiagnostics {
61
+ /** True if any account/mailbox could not be fully searched (timeout or skip). */
62
+ partial: boolean;
63
+ /** Accounts that timed out entirely (whole-account AppleScript was killed). */
64
+ timedOutAccounts: string[];
65
+ /**
66
+ * Mailboxes skipped because their message count exceeded the scan threshold,
67
+ * formatted as "Account / Mailbox (count)".
68
+ */
69
+ skippedLargeMailboxes: string[];
70
+ /**
71
+ * Mailboxes that were reached but timed out or errored mid-scan, formatted as
72
+ * "Account / Mailbox".
73
+ */
74
+ notSearchedMailboxes: string[];
75
+ }
76
+ /**
77
+ * A search result paired with diagnostics about coverage.
78
+ */
79
+ export interface SearchResult {
80
+ messages: Message[];
81
+ diagnostics: SearchDiagnostics;
82
+ }
50
83
  /**
51
84
  * Represents the content of an email message.
52
85
  */
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "apple-mail-mcp",
3
- "version": "1.6.0",
3
+ "version": "1.6.1",
4
4
  "description": "MCP server for Apple Mail - read, search, send, and manage emails via Claude",
5
5
  "type": "module",
6
6
  "main": "build/index.js",