apple-mail-mcp 1.6.6 → 1.6.8

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 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.boolean().optional().describe("Return HTML source instead of plain text"),
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
- const content = mailManager.getMessageContent(id);
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
- getMessageContent(id: string): MessageContent | null;
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":"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"}
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
- -- MIME-embedded attachments are invisible to AppleScript's
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
- set htmlContent to ""
739
- try
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 htmlContent = htmlSplit.length > 1 ? htmlSplit[1] : undefined;
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: htmlContent || undefined,
783
+ htmlContent,
768
784
  };
769
785
  }
770
786
  /**
@@ -1913,24 +1929,55 @@ export class AppleMailManager {
1913
1929
  const safeOld = escapeForAppleScript(resolvedOld);
1914
1930
  const safeNew = escapeForAppleScript(resolvedNew);
1915
1931
  const safeAccount = escapeForAppleScript(targetAccount);
1932
+ // Mail.app has no reliable in-place mailbox rename across account types, so
1933
+ // rename is emulated as create-new + move-all + delete-old. The risk (issue
1934
+ // #33) is that the old code iterated `messages of srcMailbox` *while moving*
1935
+ // (mutating the collection it was iterating, which can skip messages) and
1936
+ // then deleted the source unconditionally — so a move that errored or timed
1937
+ // out part-way lost the un-moved remainder. This version:
1938
+ // - snapshots the message references up front (move can't disturb iteration),
1939
+ // - moves each within its own `try` so one bad message doesn't abort the rest,
1940
+ // - and deletes the source ONLY if it is empty afterwards (every message
1941
+ // moved). On a partial move the source is left intact and we report how
1942
+ // many remain, so no mail is lost.
1916
1943
  const moveScript = buildAppLevelScript(`
1917
1944
  try
1918
1945
  set srcMailbox to mailbox "${safeOld}" of account "${safeAccount}"
1919
1946
  set destMailbox to mailbox "${safeNew}" of account "${safeAccount}"
1920
- repeat with msg in messages of srcMailbox
1921
- move msg to destMailbox
1947
+ set srcCount to count of messages of srcMailbox
1948
+ set msgs to (every message of srcMailbox)
1949
+ repeat with m in msgs
1950
+ try
1951
+ move m to destMailbox
1952
+ end try
1922
1953
  end repeat
1923
- delete mailbox "${safeOld}" of account "${safeAccount}"
1924
- return "ok"
1954
+ set srcAfter to count of messages of srcMailbox
1955
+ if srcAfter is 0 then
1956
+ delete mailbox "${safeOld}" of account "${safeAccount}"
1957
+ return "ok${FIELD_SEP}" & srcCount
1958
+ else
1959
+ return "partial${FIELD_SEP}" & (srcCount - srcAfter) & "${FIELD_SEP}" & srcCount & "${FIELD_SEP}" & srcAfter
1960
+ end if
1925
1961
  on error errMsg
1926
1962
  return "error:" & errMsg
1927
1963
  end try
1928
1964
  `);
1929
- const result = executeAppleScript(moveScript, { timeoutMs: 60000 });
1965
+ // Moving a large source mailbox is slow; give it room. If it's still killed,
1966
+ // the source is never deleted (delete only runs after a verified-empty
1967
+ // check), so a truncated move is recoverable rather than lossy.
1968
+ const result = executeAppleScript(moveScript, { timeoutMs: 120000 });
1930
1969
  if (!result.success || result.output.startsWith("error:")) {
1931
1970
  console.error(`Failed to rename mailbox: ${result.error || result.output}`);
1932
1971
  return false;
1933
1972
  }
1973
+ if (result.output.startsWith("partial")) {
1974
+ const parts = result.output.split(FIELD_SEP);
1975
+ const remaining = parts[3] ?? "?";
1976
+ const total = parts[2] ?? "?";
1977
+ console.error(`Failed to rename mailbox: only ${parts[1] ?? "?"} of ${total} messages moved, ${remaining} remain in "${resolvedOld}"; source was NOT deleted (both mailboxes left intact). Retry to move the rest.`);
1978
+ this.invalidateCache(); // the new mailbox now exists and holds the moved messages
1979
+ return false;
1980
+ }
1934
1981
  this.invalidateCache();
1935
1982
  return true;
1936
1983
  }
@@ -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"}
@@ -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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "apple-mail-mcp",
3
- "version": "1.6.6",
3
+ "version": "1.6.8",
4
4
  "description": "MCP server for Apple Mail - read, search, send, and manage emails via Claude",
5
5
  "type": "module",
6
6
  "main": "build/index.js",