apple-mail-mcp 2.10.25 → 2.10.26
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 -0
- package/build/index.js +48 -7
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -824,6 +824,11 @@ List attachments on a message.
|
|
|
824
824
|
|
|
825
825
|
Save a message attachment to disk.
|
|
826
826
|
|
|
827
|
+
The destination must not already exist: `save-attachment` fails closed instead
|
|
828
|
+
of overwriting an existing file. AppleScript and MIME fallback paths stage the
|
|
829
|
+
bytes privately, commit with an exclusive create, and leave the saved file
|
|
830
|
+
owner-readable/writable (`0600`).
|
|
831
|
+
|
|
827
832
|
| Parameter | Type | Required | Description |
|
|
828
833
|
|-----------|------|----------|-------------|
|
|
829
834
|
| `id` | string | Yes | Message ID |
|
package/build/index.js
CHANGED
|
@@ -77516,6 +77516,8 @@ var StdioServerTransport = class {
|
|
|
77516
77516
|
// src/services/appleMailManager.ts
|
|
77517
77517
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
77518
77518
|
import {
|
|
77519
|
+
constants as fsConstants,
|
|
77520
|
+
chmodSync,
|
|
77519
77521
|
existsSync as existsSync3,
|
|
77520
77522
|
writeFileSync as writeFileSync3,
|
|
77521
77523
|
readFileSync as readFileSync2,
|
|
@@ -78375,8 +78377,11 @@ function resolveAttachmentSaveTarget(savePath, attachmentName) {
|
|
|
78375
78377
|
if (!isPathWithinAllowedRoots(savedPath)) {
|
|
78376
78378
|
throw new Error(`Output path "${savedPath}" is outside allowed directories`);
|
|
78377
78379
|
}
|
|
78378
|
-
if (existsSync3(savedPath)
|
|
78379
|
-
|
|
78380
|
+
if (existsSync3(savedPath)) {
|
|
78381
|
+
if (lstatSync(savedPath).isSymbolicLink()) {
|
|
78382
|
+
throw new Error(`Refusing to overwrite symbolic link "${savedPath}"`);
|
|
78383
|
+
}
|
|
78384
|
+
throw new Error(`Refusing to overwrite existing file "${savedPath}"`);
|
|
78380
78385
|
}
|
|
78381
78386
|
return { saveDirectory, savedPath };
|
|
78382
78387
|
}
|
|
@@ -81162,7 +81167,21 @@ ${this.errorEmit(" ")}
|
|
|
81162
81167
|
return false;
|
|
81163
81168
|
}
|
|
81164
81169
|
const safeName = escapeForAppleScript(attachmentName);
|
|
81165
|
-
|
|
81170
|
+
let temporaryDirectory;
|
|
81171
|
+
try {
|
|
81172
|
+
temporaryDirectory = mkdtempSync2(join4(target.saveDirectory, ".apple-mail-mcp-"));
|
|
81173
|
+
} catch (error2) {
|
|
81174
|
+
console.error(`Failed to create attachment staging directory: ${error2}`);
|
|
81175
|
+
return false;
|
|
81176
|
+
}
|
|
81177
|
+
const temporaryPath = join4(temporaryDirectory, "attachment");
|
|
81178
|
+
const safeTemporaryPath = escapeForAppleScript(temporaryPath);
|
|
81179
|
+
const cleanupTemporaryDirectory = () => {
|
|
81180
|
+
try {
|
|
81181
|
+
rmSync2(temporaryDirectory, { recursive: true, force: true });
|
|
81182
|
+
} catch {
|
|
81183
|
+
}
|
|
81184
|
+
};
|
|
81166
81185
|
const numericId = Number(id);
|
|
81167
81186
|
const script = buildAppLevelScript(`
|
|
81168
81187
|
try
|
|
@@ -81174,7 +81193,7 @@ ${this.errorEmit(" ")}
|
|
|
81174
81193
|
set msg to item 1 of matchingMsgs
|
|
81175
81194
|
repeat with att in mail attachments of msg
|
|
81176
81195
|
if name of att is "${safeName}" then
|
|
81177
|
-
set savePath to POSIX file "${
|
|
81196
|
+
set savePath to POSIX file "${safeTemporaryPath}"
|
|
81178
81197
|
save att in savePath
|
|
81179
81198
|
return "ok"
|
|
81180
81199
|
end if
|
|
@@ -81191,8 +81210,18 @@ ${this.errorEmit(" ")}
|
|
|
81191
81210
|
`);
|
|
81192
81211
|
const result = executeAppleScript(script, { timeoutMs: 6e4 });
|
|
81193
81212
|
if (result.success && result.output === "ok") {
|
|
81194
|
-
|
|
81213
|
+
try {
|
|
81214
|
+
copyFileSync(temporaryPath, target.savedPath, fsConstants.COPYFILE_EXCL);
|
|
81215
|
+
chmodSync(target.savedPath, 384);
|
|
81216
|
+
cleanupTemporaryDirectory();
|
|
81217
|
+
return true;
|
|
81218
|
+
} catch (err) {
|
|
81219
|
+
cleanupTemporaryDirectory();
|
|
81220
|
+
console.error(`Failed to commit attachment to disk: ${err}`);
|
|
81221
|
+
return false;
|
|
81222
|
+
}
|
|
81195
81223
|
}
|
|
81224
|
+
cleanupTemporaryDirectory();
|
|
81196
81225
|
const rawSource = this.getRawSource(id);
|
|
81197
81226
|
if (!rawSource) {
|
|
81198
81227
|
console.error(`Failed to save attachment: could not retrieve message source`);
|
|
@@ -81203,12 +81232,24 @@ ${this.errorEmit(" ")}
|
|
|
81203
81232
|
console.error(`Failed to save attachment: "${attachmentName}" not found in MIME source`);
|
|
81204
81233
|
return false;
|
|
81205
81234
|
}
|
|
81235
|
+
let mimeTemporaryDirectory;
|
|
81206
81236
|
try {
|
|
81207
|
-
|
|
81237
|
+
mimeTemporaryDirectory = mkdtempSync2(join4(target.saveDirectory, ".apple-mail-mcp-"));
|
|
81238
|
+
const mimeTemporaryPath = join4(mimeTemporaryDirectory, "attachment");
|
|
81239
|
+
writeFileSync3(mimeTemporaryPath, attachment.data, { flag: "wx", mode: 384 });
|
|
81240
|
+
copyFileSync(mimeTemporaryPath, target.savedPath, fsConstants.COPYFILE_EXCL);
|
|
81241
|
+
chmodSync(target.savedPath, 384);
|
|
81208
81242
|
return true;
|
|
81209
81243
|
} catch (err) {
|
|
81210
81244
|
console.error(`Failed to write attachment to disk: ${err}`);
|
|
81211
81245
|
return false;
|
|
81246
|
+
} finally {
|
|
81247
|
+
if (mimeTemporaryDirectory) {
|
|
81248
|
+
try {
|
|
81249
|
+
rmSync2(mimeTemporaryDirectory, { recursive: true, force: true });
|
|
81250
|
+
} catch {
|
|
81251
|
+
}
|
|
81252
|
+
}
|
|
81212
81253
|
}
|
|
81213
81254
|
}
|
|
81214
81255
|
/**
|
|
@@ -85676,7 +85717,7 @@ registerTool(
|
|
|
85676
85717
|
if (!r.success || !r.base64) {
|
|
85677
85718
|
return errorResponse(r.error || `Failed to fetch attachment "${attachmentName}"`);
|
|
85678
85719
|
}
|
|
85679
|
-
writeFileSync4(target.savedPath, Buffer.from(r.base64, "base64"));
|
|
85720
|
+
writeFileSync4(target.savedPath, Buffer.from(r.base64, "base64"), { flag: "wx", mode: 384 });
|
|
85680
85721
|
return successResponse(`Attachment "${attachmentName}" saved to ${savePath}`, {
|
|
85681
85722
|
ok: true,
|
|
85682
85723
|
attachmentName,
|
package/package.json
CHANGED