proton-mail-bridge-client 2.0.4 → 2.0.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/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +39 -10
- package/dist/index.js.map +1 -1
- package/dist/services/delivery-queue-service.d.ts.map +1 -1
- package/dist/services/delivery-queue-service.js +17 -0
- package/dist/services/delivery-queue-service.js.map +1 -1
- package/dist/services/draft-store-service.d.ts.map +1 -1
- package/dist/services/draft-store-service.js +12 -0
- package/dist/services/draft-store-service.js.map +1 -1
- package/dist/services/local-index-service.d.ts +2 -0
- package/dist/services/local-index-service.d.ts.map +1 -1
- package/dist/services/local-index-service.js +313 -9
- package/dist/services/local-index-service.js.map +1 -1
- package/dist/services/simple-imap-service.d.ts +3 -0
- package/dist/services/simple-imap-service.d.ts.map +1 -1
- package/dist/services/simple-imap-service.js +54 -7
- package/dist/services/simple-imap-service.js.map +1 -1
- package/dist/services/smtp-service.d.ts.map +1 -1
- package/dist/services/smtp-service.js +9 -0
- package/dist/services/smtp-service.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -26,6 +26,8 @@ export declare function getReplyRecipients(detail: EmailDetail, ownerEmail: stri
|
|
|
26
26
|
to: string[];
|
|
27
27
|
cc: string[];
|
|
28
28
|
};
|
|
29
|
+
export declare function getBulkMaxBatchSize(args: Record<string, unknown>): number;
|
|
30
|
+
export declare function ensureBulkBatchSize(uidsLength: number, max: number): void;
|
|
29
31
|
export declare function buildConfigFromEnv(): ProtonMailConfig;
|
|
30
32
|
export declare function createServer(config: ProtonMailConfig, options?: {
|
|
31
33
|
startBackgroundSync?: boolean;
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AASA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAYnE,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,EAAE,qBAAqB,EAAE,MAAM,uCAAuC,CAAC;AAC9E,OAAO,EAAE,oBAAoB,EAAE,MAAM,sCAAsC,CAAC;AAC5E,OAAO,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AACtE,OAAO,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AACtE,OAAO,EAA2H,iBAAiB,EAA+B,MAAM,mCAAmC,CAAC;AAC5N,OAAO,EAAkB,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACzE,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAE7D,OAAO,KAAK,EAUV,WAAW,EAEX,gBAAgB,EAEjB,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AASA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAYnE,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,EAAE,qBAAqB,EAAE,MAAM,uCAAuC,CAAC;AAC9E,OAAO,EAAE,oBAAoB,EAAE,MAAM,sCAAsC,CAAC;AAC5E,OAAO,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AACtE,OAAO,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AACtE,OAAO,EAA2H,iBAAiB,EAA+B,MAAM,mCAAmC,CAAC;AAC5N,OAAO,EAAkB,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACzE,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAE7D,OAAO,KAAK,EAUV,WAAW,EAEX,gBAAgB,EAEjB,MAAM,kBAAkB,CAAC;AA6qD1B,eAAO,MAAM,eAAe,aAyB1B,CAAC;AAgGH,wBAAsB,SAAS,CAAC,CAAC,EAC/B,YAAY,EAAE,YAAY,EAC1B,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,SAAS,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAC1B,OAAO,CAAC,CAAC,CAAC,CAwBZ;AAmED,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAK3G;AAKD,wBAAgB,0BAA0B,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAI1G;AASD,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAa9E;AAED,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,WAAW,GAAG;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,CAS7F;AA4KD,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,WAAW,EACnB,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,OAAO,GAChB;IAAE,EAAE,EAAE,MAAM,EAAE,CAAC;IAAC,EAAE,EAAE,MAAM,EAAE,CAAA;CAAE,CAyBhC;AAoiBD,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAEzE;AAED,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAOzE;AAyQD,wBAAgB,kBAAkB,IAAI,gBAAgB,CAkGrD;AAED,wBAAgB,YAAY,CAC1B,MAAM,EAAE,gBAAgB,EACxB,OAAO,GAAE;IACP,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC1B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAgjGP;AAED,wBAAsB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAmE1C"}
|
package/dist/index.js
CHANGED
|
@@ -1131,6 +1131,7 @@ const TOOLS = [
|
|
|
1131
1131
|
description: "Preview the impact without mutating the mailbox.",
|
|
1132
1132
|
default: false,
|
|
1133
1133
|
},
|
|
1134
|
+
maxBatchSize: { type: "number", description: "Maximum number of messages to process. Defaults to 500. Use to prevent runaway operations." },
|
|
1134
1135
|
},
|
|
1135
1136
|
required: ["emailIds", "action"],
|
|
1136
1137
|
},
|
|
@@ -1171,6 +1172,7 @@ const TOOLS = [
|
|
|
1171
1172
|
description: "Refresh the local mailbox index from IMAP before resolving the thread.",
|
|
1172
1173
|
default: false,
|
|
1173
1174
|
},
|
|
1175
|
+
maxBatchSize: { type: "number", description: "Maximum number of messages to process. Defaults to 500. Use to prevent runaway operations." },
|
|
1174
1176
|
},
|
|
1175
1177
|
required: ["threadId", "action"],
|
|
1176
1178
|
},
|
|
@@ -2498,10 +2500,10 @@ async function previewEmailAction(imapService, emailId, action, targetFolder) {
|
|
|
2498
2500
|
async function verifySentCopy(imapService, messageId) {
|
|
2499
2501
|
return imapService.sentCopyVerify(messageId, "Sent", 8_000);
|
|
2500
2502
|
}
|
|
2501
|
-
function getBulkMaxBatchSize(args) {
|
|
2503
|
+
export function getBulkMaxBatchSize(args) {
|
|
2502
2504
|
return typeof args.maxBatchSize === "number" ? Math.min(args.maxBatchSize, 2000) : 500;
|
|
2503
2505
|
}
|
|
2504
|
-
function ensureBulkBatchSize(uidsLength, max) {
|
|
2506
|
+
export function ensureBulkBatchSize(uidsLength, max) {
|
|
2505
2507
|
if (uidsLength > max) {
|
|
2506
2508
|
throw new McpError(ErrorCode.InvalidParams, "Batch size " + uidsLength + " exceeds limit " + max + ". Use match criteria to narrow the scope, or increase maxBatchSize.");
|
|
2507
2509
|
}
|
|
@@ -3850,6 +3852,15 @@ export function createServer(config, options = {}) {
|
|
|
3850
3852
|
// after an ambiguous response) sailed past the status check above
|
|
3851
3853
|
// and enqueued a second, independent delivery-queue record. Both
|
|
3852
3854
|
// fire independently later, delivering the same email twice.
|
|
3855
|
+
//
|
|
3856
|
+
// Found live: this list()-then-check was itself a non-atomic
|
|
3857
|
+
// TOCTOU race — two concurrent schedule_draft calls could both
|
|
3858
|
+
// observe no pending record here and both enqueue. The real
|
|
3859
|
+
// enforcement now lives inside deliveryQueueService.enqueue()
|
|
3860
|
+
// itself, under its lock, which is what actually prevents the
|
|
3861
|
+
// duplicate. This external check is kept only as an optional
|
|
3862
|
+
// early-exit optimization to avoid a wasted round-trip to the lock
|
|
3863
|
+
// in the common non-racing case.
|
|
3853
3864
|
const alreadyPendingScheduled = (await deliveryQueueService.list()).find((record) => record.sourceDraftId === draft.id && record.status === "pending");
|
|
3854
3865
|
if (alreadyPendingScheduled) {
|
|
3855
3866
|
throw new McpError(ErrorCode.InvalidParams, `This draft already has a pending scheduled send (id ${alreadyPendingScheduled.id}, sendAt ${alreadyPendingScheduled.sendAt}). Scheduling it again would deliver it twice. Cancel the existing one with cancel_send first if you want a different sendAt.`);
|
|
@@ -4121,15 +4132,23 @@ export function createServer(config, options = {}) {
|
|
|
4121
4132
|
// mailbox each time.
|
|
4122
4133
|
const currentUidValidity = emailIds ? await imapService.getMailboxUidValidity(folder) : undefined;
|
|
4123
4134
|
const notFoundEmailIds = getBulkNotFoundEmailIds(emailIds, folder, currentUidValidity);
|
|
4124
|
-
|
|
4125
|
-
|
|
4126
|
-
|
|
4127
|
-
|
|
4128
|
-
|
|
4129
|
-
|
|
4130
|
-
|
|
4131
|
-
ensureBulkBatchSize(preview.total, max);
|
|
4135
|
+
// Resolve the match/emailIds set exactly once and reuse it for both
|
|
4136
|
+
// the preview and the real run — see resolveUidsForBulkOp's
|
|
4137
|
+
// comment for why re-resolving `match` a second time (the old
|
|
4138
|
+
// dry-run-then-real-run pattern) could silently exceed maxBatchSize.
|
|
4139
|
+
// Also excludes any id whose embedded UIDVALIDITY is stale.
|
|
4140
|
+
const uids = await imapService.resolveUidsForBulkOp(folder, emailIds, match, currentUidValidity);
|
|
4141
|
+
ensureBulkBatchSize(uids.length, max);
|
|
4132
4142
|
if (normalizeBoolean(args.dryRun, false)) {
|
|
4143
|
+
const preview = await imapService.bulkMove({
|
|
4144
|
+
emailIds,
|
|
4145
|
+
match,
|
|
4146
|
+
folder,
|
|
4147
|
+
targetFolder,
|
|
4148
|
+
resolvedUids: uids,
|
|
4149
|
+
uidValidity: currentUidValidity,
|
|
4150
|
+
dryRun: true,
|
|
4151
|
+
});
|
|
4133
4152
|
return createTextResult(withBulkNotFound(preview, notFoundEmailIds));
|
|
4134
4153
|
}
|
|
4135
4154
|
const result = await withAudit(auditService, name, args, () => imapService.bulkMove({
|
|
@@ -4137,6 +4156,8 @@ export function createServer(config, options = {}) {
|
|
|
4137
4156
|
match,
|
|
4138
4157
|
folder,
|
|
4139
4158
|
targetFolder,
|
|
4159
|
+
resolvedUids: uids,
|
|
4160
|
+
uidValidity: currentUidValidity,
|
|
4140
4161
|
dryRun: false,
|
|
4141
4162
|
}));
|
|
4142
4163
|
return createTextResult(withBulkNotFound(result, notFoundEmailIds));
|
|
@@ -4534,6 +4555,10 @@ export function createServer(config, options = {}) {
|
|
|
4534
4555
|
if (emailIds.length === 0) {
|
|
4535
4556
|
throw new McpError(ErrorCode.InvalidParams, "emailIds must contain at least one email id.");
|
|
4536
4557
|
}
|
|
4558
|
+
// Same safety rail as the bulk_* tools (bulk_delete etc.) — without
|
|
4559
|
+
// it, an arbitrarily large emailIds array would be processed in
|
|
4560
|
+
// full with no size limit at all.
|
|
4561
|
+
ensureBulkBatchSize(emailIds.length, getBulkMaxBatchSize(args));
|
|
4537
4562
|
const action = requireEmailAction(args);
|
|
4538
4563
|
ensureEmailActionAllowed(config.runtime, action);
|
|
4539
4564
|
if (action === "delete") {
|
|
@@ -5116,6 +5141,10 @@ export function createServer(config, options = {}) {
|
|
|
5116
5141
|
const emailIds = [...new Set(thread.messages
|
|
5117
5142
|
.filter((message) => !unreadOnly || !message.isRead)
|
|
5118
5143
|
.map((message) => message.primaryEmailId))];
|
|
5144
|
+
// Same safety rail as the bulk_* tools (bulk_delete etc.) — without
|
|
5145
|
+
// it, a thread with an arbitrarily large message count would be
|
|
5146
|
+
// processed in full with no size limit at all.
|
|
5147
|
+
ensureBulkBatchSize(emailIds.length, getBulkMaxBatchSize(args));
|
|
5119
5148
|
if (action === "delete") {
|
|
5120
5149
|
ensureDestructiveConfirmed(config.runtime, normalizeBoolean(args.confirmed, false), `Permanently delete ${emailIds.length} email(s) in thread (cannot be recovered)`);
|
|
5121
5150
|
}
|