apple-mail-mcp 2.19.11 → 2.19.12
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 +5 -3
- package/build/index.js +56 -15
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -826,7 +826,7 @@ Reply to an existing message.
|
|
|
826
826
|
| Parameter | Type | Required | Description |
|
|
827
827
|
| ----------- | ------- | -------- | ---------------------------------------------------------------------------------------------- |
|
|
828
828
|
| `id` | string | Yes | Message ID to reply to |
|
|
829
|
-
| `body` | string | Yes | Reply body
|
|
829
|
+
| `body` | string | Yes | Reply body (plain text; HTML tags such as `<br>` are not rendered) |
|
|
830
830
|
| `replyAll` | boolean | No | Reply to all recipients (default: false) |
|
|
831
831
|
| `send` | boolean | No | Send immediately (default: true, false = save as draft) |
|
|
832
832
|
| `transport` | string | No | `smtp` or `applescript`; omitted prefers configured SMTP when sending. Drafts use AppleScript. |
|
|
@@ -853,6 +853,8 @@ Reply to an existing message.
|
|
|
853
853
|
|
|
854
854
|
**Delivery:** `imap:` IDs are read directly from their encoded account, mailbox, and UID. Numeric IDs are read through Mail.app. With SMTP configured, replies use clean MIME with the original `Message-ID` in `In-Reply-To` and the full `References` chain. Only the original plain-text body is quoted; the new text is not. Pass `transport: "smtp"` to require this path, or `transport: "applescript"` to use Mail.app explicitly.
|
|
855
855
|
|
|
856
|
+
**AppleScript transport quoting (v2.19.12):** every draft (`send: false`) and any send that falls back to AppleScript (SMTP not configured) also gets the original quoted — an "On \<date\>, \<sender\> wrote:" attribution line followed by the `> `-prefixed original body, built the same way as the SMTP path. Mail's own `reply`/`forward` AppleScript commands generate this quote internally but expose no way to read it back, so it's built here instead of relying on Mail's (unreadable) copy. Unlike SMTP, this path has no sending-identity restriction — it's read-only source lookup, not sending.
|
|
857
|
+
|
|
856
858
|
**Failure behavior:** once SMTP is selected, a missing password, unreadable source, missing reply address or `Message-ID`, or SMTP failure returns an error. It does not silently switch to AppleScript or create an unthreaded new message. With SMTP unconfigured and transport omitted, AppleScript remains available. `send: false` saves a Mail.app draft; combining it with `transport: "smtp"` is rejected before composing.
|
|
857
859
|
|
|
858
860
|
The direct IMAP source read is bounded to 25 MiB, including MIME attachments. Its account login must match the SMTP login, configured From, or an explicitly configured `APPLE_MAIL_MCP_SMTP_ALLOWED_FROM` identity; otherwise the call fails rather than sending from an unrelated account. The SMTP configuration still represents a single sending identity, not a per-account SMTP registry.
|
|
@@ -871,11 +873,11 @@ Forward a message to new recipients.
|
|
|
871
873
|
| ----------- | -------- | -------- | ---------------------------------------------------------------------------------------------- |
|
|
872
874
|
| `id` | string | Yes | Message ID to forward |
|
|
873
875
|
| `to` | string[] | Yes | Recipients to forward to |
|
|
874
|
-
| `body` | string | No | Message to prepend
|
|
876
|
+
| `body` | string | No | Message to prepend (plain text) |
|
|
875
877
|
| `send` | boolean | No | Send immediately (default: true, false = save as draft) |
|
|
876
878
|
| `transport` | string | No | `smtp` or `applescript`; omitted prefers configured SMTP when sending. Drafts use AppleScript. |
|
|
877
879
|
|
|
878
|
-
**Delivery:** uses the same source lookup, transport selection, 25 MiB source limit, account-identity check, and failure behavior as `reply-to-message`. A forward deliberately starts a new conversation, so it has no `In-Reply-To` or `References` headers. The existing plain-text forwarding behavior is unchanged: original attachments are not reattached. See [SMTP transport](#smtp-transport).
|
|
880
|
+
**Delivery:** uses the same source lookup, transport selection, 25 MiB source limit, account-identity check, and failure behavior as `reply-to-message`. A forward deliberately starts a new conversation, so it has no `In-Reply-To` or `References` headers. The existing plain-text forwarding behavior is unchanged: original attachments are not reattached. See [SMTP transport](#smtp-transport). On the AppleScript transport, a `body` is merged with the forwarded-message header block and original text the same way the SMTP path builds it (see `reply-to-message`'s AppleScript transport quoting note); with no `body`, Mail's own forward content is left untouched.
|
|
879
881
|
|
|
880
882
|
SMTP forwarding requires a readable plain-text original. HTML-only IMAP messages and failed Mail.app body reads return an error before sending instead of silently omitting the original content. Explicitly select `transport: "applescript"` to forward these with Mail.app; no automatic fallback occurs. An intentionally empty plain-text message is still valid.
|
|
881
883
|
|
package/build/index.js
CHANGED
|
@@ -86847,10 +86847,6 @@ function buildReplyOptions(args) {
|
|
|
86847
86847
|
);
|
|
86848
86848
|
cc = extra.length ? extra : void 0;
|
|
86849
86849
|
}
|
|
86850
|
-
const attribution = buildAttribution(original);
|
|
86851
|
-
const quoted = originalPlainText.trim() ? `
|
|
86852
|
-
|
|
86853
|
-
${attribution}${quoteBody(originalPlainText)}` : "";
|
|
86854
86850
|
const references = dedupe(
|
|
86855
86851
|
original.messageId ? [...original.references, original.messageId] : original.references
|
|
86856
86852
|
);
|
|
@@ -86858,12 +86854,19 @@ ${attribution}${quoteBody(originalPlainText)}` : "";
|
|
|
86858
86854
|
to,
|
|
86859
86855
|
cc,
|
|
86860
86856
|
subject: withSubjectPrefix(original.subject, "Re:"),
|
|
86861
|
-
body:
|
|
86857
|
+
body: buildReplyBody(body, original, originalPlainText),
|
|
86862
86858
|
inReplyTo: original.messageId,
|
|
86863
86859
|
references: references.length ? references : void 0,
|
|
86864
86860
|
from
|
|
86865
86861
|
};
|
|
86866
86862
|
}
|
|
86863
|
+
function buildReplyBody(body, original, originalPlainText) {
|
|
86864
|
+
const attribution = buildAttribution(original);
|
|
86865
|
+
const quoted = originalPlainText.trim() ? `
|
|
86866
|
+
|
|
86867
|
+
${attribution}${quoteBody(originalPlainText)}` : "";
|
|
86868
|
+
return `${body}${quoted}`;
|
|
86869
|
+
}
|
|
86867
86870
|
function buildAttribution(original) {
|
|
86868
86871
|
const who = original.from[0] ?? original.replyTo[0] ?? "the sender";
|
|
86869
86872
|
return original.date ? `On ${original.date}, ${who} wrote:
|
|
@@ -86872,6 +86875,14 @@ function buildAttribution(original) {
|
|
|
86872
86875
|
}
|
|
86873
86876
|
function buildForwardOptions(args) {
|
|
86874
86877
|
const { original, originalPlainText, to, body, from } = args;
|
|
86878
|
+
return {
|
|
86879
|
+
to: dedupe(to),
|
|
86880
|
+
subject: withSubjectPrefix(original.subject, "Fwd:"),
|
|
86881
|
+
body: buildForwardBody(original, originalPlainText, body),
|
|
86882
|
+
from
|
|
86883
|
+
};
|
|
86884
|
+
}
|
|
86885
|
+
function buildForwardBody(original, originalPlainText, body) {
|
|
86875
86886
|
const headerBlock = [
|
|
86876
86887
|
"---------- Forwarded message ----------",
|
|
86877
86888
|
original.from.length ? `From: ${original.from.join(", ")}` : "",
|
|
@@ -86883,14 +86894,9 @@ function buildForwardOptions(args) {
|
|
|
86883
86894
|
const prefix = body?.trim() ? `${body}
|
|
86884
86895
|
|
|
86885
86896
|
` : "";
|
|
86886
|
-
return {
|
|
86887
|
-
to: dedupe(to),
|
|
86888
|
-
subject: withSubjectPrefix(original.subject, "Fwd:"),
|
|
86889
|
-
body: `${prefix}${headerBlock}
|
|
86897
|
+
return `${prefix}${headerBlock}
|
|
86890
86898
|
|
|
86891
|
-
${originalPlainText}
|
|
86892
|
-
from
|
|
86893
|
-
};
|
|
86899
|
+
${originalPlainText}`;
|
|
86894
86900
|
}
|
|
86895
86901
|
|
|
86896
86902
|
// src/tools/compose.ts
|
|
@@ -87028,6 +87034,31 @@ async function readOriginal(deps, id, cfg) {
|
|
|
87028
87034
|
const content = deps.mail.getMessageContent(id);
|
|
87029
87035
|
return { original: parseOriginalHeaders(raw), plainText: content?.plainText ?? null };
|
|
87030
87036
|
}
|
|
87037
|
+
async function readOriginalForQuote(deps, id) {
|
|
87038
|
+
if (decodeImapId(id)) {
|
|
87039
|
+
try {
|
|
87040
|
+
const source = await deps.imapSource(id);
|
|
87041
|
+
const original = parseOriginalHeaders(source.raw);
|
|
87042
|
+
if (source.subject !== void 0) original.subject = source.subject;
|
|
87043
|
+
return { original, plainText: extractTextBody(source.raw) ?? "" };
|
|
87044
|
+
} catch {
|
|
87045
|
+
return null;
|
|
87046
|
+
}
|
|
87047
|
+
}
|
|
87048
|
+
const raw = deps.mail.getRawSource(id);
|
|
87049
|
+
if (!raw) return null;
|
|
87050
|
+
const content = deps.mail.getMessageContent(id);
|
|
87051
|
+
return { original: parseOriginalHeaders(raw), plainText: content?.plainText ?? "" };
|
|
87052
|
+
}
|
|
87053
|
+
async function replyComposeBody(deps, id, body) {
|
|
87054
|
+
const source = await readOriginalForQuote(deps, id);
|
|
87055
|
+
return source ? buildReplyBody(body, source.original, source.plainText) : body;
|
|
87056
|
+
}
|
|
87057
|
+
async function forwardComposeBody(deps, id, body) {
|
|
87058
|
+
if (!body) return body;
|
|
87059
|
+
const source = await readOriginalForQuote(deps, id);
|
|
87060
|
+
return source ? buildForwardBody(source.original, source.plainText, body) : body;
|
|
87061
|
+
}
|
|
87031
87062
|
async function runCompose(deps, args) {
|
|
87032
87063
|
const { id, send, transport: transport2 } = args;
|
|
87033
87064
|
const verb = args.kind === "reply" ? "reply to" : "forward";
|
|
@@ -87098,7 +87129,17 @@ async function runCompose(deps, args) {
|
|
|
87098
87129
|
return errorResponse(
|
|
87099
87130
|
`Failed to ${verb} message "${id}": ${resolved.error ?? "message not found"}`
|
|
87100
87131
|
);
|
|
87101
|
-
const outcome = args.kind === "reply" ? deps.mail.replyToMessage(
|
|
87132
|
+
const outcome = args.kind === "reply" ? deps.mail.replyToMessage(
|
|
87133
|
+
resolved.numericId,
|
|
87134
|
+
await replyComposeBody(deps, id, args.body),
|
|
87135
|
+
args.replyAll,
|
|
87136
|
+
send
|
|
87137
|
+
) : deps.mail.forwardMessage(
|
|
87138
|
+
resolved.numericId,
|
|
87139
|
+
args.to,
|
|
87140
|
+
await forwardComposeBody(deps, id, args.body),
|
|
87141
|
+
send
|
|
87142
|
+
);
|
|
87102
87143
|
if (!outcome.success)
|
|
87103
87144
|
return errorResponse(
|
|
87104
87145
|
`Failed to ${verb} message "${id}": ${outcome.error ?? "Mail.app compose failed"}`
|
|
@@ -88858,7 +88899,7 @@ registerTool(
|
|
|
88858
88899
|
inputSchema: {
|
|
88859
88900
|
id: MESSAGE_ID_SCHEMA,
|
|
88860
88901
|
transport: COMPOSE_TRANSPORT_SCHEMA,
|
|
88861
|
-
body: external_exports.string().min(1, "Reply body is required"),
|
|
88902
|
+
body: external_exports.string().min(1, "Reply body is required").describe("Reply body (plain text; HTML tags such as <br> are not rendered)"),
|
|
88862
88903
|
replyAll: external_exports.boolean().optional().default(false).describe("Reply to all recipients"),
|
|
88863
88904
|
send: external_exports.boolean().optional().default(true).describe("Send immediately (false = save as draft)")
|
|
88864
88905
|
},
|
|
@@ -88882,7 +88923,7 @@ registerTool(
|
|
|
88882
88923
|
id: MESSAGE_ID_SCHEMA,
|
|
88883
88924
|
transport: COMPOSE_TRANSPORT_SCHEMA,
|
|
88884
88925
|
to: external_exports.array(external_exports.string()).min(1, "At least one recipient is required"),
|
|
88885
|
-
body: external_exports.string().optional().describe("Optional message to prepend"),
|
|
88926
|
+
body: external_exports.string().optional().describe("Optional message to prepend (plain text)"),
|
|
88886
88927
|
send: external_exports.boolean().optional().default(true).describe("Send immediately (false = save as draft)")
|
|
88887
88928
|
},
|
|
88888
88929
|
outputSchema: {
|
package/package.json
CHANGED