proton-mail-bridge-client 1.17.1 → 1.18.0

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 CHANGED
@@ -346,6 +346,7 @@ PROTONMAIL_IMAP_PORT='1143'
346
346
  PROTONMAIL_IMAP_SECURE='false'
347
347
  PROTONMAIL_SMTP_HOST='127.0.0.1'
348
348
  PROTONMAIL_SMTP_PORT='1025'
349
+ PROTONMAIL_SMTP_SECURE='true' # Bridge's local SMTP port requires implicit TLS from the first byte; set false only for a non-Bridge SMTP relay
349
350
 
350
351
  # Secrets via file or command (avoids raw credentials in config)
351
352
  PROTONMAIL_USERNAME_FILE='/path/to/user.txt'
package/dist/index.d.ts CHANGED
@@ -9,6 +9,7 @@ import { SimpleIMAPService } from "./services/simple-imap-service.js";
9
9
  import { SMTPService } from "./services/smtp-service.js";
10
10
  import { SnoozeService } from "./services/snooze-service.js";
11
11
  import type { EmailDetail, ProtonMailConfig } from "./types/index.js";
12
+ export declare const CORE_TOOL_NAMES: Set<string>;
12
13
  export declare function headerString(headers: Record<string, unknown> | undefined, name: string): string | undefined;
13
14
  export declare function parseAuthenticationResults(value?: string): {
14
15
  dkim?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAOA,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,EAAwD,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AAC5H,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;AA82D1B,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;AAs5BD,wBAAgB,kBAAkB,IAAI,gBAAgB,CA4FrD;AAED,wBAAgB,YAAY,CAC1B,MAAM,EAAE,gBAAgB,EACxB,OAAO,GAAE;IACP,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC1B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAupFP;AAED,wBAAsB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAqD1C"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAOA,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,EAAwD,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AAC5H,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;AAkqD1B,eAAO,MAAM,eAAe,aAyB1B,CAAC;AAuLH,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;AAk5BD,wBAAgB,kBAAkB,IAAI,gBAAgB,CAgGrD;AAED,wBAAgB,YAAY,CAC1B,MAAM,EAAE,gBAAgB,EACxB,OAAO,GAAE;IACP,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC1B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA6pFP;AAED,wBAAsB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAqD1C"}
package/dist/index.js CHANGED
@@ -718,7 +718,7 @@ const TOOLS = [
718
718
  },
