apple-mail-mcp 2.20.19 → 2.20.21
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 +11 -0
- package/build/cli.js +9 -5
- package/build/index.js +74 -40
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1075,6 +1075,12 @@ List attachments on a message.
|
|
|
1075
1075
|
**Returns:** List of attachments with name, MIME type, and `size` — the **decoded** byte count,
|
|
1076
1076
|
i.e. what `fetch-attachment` returns.
|
|
1077
1077
|
|
|
1078
|
+
**A numeric `id` resolves the same way the read tools resolve one** (2.20.21): the mailbox the id
|
|
1079
|
+
was listed from when that is known, else a bounded cross-mailbox scan that skips very large
|
|
1080
|
+
mailboxes and stops at its time budget. An id that several mailboxes hold is **refused**, with the
|
|
1081
|
+
candidates named, rather than answered for whichever copy came first — so list or search the
|
|
1082
|
+
mailbox you mean immediately before calling this. `imap:…` ids are never ambiguous.
|
|
1083
|
+
|
|
1078
1084
|
**Sizes over IMAP.** `BODYSTRUCTURE` reports a part's size in its transfer encoding, so a
|
|
1079
1085
|
base64 attachment's raw figure is ~4/3 of the file. `list-attachments` converts it: a
|
|
1080
1086
|
`Content-Disposition` `size=` parameter wins when present; 7bit/8bit/binary parts are exact
|
|
@@ -1096,6 +1102,11 @@ of overwriting an existing file. AppleScript and MIME fallback paths stage the
|
|
|
1096
1102
|
bytes privately, commit with an exclusive create, and leave the saved file
|
|
1097
1103
|
owner-readable/writable (`0600`).
|
|
1098
1104
|
|
|
1105
|
+
**A numeric `id` resolves the same way the read tools resolve one** (2.20.21): the mailbox the id
|
|
1106
|
+
was listed from when that is known, else the bounded cross-mailbox scan. An id that several
|
|
1107
|
+
mailboxes hold **saves nothing** rather than writing some other message's attachment under the
|
|
1108
|
+
name you asked for.
|
|
1109
|
+
|
|
1099
1110
|
| Parameter | Type | Required | Description |
|
|
1100
1111
|
| ---------------- | ------ | -------- | -------------------------- |
|
|
1101
1112
|
| `id` | string | Yes | Message ID |
|
package/build/cli.js
CHANGED
|
@@ -58581,10 +58581,13 @@ async function searchUids(client, path3, criteria, size) {
|
|
|
58581
58581
|
async function filterUidsByColor(client, uids, colorIndex) {
|
|
58582
58582
|
if (uids.length === 0) return uids;
|
|
58583
58583
|
const keep = /* @__PURE__ */ new Set();
|
|
58584
|
-
for
|
|
58585
|
-
|
|
58586
|
-
const
|
|
58587
|
-
|
|
58584
|
+
for (let i = 0; i < uids.length; i += COLOR_FETCH_CHUNK) {
|
|
58585
|
+
const slice = uids.slice(i, i + COLOR_FETCH_CHUNK).join(",");
|
|
58586
|
+
for await (const msg of client.fetch(slice, { uid: true, flags: true }, { uid: true })) {
|
|
58587
|
+
if (typeof msg?.uid !== "number") continue;
|
|
58588
|
+
const idx = mailFlagColorIndex(msg.flags);
|
|
58589
|
+
if (colorIndex === 0 ? idx === void 0 : idx === colorIndex) keep.add(msg.uid);
|
|
58590
|
+
}
|
|
58588
58591
|
}
|
|
58589
58592
|
return uids.filter((uid) => keep.has(uid));
|
|
58590
58593
|
}
|
|
@@ -60075,7 +60078,7 @@ async function imapThread(id, deps = {}, limit = 50) {
|
|
|
60075
60078
|
true
|
|
60076
60079
|
);
|
|
60077
60080
|
}
|
|
60078
|
-
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;
|
|
60081
|
+
var import_imapflow, IMAP_ENV, defaultConnect, SPECIAL_USE_ALIASES, NOT_DELETED, LARGE_MAILBOX_MESSAGES, FIRST_SEARCH_WINDOW, MAX_WINDOW, MAX_UNSCOPED_SEARCH_DEPTH, COLOR_FETCH_CHUNK, 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;
|
|
60079
60082
|
var init_imapClient = __esm({
|
|
60080
60083
|
"src/services/imapClient.ts"() {
|
|
60081
60084
|
"use strict";
|
|
@@ -60151,6 +60154,7 @@ var init_imapClient = __esm({
|
|
|
60151
60154
|
FIRST_SEARCH_WINDOW = 5e3;
|
|
60152
60155
|
MAX_WINDOW = 5e4;
|
|
60153
60156
|
MAX_UNSCOPED_SEARCH_DEPTH = 5e3;
|
|
60157
|
+
COLOR_FETCH_CHUNK = 500;
|
|
60154
60158
|
ROW_QUERY = {
|
|
60155
60159
|
envelope: true,
|
|
60156
60160
|
flags: true,
|
package/build/index.js
CHANGED
|
@@ -66334,10 +66334,13 @@ async function searchUids(client, path3, criteria, size) {
|
|
|
66334
66334
|
async function filterUidsByColor(client, uids, colorIndex) {
|
|
66335
66335
|
if (uids.length === 0) return uids;
|
|
66336
66336
|
const keep = /* @__PURE__ */ new Set();
|
|
66337
|
-
for
|
|
66338
|
-
|
|
66339
|
-
const
|
|
66340
|
-
|
|
66337
|
+
for (let i = 0; i < uids.length; i += COLOR_FETCH_CHUNK) {
|
|
66338
|
+
const slice = uids.slice(i, i + COLOR_FETCH_CHUNK).join(",");
|
|
66339
|
+
for await (const msg of client.fetch(slice, { uid: true, flags: true }, { uid: true })) {
|
|
66340
|
+
if (typeof msg?.uid !== "number") continue;
|
|
66341
|
+
const idx = mailFlagColorIndex(msg.flags);
|
|
66342
|
+
if (colorIndex === 0 ? idx === void 0 : idx === colorIndex) keep.add(msg.uid);
|
|
66343
|
+
}
|
|
66341
66344
|
}
|
|
66342
66345
|
return uids.filter((uid) => keep.has(uid));
|
|
66343
66346
|
}
|
|
@@ -67828,7 +67831,7 @@ async function imapThread(id, deps = {}, limit = 50) {
|
|
|
67828
67831
|
true
|
|
67829
67832
|
);
|
|
67830
67833
|
}
|
|
67831
|
-
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;
|
|
67834
|
+
var import_imapflow, IMAP_ENV, defaultConnect, SPECIAL_USE_ALIASES, NOT_DELETED, LARGE_MAILBOX_MESSAGES, FIRST_SEARCH_WINDOW, MAX_WINDOW, MAX_UNSCOPED_SEARCH_DEPTH, COLOR_FETCH_CHUNK, 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;
|
|
67832
67835
|
var init_imapClient = __esm({
|
|
67833
67836
|
"src/services/imapClient.ts"() {
|
|
67834
67837
|
"use strict";
|
|
@@ -67904,6 +67907,7 @@ var init_imapClient = __esm({
|
|
|
67904
67907
|
FIRST_SEARCH_WINDOW = 5e3;
|
|
67905
67908
|
MAX_WINDOW = 5e4;
|
|
67906
67909
|
MAX_UNSCOPED_SEARCH_DEPTH = 5e3;
|
|
67910
|
+
COLOR_FETCH_CHUNK = 500;
|
|
67907
67911
|
ROW_QUERY = {
|
|
67908
67912
|
envelope: true,
|
|
67909
67913
|
flags: true,
|
|
@@ -83310,6 +83314,7 @@ var DATES_MARKER = "DATES";
|
|
|
83310
83314
|
var HTML_MARKER = "HTML";
|
|
83311
83315
|
var LOOKUP_ERROR_MARKER = "ERR";
|
|
83312
83316
|
var BATCH_FATAL = "FATAL";
|
|
83317
|
+
var ATTACHMENTS_MARKER = "ATT";
|
|
83313
83318
|
var RECON_TAG = "RECON";
|
|
83314
83319
|
var SNAP_TAG = "SNAP";
|
|
83315
83320
|
var SNAP_PAIR = "P";
|
|
@@ -83560,10 +83565,17 @@ function buildMessageRowLoop(opts) {
|
|
|
83560
83565
|
set _dates to date received of _msgs
|
|
83561
83566
|
set _reads to read status of _msgs
|
|
83562
83567
|
set _flags to flagged status of _msgs
|
|
83563
|
-
set _flagColors to flag index of _msgs
|
|
83564
83568
|
on error
|
|
83565
83569
|
set _bulkOK to false
|
|
83566
83570
|
end try
|
|
83571
|
+
-- Its own try, like the sent dates: a getter that fails on one account type must
|
|
83572
|
+
-- not send every other property down the slow per-message path.
|
|
83573
|
+
set _flagBulkOK to true
|
|
83574
|
+
try
|
|
83575
|
+
set _flagColors to flag index of _msgs
|
|
83576
|
+
on error
|
|
83577
|
+
set _flagBulkOK to false
|
|
83578
|
+
end try
|
|
83567
83579
|
set _sentBulkOK to true
|
|
83568
83580
|
try
|
|
83569
83581
|
set _sentDates to date sent of _msgs
|
|
@@ -83591,15 +83603,21 @@ function buildMessageRowLoop(opts) {
|
|
|
83591
83603
|
set msgSender to item _i of _sndrs
|
|
83592
83604
|
set msgRead to (item _i of _reads) as string
|
|
83593
83605
|
set msgFlagged to (item _i of _flags) as string
|
|
83594
|
-
set msgFlagColorRaw to (item _i of _flagColors) as string
|
|
83595
83606
|
else
|
|
83596
83607
|
set _m to item _i of _msgs
|
|
83597
83608
|
set msgSubject to subject of _m
|
|
83598
83609
|
set msgSender to sender of _m
|
|
83599
83610
|
set msgRead to read status of _m as string
|
|
83600
83611
|
set msgFlagged to flagged status of _m as string
|
|
83601
|
-
|
|
83602
|
-
|
|
83612
|
+
end if
|
|
83613
|
+
set msgFlagColorRaw to "-1"
|
|
83614
|
+
try
|
|
83615
|
+
if _bulkOK and _flagBulkOK then
|
|
83616
|
+
set msgFlagColorRaw to (item _i of _flagColors) as string
|
|
83617
|
+
else
|
|
83618
|
+
set msgFlagColorRaw to (flag index of (item _i of _msgs)) as string
|
|
83619
|
+
end if
|
|
83620
|
+
end try${attRow}
|
|
83603
83621
|
set msgDateStr to ${AS_DATE_TO_STRING}
|
|
83604
83622
|
set msgDateSentStr to ""
|
|
83605
83623
|
try
|
|
@@ -86886,14 +86904,7 @@ ${this.errorEmit(" ")}
|
|
|
86886
86904
|
* when AppleScript returns empty (known issue across all account types).
|
|
86887
86905
|
*/
|
|
86888
86906
|
listAttachments(id) {
|
|
86889
|
-
const
|
|
86890
|
-
try
|
|
86891
|
-
repeat with acct in accounts
|
|
86892
|
-
repeat with mb in mailboxes of acct
|
|
86893
|
-
try
|
|
86894
|
-
set matchingMsgs to (messages of mb whose id is ${Number(id)})
|
|
86895
|
-
if (count of matchingMsgs) > 0 then
|
|
86896
|
-
set msg to item 1 of matchingMsgs
|
|
86907
|
+
const attachmentLoop = `
|
|
86897
86908
|
set outputText to ""
|
|
86898
86909
|
set attCount to 0
|
|
86899
86910
|
-- Each property is read inside its own try: \`MIME type of att\` throws
|
|
@@ -86919,20 +86930,20 @@ ${this.errorEmit(" ")}
|
|
|
86919
86930
|
set outputText to outputText & attName & "${FIELD_SEP}" & attType & "${FIELD_SEP}" & attSize
|
|
86920
86931
|
set attCount to attCount + 1
|
|
86921
86932
|
end if
|
|
86922
|
-
end repeat
|
|
86923
|
-
|
|
86924
|
-
|
|
86925
|
-
|
|
86926
|
-
|
|
86927
|
-
|
|
86928
|
-
|
|
86929
|
-
|
|
86930
|
-
|
|
86931
|
-
|
|
86932
|
-
|
|
86933
|
-
|
|
86934
|
-
if (
|
|
86935
|
-
const items =
|
|
86933
|
+
end repeat`;
|
|
86934
|
+
this.lastMessageLookupError = void 0;
|
|
86935
|
+
const output = this.resolveById(
|
|
86936
|
+
id,
|
|
86937
|
+
`${attachmentLoop}
|
|
86938
|
+
return "${ATTACHMENTS_MARKER}" & outputText`,
|
|
86939
|
+
void 0
|
|
86940
|
+
);
|
|
86941
|
+
if (output === null) {
|
|
86942
|
+
const refusal = this.consumeLastMessageLookupError();
|
|
86943
|
+
if (refusal) throw new Error(refusal);
|
|
86944
|
+
}
|
|
86945
|
+
if (output?.startsWith(ATTACHMENTS_MARKER) && output.length > ATTACHMENTS_MARKER.length) {
|
|
86946
|
+
const items = output.slice(ATTACHMENTS_MARKER.length).split(RECORD_SEP);
|
|
86936
86947
|
const attachments = [];
|
|
86937
86948
|
for (const item of items) {
|
|
86938
86949
|
const parts = item.split(FIELD_SEP);
|
|
@@ -86990,14 +87001,28 @@ ${this.errorEmit(" ")}
|
|
|
86990
87001
|
}
|
|
86991
87002
|
};
|
|
86992
87003
|
const numericId = Number(id);
|
|
86993
|
-
|
|
86994
|
-
|
|
86995
|
-
|
|
86996
|
-
|
|
86997
|
-
|
|
86998
|
-
|
|
86999
|
-
|
|
87000
|
-
|
|
87004
|
+
this.lastMessageLookupError = void 0;
|
|
87005
|
+
const located = this.resolveById(
|
|
87006
|
+
id,
|
|
87007
|
+
`set _where to ""
|
|
87008
|
+
try
|
|
87009
|
+
${mailboxPathFragment("_hitMb", "_where")}
|
|
87010
|
+
end try
|
|
87011
|
+
return _hitAcct & "${FIELD_SEP}" & _where`,
|
|
87012
|
+
void 0
|
|
87013
|
+
);
|
|
87014
|
+
if (located === null) {
|
|
87015
|
+
const why = this.consumeLastMessageLookupError();
|
|
87016
|
+
if (why) {
|
|
87017
|
+
cleanupTemporaryDirectory();
|
|
87018
|
+
console.error(`Failed to save attachment: ${why}`);
|
|
87019
|
+
return false;
|
|
87020
|
+
}
|
|
87021
|
+
}
|
|
87022
|
+
const [holderAccount, holderMailbox] = (located ?? "").split(FIELD_SEP);
|
|
87023
|
+
if (holderAccount && holderMailbox)
|
|
87024
|
+
this.rememberLocation(String(id), holderAccount, holderMailbox);
|
|
87025
|
+
const saveAction = `
|
|
87001
87026
|
repeat with att in mail attachments of msg
|
|
87002
87027
|
if name of att is "${safeName}" then
|
|
87003
87028
|
set savePath to POSIX file "${safeTemporaryPath}"
|
|
@@ -87005,7 +87030,16 @@ ${this.errorEmit(" ")}
|
|
|
87005
87030
|
return "ok"
|
|
87006
87031
|
end if
|
|
87007
87032
|
end repeat
|
|
87008
|
-
return "error:Attachment not found"
|
|
87033
|
+
return "error:Attachment not found"`;
|
|
87034
|
+
const script = holderAccount && holderMailbox ? this.scopedByIdScript(holderAccount, holderMailbox, id, saveAction) : buildAppLevelScript(`
|
|
87035
|
+
try
|
|
87036
|
+
repeat with acct in accounts
|
|
87037
|
+
repeat with mb in mailboxes of acct
|
|
87038
|
+
try
|
|
87039
|
+
set matchingMsgs to (messages of mb whose id is ${numericId})
|
|
87040
|
+
if (count of matchingMsgs) > 0 then
|
|
87041
|
+
set msg to item 1 of matchingMsgs
|
|
87042
|
+
${saveAction}
|
|
87009
87043
|
end if
|
|
87010
87044
|
end try
|
|
87011
87045
|
end repeat
|
package/package.json
CHANGED