proton-mail-bridge-client 2.1.14 → 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 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;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
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
  },
@@ -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: 100 },
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: 100 },
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
  },
@@ -2341,6 +2342,17 @@ const DRAFT_BODY_PREVIEW_LENGTH = 500;
2341
2342
  // for the text body instead of base64. get_draft deliberately keeps the full
2342
2343
  // body — it's the "let me look at this one draft" call, not a repeated-edit
2343
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
+ }
2344
2356
  export function truncateDraftBodyForResponse(draft) {
2345
2357
  if (draft.body.length <= DRAFT_BODY_PREVIEW_LENGTH) {
2346
2358
  return draft;
@@ -2362,7 +2374,10 @@ export function redactQueueRecordAttachments(record) {
2362
2374
  const attachments = record.payload.attachments;
2363
2375
  const body = record.payload.body;
2364
2376
  const bodyTooLong = typeof body === "string" && body.length > DRAFT_BODY_PREVIEW_LENGTH;
2365
- if ((!attachments || attachments.length === 0) && !bodyTooLong) {
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 {
@@ -2370,6 +2385,7 @@ export function redactQueueRecordAttachments(record) {
2370
2385
  payload: {
2371
2386
  ...record.payload,
2372
2387
  ...(bodyTooLong ? truncateDraftBodyForResponse({ body }) : {}),
2388
+ ...(hasHtmlBody ? { htmlBody: undefined, htmlBodyOmitted: true } : {}),
2373
2389
  ...(attachments && attachments.length > 0
2374
2390
  ? {
2375
2391
  attachments: attachments.map((attachment) => ({
@@ -3692,7 +3708,7 @@ export function createServer(config, options = {}) {
3692
3708
  const all = await withAudit(auditService, name, args, async () => deliveryQueueService.list());
3693
3709
  const filtered = (statusFilter ? all.filter((item) => item.status === statusFilter) : all)
3694
3710
  .map(redactQueueRecordAttachments);
3695
- return createTextResult(filtered);
3711
+ return createTextResult(typeof args.limit === "number" ? filtered.slice(0, normalizeLimit(args.limit, filtered.length, 1, 10_000)) : filtered);
3696
3712
  }
3697
3713
  const perAccount = await withAudit(auditService, name, args, async () => Promise.all(accountManager.all().map(async (bundle) => ({
3698
3714
  bundle,
@@ -3701,7 +3717,7 @@ export function createServer(config, options = {}) {
3701
3717
  const tagged = perAccount.flatMap(({ bundle, items }) => items.map((item) => ({ ...item, id: withAccountPrefix(responseSlug(bundle), item.id) })));
3702
3718
  const filtered = (statusFilter ? tagged.filter((item) => item.status === statusFilter) : tagged)
3703
3719
  .map(redactQueueRecordAttachments);
3704
- return createTextResult(filtered);
3720
+ return createTextResult(typeof args.limit === "number" ? filtered.slice(0, normalizeLimit(args.limit, filtered.length, 1, 10_000)) : filtered);
3705
3721
  }
3706
3722
  case "get_unsubscribe_info": {
3707
3723
  const rawEmailId = requireString(args, "emailId");
@@ -4396,22 +4412,30 @@ export function createServer(config, options = {}) {
4396
4412
  if (from && !isValidEmail(from)) {
4397
4413
  throw new McpError(ErrorCode.InvalidParams, "from must be a valid email address.");
4398
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
+ };
4399
4430
  const result = await withAudit(auditService, name, args, async () => {
4400
- const draft = await updateDraftBundle.draftStore.updateDraft(updateDraftIdRest, {
4401
- to,
4402
- cc,
4403
- bcc,
4404
- subject: optionalString(args, "subject"),
4405
- body,
4406
- isHtml: typeof args.isHtml === "boolean" ? args.isHtml : undefined,
4407
- priority: priority === "high" || priority === "low" || priority === "normal"
4408
- ? priority
4409
- : undefined,
4410
- replyTo,
4411
- from,
4412
- attachments,
4413
- notes: optionalString(args, "notes"),
4414
- });
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);
4415
4439
  const remoteSyncDecision = resolveRemoteDraftSync(config.runtime, normalizeBoolean(args.syncToRemote, true));
4416
4440
  const synced = remoteSyncDecision.enabled
4417
4441
  ? await syncDraftToRemote(updateDraftBundle.draftStore, updateDraftBundle.smtpService, updateDraftBundle.imapService, draft)
@@ -4901,7 +4925,7 @@ export function createServer(config, options = {}) {
4901
4925
  return createTextResult({ requested: emailIds.length, succeeded: results.filter((entry) => entry.ok).length, results }, false, sources);
4902
4926
  }
4903
4927
  case "search_emails": {
4904
- const effectiveLimit = normalizeLimit(args.limit, 100);
4928
+ const effectiveLimit = normalizeLimit(args.limit, 50);
4905
4929
  try {
4906
4930
  const result = await imapService.searchEmails({
4907
4931
  query: optionalString(args, "query"),