apple-mail-mcp 2.20.10 → 2.20.11

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/build/cli.js CHANGED
@@ -58328,23 +58328,9 @@ function buildCriteria(a, listMode) {
58328
58328
  if (a.dateTo) c.before = new Date(a.dateTo);
58329
58329
  if (a.flagColorIndex !== void 0) {
58330
58330
  c.flagged = true;
58331
- Object.assign(c, flagColorSearchTerm(a.flagColorIndex));
58332
58331
  }
58333
58332
  return c;
58334
58333
  }
58335
- function flagColorSearchTerm(colorIndex) {
58336
- const { set, clear } = mailFlagBitsFor(colorIndex);
58337
- const terms = [
58338
- ...set.map((kw) => ({ keyword: kw })),
58339
- ...clear.map((kw) => ({ unKeyword: kw }))
58340
- ];
58341
- if (terms.length === 0) return {};
58342
- if (terms.length === 1) return terms[0];
58343
- const negated = terms.map(
58344
- (t) => "keyword" in t ? { unKeyword: t.keyword } : { keyword: t.unKeyword }
58345
- );
58346
- return { not: { or: negated } };
58347
- }
58348
58334
  function validDate(d) {
58349
58335
  if (!d) return void 0;
58350
58336
  const parsed = d instanceof Date ? d : new Date(d);
@@ -58493,6 +58479,16 @@ async function searchUids(client, path3, criteria, size) {
58493
58479
  `IMAP SEARCH on "${path3}"${sized} failed: ` + (cause ? errText(cause) : "the server rejected it or the connection dropped before it answered (on a mailbox this size, usually a server-side timeout)")
58494
58480
  );
58495
58481
  }
