apple-mail-mcp 2.8.3 → 2.8.5
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 +19 -0
- package/build/index.js +33 -7
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -98,6 +98,25 @@ npm install -g github:sweetrb/apple-mail-mcp
|
|
|
98
98
|
|
|
99
99
|
On first use, macOS will ask for permission to automate Mail.app. Click "OK" to allow.
|
|
100
100
|
|
|
101
|
+
## Configuring email (IMAP & SMTP)
|
|
102
|
+
|
|
103
|
+
The server works out of the box over AppleScript with **no configuration**. Two
|
|
104
|
+
**opt-in** power features take a one-time setup:
|
|
105
|
+
|
|
106
|
+
- **Fast IMAP reads** — server-side search, counts, and large-mailbox handling
|
|
107
|
+
that AppleScript is too slow for (it times out on big Gmail mailboxes).
|
|
108
|
+
- **Clean SMTP sending** — `send-email` submits clean MIME directly, avoiding the
|
|
109
|
+
macOS 15+ Mail.app `<blockquote>` wrapping that otherwise makes sent mail look
|
|
110
|
+
quoted/indented like a reply.
|
|
111
|
+
|
|
112
|
+
Both are driven by non-secret `APPLE_MAIL_MCP_*` settings — supplied via an `env`
|
|
113
|
+
block **or** a `config.json` file (for hosts like Claude Desktop that strip `env`)
|
|
114
|
+
— with passwords kept in the macOS **Keychain**, never in config.
|
|
115
|
+
|
|
116
|
+
👉 **[IMAP / SMTP Setup Guide](docs/IMAP-SETUP.md)** — step-by-step: app passwords,
|
|
117
|
+
Keychain, both config methods, multi-account, SMTP, verification with the `doctor`
|
|
118
|
+
tool, and troubleshooting. Verify any time by running the **`doctor`** tool.
|
|
119
|
+
|
|
101
120
|
## Requirements
|
|
102
121
|
|
|
103
122
|
- **macOS** - Apple Mail and AppleScript are macOS-only
|
package/build/index.js
CHANGED
|
@@ -80308,6 +80308,28 @@ async function imapMoveMessageById(id, destMailbox, deps = {}) {
|
|
|
80308
80308
|
}
|
|
80309
80309
|
});
|
|
80310
80310
|
}
|
|
80311
|
+
async function resolveTrashPath(client) {
|
|
80312
|
+
try {
|
|
80313
|
+
const boxes = await client.list();
|
|
80314
|
+
const special = boxes.find((b) => b.specialUse === "\\Trash");
|
|
80315
|
+
if (special) return special.path;
|
|
80316
|
+
const named = boxes.find(
|
|
80317
|
+
(b) => /^(trash|deleted messages|deleted items|bin)$/i.test(b.name) || /(^|\/)trash$/i.test(b.path)
|
|
80318
|
+
);
|
|
80319
|
+
if (named) return named.path;
|
|
80320
|
+
} catch {
|
|
80321
|
+
}
|
|
80322
|
+
return resolveMailboxPath("trash", "list");
|
|
80323
|
+
}
|
|
80324
|
+
async function trashUids(client, uids, srcPath) {
|
|
80325
|
+
const dest = await resolveTrashPath(client);
|
|
80326
|
+
if (srcPath.trim().toLowerCase() === dest.trim().toLowerCase()) {
|
|
80327
|
+
await client.messageDelete(uids, { uid: true });
|
|
80328
|
+
return { dest, expunged: true };
|
|
80329
|
+
}
|
|
80330
|
+
await client.messageMove(uids, dest, { uid: true });
|
|
80331
|
+
return { dest, expunged: false };
|
|
80332
|
+
}
|
|
80311
80333
|
async function imapDeleteMessageById(id, deps = {}) {
|
|
80312
80334
|
const ref = decodeImapId(id);
|
|
80313
80335
|
if (!ref) return { success: false, error: `Not an IMAP message id: "${id}".` };
|
|
@@ -80316,9 +80338,11 @@ async function imapDeleteMessageById(id, deps = {}) {
|
|
|
80316
80338
|
{ ...deps, account: deps.account ?? ref.account },
|
|
80317
80339
|
async (client) => {
|
|
80318
80340
|
try {
|
|
80319
|
-
const
|
|
80320
|
-
|
|
80321
|
-
|
|
80341
|
+
const { dest, expunged } = await trashUids(client, [ref.uid], ref.path);
|
|
80342
|
+
return {
|
|
80343
|
+
success: true,
|
|
80344
|
+
info: expunged ? `Permanently deleted UID ${ref.uid} from Trash ("${ref.path}") via IMAP.` : `Moved UID ${ref.uid} to Trash ("${dest}") via IMAP.`
|
|
80345
|
+
};
|
|
80322
80346
|
} catch (e) {
|
|
80323
80347
|
return { success: false, error: `IMAP delete failed for UID ${ref.uid}: ${errText(e)}` };
|
|
80324
80348
|
}
|
|
@@ -80445,8 +80469,8 @@ var imapBatchFlag = (ids, deps = {}) => imapBatch(ids, deps, async (c, uids) =>
|
|
|
80445
80469
|
var imapBatchUnflag = (ids, deps = {}) => imapBatch(ids, deps, async (c, uids) => {
|
|
80446
80470
|
await c.messageFlagsRemove(uids, ["\\Flagged"], { uid: true });
|
|
80447
80471
|
});
|
|
80448
|
-
var imapBatchDelete = (ids, deps = {}) => imapBatch(ids, deps, async (c, uids) => {
|
|
80449
|
-
await c
|
|
80472
|
+
var imapBatchDelete = (ids, deps = {}) => imapBatch(ids, deps, async (c, uids, path) => {
|
|
80473
|
+
await trashUids(c, uids, path);
|
|
80450
80474
|
});
|
|
80451
80475
|
function imapBatchMove(ids, destMailbox, deps = {}) {
|
|
80452
80476
|
return imapBatch(ids, deps, async (c, uids) => {
|
|
@@ -80733,6 +80757,8 @@ async function routeMessage(id, opts) {
|
|
|
80733
80757
|
}
|
|
80734
80758
|
|
|
80735
80759
|
// src/tools/doctor.ts
|
|
80760
|
+
var SETUP_GUIDE = "https://github.com/sweetrb/apple-mail-mcp/blob/main/docs/IMAP-SETUP.md";
|
|
80761
|
+
var CONFIG_FILE_HINT = "If your MCP host ignores the server 'env' block (e.g. Claude Desktop), put these in ~/Library/Application Support/apple-mail-mcp/config.json instead";
|
|
80736
80762
|
async function runDoctor(mailManager2) {
|
|
80737
80763
|
const checks = [];
|
|
80738
80764
|
const hc = mailManager2.healthCheck();
|
|
@@ -80764,7 +80790,7 @@ async function runDoctor(mailManager2) {
|
|
|
80764
80790
|
checks.push({
|
|
80765
80791
|
name: "IMAP backend",
|
|
80766
80792
|
status: "warn",
|
|
80767
|
-
detail: `not configured \u2014 AppleScript is used for all accounts. Set ${IMAP_ENV.user} (+ Keychain/password), or ${IMAP_ENV.accounts} for multiple accounts, to enable server-side search and server-mailbox ops
|
|
80793
|
+
detail: `not configured \u2014 AppleScript is used for all accounts. Set ${IMAP_ENV.user} (+ Keychain/password), or ${IMAP_ENV.accounts} for multiple accounts, to enable server-side search and server-mailbox ops. ${CONFIG_FILE_HINT}. Setup guide: ${SETUP_GUIDE}`
|
|
80768
80794
|
});
|
|
80769
80795
|
} else {
|
|
80770
80796
|
for (const label of imapAccounts) {
|
|
@@ -80780,7 +80806,7 @@ async function runDoctor(mailManager2) {
|
|
|
80780
80806
|
checks.push({
|
|
80781
80807
|
name: "SMTP transport",
|
|
80782
80808
|
status: isSmtpConfigured() ? "ok" : "warn",
|
|
80783
|
-
detail: isSmtpConfigured() ? `configured (${smtpHost}); send-email auto-prefers clean SMTP (no Mail.app Sent-folder copy; a non-email "account" label still routes to AppleScript). Pass transport:"applescript" to force Mail.app. The apple-mail-send CLI is also available.` : `not configured \u2014 send-email uses AppleScript (subject to macOS 15+ blockquote wrapping). Set ${SMTP_ENV.host} and ${SMTP_ENV.user} (+ password via Keychain) to enable
|
|
80809
|
+
detail: isSmtpConfigured() ? `configured (${smtpHost}); send-email auto-prefers clean SMTP (no Mail.app Sent-folder copy; a non-email "account" label still routes to AppleScript). Pass transport:"applescript" to force Mail.app. The apple-mail-send CLI is also available.` : `not configured \u2014 send-email uses AppleScript (subject to macOS 15+ blockquote wrapping). Set ${SMTP_ENV.host} and ${SMTP_ENV.user} (+ password via Keychain) to enable. ${CONFIG_FILE_HINT}. Setup guide: ${SETUP_GUIDE}`
|
|
80784
80810
|
});
|
|
80785
80811
|
const healthy = !checks.some((c) => c.status === "fail");
|
|
80786
80812
|
return { healthy, checks };
|
package/package.json
CHANGED