apple-mail-mcp 2.11.0 → 2.11.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/build/index.js +29 -8
- package/package.json +1 -1
package/build/index.js
CHANGED
|
@@ -78071,11 +78071,17 @@ function sleep(ms) {
|
|
|
78071
78071
|
}
|
|
78072
78072
|
}
|
|
78073
78073
|
}
|
|
78074
|
+
var PERMISSION_DENIED_PATTERN = /not authorized|not permitted|access.*denied/i;
|
|
78075
|
+
var PERMISSION_DENIED_MESSAGE = "Permission denied. Grant automation access in System Settings > Privacy & Security > Automation.";
|
|
78076
|
+
function isPermissionDenied(error2) {
|
|
78077
|
+
if (!error2) return false;
|
|
78078
|
+
return PERMISSION_DENIED_PATTERN.test(error2) || error2.includes(PERMISSION_DENIED_MESSAGE);
|
|
78079
|
+
}
|
|
78074
78080
|
var ERROR_MAPPINGS = [
|
|
78075
78081
|
// Permission errors
|
|
78076
78082
|
{
|
|
78077
|
-
pattern:
|
|
78078
|
-
message:
|
|
78083
|
+
pattern: PERMISSION_DENIED_PATTERN,
|
|
78084
|
+
message: PERMISSION_DENIED_MESSAGE
|
|
78079
78085
|
},
|
|
78080
78086
|
// Application not running
|
|
78081
78087
|
{
|
|
@@ -82841,7 +82847,7 @@ ${actionStmts.join("\n")}
|
|
|
82841
82847
|
message: "Mail.app is accessible"
|
|
82842
82848
|
});
|
|
82843
82849
|
} else {
|
|
82844
|
-
const errorHint = mailCheck.error
|
|
82850
|
+
const errorHint = isPermissionDenied(mailCheck.error) ? " (check System Settings > Privacy & Security > Automation)" : "";
|
|
82845
82851
|
checks.push({
|
|
82846
82852
|
name: "mail_app",
|
|
82847
82853
|
passed: false,
|
|
@@ -82857,7 +82863,7 @@ ${actionStmts.join("\n")}
|
|
|
82857
82863
|
message: "AppleScript automation permissions granted"
|
|
82858
82864
|
});
|
|
82859
82865
|
} else {
|
|
82860
|
-
const isPermError =
|
|
82866
|
+
const isPermError = isPermissionDenied(permCheck.error);
|
|
82861
82867
|
checks.push({
|
|
82862
82868
|
name: "permissions",
|
|
82863
82869
|
passed: !isPermError,
|
|
@@ -83681,7 +83687,12 @@ function structuredRow(m, account, path) {
|
|
|
83681
83687
|
flagColorIndex: mailFlagColorIndex(m.flags),
|
|
83682
83688
|
mailbox: path,
|
|
83683
83689
|
account,
|
|
83684
|
-
|
|
83690
|
+
// Derived from BODYSTRUCTURE, which the list/search fetch now requests.
|
|
83691
|
+
// This was hardcoded `false` from 2.2.0 until 2.11.1 — indistinguishable to
|
|
83692
|
+
// a caller from "no attachments", so every IMAP-sourced message claimed to
|
|
83693
|
+
// have none. Falls back to false only when the fetch carried no
|
|
83694
|
+
// BODYSTRUCTURE at all.
|
|
83695
|
+
hasAttachments: bodyStructureHasAttachments(m.bodyStructure),
|
|
83685
83696
|
// Message-ID (when the envelope carries it) is the strongest cross-/intra-
|
|
83686
83697
|
// backend dedup key for the multi-account merge (imapMultiAccount.ts). The
|
|
83687
83698
|
// AppleScript path does not expose it, so cross-backend dedup falls back to
|
|
@@ -83712,7 +83723,10 @@ async function run(args, listMode, deps) {
|
|
|
83712
83723
|
const byUid = /* @__PURE__ */ new Map();
|
|
83713
83724
|
for await (const msg of client.fetch(
|
|
83714
83725
|
newest.join(","),
|
|
83715
|
-
|
|
83726
|
+
// BODYSTRUCTURE rides along so `hasAttachments` is computed rather
|
|
83727
|
+
// than assumed. Measured on 50 real messages: ~390ms -> ~465ms for
|
|
83728
|
+
// the fetch (~17%), same single round trip, no extra request.
|
|
83729
|
+
{ envelope: true, flags: true, bodyStructure: true },
|
|
83716
83730
|
{ uid: true }
|
|
83717
83731
|
)) {
|
|
83718
83732
|
byUid.set(msg.uid, msg);
|
|
@@ -84206,7 +84220,8 @@ function collectAttachments(node, out = []) {
|
|
|
84206
84220
|
if (!node) return out;
|
|
84207
84221
|
const filename = node.dispositionParameters?.filename || node.parameters?.name;
|
|
84208
84222
|
const disposition = node.disposition?.toLowerCase();
|
|
84209
|
-
const
|
|
84223
|
+
const isEmbeddedByReference = disposition === "inline" && !!node.id;
|
|
84224
|
+
const isAttachment = !!node.part && (disposition === "attachment" || !!filename && !isEmbeddedByReference);
|
|
84210
84225
|
if (isAttachment) {
|
|
84211
84226
|
out.push({
|
|
84212
84227
|
part: node.part,
|
|
@@ -84218,6 +84233,9 @@ function collectAttachments(node, out = []) {
|
|
|
84218
84233
|
for (const child of node.childNodes ?? []) collectAttachments(child, out);
|
|
84219
84234
|
return out;
|
|
84220
84235
|
}
|
|
84236
|
+
function bodyStructureHasAttachments(node) {
|
|
84237
|
+
return !!node && collectAttachments(node).length > 0;
|
|
84238
|
+
}
|
|
84221
84239
|
async function streamToBuffer(content, maxBytes) {
|
|
84222
84240
|
const chunks = [];
|
|
84223
84241
|
let total = 0;
|
|
@@ -84389,7 +84407,10 @@ async function imapThread(id, deps = {}, limit = 50) {
|
|
|
84389
84407
|
const msgs = [];
|
|
84390
84408
|
for await (const msg of client.fetch(
|
|
84391
84409
|
uids.join(","),
|
|
84392
|
-
|
|
84410
|
+
// Same reason as the list/search fetch: get-thread emits structured
|
|
84411
|
+
// rows too, so it needs BODYSTRUCTURE or its hasAttachments would
|
|
84412
|
+
// silently disagree with the same message seen via search.
|
|
84413
|
+
{ envelope: true, flags: true, bodyStructure: true },
|
|
84393
84414
|
{ uid: true }
|
|
84394
84415
|
)) {
|
|
84395
84416
|
msgs.push(msg);
|
package/package.json
CHANGED