apple-mail-mcp 2.20.9 → 2.20.10
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 +27 -3
- package/build/cli.js +46 -2
- package/build/index.js +20455 -20380
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -237,12 +237,29 @@ Search for messages matching criteria. Searches all accounts by default.
|
|
|
237
237
|
| `account` | string | No | Account to search in (omit to search all accounts) |
|
|
238
238
|
| `isRead` | boolean | No | Filter by read status |
|
|
239
239
|
| `isFlagged` | boolean | No | Filter by flagged status |
|
|
240
|
+
| `flagColor` | string | No | Filter to messages flagged with exactly this color — see [`flag-message`](#flag-message--unflag-message) for the palette. Implies `isFlagged: true`; pairing this with `isFlagged: false` is rejected. See the flag-color note below. |
|
|
240
241
|
| `dateFrom` | string | No | Start date filter (e.g., "January 1, 2026") |
|
|
241
242
|
| `dateTo` | string | No | End date filter (e.g., "March 1, 2026") |
|
|
242
243
|
| `limit` | number | No | Max results, 1–500 (default: 50) |
|
|
243
244
|
| `offset` | number | No | Newest matches to skip, ≥ 0 (for pagination). IMAP accounts only; without a `mailbox`, `offset` + `limit` may not exceed 5,000 |
|
|
244
245
|
|
|
245
|
-
**Returns:** List of matching messages with ID, date, subject, sender,
|
|
246
|
+
**Returns:** List of matching messages with ID, date, subject, sender, read state,
|
|
247
|
+
and `flagColor` when flagged with an explicit color.
|
|
248
|
+
|
|
249
|
+
**Flag color as a label (#286).** Every row from both backends carries
|
|
250
|
+
`flagColor` (the palette name — `red`, `orange`, `yellow`, `green`, `blue`,
|
|
251
|
+
`purple`, `gray`) whenever the message is flagged with an explicit color;
|
|
252
|
+
omitted for an unflagged message or one flagged with Mail's plain default (no
|
|
253
|
+
color chosen). Combined with the `flagColor` filter above, a colored flag
|
|
254
|
+
works as a label across mailboxes: flag a set of messages with
|
|
255
|
+
`flag-message`/`batch-flag-messages`, then find exactly that set later with
|
|
256
|
+
`search-messages`, without moving anything into a dedicated folder. **Known
|
|
257
|
+
limitation, inherent to Apple's `$MailFlagBit0/1/2` IMAP wire encoding, not
|
|
258
|
+
specific to this server:** `red` (palette index 0) sets no keyword bits, so
|
|
259
|
+
over IMAP it is indistinguishable from a plain colorless flag, both when
|
|
260
|
+
reading `flagColor` back and when filtering on it. AppleScript-backed
|
|
261
|
+
accounts are unaffected (Mail's own `flag index` property is `0` for red, `-1`
|
|
262
|
+
for none).
|
|
246
263
|
|
|
247
264
|
⚠️ **Row dates.** Since 2.19.7 every row — on both the IMAP and AppleScript
|
|
248
265
|
backends — carries both `dateSent` (the message's `Date:` header) and
|
|
@@ -392,7 +409,9 @@ List messages in a mailbox.
|
|
|
392
409
|
| `from` | string | No | Filter by sender email address or name |
|
|
393
410
|
| `unreadOnly` | boolean | No | Only show unread messages |
|
|
394
411
|
|
|
395
|
-
**Returns:** List of messages with ID, date, subject, and
|
|
412
|
+
**Returns:** List of messages with ID, date, subject, sender, and `flagColor`
|
|
413
|
+
when flagged with an explicit color (see the flag-color note under
|
|
414
|
+
[`search-messages`](#search-messages), which also supports filtering by it).
|
|
396
415
|
|
|
397
416
|
⚠️ **Row dates.** Since 2.19.7 every row — on both the **IMAP** and
|
|
398
417
|
**AppleScript** backends — carries both `dateSent` (the message's `Date:`
|
|
@@ -995,7 +1014,12 @@ Flag or unflag a message. `flag-message` optionally takes a flag **color**; `unf
|
|
|
995
1014
|
|
|
996
1015
|
**Flag colors** are an Apple Mail feature — the message's `flag index` (0 red, 1 orange, 2 yellow, 3 green, 4 blue, 5 purple, 6 gray), which is the property a Mail smart mailbox can match on. **The color is applied on both routes** (since 2.10.0): AppleScript sets the flag index directly, and for an **IMAP-routed** id (`imap:…`) the color is written as Mail.app's `$MailFlagBit0/1/2` keywords — a 3-bit field holding the same palette index. `\Flagged` on its own really is colorless, but those keywords ride alongside it in an ordinary `UID STORE`, so a smart mailbox keyed on flag color matches an IMAP-flagged message too. You do **not** need to resolve to a numeric id just to color a flag.
|
|
997
1016
|
|
|
998
|
-
To **read** a color
|
|
1017
|
+
To **read** a color back, or **find** messages by color, use
|
|
1018
|
+
[`search-messages`](#search-messages) (or [`list-messages`](#list-messages) for
|
|
1019
|
+
read-back only) — both routes now return `flagColor` (the palette name) on
|
|
1020
|
+
every flagged-with-a-color row, and `search-messages` takes a `flagColor`
|
|
1021
|
+
filter using this same palette (#286). The IMAP route additionally still
|
|
1022
|
+
carries the raw 0-6 `flagColorIndex` for back-compat.
|
|
999
1023
|
|
|
1000
1024
|
---
|
|
1001
1025
|
|
package/build/cli.js
CHANGED
|
@@ -58021,6 +58021,7 @@ var init_auditLog = __esm({
|
|
|
58021
58021
|
// src/services/imapClient.ts
|
|
58022
58022
|
var imapClient_exports = {};
|
|
58023
58023
|
__export(imapClient_exports, {
|
|
58024
|
+
FLAG_COLOR_NAMES: () => FLAG_COLOR_NAMES,
|
|
58024
58025
|
HEADER_WINDOW_BYTES: () => HEADER_WINDOW_BYTES,
|
|
58025
58026
|
IMAP_ENV: () => IMAP_ENV,
|
|
58026
58027
|
LARGE_MAILBOX_MESSAGES: () => LARGE_MAILBOX_MESSAGES,
|
|
@@ -58038,6 +58039,7 @@ __export(imapClient_exports, {
|
|
|
58038
58039
|
decodedSizeWithoutBody: () => decodedSizeWithoutBody,
|
|
58039
58040
|
dropAllPools: () => dropAllPools,
|
|
58040
58041
|
encodeImapId: () => encodeImapId,
|
|
58042
|
+
flagColorName: () => flagColorName,
|
|
58041
58043
|
imapAppendDraft: () => imapAppendDraft,
|
|
58042
58044
|
imapAppendSentCopy: () => imapAppendSentCopy,
|
|
58043
58045
|
imapBatchDelete: () => imapBatchDelete,
|
|
@@ -58324,8 +58326,25 @@ function buildCriteria(a, listMode) {
|
|
|
58324
58326
|
if (a.isFlagged === false) c.unflagged = true;
|
|
58325
58327
|
if (a.dateFrom) c.since = new Date(a.dateFrom);
|
|
58326
58328
|
if (a.dateTo) c.before = new Date(a.dateTo);
|
|
58329
|
+
if (a.flagColorIndex !== void 0) {
|
|
58330
|
+
c.flagged = true;
|
|
58331
|
+
Object.assign(c, flagColorSearchTerm(a.flagColorIndex));
|
|
58332
|
+
}
|
|
58327
58333
|
return c;
|
|
58328
58334
|
}
|
|
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
|
+
}
|
|
58329
58348
|
function validDate(d) {
|
|
58330
58349
|
if (!d) return void 0;
|
|
58331
58350
|
const parsed = d instanceof Date ? d : new Date(d);
|
|
@@ -58366,6 +58385,7 @@ function isoOrEmpty(d) {
|
|
|
58366
58385
|
}
|
|
58367
58386
|
function structuredRow(m, account, path3) {
|
|
58368
58387
|
const env = m.envelope ?? {};
|
|
58388
|
+
const flagColorIndex = mailFlagColorIndex(m.flags);
|
|
58369
58389
|
return {
|
|
58370
58390
|
id: encodeImapId(account, path3, m.uid),
|
|
58371
58391
|
subject: env.subject || "(no subject)",
|
|
@@ -58382,7 +58402,19 @@ function structuredRow(m, account, path3) {
|
|
|
58382
58402
|
dateReceived: isoOrEmpty(validDate(m.internalDate) ?? headerDate(m)),
|
|
58383
58403
|
isRead: m.flags?.has("\\Seen") ?? false,
|
|
58384
58404
|
isFlagged: m.flags?.has("\\Flagged") ?? false,
|
|
58385
|
-
flagColorIndex
|
|
58405
|
+
// flagColorIndex has been computed here since 2.19.x but never reached a
|
|
58406
|
+
// caller in friendly form (#286, @j5pu) — flagColor is the palette name
|
|
58407
|
+
// (e.g. "orange"), omitted whenever the index is (unflagged, or flagged
|
|
58408
|
+
// with Mail's plain default and no explicit color). flagColorIndex stays
|
|
58409
|
+
// for back-compat.
|
|
58410
|
+
// ⚠️ "red" (index 0) sets no $MailFlagBit keyword — it is wire-identical to
|
|
58411
|
+
// a plain colorless flag over IMAP, so a red-flagged message reads back
|
|
58412
|
+
// here with no flagColor (and flagColor: "red" in search-messages also
|
|
58413
|
+
// matches a plain flag). Inherent to Apple's bitfield encoding, not
|
|
58414
|
+
// fixable from the client side; the AppleScript route is unaffected (Mail's
|
|
58415
|
+
// own `flag index` is 0 for red, -1 for none).
|
|
58416
|
+
flagColorIndex,
|
|
58417
|
+
flagColor: flagColorName(flagColorIndex),
|
|
58386
58418
|
mailbox: path3,
|
|
58387
58419
|
account,
|
|
58388
58420
|
// Derived from BODYSTRUCTURE, which the list/search fetch now requests.
|
|
@@ -59427,6 +59459,9 @@ function mailFlagColorIndex(flags) {
|
|
|
59427
59459
|
}
|
|
59428
59460
|
return any ? idx : void 0;
|
|
59429
59461
|
}
|
|
59462
|
+
function flagColorName(index) {
|
|
59463
|
+
return index === void 0 ? void 0 : FLAG_COLOR_NAMES[index];
|
|
59464
|
+
}
|
|
59430
59465
|
function flagOp(id, flag, add, deps) {
|
|
59431
59466
|
const ref = decodeImapId(id);
|
|
59432
59467
|
if (!ref) return Promise.resolve({ success: false, error: `Not an IMAP message id: "${id}".` });
|
|
@@ -59940,7 +59975,7 @@ async function imapThread(id, deps = {}, limit = 50) {
|
|
|
59940
59975
|
true
|
|
59941
59976
|
);
|
|
59942
59977
|
}
|
|
59943
|
-
var import_imapflow, IMAP_ENV, defaultConnect, SPECIAL_USE_ALIASES, NOT_DELETED, LARGE_MAILBOX_MESSAGES, FIRST_SEARCH_WINDOW, MAX_WINDOW, MAX_UNSCOPED_SEARCH_DEPTH, ROW_QUERY, ROW_QUERY_NO_STRUCTURE, ROW_QUERY_HEADERS_ONLY, DELETED_MARGIN, poolConnect, pools, connecting, MAX_COMPOSE_SOURCE_BYTES, MAX_RFC822_INLINE_BYTES, MAX_RFC822_FILE_BYTES, HEADER_WINDOW_BYTES, MAIL_FLAG_BITS, imapMarkRead, imapMarkUnread, FALLBACK_TRASH_PATH, BASE64_TAIL_WINDOW, QP_EXACT_MAX_BYTES, imapBatchMarkRead, imapBatchMarkUnread, imapBatchFlag, imapBatchUnflag, imapBatchDelete;
|
|
59978
|
+
var import_imapflow, IMAP_ENV, defaultConnect, SPECIAL_USE_ALIASES, NOT_DELETED, LARGE_MAILBOX_MESSAGES, FIRST_SEARCH_WINDOW, MAX_WINDOW, MAX_UNSCOPED_SEARCH_DEPTH, ROW_QUERY, ROW_QUERY_NO_STRUCTURE, ROW_QUERY_HEADERS_ONLY, DELETED_MARGIN, poolConnect, pools, connecting, MAX_COMPOSE_SOURCE_BYTES, MAX_RFC822_INLINE_BYTES, MAX_RFC822_FILE_BYTES, HEADER_WINDOW_BYTES, MAIL_FLAG_BITS, FLAG_COLOR_NAMES, imapMarkRead, imapMarkUnread, FALLBACK_TRASH_PATH, BASE64_TAIL_WINDOW, QP_EXACT_MAX_BYTES, imapBatchMarkRead, imapBatchMarkUnread, imapBatchFlag, imapBatchUnflag, imapBatchDelete;
|
|
59944
59979
|
var init_imapClient = __esm({
|
|
59945
59980
|
"src/services/imapClient.ts"() {
|
|
59946
59981
|
"use strict";
|
|
@@ -60043,6 +60078,15 @@ var init_imapClient = __esm({
|
|
|
60043
60078
|
MAX_RFC822_FILE_BYTES = MAX_COMPOSE_SOURCE_BYTES;
|
|
60044
60079
|
HEADER_WINDOW_BYTES = 64 * 1024;
|
|
60045
60080
|
MAIL_FLAG_BITS = ["$MailFlagBit0", "$MailFlagBit1", "$MailFlagBit2"];
|
|
60081
|
+
FLAG_COLOR_NAMES = [
|
|
60082
|
+
"red",
|
|
60083
|
+
"orange",
|
|
60084
|
+
"yellow",
|
|
60085
|
+
"green",
|
|
60086
|
+
"blue",
|
|
60087
|
+
"purple",
|
|
60088
|
+
"gray"
|
|
60089
|
+
];
|
|
60046
60090
|
imapMarkRead = (id, deps = {}) => flagOp(id, "\\Seen", true, deps);
|
|
60047
60091
|
imapMarkUnread = (id, deps = {}) => flagOp(id, "\\Seen", false, deps);
|
|
60048
60092
|
FALLBACK_TRASH_PATH = "Trash";
|