719
719
  {
720
720
  name: "snooze_email",
721
- description: "Move an email out of sight into Folders/Snoozed and bring it back to its original folder at wakeAt. IMPORTANT: like scheduled sends, wake only fires while this MCP server process stays running — if the app is closed before wakeAt, the email wakes on next server startup instead of at the requested time, not reliably at wakeAt itself. Cancelable via cancel_snooze, which wakes it immediately.",
721
+ description: "Move an email out of sight into Folders/MCP-Snoozed and bring it back to its original folder at wakeAt. IMPORTANT: like scheduled sends, wake only fires while this MCP server process stays running — if the app is closed before wakeAt, the email wakes on next server startup instead of at the requested time, not reliably at wakeAt itself. Cancelable via cancel_snooze, which wakes it immediately.",
722
722
  annotations: { destructiveHint: false },
723
723
  inputSchema: {
724
724
  type: "object",
@@ -1668,10 +1668,14 @@ const TOOLS = [
1668
1668
  // Core tier: the 20 tools that cover ~80% of daily email use.
1669
1669
  // Set PROTONMAIL_TOOL_TIER=core to expose only these — reduces context-window burn
1670
1670
  // significantly on every session. Default is "full" (all tools).
1671
- const CORE_TOOL_NAMES = new Set([
1671
+ export const CORE_TOOL_NAMES = new Set([
1672
1672
  "get_emails",
1673
1673
  "get_email_by_id",
1674
- "search_emails",
1674
+ // search_emails (live IMAP) is deliberately excluded from core — it
1675
+ // overlaps with search_indexed_emails (faster, offline-capable, and
1676
+ // already the "prefer" default per its own description) and the core
1677
+ // tier exists specifically to reduce tool-selection overlap. Still
1678
+ // available under PROTONMAIL_TOOL_TIER=full for stale-index/live-only cases.
1675
1679
  "search_indexed_emails",
1676
1680
  "send_email",
1677
1681
  "reply_to_email",
@@ -2427,20 +2431,17 @@ async function previewEmailAction(imapService, emailId, action, targetFolder) {
2427
2431
  isStarred: detail.isStarred,
2428
2432
  };
2429
2433
  }
2434
+ // Best-effort: confirms the sent copy landed in the Sent folder, purely for
2435
+ // the sentCopy:"[sent-copy:verified]" hint in the response. sentCopyVerify
2436
+ // already does its own robust folder resolution internally (by specialUse,
2437
+ // then by name) on every call — retrying it with different guessed folder
2438
+ // names here was redundant and, worse, sequential (up to 3 x 30s = 90s),
2439
+ // which blocked the send_email response long enough to trip the MCP
2440
+ // client's own request timeout on an email that had already sent
2441
+ // successfully. One bounded call; failing to verify quickly just means the
2442
+ // hint stays "unverified", never a false failure.
2430
2443
  async function verifySentCopy(imapService, messageId) {
2431
- const resolver = imapService.resolveSentFolder;
2432
- const resolved = await resolver?.();
2433
- if (resolved) {
2434
- return imapService.sentCopyVerify(messageId, resolved, 30_000);
2435
- }
2436
- let lastResult = { found: false };
2437
- for (const sentFolderName of ["Sent", "Sent Mail", "Sent Messages"]) {
2438
- lastResult = await imapService.sentCopyVerify(messageId, sentFolderName, 30_000);
2439
- if (lastResult.found) {
2440
- return lastResult;
2441
- }
2442
- }
2443
- return lastResult;
2444
+ return imapService.sentCopyVerify(messageId, "Sent", 8_000);
2444
2445
  }
2445
2446
  function getBulkMaxBatchSize(args) {
2446
2447
  return typeof args.maxBatchSize === "number" ? Math.min(args.maxBatchSize, 2000) : 500;
@@ -2609,7 +2610,11 @@ export function buildConfigFromEnv() {
2609
2610
  if (!username || !password) {
2610
2611
  throw new Error("Missing required environment variables or secret sources: PROTONMAIL_USERNAME and PROTONMAIL_PASSWORD.");
2611
2612
  }
2612
- const smtpPort = parseIntegerEnv("PROTONMAIL_SMTP_PORT", 587, 1, 65_535);
2613
+ const smtpPort = parseIntegerEnv("PROTONMAIL_SMTP_PORT", 1025, 1, 65_535);
2614
+ // Bridge's local SMTP port requires implicit TLS from the first byte (no
2615
+ // plaintext greeting, no STARTTLS) — confirmed against a live Bridge
2616
+ // instance. Overridable for non-Bridge SMTP setups.
2617
+ const smtpSecure = parseBooleanEnv("PROTONMAIL_SMTP_SECURE", true);
2613
2618
  const imapPort = parseIntegerEnv("PROTONMAIL_IMAP_PORT", 1143, 1, 65_535);
2614
2619
  const debug = parseBooleanEnv("DEBUG", false);
2615
2620
  const readOnly = parseBooleanEnv("PROTONMAIL_READ_ONLY", false);
@@ -2645,7 +2650,7 @@ export function buildConfigFromEnv() {
2645
2650
  smtp: {
2646
2651
  host: smtpHost,
2647
2652
  port: smtpPort,
2648
- secure: smtpPort === 465,
2653
+ secure: smtpSecure,
2649
2654
  username,
2650
2655
  password,
2651
2656
  },
@@ -4883,7 +4888,16 @@ export function createServer(config, options = {}) {
4883
4888
  if (isLikelyConnectionError(error)) {
4884
4889
  throw new McpError(ErrorCode.InternalError, "Could not connect to Proton Bridge. Make sure the Bridge app is running, and that PROTONMAIL_IMAP_HOST/PORT and PROTONMAIL_SMTP_HOST/PORT match the ports shown in Bridge's settings. Run run_doctor for a full connectivity check.");
4885
4890
  }
4886
- throw new McpError(ErrorCode.InternalError, "An internal error occurred. Check get_logs for details, or run run_doctor for a full connectivity check.");
4891
+ // Every throw new Error(...) across src/services and src/utils is a
4892
+ // deliberately-worded, actionable message (not-found, validation,
4893
+ // policy-disabled, etc.) with no secrets or stack traces in it —
4894
+ // surface it directly instead of discarding it into a generic
4895
+ // "check get_logs" message that sends the caller on a diagnostic
4896
+ // wild goose chase for something that was already fully explained.
4897
+ const message = error instanceof Error && error.message
4898
+ ? error.message
4899
+ : "An internal error occurred. Check get_logs for details, or run run_doctor for a full connectivity check.";
4900
+ throw new McpError(ErrorCode.InternalError, message);
4887
4901
  }
4888
4902
  });
4889
4903
  return {