proton-mail-bridge-client 2.1.20 → 2.1.21
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 +2 -2
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +27 -15
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +52 -14
- package/dist/index.js.map +1 -1
- package/dist/services/simple-imap-service.d.ts +2 -0
- package/dist/services/simple-imap-service.d.ts.map +1 -1
- package/dist/services/simple-imap-service.js +41 -30
- package/dist/services/simple-imap-service.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -154,6 +154,7 @@ const TOOLS = [
|
|
|
154
154
|
type: "object",
|
|
155
155
|
properties: {
|
|
156
156
|
emailId: { type: "string", description: "Original email id." },
|
|
157
|
+
undoWindowSeconds: { type: "number", description: "Override PROTONMAIL_SEND_DELAY_SECONDS for this one send: queue it for this many seconds (cancelable via cancel_send) instead of the server's configured default. 0 sends immediately even if the server has a default window configured. Same caveat as the server default: only fires while this server process stays running." },
|
|
157
158
|
body: { type: "string", description: "Reply body to prepend (plain text). Required unless markdownBody is provided." },
|
|
158
159
|
markdownBody: { type: "string", description: "Reply body in Markdown. Rendered to HTML with body as plain-text fallback; takes precedence over body+isHtml." },
|
|
159
160
|
replyAll: { type: "boolean", description: "Reply to all original recipients.", default: false },
|
|
@@ -194,6 +195,7 @@ const TOOLS = [
|
|
|
194
195
|
type: "object",
|
|
195
196
|
properties: {
|
|
196
197
|
emailId: { type: "string", description: "Original email id." },
|
|
198
|
+
undoWindowSeconds: { type: "number", description: "Override PROTONMAIL_SEND_DELAY_SECONDS for this one send: queue it for this many seconds (cancelable via cancel_send) instead of the server's configured default. 0 sends immediately even if the server has a default window configured. Same caveat as the server default: only fires while this server process stays running." },
|
|
197
199
|
body: { type: "string", description: "Reply body to prepend (plain text). Required unless markdownBody is provided." },
|
|
198
200
|
markdownBody: { type: "string", description: "Reply body in Markdown. Rendered to HTML with body as plain-text fallback; takes precedence over body+isHtml." },
|
|
199
201
|
isHtml: { type: "boolean", description: "Send body as HTML (ignored when markdownBody is provided).", default: false },
|
|
@@ -233,6 +235,7 @@ const TOOLS = [
|
|
|
233
235
|
type: "object",
|
|
234
236
|
properties: {
|
|
235
237
|
emailId: { type: "string", description: "Original email id." },
|
|
238
|
+
undoWindowSeconds: { type: "number", description: "Override PROTONMAIL_SEND_DELAY_SECONDS for this one send: queue it for this many seconds (cancelable via cancel_send) instead of the server's configured default. 0 sends immediately even if the server has a default window configured. Same caveat as the server default: only fires while this server process stays running." },
|
|
236
239
|
to: { type: "string", description: "Forward recipient list, comma-separated." },
|
|
237
240
|
body: { type: "string", description: "Optional message before the forwarded content (plain text)." },
|
|
238
241
|
markdownBody: { type: "string", description: "Optional introductory note in Markdown. Rendered to HTML with body as plain-text fallback; takes precedence over body+isHtml." },
|
|
@@ -3441,6 +3444,33 @@ export function createServer(config, options = {}) {
|
|
|
3441
3444
|
function responseSlug(bundle) {
|
|
3442
3445
|
return bundle.account.slug === accountManager.primary().account.slug ? undefined : bundle.account.slug;
|
|
3443
3446
|
}
|
|
3447
|
+
// Undo-send window for one send: the server default (PROTONMAIL_SEND_DELAY_SECONDS),
|
|
3448
|
+
// overridable per call with undoWindowSeconds (0 = send immediately). Shared by
|
|
3449
|
+
// send_email, reply_to_email, reply_all_email and forward_email.
|
|
3450
|
+
function resolveUndoWindowSeconds(args) {
|
|
3451
|
+
if (args.undoWindowSeconds === undefined) {
|
|
3452
|
+
return config.runtime.sendDelaySeconds ?? 0;
|
|
3453
|
+
}
|
|
3454
|
+
const requested = Number(args.undoWindowSeconds);
|
|
3455
|
+
if (!Number.isInteger(requested) || requested < 0 || requested > 300) {
|
|
3456
|
+
throw new McpError(ErrorCode.InvalidParams, "undoWindowSeconds must be an integer between 0 and 300.");
|
|
3457
|
+
}
|
|
3458
|
+
return requested;
|
|
3459
|
+
}
|
|
3460
|
+
// Queues a send on the SENDING account's own delivery queue (so it fires through that
|
|
3461
|
+
// account's SMTP) and returns the tool result. The id carries that account's slug so
|
|
3462
|
+
// cancel_send/list_scheduled_sends can find it again.
|
|
3463
|
+
async function queueUndoSend(bundle, payload, undoWindowSeconds, toolName, toolArgs, extra = {}) {
|
|
3464
|
+
const sendAt = new Date(Date.now() + undoWindowSeconds * 1000).toISOString();
|
|
3465
|
+
const queued = await withAudit(auditService, toolName, toolArgs, async () => bundle.deliveryQueueService.enqueue(payload, sendAt, "undo_send"));
|
|
3466
|
+
return createTextResult({
|
|
3467
|
+
queued: true,
|
|
3468
|
+
id: withAccountPrefix(responseSlug(bundle), queued.id),
|
|
3469
|
+
sendAt: queued.sendAt,
|
|
3470
|
+
...extra,
|
|
3471
|
+
note: `Not sent yet — will send in ~${undoWindowSeconds}s unless canceled with cancel_send. This server must stay running for the send to fire; if it's restarted before sendAt, the send fires on next startup instead.`,
|
|
3472
|
+
});
|
|
3473
|
+
}
|
|
3444
3474
|
// Alias for responseSlug — tagAccountIds (added alongside the digest/follow-up
|
|
3445
3475
|
// multi-account fan-out) was written against this name; kept as a thin alias rather
|
|
3446
3476
|
// than rewriting every call site to the other name.
|
|
@@ -3706,14 +3736,7 @@ export function createServer(config, options = {}) {
|
|
|
3706
3736
|
// immediately, cancelable via cancel_send until the window elapses.
|
|
3707
3737
|
// undoWindowSeconds overrides the server default for this one send —
|
|
3708
3738
|
// including forcing 0 (send immediately) when a default is configured.
|
|
3709
|
-
|
|
3710
|
-
if (args.undoWindowSeconds !== undefined) {
|
|
3711
|
-
const requested = Number(args.undoWindowSeconds);
|
|
3712
|
-
if (!Number.isInteger(requested) || requested < 0 || requested > 300) {
|
|
3713
|
-
throw new McpError(ErrorCode.InvalidParams, "undoWindowSeconds must be an integer between 0 and 300.");
|
|
3714
|
-
}
|
|
3715
|
-
undoWindowSeconds = requested;
|
|
3716
|
-
}
|
|
3739
|
+
const undoWindowSeconds = resolveUndoWindowSeconds(args);
|
|
3717
3740
|
// A `from` matching a configured additional account routes through that
|
|
3718
3741
|
// account's own SMTP connection — required under Bridge's Split Addresses
|
|
3719
3742
|
// feature, where each address is its own separate IMAP/SMTP login, not just
|
|
@@ -3928,7 +3951,7 @@ export function createServer(config, options = {}) {
|
|
|
3928
3951
|
if (dryRunReply) {
|
|
3929
3952
|
return createTextResult({ dryRun: true, wouldSendTo: { to, cc, bcc: extraBcc }, subject: prefixedSubject(detail.subject, "Re:"), note: "No email was sent." }, false, [emailSource({ ...detail, id: prefixedIdFor(readBundleReply, detail.id) })]);
|
|
3930
3953
|
}
|
|
3931
|
-
const
|
|
3954
|
+
const replyPayload = {
|
|
3932
3955
|
to,
|
|
3933
3956
|
cc,
|
|
3934
3957
|
bcc: extraBcc,
|
|
@@ -3944,7 +3967,12 @@ export function createServer(config, options = {}) {
|
|
|
3944
3967
|
attachments,
|
|
3945
3968
|
// Already applied above, before quote-wrapping.
|
|
3946
3969
|
appendSignature: false,
|
|
3947
|
-
}
|
|
3970
|
+
};
|
|
3971
|
+
const undoWindowreply = resolveUndoWindowSeconds(args);
|
|
3972
|
+
if (undoWindowreply > 0) {
|
|
3973
|
+
return queueUndoSend(sendBundleForReply, replyPayload, undoWindowreply, name, args, { repliedTo: prefixedIdFor(readBundleReply, detail.id), to, cc });
|
|
3974
|
+
}
|
|
3975
|
+
const result = await withAudit(auditService, name, args, async () => sendBundleForReply.smtpService.sendEmail(replyPayload));
|
|
3948
3976
|
let sentCopyTokenReply = "[sent-copy:unverified]";
|
|
3949
3977
|
try {
|
|
3950
3978
|
const verifyMsgId = result.messageId;
|
|
@@ -4017,7 +4045,7 @@ export function createServer(config, options = {}) {
|
|
|
4017
4045
|
const replyHtmlBodyRa = includeQuoteRa && signedReplyRa.htmlBody !== undefined
|
|
4018
4046
|
? buildReplyHtml(detailRa, signedReplyRa.htmlBody)
|
|
4019
4047
|
: signedReplyRa.htmlBody;
|
|
4020
|
-
const
|
|
4048
|
+
const replyAllPayload = {
|
|
4021
4049
|
to: toRa,
|
|
4022
4050
|
cc: ccRa,
|
|
4023
4051
|
bcc: extraBccRa,
|
|
@@ -4033,7 +4061,12 @@ export function createServer(config, options = {}) {
|
|
|
4033
4061
|
attachments: attachmentsRa,
|
|
4034
4062
|
// Already applied above, before quote-wrapping.
|
|
4035
4063
|
appendSignature: false,
|
|
4036
|
-
}
|
|
4064
|
+
};
|
|
4065
|
+
const undoWindowreplyAll = resolveUndoWindowSeconds(args);
|
|
4066
|
+
if (undoWindowreplyAll > 0) {
|
|
4067
|
+
return queueUndoSend(sendBundleForRa, replyAllPayload, undoWindowreplyAll, name, args, { repliedTo: prefixedIdFor(readBundleRa, detailRa.id), to: toRa, cc: ccRa });
|
|
4068
|
+
}
|
|
4069
|
+
const resultRa = await withAudit(auditService, name, args, async () => sendBundleForRa.smtpService.sendEmail(replyAllPayload));
|
|
4037
4070
|
let sentCopyTokenRa = "[sent-copy:unverified]";
|
|
4038
4071
|
try {
|
|
4039
4072
|
const verifyMsgId = resultRa.messageId;
|
|
@@ -4130,7 +4163,7 @@ export function createServer(config, options = {}) {
|
|
|
4130
4163
|
const forwardHtmlBody = signedFwd.htmlBody !== undefined
|
|
4131
4164
|
? buildForwardHtml(detail, signedFwd.htmlBody)
|
|
4132
4165
|
: signedFwd.htmlBody;
|
|
4133
|
-
const
|
|
4166
|
+
const forwardPayload = {
|
|
4134
4167
|
to,
|
|
4135
4168
|
cc,
|
|
4136
4169
|
bcc,
|
|
@@ -4144,7 +4177,12 @@ export function createServer(config, options = {}) {
|
|
|
4144
4177
|
attachments: fwdAttachments,
|
|
4145
4178
|
// Already applied above, before quote-wrapping.
|
|
4146
4179
|
appendSignature: false,
|
|
4147
|
-
}
|
|
4180
|
+
};
|
|
4181
|
+
const undoWindowforward = resolveUndoWindowSeconds(args);
|
|
4182
|
+
if (undoWindowforward > 0) {
|
|
4183
|
+
return queueUndoSend(sendBundleForFwd, forwardPayload, undoWindowforward, name, args, { forwardedMessage: prefixedIdFor(readBundleFwd, detail.id), to, cc });
|
|
4184
|
+
}
|
|
4185
|
+
const result = await withAudit(auditService, name, args, async () => sendBundleForFwd.smtpService.sendEmail(forwardPayload));
|
|
4148
4186
|
let sentCopyTokenFwd = "[sent-copy:unverified]";
|
|
4149
4187
|
try {
|
|
4150
4188
|
const verifyMsgId = result.messageId;
|