proton-mail-bridge-client 2.10.0 → 2.11.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 +22 -20
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +5 -1
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +68 -15
- package/dist/index.js.map +1 -1
- package/dist/scripts/install-claude-desktop.d.ts.map +1 -1
- package/dist/scripts/install-claude-desktop.js +21 -2
- package/dist/scripts/install-claude-desktop.js.map +1 -1
- package/dist/services/account-manager.d.ts.map +1 -1
- package/dist/services/account-manager.js +1 -0
- package/dist/services/account-manager.js.map +1 -1
- package/dist/services/local-index-service.d.ts.map +1 -1
- package/dist/services/local-index-service.js +3 -0
- package/dist/services/local-index-service.js.map +1 -1
- package/dist/services/simple-imap-service.d.ts +9 -1
- package/dist/services/simple-imap-service.d.ts.map +1 -1
- package/dist/services/simple-imap-service.js +69 -19
- package/dist/services/simple-imap-service.js.map +1 -1
- package/dist/services/smtp-service.d.ts +3 -0
- package/dist/services/smtp-service.d.ts.map +1 -1
- package/dist/services/smtp-service.js +32 -5
- package/dist/services/smtp-service.js.map +1 -1
- package/dist/types/index.d.ts +10 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/utils/helpers.d.ts.map +1 -1
- package/dist/utils/helpers.js +23 -1
- package/dist/utils/helpers.js.map +1 -1
- package/dist/utils/pdf-text.d.ts +23 -0
- package/dist/utils/pdf-text.d.ts.map +1 -0
- package/dist/utils/pdf-text.js +122 -0
- package/dist/utils/pdf-text.js.map +1 -0
- package/dist/utils/runtime-policy.d.ts.map +1 -1
- package/dist/utils/runtime-policy.js +2 -1
- package/dist/utils/runtime-policy.js.map +1 -1
- package/package.json +3 -2
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;AAenE,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,EAAE,iBAAiB,EAAuD,MAAM,mCAAmC,CAAC;AAC3H,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,KAAK,EAMV,mBAAmB,EACnB,cAAc,EACd,WAAW,EAKX,WAAW,EAIX,gBAAgB,EAEhB,cAAc,EAGf,MAAM,kBAAkB,CAAC;AA2B1B,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
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
2
|
+
import { execSync } from "node:child_process";
|
|
3
3
|
import { readFileSync } from "node:fs";
|
|
4
4
|
import { chmod, mkdir } from "node:fs/promises";
|
|
5
5
|
import { createRequire } from "node:module";
|
|
@@ -18,6 +18,7 @@ import { applySignature, plainTextToHtml } from "./services/smtp-service.js";
|
|
|
18
18
|
import { ensureValidEmails, foldQuotedHistory, isTextLikeMimeType, isValidEmail, isSelfAddress, lowerCaseAddress, InvalidArgumentError, isOutgoingMessage, isPathInside, normalizeBoolean, normalizeLimit, optionalBoolean, optionalInteger, optionalNumber, normalizeJsonValue, parseEmailId, parseEmails, projectFields, trimAttachmentsForListing, renderMarkdown, slugifyAccountAddress, splitAccountPrefix, stringifyForJson, withAccountPrefix, } from "./utils/helpers.js";
|
|
19
19
|
import { AccountManager } from "./services/account-manager.js";
|
|
20
20
|
import { logger } from "./utils/logger.js";
|
|
21
|
+
import { DEFAULT_PDF_MAX_MB, DEFAULT_PDF_MAX_PAGES } from "./utils/pdf-text.js";
|
|
21
22
|
import { ensureDestructiveConfirmed, ensureEmailActionAllowed, ensureFlagChangeAllowed, ensureMailboxWriteAllowed, ensureOutboundRecipientsAllowed, ensureRemoteDraftSyncAllowed, ensureSendAllowed, resolveRemoteDraftSync, sanitizeRuntimeConfig, } from "./utils/runtime-policy.js";
|
|
22
23
|
import { InviteError, buildInviteReply, findMyAttendee, parseInvite } from "./utils/ical-reply.js";
|
|
23
24
|
const require = createRequire(import.meta.url);
|
|
@@ -1724,7 +1725,7 @@ const TOOLS = [
|
|
|
1724
1725
|
},
|
|
1725
1726
|
{
|
|
1726
1727
|
name: "get_attachment_text",
|
|
1727
|
-
description: "Extract plain text from a text-like attachment (text/plain, text/csv, text/markdown, application/json, application/xml, text/html stripped of markup, text/calendar summarized) without dealing with base64 encoding.
|
|
1728
|
+
description: "Extract plain text from a text-like attachment (text/plain, text/csv, text/markdown, application/json, application/xml, text/html stripped of markup, text/calendar summarized) or a PDF, without dealing with base64 encoding. PDF text comes back page by page with a \"--- Page N of M ---\" marker before each page; a PDF is bounded by PROTONMAIL_PDF_MAX_MB (default 10) and PROTONMAIL_PDF_MAX_PAGES (default 50), and a longer one is cut off with a note saying how many pages are missing (the pdf field reports totalPages and omittedPages). Password-protected, damaged and scanned PDFs without a text layer fail with a plain explanation. Other text formats are not gated by the smaller inline-base64 size limit that get_attachment_content uses — bounded separately at 512KB of raw content. Fails clearly for images and other non-text formats — use get_attachment_content or save_attachment for those.",
|
|
1728
1729
|
annotations: { readOnlyHint: true },
|
|
1729
1730
|
inputSchema: {
|
|
1730
1731
|
type: "object",
|
|
@@ -3596,7 +3597,8 @@ function readEnvValue(name) {
|
|
|
3596
3597
|
}
|
|
3597
3598
|
const command = process.env[`${name}_COMMAND`]?.trim();
|
|
3598
3599
|
if (command) {
|
|
3599
|
-
|
|
3600
|
+
// The platform shell: /bin/sh on macOS and Linux (as before), cmd.exe on Windows, which has no /bin/sh.
|
|
3601
|
+
return execSync(command, { encoding: "utf-8" }).trim();
|
|
3600
3602
|
}
|
|
3601
3603
|
const filePath = process.env[`${name}_FILE`]?.trim();
|
|
3602
3604
|
if (!filePath) {
|
|
@@ -3715,16 +3717,15 @@ function parseAdditionalAccountsEnv(primary) {
|
|
|
3715
3717
|
}
|
|
3716
3718
|
const value = entry;
|
|
3717
3719
|
const address = typeof value.address === "string" ? value.address.trim() : "";
|
|
3718
|
-
const password = typeof value.password === "string" ? value.password : "";
|
|
3719
3720
|
if (!address || !isValidEmail(address)) {
|
|
3720
3721
|
throw new Error(`PROTONMAIL_ACCOUNTS_JSON[${index}].address must be a valid email address.`);
|
|
3721
3722
|
}
|
|
3722
|
-
|
|
3723
|
-
throw new Error(`PROTONMAIL_ACCOUNTS_JSON[${index}].password is required.`);
|
|
3724
|
-
}
|
|
3723
|
+
const password = readAccountPassword(value, index);
|
|
3725
3724
|
const lowerAddress = address.toLowerCase();
|
|
3726
3725
|
if (seenAddresses.has(lowerAddress)) {
|
|
3727
|
-
|
|
3726
|
+
const isPrimary = lowerAddress === primary.address.toLowerCase();
|
|
3727
|
+
throw new Error(`PROTONMAIL_ACCOUNTS_JSON[${index}]: duplicate address "${address}".` +
|
|
3728
|
+
(isPrimary ? " The primary account (PROTONMAIL_USERNAME) is already configured: list only the additional accounts here." : ""));
|
|
3728
3729
|
}
|
|
3729
3730
|
seenAddresses.add(lowerAddress);
|
|
3730
3731
|
const slug = slugifyAccountAddress(address);
|
|
@@ -3750,12 +3751,41 @@ function parseAdditionalAccountsEnv(primary) {
|
|
|
3750
3751
|
host: stringField("smtpHost", primary.smtp.host),
|
|
3751
3752
|
port: numberField("smtpPort", primary.smtp.port),
|
|
3752
3753
|
secure: boolField("smtpSecure", primary.smtp.secure),
|
|
3754
|
+
secureExplicit: typeof value.smtpSecure === "boolean" || primary.smtp.secureExplicit === true,
|
|
3753
3755
|
username: stringField("smtpUsername", address),
|
|
3754
3756
|
password: stringField("smtpPassword", password),
|
|
3755
3757
|
},
|
|
3758
|
+
...(typeof value.autoSyncFolder === "string" && value.autoSyncFolder.trim()
|
|
3759
|
+
? { autoSyncFolder: value.autoSyncFolder.trim() }
|
|
3760
|
+
: {}),
|
|
3756
3761
|
};
|
|
3757
3762
|
});
|
|
3758
3763
|
}
|
|
3764
|
+
// An additional account's Bridge password: inline, or read from a file / a command so it need not sit in the
|
|
3765
|
+
// client config (same idea as PROTONMAIL_PASSWORD_FILE / _COMMAND for the primary account).
|
|
3766
|
+
function readAccountPassword(value, index) {
|
|
3767
|
+
const where = `PROTONMAIL_ACCOUNTS_JSON[${index}]`;
|
|
3768
|
+
const inline = typeof value.password === "string" ? value.password : "";
|
|
3769
|
+
const file = typeof value.passwordFile === "string" ? value.passwordFile.trim() : "";
|
|
3770
|
+
const command = typeof value.passwordCommand === "string" ? value.passwordCommand.trim() : "";
|
|
3771
|
+
if ([inline, file, command].filter(Boolean).length > 1) {
|
|
3772
|
+
throw new Error(`${where}: use only one of password, passwordFile, passwordCommand.`);
|
|
3773
|
+
}
|
|
3774
|
+
let password = inline;
|
|
3775
|
+
try {
|
|
3776
|
+
if (file)
|
|
3777
|
+
password = readFileSync(file, "utf8").trim();
|
|
3778
|
+
else if (command)
|
|
3779
|
+
password = execSync(command, { encoding: "utf-8" }).trim();
|
|
3780
|
+
}
|
|
3781
|
+
catch (error) {
|
|
3782
|
+
throw new Error(`${where}: could not read the password from ${file ? "passwordFile" : "passwordCommand"}: ${error instanceof Error ? error.message : String(error)}`);
|
|
3783
|
+
}
|
|
3784
|
+
if (!password) {
|
|
3785
|
+
throw new Error(`${where}.password is required (or passwordFile / passwordCommand).`);
|
|
3786
|
+
}
|
|
3787
|
+
return password;
|
|
3788
|
+
}
|
|
3759
3789
|
// The one configuration error the server can still answer: without a login it cannot reach Bridge, but it can
|
|
3760
3790
|
// list its tools and say what is missing (registries and MCP clients start servers without credentials to
|
|
3761
3791
|
// inspect them, and "Connection closed" tells nobody anything).
|
|
@@ -3777,6 +3807,9 @@ export function buildConfigFromEnv() {
|
|
|
3777
3807
|
// plaintext greeting, no STARTTLS) — confirmed against a live Bridge
|
|
3778
3808
|
// instance. Overridable for non-Bridge SMTP setups.
|
|
3779
3809
|
const smtpSecure = parseBooleanEnv("PROTONMAIL_SMTP_SECURE", true);
|
|
3810
|
+
// Set by the user (a non-empty value that is not an unfilled "${user_config...}" placeholder), as opposed to the default.
|
|
3811
|
+
const smtpSecureRaw = process.env.PROTONMAIL_SMTP_SECURE?.trim() ?? "";
|
|
3812
|
+
const smtpSecureExplicit = smtpSecureRaw !== "" && !smtpSecureRaw.startsWith("${");
|
|
3780
3813
|
validatePortEnv("PROTONMAIL_IMAP_PORT");
|
|
3781
3814
|
const imapPort = parseIntegerEnv("PROTONMAIL_IMAP_PORT", 1143, 1, 65_535);
|
|
3782
3815
|
const debug = parseBooleanEnv("DEBUG", false);
|
|
@@ -3813,7 +3846,7 @@ export function buildConfigFromEnv() {
|
|
|
3813
3846
|
if (isLocalBridgeHost(imapHost)) {
|
|
3814
3847
|
logger.warn("TLS verification is disabled for local Bridge IMAP connections.", "MCPServer", { host: imapHost });
|
|
3815
3848
|
}
|
|
3816
|
-
const primarySmtp = { host: smtpHost, port: smtpPort, secure: smtpSecure, username, password };
|
|
3849
|
+
const primarySmtp = { host: smtpHost, port: smtpPort, secure: smtpSecure, secureExplicit: smtpSecureExplicit, username, password };
|
|
3817
3850
|
const primaryImap = { host: imapHost, port: imapPort, secure: imapSecure, username: imapUsername, password: imapPassword };
|
|
3818
3851
|
const primaryAccount = {
|
|
3819
3852
|
address: username,
|
|
@@ -3852,7 +3885,10 @@ export function buildConfigFromEnv() {
|
|
|
3852
3885
|
allowEmptyFolder,
|
|
3853
3886
|
restrictOutboundToSelf,
|
|
3854
3887
|
allowFileDownloadDir,
|
|
3855
|
-
|
|
3888
|
+
// The value is in KB despite the historical name; PROTONMAIL_MAX_INLINE_KB is the clear spelling and wins.
|
|
3889
|
+
maxInlineBytes: parseIntegerEnv("PROTONMAIL_MAX_INLINE_KB", parseIntegerEnv("PROTONMAIL_MAX_INLINE_BYTES", 40, 1, 10240), 1, 10240),
|
|
3890
|
+
pdfMaxMb: parseIntegerEnv("PROTONMAIL_PDF_MAX_MB", DEFAULT_PDF_MAX_MB, 1, 100),
|
|
3891
|
+
pdfMaxPages: parseIntegerEnv("PROTONMAIL_PDF_MAX_PAGES", DEFAULT_PDF_MAX_PAGES, 1, 2000),
|
|
3856
3892
|
opDelayMs,
|
|
3857
3893
|
sendDelaySeconds,
|
|
3858
3894
|
},
|
|
@@ -7199,6 +7235,7 @@ export function createServer(config, options = {}) {
|
|
|
7199
7235
|
complete: snapshot.complete,
|
|
7200
7236
|
remainingFolders: snapshot.remainingFolders,
|
|
7201
7237
|
...(snapshot.failedFolders.length > 0 ? { failedFolders: snapshot.failedFolders } : {}),
|
|
7238
|
+
...(snapshot.skippedFolders.length > 0 ? { skippedFolders: snapshot.skippedFolders } : {}),
|
|
7202
7239
|
elapsedMs: Date.now() - startedAtMs,
|
|
7203
7240
|
budgetMs,
|
|
7204
7241
|
...(snapshot.complete
|
|
@@ -8072,18 +8109,34 @@ export function createServer(config, options = {}) {
|
|
|
8072
8109
|
}
|
|
8073
8110
|
}
|
|
8074
8111
|
catch (error) {
|
|
8112
|
+
// A tool that ran and failed is a tool result with isError (MCP spec), not a protocol error: clients such as
|
|
8113
|
+
// Claude Desktop pass a protocol error to the user as a generic "connector returned an error" and never to the
|
|
8114
|
+
// model, which then cannot read what went wrong or adjust (an inline limit, a missing setting). Only a tool
|
|
8115
|
+
// that does not exist stays a protocol error.
|
|
8116
|
+
// The CLI starts this server as a child with PROTONMAIL_TOOL_ERRORS=protocol: it reports a failure on stderr
|
|
8117
|
+
// with its own exit codes, which scripts rely on.
|
|
8118
|
+
const asProtocolError = process.env.PROTONMAIL_TOOL_ERRORS?.trim().toLowerCase() === "protocol";
|
|
8119
|
+
const failed = (message, code = ErrorCode.InternalError) => {
|
|
8120
|
+
if (asProtocolError)
|
|
8121
|
+
throw new McpError(code, message);
|
|
8122
|
+
return createTextResult(message, true);
|
|
8123
|
+
};
|
|
8075
8124
|
if (error instanceof McpError) {
|
|
8076
|
-
|
|
8125
|
+
const message = error.message.replace(/^MCP error -?\d+: /, "");
|
|
8126
|
+
if (error.code === ErrorCode.InvalidParams && message.startsWith("Unknown tool")) {
|
|
8127
|
+
throw error;
|
|
8128
|
+
}
|
|
8129
|
+
return failed(message, error.code);
|
|
8077
8130
|
}
|
|
8078
8131
|
if (error instanceof InvalidArgumentError) {
|
|
8079
|
-
|
|
8132
|
+
return failed(error.message, ErrorCode.InvalidParams);
|
|
8080
8133
|
}
|
|
8081
8134
|
logger.error("Tool call failed", "MCPServer", { name, error });
|
|
8082
8135
|
if (isLikelyAuthenticationError(error)) {
|
|
8083
|
-
|
|
8136
|
+
return failed("IMAP authentication failed. Check that PROTONMAIL_PASSWORD is your Proton Bridge password (not your Proton account password) and that you're signed in inside the Bridge app. Run run_doctor for a full connectivity check.");
|
|
8084
8137
|
}
|
|
8085
8138
|
if (isLikelyConnectionError(error)) {
|
|
8086
|
-
|
|
8139
|
+
return failed("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.");
|
|
8087
8140
|
}
|
|
8088
8141
|
// Every throw new Error(...) across src/services and src/utils is a
|
|
8089
8142
|
// deliberately-worded, actionable message (not-found, validation,
|
|
@@ -8096,7 +8149,7 @@ export function createServer(config, options = {}) {
|
|
|
8096
8149
|
// IMAP NO/BAD response bubble up as a bare "Command failed".
|
|
8097
8150
|
const message = describeImapError(error)
|
|
8098
8151
|
?? "An internal error occurred. Check get_logs for details, or run run_doctor for a full connectivity check.";
|
|
8099
|
-
|
|
8152
|
+
return failed(message);
|
|
8100
8153
|
}
|
|
8101
8154
|
}));
|
|
8102
8155
|
return {
|