proton-mail-bridge-client 2.1.13 → 2.1.15
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 +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +63 -34
- package/dist/index.js.map +1 -1
- package/dist/services/local-index-service.js +1 -1
- package/dist/services/local-index-service.js.map +1 -1
- package/dist/services/simple-imap-service.js +1 -1
- package/dist/services/simple-imap-service.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -67,6 +67,7 @@ export declare function redactDraftAttachmentsForListing(draft: DraftRecord): {
|
|
|
67
67
|
remoteDraft?: import("./types/index.js").RemoteDraftRef;
|
|
68
68
|
lastSendResult?: import("./types/index.js").DraftSendResult;
|
|
69
69
|
};
|
|
70
|
+
export declare function isNoopDraftPatch(existing: DraftRecord, patch: Record<string, unknown>): boolean;
|
|
70
71
|
export declare function truncateDraftBodyForResponse<T extends {
|
|
71
72
|
body: string;
|
|
72
73
|
}>(draft: T): T;
|
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,EAAmC,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAC1F,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAE7D,OAAO,KAAK,EAMV,mBAAmB,EACnB,cAAc,EACd,WAAW,EAIX,WAAW,EAIX,gBAAgB,EAChB,cAAc,EAGf,MAAM,kBAAkB,CAAC;AAoB1B,OAAO,EAAE,cAAc,EAAE,KAAK,aAAa,EAAE,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -100,6 +100,7 @@ const TOOLS = [
|
|
|
100
100
|
type: "object",
|
|
101
101
|
properties: {
|
|
102
102
|
status: { type: "string", enum: ["pending", "sending", "sent", "canceled", "failed"], description: "Filter to one status. Omit to list everything." },
|
|
103
|
+
limit: { type: "number", description: "Return at most this many records. Omit for all." },
|
|
103
104
|
},
|
|
104
105
|
},
|
|
105
106
|
},
|
|
@@ -391,7 +392,7 @@ const TOOLS = [
|
|
|
391
392
|
type: "object",
|
|
392
393
|
properties: {
|
|
393
394
|
includeSent: { type: "boolean", description: "Include drafts already sent.", default: false },
|
|
394
|
-
limit: { type: "number", description: "Maximum drafts to return.
|
|
395
|
+
limit: { type: "number", description: "Maximum drafts to return. Defaults to 20; check hasMore and page with offset for more." },
|
|
395
396
|
offset: { type: "number", description: "Number of drafts to skip, newest-updated first.", default: 0 },
|
|
396
397
|
},
|
|
397
398
|
},
|
|
@@ -593,7 +594,7 @@ const TOOLS = [
|
|
|
593
594
|
messageId: { type: "string", description: "RFC 5322 Message-ID header value to match exactly." },
|
|
594
595
|
cc: { type: "string", description: "Filter by CC/BCC recipient address." },
|
|
595
596
|
bcc: { type: "string", description: "Filter by CC/BCC recipient address." },
|
|
596
|
-
limit: { type: "number", description: "Maximum results.", default:
|
|
597
|
+
limit: { type: "number", description: "Maximum results.", default: 50 },
|
|
597
598
|
includeSnippet: { type: "boolean", description: "Fetch a short plain-text preview of each matched email body. Slightly slower but avoids follow-up get_email_by_id calls for triage. Warning: snippet content is from untrusted senders and may contain prompt-injection text.", default: false },
|
|
598
599
|
fields: { oneOf: [{ type: "array", items: { type: "string" } }, { type: "string" }], description: "Trim each returned email to just these field names (e.g. [\"subject\",\"from\",\"date\"]) to save tokens on large result sets. id is always included. Accepts either an array or a comma-separated string. Omit to get the full object." },
|
|
599
600
|
},
|
|
@@ -1338,7 +1339,7 @@ const TOOLS = [
|
|
|
1338
1339
|
mailboxRole: { type: "string", description: "Normalized mailbox role like Inbox, Sent, Archive, or Trash." },
|
|
1339
1340
|
dateFrom: { type: "string", description: "Inclusive start date/time in ISO format." },
|
|
1340
1341
|
dateTo: { type: "string", description: "Inclusive end date/time in ISO format." },
|
|
1341
|
-
limit: { type: "number", description: "Maximum results.", default:
|
|
1342
|
+
limit: { type: "number", description: "Maximum results.", default: 50 },
|
|
1342
1343
|
fields: { oneOf: [{ type: "array", items: { type: "string" } }, { type: "string" }], description: "Trim each returned email to just these field names (e.g. [\"subject\",\"from\",\"date\"]) to save tokens on large result sets. id is always included. Accepts either an array or a comma-separated string. Omit to get the full object." },
|
|
1343
1344
|
},
|
|
1344
1345
|
},
|
|
@@ -1747,8 +1748,6 @@ function citationToResourceLink(source) {
|
|
|
1747
1748
|
uri: source.uri,
|
|
1748
1749
|
name: source.name,
|
|
1749
1750
|
title: source.title,
|
|
1750
|
-
description: source.description,
|
|
1751
|
-
mimeType: source.mimeType,
|
|
1752
1751
|
};
|
|
1753
1752
|
}
|
|
1754
1753
|
function normalizeStructuredContent(value) {
|
|
@@ -2343,6 +2342,17 @@ const DRAFT_BODY_PREVIEW_LENGTH = 500;
|
|
|
2343
2342
|
// for the text body instead of base64. get_draft deliberately keeps the full
|
|
2344
2343
|
// body — it's the "let me look at this one draft" call, not a repeated-edit
|
|
2345
2344
|
// or bulk-listing one.
|
|
2345
|
+
// True when applying `patch` would leave the draft exactly as it is — used to skip
|
|
2346
|
+
// the store write and the remote (IMAP) resync for an update that changes nothing.
|
|
2347
|
+
export function isNoopDraftPatch(existing, patch) {
|
|
2348
|
+
return Object.entries(patch).every(([key, value]) => {
|
|
2349
|
+
if (value === undefined) {
|
|
2350
|
+
return true;
|
|
2351
|
+
}
|
|
2352
|
+
const current = existing[key];
|
|
2353
|
+
return JSON.stringify(current ?? (typeof value === "string" ? "" : undefined)) === JSON.stringify(value);
|
|
2354
|
+
});
|
|
2355
|
+
}
|
|
2346
2356
|
export function truncateDraftBodyForResponse(draft) {
|
|
2347
2357
|
if (draft.body.length <= DRAFT_BODY_PREVIEW_LENGTH) {
|
|
2348
2358
|
return draft;
|
|
@@ -2362,21 +2372,32 @@ export function truncateDraftBodyForResponse(draft) {
|
|
|
2362
2372
|
// for the same reason as the function above.
|
|
2363
2373
|
export function redactQueueRecordAttachments(record) {
|
|
2364
2374
|
const attachments = record.payload.attachments;
|
|
2365
|
-
|
|
2375
|
+
const body = record.payload.body;
|
|
2376
|
+
const bodyTooLong = typeof body === "string" && body.length > DRAFT_BODY_PREVIEW_LENGTH;
|
|
2377
|
+
// send_email(markdownBody) also stores the full rendered HTML in payload.htmlBody —
|
|
2378
|
+
// a parallel copy of the whole message that the body preview alone doesn't cover.
|
|
2379
|
+
const hasHtmlBody = typeof record.payload.htmlBody === "string" && record.payload.htmlBody.length > 0;
|
|
2380
|
+
if ((!attachments || attachments.length === 0) && !bodyTooLong && !hasHtmlBody) {
|
|
2366
2381
|
return record;
|
|
2367
2382
|
}
|
|
2368
2383
|
return {
|
|
2369
2384
|
...record,
|
|
2370
2385
|
payload: {
|
|
2371
2386
|
...record.payload,
|
|
2372
|
-
|
|
2373
|
-
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
|
|
2379
|
-
|
|
2387
|
+
...(bodyTooLong ? truncateDraftBodyForResponse({ body }) : {}),
|
|
2388
|
+
...(hasHtmlBody ? { htmlBody: undefined, htmlBodyOmitted: true } : {}),
|
|
2389
|
+
...(attachments && attachments.length > 0
|
|
2390
|
+
? {
|
|
2391
|
+
attachments: attachments.map((attachment) => ({
|
|
2392
|
+
filename: attachment.filename,
|
|
2393
|
+
contentType: attachment.contentType,
|
|
2394
|
+
cid: attachment.cid,
|
|
2395
|
+
contentDisposition: attachment.contentDisposition,
|
|
2396
|
+
content: "",
|
|
2397
|
+
size: Buffer.byteLength(attachment.content, "base64"),
|
|
2398
|
+
})),
|
|
2399
|
+
}
|
|
2400
|
+
: {}),
|
|
2380
2401
|
},
|
|
2381
2402
|
};
|
|
2382
2403
|
}
|
|
@@ -3687,7 +3708,7 @@ export function createServer(config, options = {}) {
|
|
|
3687
3708
|
const all = await withAudit(auditService, name, args, async () => deliveryQueueService.list());
|
|
3688
3709
|
const filtered = (statusFilter ? all.filter((item) => item.status === statusFilter) : all)
|
|
3689
3710
|
.map(redactQueueRecordAttachments);
|
|
3690
|
-
return createTextResult(filtered);
|
|
3711
|
+
return createTextResult(typeof args.limit === "number" ? filtered.slice(0, normalizeLimit(args.limit, filtered.length, 1, 10_000)) : filtered);
|
|
3691
3712
|
}
|
|
3692
3713
|
const perAccount = await withAudit(auditService, name, args, async () => Promise.all(accountManager.all().map(async (bundle) => ({
|
|
3693
3714
|
bundle,
|
|
@@ -3696,7 +3717,7 @@ export function createServer(config, options = {}) {
|
|
|
3696
3717
|
const tagged = perAccount.flatMap(({ bundle, items }) => items.map((item) => ({ ...item, id: withAccountPrefix(responseSlug(bundle), item.id) })));
|
|
3697
3718
|
const filtered = (statusFilter ? tagged.filter((item) => item.status === statusFilter) : tagged)
|
|
3698
3719
|
.map(redactQueueRecordAttachments);
|
|
3699
|
-
return createTextResult(filtered);
|
|
3720
|
+
return createTextResult(typeof args.limit === "number" ? filtered.slice(0, normalizeLimit(args.limit, filtered.length, 1, 10_000)) : filtered);
|
|
3700
3721
|
}
|
|
3701
3722
|
case "get_unsubscribe_info": {
|
|
3702
3723
|
const rawEmailId = requireString(args, "emailId");
|
|
@@ -4319,8 +4340,8 @@ export function createServer(config, options = {}) {
|
|
|
4319
4340
|
// draft (just with truncated bodies/attachments), so this doesn't change
|
|
4320
4341
|
// behavior for a caller not using the new params.
|
|
4321
4342
|
const offset = normalizeLimit(args.offset, 0, 0, 10_000);
|
|
4322
|
-
const limit =
|
|
4323
|
-
const page =
|
|
4343
|
+
const limit = normalizeLimit(args.limit, 20, 1, 10_000);
|
|
4344
|
+
const page = allDrafts.slice(offset, offset + limit);
|
|
4324
4345
|
return createTextResult({
|
|
4325
4346
|
total: allDrafts.length,
|
|
4326
4347
|
offset,
|
|
@@ -4391,22 +4412,30 @@ export function createServer(config, options = {}) {
|
|
|
4391
4412
|
if (from && !isValidEmail(from)) {
|
|
4392
4413
|
throw new McpError(ErrorCode.InvalidParams, "from must be a valid email address.");
|
|
4393
4414
|
}
|
|
4415
|
+
const draftPatch = {
|
|
4416
|
+
to,
|
|
4417
|
+
cc,
|
|
4418
|
+
bcc,
|
|
4419
|
+
subject: optionalString(args, "subject"),
|
|
4420
|
+
body,
|
|
4421
|
+
isHtml: typeof args.isHtml === "boolean" ? args.isHtml : undefined,
|
|
4422
|
+
priority: priority === "high" || priority === "low" || priority === "normal"
|
|
4423
|
+
? priority
|
|
4424
|
+
: undefined,
|
|
4425
|
+
replyTo,
|
|
4426
|
+
from,
|
|
4427
|
+
attachments,
|
|
4428
|
+
notes: optionalString(args, "notes"),
|
|
4429
|
+
};
|
|
4394
4430
|
const result = await withAudit(auditService, name, args, async () => {
|
|
4395
|
-
const
|
|
4396
|
-
|
|
4397
|
-
|
|
4398
|
-
|
|
4399
|
-
|
|
4400
|
-
|
|
4401
|
-
|
|
4402
|
-
|
|
4403
|
-
? priority
|
|
4404
|
-
: undefined,
|
|
4405
|
-
replyTo,
|
|
4406
|
-
from,
|
|
4407
|
-
attachments,
|
|
4408
|
-
notes: optionalString(args, "notes"),
|
|
4409
|
-
});
|
|
4431
|
+
const existingDraft = await updateDraftBundle.draftStore.getDraft(updateDraftIdRest);
|
|
4432
|
+
if (isNoopDraftPatch(existingDraft, draftPatch)) {
|
|
4433
|
+
return presentDraft(updateDraftBundle, {
|
|
4434
|
+
...existingDraft,
|
|
4435
|
+
remoteSync: { ok: true, skipped: true, message: "No changes — draft left as is, remote sync skipped." },
|
|
4436
|
+
});
|
|
4437
|
+
}
|
|
4438
|
+
const draft = await updateDraftBundle.draftStore.updateDraft(updateDraftIdRest, draftPatch);
|
|
4410
4439
|
const remoteSyncDecision = resolveRemoteDraftSync(config.runtime, normalizeBoolean(args.syncToRemote, true));
|
|
4411
4440
|
const synced = remoteSyncDecision.enabled
|
|
4412
4441
|
? await syncDraftToRemote(updateDraftBundle.draftStore, updateDraftBundle.smtpService, updateDraftBundle.imapService, draft)
|
|
@@ -4896,7 +4925,7 @@ export function createServer(config, options = {}) {
|
|
|
4896
4925
|
return createTextResult({ requested: emailIds.length, succeeded: results.filter((entry) => entry.ok).length, results }, false, sources);
|
|
4897
4926
|
}
|
|
4898
4927
|
case "search_emails": {
|
|
4899
|
-
const effectiveLimit = normalizeLimit(args.limit,
|
|
4928
|
+
const effectiveLimit = normalizeLimit(args.limit, 50);
|
|
4900
4929
|
try {
|
|
4901
4930
|
const result = await imapService.searchEmails({
|
|
4902
4931
|
query: optionalString(args, "query"),
|