apple-mail-mcp 2.10.13 → 2.10.15
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 +34 -2
- package/build/index.js +200 -56
- package/docs/IMAP-SETUP.md +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -579,7 +579,7 @@ Dropped connections reconnect with backoff, and the watchers shut down cleanly o
|
|
|
579
579
|
|
|
580
580
|
Enable it in your MCP client config alongside the IMAP settings:
|
|
581
581
|
|
|
582
|
-
```
|
|
582
|
+
```json
|
|
583
583
|
{
|
|
584
584
|
"mcpServers": {
|
|
585
585
|
"apple-mail": {
|
|
@@ -680,6 +680,20 @@ Return an attachment's bytes as base64 (the read counterpart to inline-base64 se
|
|
|
680
680
|
|
|
681
681
|
---
|
|
682
682
|
|
|
683
|
+
#### `resolve-message-id`
|
|
684
|
+
|
|
685
|
+
Map `imap:` message IDs to their numeric Mail.app IDs, via each message's RFC 5322 `Message-ID` (the join key both backends share). Needed only for the two tools that are numeric-ID-only — `reply-to-message` and `forward-message`. Numeric IDs pass through unchanged.
|
|
686
|
+
|
|
687
|
+
| Parameter | Type | Required | Description |
|
|
688
|
+
|-----------|------|----------|-------------|
|
|
689
|
+
| `ids` | string[] | Yes | 1–100 message IDs, each numeric or `imap:…` |
|
|
690
|
+
|
|
691
|
+
**Returns:** For each input ID, its `numericId` (or `null` when it can't be resolved) and the `messageId` used, plus `count` and `resolvedCount`. The lookup scopes to the message's account and checks its INBOX first, to avoid scanning a large All Mail/Archive mailbox.
|
|
692
|
+
|
|
693
|
+
> **You do not need this for flag colors (v2.10.0+).** Colors used to require the numeric-ID path, and older docs and tool descriptions said so. `flag-message` and `batch-flag-messages` now write the color over IMAP directly, as Mail.app's `$MailFlagBit0/1/2` keywords, so a smart mailbox keyed on flag color matches an IMAP-flagged message. Resolving IDs just to apply a color reintroduces the AppleScript/TCC dependency 2.10.0 removed. Flag, move, mark, and delete all accept `imap:` IDs as-is.
|
|
694
|
+
|
|
695
|
+
---
|
|
696
|
+
|
|
683
697
|
#### `reply-to-message`
|
|
684
698
|
|
|
685
699
|
Reply to an existing message.
|
|
@@ -815,6 +829,15 @@ Save a message attachment to disk.
|
|
|
815
829
|
|
|
816
830
|
All batch operations accept an array of message IDs (max 100 per batch) and return per-item success/failure results.
|
|
817
831
|
|
|
832
|
+
**Numeric IDs are scoped to the mailbox you listed them from.** Mail.app numbers messages per
|
|
833
|
+
mailbox, so on a label store (Gmail, iCloud) one message answers to the same id in `INBOX`,
|
|
834
|
+
`Important` and `All Mail` at once — and deleting the `All Mail` copy is not the same operation as
|
|
835
|
+
deleting the `INBOX` copy. Each id is therefore bound to the mailbox it was listed/searched from and
|
|
836
|
+
the operation is applied only there, so **list or search the mailbox immediately before acting on
|
|
837
|
+
it**. An id the server hasn't seen listed is accepted only when exactly one mailbox holds it;
|
|
838
|
+
if several do, that id fails with the candidate mailboxes named instead of being applied to an
|
|
839
|
+
arbitrary copy. `imap:…` ids carry their own account + mailbox + UID and are never ambiguous.
|
|
840
|
+
|
|
818
841
|
#### `batch-delete-messages`
|
|
819
842
|
|
|
820
843
|
| Parameter | Type | Required | Description |
|
|
@@ -1309,7 +1332,7 @@ This repo ships a `.mcp.json` at its root so that, when you run `claude` from in
|
|
|
1309
1332
|
|
|
1310
1333
|
The entrypoint is written as:
|
|
1311
1334
|
|
|
1312
|
-
```
|
|
1335
|
+
```text
|
|
1313
1336
|
"args": ["${CLAUDE_PROJECT_DIR:-.}/build/index.js"]
|
|
1314
1337
|
```
|
|
1315
1338
|
|
|
@@ -1424,6 +1447,15 @@ In a JSON string literal, `\\` — two characters — denotes **one** literal ba
|
|
|
1424
1447
|
- Message IDs change if the message is moved between mailboxes
|
|
1425
1448
|
- Use `search-messages` to find the current message ID
|
|
1426
1449
|
|
|
1450
|
+
### "... is present in more than one mailbox"
|
|
1451
|
+
- A bare numeric ID identifies a message only *within a mailbox*, and a label store (Gmail, iCloud)
|
|
1452
|
+
reports the same message under the same ID in `INBOX`, `Important` and `All Mail` at once. The
|
|
1453
|
+
server refuses rather than guessing which copy you meant.
|
|
1454
|
+
- Fix it by running `list-messages`/`search-messages` on the mailbox you actually want to act on,
|
|
1455
|
+
then using the IDs from that result — the operation is then scoped to that mailbox.
|
|
1456
|
+
- It only affects IDs the server hasn't seen listed (carried over from an earlier session, or typed
|
|
1457
|
+
by hand). `imap:…` IDs encode their own mailbox and never hit this.
|
|
1458
|
+
|
|
1427
1459
|
### `search-messages` says "Partial results" or skips a mailbox
|
|
1428
1460
|
- 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.
|
|
1429
1461
|
- To search inside one, scope the call with `mailbox` **and** a `dateFrom`/`dateTo` window.
|
package/build/index.js
CHANGED
|
@@ -78237,6 +78237,8 @@ var CONTENT_MARKER = "CONTENT";
|
|
|
78237
78237
|
var MSGID_MARKER = "MSGID";
|
|
78238
78238
|
var HTML_MARKER = "HTML";
|
|
78239
78239
|
var BATCH_FATAL = "FATAL";
|
|
78240
|
+
var AMBIGUOUS_ID_PREFIX = "Message id ";
|
|
78241
|
+
var AMBIGUOUS_ID_BATCH = "This message id is present in more than one mailbox ";
|
|
78240
78242
|
function normalizeRfcMessageId(mid) {
|
|
78241
78243
|
return (mid || "").trim().replace(/^<+/, "").replace(/>+$/, "").trim();
|
|
78242
78244
|
}
|
|
@@ -78575,6 +78577,32 @@ var AppleMailManager = class {
|
|
|
78575
78577
|
if (oldest !== void 0) this.idLocationIndex.delete(oldest);
|
|
78576
78578
|
}
|
|
78577
78579
|
}
|
|
78580
|
+
/** Where a message id was last listed/searched from, if we've seen it. */
|
|
78581
|
+
locationFor(id) {
|
|
78582
|
+
return this.idLocationIndex.get(String(id));
|
|
78583
|
+
}
|
|
78584
|
+
/**
|
|
78585
|
+
* AppleScript fragment resolving `account` + `mailbox` into `_tmb`, leaving
|
|
78586
|
+
* `_tmb` as `missing value` when it can't be pinned down. Exact-name match
|
|
78587
|
+
* only, and a name matching more than one mailbox resolves to nothing rather
|
|
78588
|
+
* than guessing — the same rule the move destination already applies.
|
|
78589
|
+
*/
|
|
78590
|
+
resolveMailboxFragment(account, mailbox) {
|
|
78591
|
+
const resolved = this.resolveMailbox(mailbox, account);
|
|
78592
|
+
return `
|
|
78593
|
+
set _tmb to missing value
|
|
78594
|
+
set _acctM to {}
|
|
78595
|
+
repeat with _a in accounts
|
|
78596
|
+
if (name of _a) is "${escapeForAppleScript(account)}" then set end of _acctM to _a
|
|
78597
|
+
end repeat
|
|
78598
|
+
if (count of _acctM) is 1 then
|
|
78599
|
+
set _mbM to {}
|
|
78600
|
+
repeat with _m in (mailboxes of (item 1 of _acctM))
|
|
78601
|
+
if (name of _m) is "${escapeForAppleScript(resolved)}" then set end of _mbM to _m
|
|
78602
|
+
end repeat
|
|
78603
|
+
if (count of _mbM) is 1 then set _tmb to item 1 of _mbM
|
|
78604
|
+
end if`;
|
|
78605
|
+
}
|
|
78578
78606
|
/**
|
|
78579
78607
|
* Returns cached accounts or fetches fresh data if cache is expired/empty.
|
|
78580
78608
|
*/
|
|
@@ -79781,24 +79809,61 @@ var AppleMailManager = class {
|
|
|
79781
79809
|
return true;
|
|
79782
79810
|
}
|
|
79783
79811
|
/**
|
|
79784
|
-
* Helper to find and operate on a message by ID
|
|
79812
|
+
* Helper to find and operate on a message by ID, scoped to the mailbox the id
|
|
79813
|
+
* was listed from.
|
|
79814
|
+
*
|
|
79815
|
+
* Mail.app numeric ids are per-mailbox, and on a label store (Gmail, iCloud)
|
|
79816
|
+
* ONE message is present in several mailboxes under the SAME id — INBOX,
|
|
79817
|
+
* "Important" and "All Mail" all report id 75816 for the same mail. This used
|
|
79818
|
+
* to walk every account's every mailbox and mutate the FIRST hit; because
|
|
79819
|
+
* `mailboxes of account` yields INBOX late, an id listed from INBOX was
|
|
79820
|
+
* reliably mutated in "Important" instead, so the op reported success while
|
|
79821
|
+
* the INBOX copy stayed put and a different copy was moved/deleted (#152).
|
|
79822
|
+
*
|
|
79823
|
+
* Which mailbox a mutation lands in is semantic — deleting the INBOX copy and
|
|
79824
|
+
* deleting the "All Mail" copy are different operations — so scope to the
|
|
79825
|
+
* mailbox the id actually came from (`idLocationIndex`, populated by every
|
|
79826
|
+
* list/search) and never guess.
|
|
79785
79827
|
*/
|
|
79786
79828
|
findMessageScript(id, operation) {
|
|
79829
|
+
const loc = this.locationFor(id);
|
|
79830
|
+
if (loc) {
|
|
79831
|
+
return buildAppLevelScript(`
|
|
79832
|
+
try
|
|
79833
|
+
${this.resolveMailboxFragment(loc.account, loc.mailbox)}
|
|
79834
|
+
if _tmb is missing value then return "error:Message not found"
|
|
79835
|
+
set matchingMsgs to (messages of _tmb whose id is ${Number(id)})
|
|
79836
|
+
if (count of matchingMsgs) > 0 then
|
|
79837
|
+
set msg to item 1 of matchingMsgs
|
|
79838
|
+
${operation}
|
|
79839
|
+
return "ok"
|
|
79840
|
+
end if
|
|
79841
|
+
return "error:Message not found"
|
|
79842
|
+
on error errMsg
|
|
79843
|
+
return "error:" & errMsg
|
|
79844
|
+
end try
|
|
79845
|
+
`);
|
|
79846
|
+
}
|
|
79787
79847
|
return buildAppLevelScript(`
|
|
79788
79848
|
try
|
|
79849
|
+
set _hits to {}
|
|
79850
|
+
set _names to ""
|
|
79789
79851
|
repeat with acct in accounts
|
|
79790
79852
|
repeat with mb in mailboxes of acct
|
|
79791
79853
|
try
|
|
79792
79854
|
set matchingMsgs to (messages of mb whose id is ${Number(id)})
|
|
79793
79855
|
if (count of matchingMsgs) > 0 then
|
|
79794
|
-
set
|
|
79795
|
-
|
|
79796
|
-
return "ok"
|
|
79856
|
+
set end of _hits to (item 1 of matchingMsgs)
|
|
79857
|
+
set _names to _names & (name of acct) & "/" & (name of mb) & ", "
|
|
79797
79858
|
end if
|
|
79798
79859
|
end try
|
|
79799
79860
|
end repeat
|
|
79800
79861
|
end repeat
|
|
79801
|
-
return "error:Message not found"
|
|
79862
|
+
if (count of _hits) is 0 then return "error:Message not found"
|
|
79863
|
+
if (count of _hits) > 1 then return "error:${AMBIGUOUS_ID_PREFIX}${Number(id)} is present in more than one mailbox (" & _names & "); list or search that mailbox first so the operation targets the right copy"
|
|
79864
|
+
set msg to item 1 of _hits
|
|
79865
|
+
${operation}
|
|
79866
|
+
return "ok"
|
|
79802
79867
|
on error errMsg
|
|
79803
79868
|
return "error:" & errMsg
|
|
79804
79869
|
end try
|
|
@@ -79983,6 +80048,31 @@ var AppleMailManager = class {
|
|
|
79983
80048
|
const targetMailbox = this.resolveMailbox(mailbox, targetAccount);
|
|
79984
80049
|
const safeMailbox = escapeForAppleScript(targetMailbox);
|
|
79985
80050
|
const safeAccount = escapeForAppleScript(targetAccount);
|
|
80051
|
+
const loc = this.locationFor(id);
|
|
80052
|
+
const findAndMove = loc ? `
|
|
80053
|
+
${this.resolveMailboxFragment(loc.account, loc.mailbox)}
|
|
80054
|
+
if _tmb is missing value then return "error:Message not found"
|
|
80055
|
+
set matchingMsgs to (messages of _tmb whose id is ${Number(id)})
|
|
80056
|
+
if (count of matchingMsgs) is 0 then return "error:Message not found"
|
|
80057
|
+
move (item 1 of matchingMsgs) to destMailbox
|
|
80058
|
+
return "ok"` : `
|
|
80059
|
+
set _hits to {}
|
|
80060
|
+
set _names to ""
|
|
80061
|
+
repeat with acct in accounts
|
|
80062
|
+
repeat with mb in (mailboxes of acct)
|
|
80063
|
+
try
|
|
80064
|
+
set matchingMsgs to (messages of mb whose id is ${Number(id)})
|
|
80065
|
+
if (count of matchingMsgs) > 0 then
|
|
80066
|
+
set end of _hits to (item 1 of matchingMsgs)
|
|
80067
|
+
set _names to _names & (name of acct) & "/" & (name of mb) & ", "
|
|
80068
|
+
end if
|
|
80069
|
+
end try
|
|
80070
|
+
end repeat
|
|
80071
|
+
end repeat
|
|
80072
|
+
if (count of _hits) is 0 then return "error:Message not found"
|
|
80073
|
+
if (count of _hits) > 1 then return "error:${AMBIGUOUS_ID_PREFIX}${Number(id)} is present in more than one mailbox (" & _names & "); list or search that mailbox first so the move targets the right copy"
|
|
80074
|
+
move (item 1 of _hits) to destMailbox
|
|
80075
|
+
return "ok"`;
|
|
79986
80076
|
const script = buildAppLevelScript(`
|
|
79987
80077
|
try
|
|
79988
80078
|
-- \`mailboxes of account\` is already flat: it includes nested mailboxes
|
|
@@ -79998,21 +80088,7 @@ var AppleMailManager = class {
|
|
|
79998
80088
|
if (count of destMatches) is 0 then return "error:Destination mailbox \\"" & destName & "\\" not found in account \\"${safeAccount}\\""
|
|
79999
80089
|
if (count of destMatches) > 1 then return "error:Destination mailbox \\"" & destName & "\\" is ambiguous (" & (count of destMatches) & " matches) in account \\"${safeAccount}\\"; disambiguate or move by full path"
|
|
80000
80090
|
set destMailbox to item 1 of destMatches
|
|
80001
|
-
|
|
80002
|
-
-- Find the message by id. The flat mailbox list already covers nested
|
|
80003
|
-
-- mailboxes, so this reaches messages in subfolders without recursing.
|
|
80004
|
-
repeat with acct in accounts
|
|
80005
|
-
repeat with mb in (mailboxes of acct)
|
|
80006
|
-
try
|
|
80007
|
-
set matchingMsgs to (messages of mb whose id is ${Number(id)})
|
|
80008
|
-
if (count of matchingMsgs) > 0 then
|
|
80009
|
-
move (item 1 of matchingMsgs) to destMailbox
|
|
80010
|
-
return "ok"
|
|
80011
|
-
end if
|
|
80012
|
-
end try
|
|
80013
|
-
end repeat
|
|
80014
|
-
end repeat
|
|
80015
|
-
return "error:Message not found"
|
|
80091
|
+
${findAndMove}
|
|
80016
80092
|
on error errMsg
|
|
80017
80093
|
return "error:" & errMsg
|
|
80018
80094
|
end try
|
|
@@ -80046,15 +80122,26 @@ var AppleMailManager = class {
|
|
|
80046
80122
|
* Previously each batch method looped and called the per-id method, so a
|
|
80047
80123
|
* 100-id batch spawned 100 osascript processes — each one re-resolving
|
|
80048
80124
|
* accounts and walking the whole account→mailbox tree — all serialized
|
|
80049
|
-
* through the gate (issue #31).
|
|
80050
|
-
*
|
|
80051
|
-
*
|
|
80052
|
-
*
|
|
80053
|
-
*
|
|
80054
|
-
*
|
|
80125
|
+
* through the gate (issue #31). Still one osascript invocation, but the ids
|
|
80126
|
+
* are now grouped by the mailbox they were listed from and each group opens
|
|
80127
|
+
* exactly that one mailbox. Per-id outcomes come back as control-char
|
|
80128
|
+
* delimited `position<FS>status` records (status: `ok`, `notfound`, or
|
|
80129
|
+
* `error:<msg>`), and results are returned in input order.
|
|
80130
|
+
*
|
|
80131
|
+
* Scoping is a CORRECTNESS requirement, not an optimization (#152). A Mail.app
|
|
80132
|
+
* numeric id is unique only within a mailbox, and a label store (Gmail,
|
|
80133
|
+
* iCloud) exposes one message in several mailboxes under the same id — INBOX,
|
|
80134
|
+
* "Important" and "All Mail" all report id 75816 for the same mail. The old
|
|
80135
|
+
* tree walk applied `operation` to the FIRST mailbox that matched, and
|
|
80136
|
+
* `mailboxes of account` yields INBOX late, so a batch of ids listed from
|
|
80137
|
+
* INBOX was reliably applied to the "Important" copies instead: every id
|
|
80138
|
+
* reported `ok` while the INBOX messages stayed put and other copies were
|
|
80139
|
+
* moved/deleted. Grouping by recorded source mailbox makes the op land on the
|
|
80140
|
+
* copy the caller actually listed; ids with no recorded mailbox are refused
|
|
80141
|
+
* when ambiguous rather than applied to an arbitrary copy.
|
|
80055
80142
|
*
|
|
80056
|
-
* `setup` runs once
|
|
80057
|
-
*
|
|
80143
|
+
* `setup` runs once up front (used by move to resolve the destination); it may
|
|
80144
|
+
* bail the whole batch by returning a `BATCH_FATAL`-prefixed string.
|
|
80058
80145
|
*/
|
|
80059
80146
|
runBatchOperation(ids, operation, setup = "") {
|
|
80060
80147
|
const valid = [];
|
|
@@ -80065,39 +80152,96 @@ var AppleMailManager = class {
|
|
|
80065
80152
|
if (valid.length === 0) {
|
|
80066
80153
|
return ids.map((id) => ({ id, success: false, error: "Invalid message ID" }));
|
|
80067
80154
|
}
|
|
80068
|
-
const
|
|
80069
|
-
|
|
80070
|
-
|
|
80071
|
-
|
|
80072
|
-
|
|
80073
|
-
|
|
80074
|
-
|
|
80155
|
+
const groups = /* @__PURE__ */ new Map();
|
|
80156
|
+
const unlocated = [];
|
|
80157
|
+
valid.forEach((v, i) => {
|
|
80158
|
+
const pos = i + 1;
|
|
80159
|
+
const loc = this.locationFor(v.id);
|
|
80160
|
+
if (!loc) {
|
|
80161
|
+
unlocated.push({ num: v.num, pos });
|
|
80162
|
+
return;
|
|
80163
|
+
}
|
|
80164
|
+
const key = `${loc.account}\0${loc.mailbox}`;
|
|
80165
|
+
const g = groups.get(key) ?? { account: loc.account, mailbox: loc.mailbox, items: [] };
|
|
80166
|
+
g.items.push({ num: v.num, pos });
|
|
80167
|
+
groups.set(key, g);
|
|
80168
|
+
});
|
|
80169
|
+
const asList = (nums) => `{${nums.join(", ")}}`;
|
|
80170
|
+
const scopedBlocks = [...groups.values()].map(
|
|
80171
|
+
(g) => `
|
|
80172
|
+
${this.resolveMailboxFragment(g.account, g.mailbox)}
|
|
80173
|
+
set _gids to ${asList(g.items.map((it) => it.num))}
|
|
80174
|
+
set _gpos to ${asList(g.items.map((it) => it.pos))}
|
|
80175
|
+
if _tmb is missing value then
|
|
80176
|
+
repeat with _k from 1 to (count of _gpos)
|
|
80177
|
+
set _out to _out & ((item _k of _gpos) as string) & "${FIELD_SEP}error:source mailbox \\"${escapeForAppleScript(g.mailbox)}\\" not found in account \\"${escapeForAppleScript(g.account)}\\"${RECORD_SEP}"
|
|
80178
|
+
end repeat
|
|
80179
|
+
else
|
|
80180
|
+
repeat with _k from 1 to (count of _gids)
|
|
80181
|
+
set _idx to item _k of _gpos
|
|
80182
|
+
try
|
|
80183
|
+
set _m to (messages of _tmb whose id is (item _k of _gids))
|
|
80184
|
+
if (count of _m) > 0 then
|
|
80185
|
+
set _msg to item 1 of _m
|
|
80186
|
+
${operation}
|
|
80187
|
+
set _out to _out & (_idx as string) & "${FIELD_SEP}ok${RECORD_SEP}"
|
|
80188
|
+
else
|
|
80189
|
+
set _out to _out & (_idx as string) & "${FIELD_SEP}notfound${RECORD_SEP}"
|
|
80190
|
+
end if
|
|
80191
|
+
on error _e
|
|
80192
|
+
set _out to _out & (_idx as string) & "${FIELD_SEP}error:" & _e & "${RECORD_SEP}"
|
|
80193
|
+
end try
|
|
80194
|
+
end repeat
|
|
80195
|
+
end if`
|
|
80196
|
+
).join("\n");
|
|
80197
|
+
const unlocatedBlock = unlocated.length ? `
|
|
80198
|
+
set _uids to ${asList(unlocated.map((it) => it.num))}
|
|
80199
|
+
set _upos to ${asList(unlocated.map((it) => it.pos))}
|
|
80200
|
+
set _ucount to count of _uids
|
|
80201
|
+
set _uhit to {}
|
|
80202
|
+
set _umsg to {}
|
|
80203
|
+
set _unames to {}
|
|
80204
|
+
repeat with _k from 1 to _ucount
|
|
80205
|
+
set end of _uhit to 0
|
|
80206
|
+
set end of _umsg to missing value
|
|
80207
|
+
set end of _unames to ""
|
|
80208
|
+
end repeat
|
|
80075
80209
|
repeat with acct in accounts
|
|
80076
|
-
if (count of _done) is _total then exit repeat
|
|
80077
80210
|
repeat with mb in (mailboxes of acct)
|
|
80078
|
-
|
|
80079
|
-
|
|
80080
|
-
|
|
80081
|
-
|
|
80082
|
-
|
|
80083
|
-
set
|
|
80084
|
-
|
|
80085
|
-
|
|
80086
|
-
|
|
80087
|
-
set end of _done to _idx
|
|
80088
|
-
set _out to _out & (_idx as string) & "${FIELD_SEP}ok${RECORD_SEP}"
|
|
80089
|
-
end if
|
|
80090
|
-
on error _e
|
|
80091
|
-
set end of _done to _idx
|
|
80092
|
-
set _out to _out & (_idx as string) & "${FIELD_SEP}error:" & _e & "${RECORD_SEP}"
|
|
80093
|
-
end try
|
|
80094
|
-
end if
|
|
80211
|
+
repeat with _k from 1 to _ucount
|
|
80212
|
+
try
|
|
80213
|
+
set _m to (messages of mb whose id is (item _k of _uids))
|
|
80214
|
+
if (count of _m) > 0 then
|
|
80215
|
+
set item _k of _uhit to ((item _k of _uhit) + 1)
|
|
80216
|
+
if (item _k of _uhit) is 1 then set item _k of _umsg to (item 1 of _m)
|
|
80217
|
+
set item _k of _unames to ((item _k of _unames) & (name of acct) & "/" & (name of mb) & ", ")
|
|
80218
|
+
end if
|
|
80219
|
+
end try
|
|
80095
80220
|
end repeat
|
|
80096
80221
|
end repeat
|
|
80097
80222
|
end repeat
|
|
80098
|
-
repeat with
|
|
80099
|
-
|
|
80100
|
-
|
|
80223
|
+
repeat with _k from 1 to _ucount
|
|
80224
|
+
set _idx to item _k of _upos
|
|
80225
|
+
if (item _k of _uhit) is 0 then
|
|
80226
|
+
set _out to _out & (_idx as string) & "${FIELD_SEP}notfound${RECORD_SEP}"
|
|
80227
|
+
else if (item _k of _uhit) > 1 then
|
|
80228
|
+
set _out to _out & (_idx as string) & "${FIELD_SEP}error:${AMBIGUOUS_ID_BATCH}(" & (item _k of _unames) & "); list or search that mailbox first so the operation targets the right copy${RECORD_SEP}"
|
|
80229
|
+
else
|
|
80230
|
+
try
|
|
80231
|
+
set _msg to item _k of _umsg
|
|
80232
|
+
${operation}
|
|
80233
|
+
set _out to _out & (_idx as string) & "${FIELD_SEP}ok${RECORD_SEP}"
|
|
80234
|
+
on error _e
|
|
80235
|
+
set _out to _out & (_idx as string) & "${FIELD_SEP}error:" & _e & "${RECORD_SEP}"
|
|
80236
|
+
end try
|
|
80237
|
+
end if
|
|
80238
|
+
end repeat` : "";
|
|
80239
|
+
const script = buildAppLevelScript(`
|
|
80240
|
+
try
|
|
80241
|
+
${setup}
|
|
80242
|
+
set _out to ""
|
|
80243
|
+
${scopedBlocks}
|
|
80244
|
+
${unlocatedBlock}
|
|
80101
80245
|
return _out
|
|
80102
80246
|
on error errMsg
|
|
80103
80247
|
return "${BATCH_FATAL}" & errMsg
|
package/docs/IMAP-SETUP.md
CHANGED
|
@@ -111,7 +111,7 @@ The server reads `APPLE_MAIL_MCP_*` settings. There are two ways to supply them;
|
|
|
111
111
|
Works with clients that pass an `env` block through to the server (e.g. **Claude
|
|
112
112
|
Code** via `~/.claude.json`, and most standard `mcpServers` configs).
|
|
113
113
|
|
|
114
|
-
```
|
|
114
|
+
```json
|
|
115
115
|
{
|
|
116
116
|
"mcpServers": {
|
|
117
117
|
"apple-mail": {
|
package/package.json
CHANGED