58482
+ async function filterUidsByColor(client, uids, colorIndex) {
58483
+ if (uids.length === 0) return uids;
58484
+ const keep = /* @__PURE__ */ new Set();
58485
+ for await (const msg of client.fetch(uids.join(","), { uid: true, flags: true }, { uid: true })) {
58486
+ if (typeof msg?.uid !== "number") continue;
58487
+ const idx = mailFlagColorIndex(msg.flags);
58488
+ if (colorIndex === 0 ? idx === void 0 : idx === colorIndex) keep.add(msg.uid);
58489
+ }
58490
+ return uids.filter((uid) => keep.has(uid));
58491
+ }
58496
58492
  function mergeFetched(into, msg) {
58497
58493
  const prev = into.get(msg.uid);
58498
58494
  if (!prev) {
@@ -58648,14 +58644,15 @@ async function listLargeMailbox(client, exists, page) {
58648
58644
  totalExact: true
58649
58645
  };
58650
58646
  }
58651
- async function searchLargeMailbox(client, path3, criteria, exists, page) {
58647
+ async function searchLargeMailbox(client, path3, criteria, exists, page, colorIndex) {
58652
58648
  const walk = await walkWindows(exists, page, FIRST_SEARCH_WINDOW, async (lo, hi, width) => {
58653
- const found = await searchUids(client, path3, { ...criteria, seq: `${lo}:${hi}` }, exists);
58649
+ let found = await searchUids(client, path3, { ...criteria, seq: `${lo}:${hi}` }, exists);
58654
58650
  if (found.length > width) {
58655
58651
  throw new Error(
58656
58652
  `IMAP SEARCH on "${path3}" reported ${found.length} matches in a ${width}-message window \u2014 discarding as corrupted rather than trusting it (see #246).`
58657
58653
  );
58658
58654
  }
58655
+ if (colorIndex !== void 0) found = await filterUidsByColor(client, found, colorIndex);
58659
58656
  return found;
58660
58657
  });
58661
58658
  return {
@@ -58664,14 +58661,14 @@ async function searchLargeMailbox(client, path3, criteria, exists, page) {
58664
58661
  totalExact: walk.exhausted
58665
58662
  };
58666
58663
  }
58667
- async function fetchMailboxMatches(client, path3, criteria, page) {
58664
+ async function fetchMailboxMatches(client, path3, criteria, page, colorIndex) {
58668
58665
  const lock = await client.getMailboxLock(path3);
58669
58666
  try {
58670
58667
  const exists = await statusMessageCount(client, path3);
58671
58668
  if (exists === 0) return { messages: [], omitted: [], total: 0, totalExact: true };
58672
58669
  if (exists !== void 0 && exists > LARGE_MAILBOX_MESSAGES) {
58673
58670
  try {
58674
- return isUnfiltered(criteria) ? await listLargeMailbox(client, exists, page) : await searchLargeMailbox(client, path3, criteria, exists, page);
58671
+ return isUnfiltered(criteria) ? await listLargeMailbox(client, exists, page) : await searchLargeMailbox(client, path3, criteria, exists, page, colorIndex);
58675
58672
  } catch (error2) {
58676
58673
  const detail = errText(error2);
58677
58674
  throw new Error(
@@ -58679,16 +58676,20 @@ async function fetchMailboxMatches(client, path3, criteria, page) {
58679
58676
  );
58680
58677
  }
58681
58678
  }
58682
- const uids = await searchUids(client, path3, criteria, exists);
58683
- if (uids.length === 0 || page.take === 0) {
58684
- return { messages: [], omitted: [], total: uids.length, totalExact: true };
58679
+ const rawUids = await searchUids(client, path3, criteria, exists);
58680
+ if (rawUids.length === 0) {
58681
+ return { messages: [], omitted: [], total: 0, totalExact: true };
58685
58682
  }
58686
58683
  const messages = exists ?? (await client.status(path3, { messages: true })).messages ?? void 0;
58687
- if (typeof messages === "number" && uids.length > messages) {
58684
+ if (typeof messages === "number" && rawUids.length > messages) {
58688
58685
  throw new Error(
58689
- `IMAP SEARCH on "${path3}" reported ${uids.length} matches, more than the mailbox's own ${messages} messages \u2014 discarding as corrupted rather than trusting it (see #246).`
58686
+ `IMAP SEARCH on "${path3}" reported ${rawUids.length} matches, more than the mailbox's own ${messages} messages \u2014 discarding as corrupted rather than trusting it (see #246).`
58690
58687
  );
58691
58688
  }
58689
+ const uids = colorIndex !== void 0 ? await filterUidsByColor(client, rawUids, colorIndex) : rawUids;
58690
+ if (uids.length === 0 || page.take === 0) {
58691
+ return { messages: [], omitted: [], total: uids.length, totalExact: true };
58692
+ }
58692
58693
  const newest = uids.slice().reverse().slice(page.skip, page.skip + page.take);
58693
58694
  return { ...pageRows(await fetchRows(client, newest)), total: uids.length, totalExact: true };
58694
58695
  } finally {
@@ -58738,7 +58739,7 @@ async function run(args, listMode, deps) {
58738
58739
  }
58739
58740
  try {
58740
58741
  const outcome = await raceStop(
58741
- fetchMailboxMatches(client, path3, criteria, page),
58742
+ fetchMailboxMatches(client, path3, criteria, page, args.flagColorIndex),
58742
58743
  deps.signal
58743
58744
  );
58744
58745
  if (outcome === STOPPED) {
package/build/index.js CHANGED
@@ -65949,23 +65949,9 @@ function buildCriteria(a, listMode) {
65949
65949
  if (a.dateTo) c.before = new Date(a.dateTo);
65950
65950
  if (a.flagColorIndex !== void 0) {
65951
65951
  c.flagged = true;
65952
- Object.assign(c, flagColorSearchTerm(a.flagColorIndex));
65953
65952
  }
65954
65953
  return c;
65955
65954
  }
65956
- function flagColorSearchTerm(colorIndex) {
65957
- const { set, clear } = mailFlagBitsFor(colorIndex);
65958
- const terms = [
65959
- ...set.map((kw) => ({ keyword: kw })),
65960
- ...clear.map((kw) => ({ unKeyword: kw }))
65961
- ];
65962
- if (terms.length === 0) return {};
65963
- if (terms.length === 1) return terms[0];
65964
- const negated = terms.map(
65965
- (t) => "keyword" in t ? { unKeyword: t.keyword } : { keyword: t.unKeyword }
65966
- );
65967
- return { not: { or: negated } };
65968
- }
65969
65955
  function validDate(d) {
65970
65956
  if (!d) return void 0;
65971
65957
  const parsed = d instanceof Date ? d : new Date(d);
@@ -66114,6 +66100,16 @@ async function searchUids(client, path3, criteria, size) {
66114
66100
  `IMAP SEARCH on "${path3}"${sized} failed: ` + (cause ? errText2(cause) : "the server rejected it or the connection dropped before it answered (on a mailbox this size, usually a server-side timeout)")
66115
66101
  );
66116
66102
  }
66103
+ async function filterUidsByColor(client, uids, colorIndex) {
66104
+ if (uids.length === 0) return uids;
66105
+ const keep = /* @__PURE__ */ new Set();
66106
+ for await (const msg of client.fetch(uids.join(","), { uid: true, flags: true }, { uid: true })) {
66107
+ if (typeof msg?.uid !== "number") continue;
66108
+ const idx = mailFlagColorIndex(msg.flags);
66109
+ if (colorIndex === 0 ? idx === void 0 : idx === colorIndex) keep.add(msg.uid);
66110
+ }
66111
+ return uids.filter((uid) => keep.has(uid));
66112
+ }
66117
66113
  function mergeFetched(into, msg) {
66118
66114
  const prev = into.get(msg.uid);
66119
66115
  if (!prev) {
@@ -66269,14 +66265,15 @@ async function listLargeMailbox(client, exists, page) {
66269
66265
  totalExact: true
66270
66266
  };
66271
66267
  }
66272
- async function searchLargeMailbox(client, path3, criteria, exists, page) {
66268
+ async function searchLargeMailbox(client, path3, criteria, exists, page, colorIndex) {
66273
66269
  const walk = await walkWindows(exists, page, FIRST_SEARCH_WINDOW, async (lo, hi, width) => {
66274
- const found = await searchUids(client, path3, { ...criteria, seq: `${lo}:${hi}` }, exists);
66270
+ let found = await searchUids(client, path3, { ...criteria, seq: `${lo}:${hi}` }, exists);
66275
66271
  if (found.length > width) {
66276
66272
  throw new Error(
66277
66273
  `IMAP SEARCH on "${path3}" reported ${found.length} matches in a ${width}-message window \u2014 discarding as corrupted rather than trusting it (see #246).`
66278
66274
  );
66279
66275
  }
66276
+ if (colorIndex !== void 0) found = await filterUidsByColor(client, found, colorIndex);
66280
66277
  return found;
66281
66278
  });
66282
66279
  return {
@@ -66285,14 +66282,14 @@ async function searchLargeMailbox(client, path3, criteria, exists, page) {
66285
66282
  totalExact: walk.exhausted
66286
66283
  };
66287
66284
  }
66288
- async function fetchMailboxMatches(client, path3, criteria, page) {
66285
+ async function fetchMailboxMatches(client, path3, criteria, page, colorIndex) {
66289
66286
  const lock = await client.getMailboxLock(path3);
66290
66287
  try {
66291
66288
  const exists = await statusMessageCount(client, path3);
66292
66289
  if (exists === 0) return { messages: [], omitted: [], total: 0, totalExact: true };
66293
66290
  if (exists !== void 0 && exists > LARGE_MAILBOX_MESSAGES) {
66294
66291
  try {
66295
- return isUnfiltered(criteria) ? await listLargeMailbox(client, exists, page) : await searchLargeMailbox(client, path3, criteria, exists, page);
66292
+ return isUnfiltered(criteria) ? await listLargeMailbox(client, exists, page) : await searchLargeMailbox(client, path3, criteria, exists, page, colorIndex);
66296
66293
  } catch (error3) {
66297
66294
  const detail = errText2(error3);
66298
66295
  throw new Error(
@@ -66300,16 +66297,20 @@ async function fetchMailboxMatches(client, path3, criteria, page) {
66300
66297
  );
66301
66298
  }
66302
66299
  }
66303
- const uids = await searchUids(client, path3, criteria, exists);
66304
- if (uids.length === 0 || page.take === 0) {
66305
- return { messages: [], omitted: [], total: uids.length, totalExact: true };
66300
+ const rawUids = await searchUids(client, path3, criteria, exists);
66301
+ if (rawUids.length === 0) {
66302
+ return { messages: [], omitted: [], total: 0, totalExact: true };
66306
66303
  }
66307
66304
  const messages = exists ?? (await client.status(path3, { messages: true })).messages ?? void 0;
66308
- if (typeof messages === "number" && uids.length > messages) {
66305
+ if (typeof messages === "number" && rawUids.length > messages) {
66309
66306
  throw new Error(
66310
- `IMAP SEARCH on "${path3}" reported ${uids.length} matches, more than the mailbox's own ${messages} messages \u2014 discarding as corrupted rather than trusting it (see #246).`
66307
+ `IMAP SEARCH on "${path3}" reported ${rawUids.length} matches, more than the mailbox's own ${messages} messages \u2014 discarding as corrupted rather than trusting it (see #246).`
66311
66308
  );
66312
66309
  }
66310
+ const uids = colorIndex !== void 0 ? await filterUidsByColor(client, rawUids, colorIndex) : rawUids;
66311
+ if (uids.length === 0 || page.take === 0) {
66312
+ return { messages: [], omitted: [], total: uids.length, totalExact: true };
66313
+ }
66313
66314
  const newest = uids.slice().reverse().slice(page.skip, page.skip + page.take);
66314
66315
  return { ...pageRows(await fetchRows(client, newest)), total: uids.length, totalExact: true };
66315
66316
  } finally {
@@ -66359,7 +66360,7 @@ async function run(args, listMode, deps) {
66359
66360
  }
66360
66361
  try {
66361
66362
  const outcome = await raceStop(
66362
- fetchMailboxMatches(client, path3, criteria, page),
66363
+ fetchMailboxMatches(client, path3, criteria, page, args.flagColorIndex),
66363
66364
  deps.signal
66364
66365
  );
66365
66366
  if (outcome === STOPPED) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "apple-mail-mcp",
3
- "version": "2.20.10",
3
+ "version": "2.20.11",
4
4
  "description": "MCP server for Apple Mail - read, search, send, and manage emails via Claude and other AI assistants",
5
5
  "type": "module",
6
6
  "main": "build/index.js",