apple-mail-mcp 1.6.6 → 1.6.7
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 +6 -2
- package/build/services/appleMailManager.d.ts +10 -3
- package/build/services/appleMailManager.d.ts.map +1 -1
- package/build/services/appleMailManager.js +38 -22
- package/build/utils/mimeParse.d.ts +15 -0
- package/build/utils/mimeParse.d.ts.map +1 -1
- package/build/utils/mimeParse.js +38 -0
- package/package.json +1 -1
package/build/index.js
CHANGED
|
@@ -174,9 +174,13 @@ server.tool("search-messages", {
|
|
|
174
174
|
// --- get-message ---
|
|
175
175
|
server.tool("get-message", {
|
|
176
176
|
id: MESSAGE_ID_SCHEMA,
|
|
177
|
-
preferHtml: z
|
|
177
|
+
preferHtml: z
|
|
178
|
+
.boolean()
|
|
179
|
+
.optional()
|
|
180
|
+
.describe("Return the HTML body (extracted from the message source) instead of plain text"),
|
|
178
181
|
}, withErrorHandling(({ id, preferHtml }) => {
|
|
179
|
-
|
|
182
|
+
// Only fetch/parse the raw source when HTML is actually requested (#32).
|
|
183
|
+
const content = mailManager.getMessageContent(id, preferHtml === true);
|
|
180
184
|
if (!content) {
|
|
181
185
|
return errorResponse(`Message with ID "${id}" not found`);
|
|
182
186
|
}
|
|
@@ -180,11 +180,18 @@ export declare class AppleMailManager {
|
|
|
180
180
|
* Note: Mail.app message IDs are unique per mailbox. This method searches
|
|
181
181
|
* all mailboxes in all accounts to find the message.
|
|
182
182
|
*/
|
|
183
|
-
getMessageById(id: string): Message | null;
|
|
183
|
+
getMessageById(id: string, deepAttachmentCheck?: boolean): Message | null;
|
|
184
184
|
/**
|
|
185
185
|
* Get the content of a message.
|
|
186
|
-
|
|
187
|
-
|
|
186
|
+
*
|
|
187
|
+
* @param id - Message ID
|
|
188
|
+
* @param includeHtml - When true, also fetch the raw MIME source and extract
|
|
189
|
+
* the `text/html` body part into `htmlContent`. This is opt-in because the
|
|
190
|
+
* source can be MB-sized (it includes base64 attachments) and the plain-text
|
|
191
|
+
* path doesn't need it; fetching it unconditionally was both slow and, worse,
|
|
192
|
+
* returned the entire raw MIME blob mislabeled as HTML (#32).
|
|
193
|
+
*/
|
|
194
|
+
getMessageContent(id: string, includeHtml?: boolean): MessageContent | null;
|
|
188
195
|
/**
|
|
189
196
|
* Get the raw MIME source of a message.
|
|
190
197
|
* Used as fallback for attachment extraction when AppleScript
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"appleMailManager.d.ts","sourceRoot":"","sources":["../../src/services/appleMailManager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAQH,OAAO,KAAK,EACV,OAAO,EACP,cAAc,EACd,OAAO,EACP,OAAO,EACP,UAAU,EACV,iBAAiB,EACjB,SAAS,EAET,oBAAoB,EACpB,UAAU,EACV,qBAAqB,EACrB,QAAQ,EACR,OAAO,EACP,aAAa,EACb,oBAAoB,EACpB,iBAAiB,EACjB,iBAAiB,EACjB,YAAY,EACb,MAAM,YAAY,CAAC;AA2DpB;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,iBAAiB,EAAE,IAAI,EAAE,iBAAiB,GAAG,IAAI,CAK7F;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,GACd;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,iBAAiB,CAAA;CAAE,CAsCrD;AAoFD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,EAAE,CAAC,EAAE,IAAI,GAAG,MAAM,CAWrE;AA2CD;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,sBAAsB;IACrC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,sBAAsB,GAAG,MAAM,CAoB5E;AAED,qBAAa,gBAAgB;IAC3B;;OAEG;IACH,OAAO,CAAC,cAAc,CAAuB;IAE7C;;;;OAIG;IACH,OAAO,CAAC,KAAK,CAGX;IAEF,8CAA8C;IAC9C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAU;IAEvC;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAUzB;;;;OAIG;IACH,OAAO,CAAC,qBAAqB;IAW7B;;;OAGG;IACH,OAAO,CAAC,eAAe;IAKvB;;;;OAIG;IACH,OAAO,CAAC,cAAc;IAwCtB;;;;;;;;;;;;;;;;;OAiBG;IACH,OAAO,CAAC,cAAc;IAyCtB;;;;;;;;OAQG;IACH,cAAc,CACZ,KAAK,CAAC,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,MAAM,EAChB,KAAK,SAAK,EACV,QAAQ,CAAC,EAAE,MAAM,EACjB,MAAM,CAAC,EAAE,MAAM,EACf,IAAI,CAAC,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,MAAM,EAChB,MAAM,CAAC,EAAE,OAAO,EAChB,SAAS,CAAC,EAAE,OAAO,GAClB,OAAO,EAAE;IAeZ;;;;;;;;;;;;;;;;;OAiBG;IACH,6BAA6B,CAC3B,KAAK,CAAC,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,MAAM,EAChB,KAAK,SAAK,EACV,QAAQ,CAAC,EAAE,MAAM,EACjB,MAAM,CAAC,EAAE,MAAM,EACf,IAAI,CAAC,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,MAAM,EAChB,MAAM,CAAC,EAAE,OAAO,EAChB,SAAS,CAAC,EAAE,OAAO,GAClB,YAAY;IAgMf;;;OAGG;IACH,OAAO,CAAC,iBAAiB;IAMzB;;;;;OAKG;IACH,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI;
|
|
1
|
+
{"version":3,"file":"appleMailManager.d.ts","sourceRoot":"","sources":["../../src/services/appleMailManager.ts"],"names":[],"mappings":"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"}
|
|
@@ -17,7 +17,7 @@ import { existsSync, writeFileSync } from "fs";
|
|
|
17
17
|
import { isAbsolute, resolve } from "path";
|
|
18
18
|
import { homedir } from "os";
|
|
19
19
|
import { executeAppleScript } from "../utils/applescript.js";
|
|
20
|
-
import { parseMimeAttachments, extractMimeAttachment } from "../utils/mimeParse.js";
|
|
20
|
+
import { parseMimeAttachments, extractMimeAttachment, extractHtmlBody } from "../utils/mimeParse.js";
|
|
21
21
|
// =============================================================================
|
|
22
22
|
// Search Tuning (issue #24)
|
|
23
23
|
// =============================================================================
|
|
@@ -652,7 +652,21 @@ export class AppleMailManager {
|
|
|
652
652
|
* Note: Mail.app message IDs are unique per mailbox. This method searches
|
|
653
653
|
* all mailboxes in all accounts to find the message.
|
|
654
654
|
*/
|
|
655
|
-
getMessageById(id) {
|
|
655
|
+
getMessageById(id, deepAttachmentCheck = false) {
|
|
656
|
+
// MIME-embedded attachments are invisible to AppleScript's `mail attachments`
|
|
657
|
+
// object, so the only way to detect them is to scan the raw `source of msg`.
|
|
658
|
+
// That reads the entire message (can be MB-sized), so it's the slowest part
|
|
659
|
+
// of this path — now opt-in via `deepAttachmentCheck` rather than run on
|
|
660
|
+
// every attachmentless message (#32). Default off: hasAttachments reflects
|
|
661
|
+
// the fast attachment count only.
|
|
662
|
+
const deepScan = deepAttachmentCheck
|
|
663
|
+
? `if hasAtt is "false" then
|
|
664
|
+
try
|
|
665
|
+
set rawSrc to source of msg
|
|
666
|
+
if rawSrc contains "Content-Disposition: attachment" then set hasAtt to "true"
|
|
667
|
+
end try
|
|
668
|
+
end if`
|
|
669
|
+
: "";
|
|
656
670
|
const script = buildAppLevelScript(`
|
|
657
671
|
try
|
|
658
672
|
repeat with acct in accounts
|
|
@@ -676,18 +690,7 @@ export class AppleMailManager {
|
|
|
676
690
|
set attCount to count of mail attachments of msg
|
|
677
691
|
if attCount > 0 then set hasAtt to "true"
|
|
678
692
|
end try
|
|
679
|
-
|
|
680
|
-
-- attachment object. Fall back to scanning the raw source.
|
|
681
|
-
-- This reads the full message source (can be MB-sized for
|
|
682
|
-
-- messages with large bodies), so it's the slowest part of
|
|
683
|
-
-- get-message for attachmentless messages. Accepted as the
|
|
684
|
-
-- cost of correct hasAttachments in the detail view.
|
|
685
|
-
if hasAtt is "false" then
|
|
686
|
-
try
|
|
687
|
-
set rawSrc to source of msg
|
|
688
|
-
if rawSrc contains "Content-Disposition: attachment" then set hasAtt to "true"
|
|
689
|
-
end try
|
|
690
|
-
end if
|
|
693
|
+
${deepScan}
|
|
691
694
|
return msgSubject & "${FIELD_SEP}" & msgSender & "${FIELD_SEP}" & msgDate & "${FIELD_SEP}" & msgRead & "${FIELD_SEP}" & msgFlagged & "${FIELD_SEP}" & msgJunk & "${FIELD_SEP}" & msgDeleted & "${FIELD_SEP}" & msgMailbox & "${FIELD_SEP}" & msgAccount & "${FIELD_SEP}" & hasAtt
|
|
692
695
|
end if
|
|
693
696
|
end try
|
|
@@ -723,8 +726,20 @@ export class AppleMailManager {
|
|
|
723
726
|
}
|
|
724
727
|
/**
|
|
725
728
|
* Get the content of a message.
|
|
729
|
+
*
|
|
730
|
+
* @param id - Message ID
|
|
731
|
+
* @param includeHtml - When true, also fetch the raw MIME source and extract
|
|
732
|
+
* the `text/html` body part into `htmlContent`. This is opt-in because the
|
|
733
|
+
* source can be MB-sized (it includes base64 attachments) and the plain-text
|
|
734
|
+
* path doesn't need it; fetching it unconditionally was both slow and, worse,
|
|
735
|
+
* returned the entire raw MIME blob mislabeled as HTML (#32).
|
|
726
736
|
*/
|
|
727
|
-
getMessageContent(id) {
|
|
737
|
+
getMessageContent(id, includeHtml = false) {
|
|
738
|
+
// Only `source of msg` is fetched when HTML is requested. `content of msg`
|
|
739
|
+
// is the plain-text body and is always cheap.
|
|
740
|
+
const sourceFetch = includeHtml
|
|
741
|
+
? `set htmlSource to ""\n try\n set htmlSource to source of msg\n end try`
|
|
742
|
+
: `set htmlSource to ""`;
|
|
728
743
|
const script = buildAppLevelScript(`
|
|
729
744
|
try
|
|
730
745
|
repeat with acct in accounts
|
|
@@ -735,11 +750,8 @@ export class AppleMailManager {
|
|
|
735
750
|
set msg to item 1 of matchingMsgs
|
|
736
751
|
set msgSubject to subject of msg
|
|
737
752
|
set msgContent to content of msg
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
set htmlContent to source of msg
|
|
741
|
-
end try
|
|
742
|
-
return msgSubject & "${CONTENT_MARKER}" & msgContent & "${HTML_MARKER}" & htmlContent
|
|
753
|
+
${sourceFetch}
|
|
754
|
+
return msgSubject & "${CONTENT_MARKER}" & msgContent & "${HTML_MARKER}" & htmlSource
|
|
743
755
|
end if
|
|
744
756
|
end try
|
|
745
757
|
end repeat
|
|
@@ -756,15 +768,19 @@ export class AppleMailManager {
|
|
|
756
768
|
}
|
|
757
769
|
const htmlSplit = result.output.split(HTML_MARKER);
|
|
758
770
|
const contentPart = htmlSplit[0];
|
|
759
|
-
const
|
|
771
|
+
const rawSource = htmlSplit.length > 1 ? htmlSplit[1] : "";
|
|
760
772
|
const parts = contentPart.split(CONTENT_MARKER);
|
|
761
773
|
if (parts.length < 2)
|
|
762
774
|
return null;
|
|
775
|
+
// Extract the actual text/html body from the raw MIME source rather than
|
|
776
|
+
// returning the whole source. Falls back to undefined when the message has
|
|
777
|
+
// no HTML part (e.g. a plain-text-only email).
|
|
778
|
+
const htmlContent = includeHtml && rawSource ? extractHtmlBody(rawSource) || undefined : undefined;
|
|
763
779
|
return {
|
|
764
780
|
id: id.toString(),
|
|
765
781
|
subject: parts[0],
|
|
766
782
|
plainText: parts[1],
|
|
767
|
-
htmlContent
|
|
783
|
+
htmlContent,
|
|
768
784
|
};
|
|
769
785
|
}
|
|
770
786
|
/**
|
|
@@ -28,6 +28,21 @@ export interface MimeAttachmentData extends MimeAttachmentInfo {
|
|
|
28
28
|
* @returns Array of attachment metadata (name, mimeType, size)
|
|
29
29
|
*/
|
|
30
30
|
export declare function parseMimeAttachments(source: string): MimeAttachmentInfo[];
|
|
31
|
+
/**
|
|
32
|
+
* Extract the decoded `text/html` body from raw MIME source.
|
|
33
|
+
*
|
|
34
|
+
* Used by get-message's `preferHtml` path so it returns the actual HTML body
|
|
35
|
+
* rather than the entire raw MIME blob (headers + base64 attachments), which is
|
|
36
|
+
* both wrong and enormous (#32). Handles both multipart messages (walks leaf
|
|
37
|
+
* parts, descending into nested multipart/* containers) and a non-multipart
|
|
38
|
+
* message whose top-level Content-Type is text/html. Bodies are decoded per
|
|
39
|
+
* Content-Transfer-Encoding (base64 / quoted-printable / raw) and returned as
|
|
40
|
+
* UTF-8 text.
|
|
41
|
+
*
|
|
42
|
+
* @param source - Raw MIME source of the email
|
|
43
|
+
* @returns The decoded HTML body, or null if the message has no text/html part
|
|
44
|
+
*/
|
|
45
|
+
export declare function extractHtmlBody(source: string): string | null;
|
|
31
46
|
/**
|
|
32
47
|
* Extract and decode a specific attachment from MIME source by filename.
|
|
33
48
|
* Supports base64, quoted-printable, and 7bit/8bit/binary transfer encodings.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mimeParse.d.ts","sourceRoot":"","sources":["../../src/utils/mimeParse.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,WAAW,kBAAkB;IACjC,uEAAuE;IACvE,IAAI,EAAE,MAAM,CAAC;IACb,yCAAyC;IACzC,QAAQ,EAAE,MAAM,CAAC;IACjB,oFAAoF;IACpF,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,kBAAmB,SAAQ,kBAAkB;IAC5D,6BAA6B;IAC7B,IAAI,EAAE,MAAM,CAAC;CACd;AAyLD;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,kBAAkB,EAAE,CAyBzE;AAED;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,MAAM,EACd,cAAc,EAAE,MAAM,GACrB,kBAAkB,GAAG,IAAI,CAwB3B"}
|
|
1
|
+
{"version":3,"file":"mimeParse.d.ts","sourceRoot":"","sources":["../../src/utils/mimeParse.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,WAAW,kBAAkB;IACjC,uEAAuE;IACvE,IAAI,EAAE,MAAM,CAAC;IACb,yCAAyC;IACzC,QAAQ,EAAE,MAAM,CAAC;IACjB,oFAAoF;IACpF,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,kBAAmB,SAAQ,kBAAkB;IAC5D,6BAA6B;IAC7B,IAAI,EAAE,MAAM,CAAC;CACd;AAyLD;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,kBAAkB,EAAE,CAyBzE;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAuB7D;AAED;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,MAAM,EACd,cAAc,EAAE,MAAM,GACrB,kBAAkB,GAAG,IAAI,CAwB3B"}
|
package/build/utils/mimeParse.js
CHANGED
|
@@ -205,6 +205,44 @@ export function parseMimeAttachments(source) {
|
|
|
205
205
|
}
|
|
206
206
|
return attachments;
|
|
207
207
|
}
|
|
208
|
+
/**
|
|
209
|
+
* Extract the decoded `text/html` body from raw MIME source.
|
|
210
|
+
*
|
|
211
|
+
* Used by get-message's `preferHtml` path so it returns the actual HTML body
|
|
212
|
+
* rather than the entire raw MIME blob (headers + base64 attachments), which is
|
|
213
|
+
* both wrong and enormous (#32). Handles both multipart messages (walks leaf
|
|
214
|
+
* parts, descending into nested multipart/* containers) and a non-multipart
|
|
215
|
+
* message whose top-level Content-Type is text/html. Bodies are decoded per
|
|
216
|
+
* Content-Transfer-Encoding (base64 / quoted-printable / raw) and returned as
|
|
217
|
+
* UTF-8 text.
|
|
218
|
+
*
|
|
219
|
+
* @param source - Raw MIME source of the email
|
|
220
|
+
* @returns The decoded HTML body, or null if the message has no text/html part
|
|
221
|
+
*/
|
|
222
|
+
export function extractHtmlBody(source) {
|
|
223
|
+
if (!source || !source.trim())
|
|
224
|
+
return null;
|
|
225
|
+
const boundary = extractBoundary(source);
|
|
226
|
+
if (boundary) {
|
|
227
|
+
for (const part of walkLeafParts(source, boundary)) {
|
|
228
|
+
if (extractMimeType(part.headers) === "text/html") {
|
|
229
|
+
const encoding = getHeader(part.headers, "Content-Transfer-Encoding");
|
|
230
|
+
return decodeBody(part.body, encoding).toString("utf8");
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
return null;
|
|
234
|
+
}
|
|
235
|
+
// Non-multipart: split top headers from body and check the top Content-Type.
|
|
236
|
+
const blankLineIdx = source.search(/\r?\n\r?\n/);
|
|
237
|
+
if (blankLineIdx === -1)
|
|
238
|
+
return null;
|
|
239
|
+
const headers = source.substring(0, blankLineIdx);
|
|
240
|
+
if (extractMimeType(headers) !== "text/html")
|
|
241
|
+
return null;
|
|
242
|
+
const body = source.substring(blankLineIdx).replace(/^\r?\n\r?\n/, "");
|
|
243
|
+
const encoding = getHeader(headers, "Content-Transfer-Encoding");
|
|
244
|
+
return decodeBody(body, encoding).toString("utf8");
|
|
245
|
+
}
|
|
208
246
|
/**
|
|
209
247
|
* Extract and decode a specific attachment from MIME source by filename.
|
|
210
248
|
* Supports base64, quoted-printable, and 7bit/8bit/binary transfer encodings.
|