proton-mail-bridge-client 2.7.1 → 2.7.3

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.
Files changed (37) hide show
  1. package/README.md +3 -0
  2. package/dist/index.d.ts +6 -0
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +116 -8
  5. package/dist/index.js.map +1 -1
  6. package/dist/scripts/setup-claude-desktop.d.ts +12 -0
  7. package/dist/scripts/setup-claude-desktop.d.ts.map +1 -1
  8. package/dist/scripts/setup-claude-desktop.js +43 -2
  9. package/dist/scripts/setup-claude-desktop.js.map +1 -1
  10. package/dist/services/delivery-queue-service.d.ts.map +1 -1
  11. package/dist/services/delivery-queue-service.js +7 -6
  12. package/dist/services/delivery-queue-service.js.map +1 -1
  13. package/dist/services/draft-store-service.d.ts.map +1 -1
  14. package/dist/services/draft-store-service.js +10 -9
  15. package/dist/services/draft-store-service.js.map +1 -1
  16. package/dist/services/local-index-service.d.ts.map +1 -1
  17. package/dist/services/local-index-service.js +6 -6
  18. package/dist/services/local-index-service.js.map +1 -1
  19. package/dist/services/simple-imap-service.d.ts +2 -0
  20. package/dist/services/simple-imap-service.d.ts.map +1 -1
  21. package/dist/services/simple-imap-service.js +33 -12
  22. package/dist/services/simple-imap-service.js.map +1 -1
  23. package/dist/services/snooze-service.d.ts.map +1 -1
  24. package/dist/services/snooze-service.js +5 -4
  25. package/dist/services/snooze-service.js.map +1 -1
  26. package/dist/services/template-service.d.ts.map +1 -1
  27. package/dist/services/template-service.js +3 -2
  28. package/dist/services/template-service.js.map +1 -1
  29. package/dist/utils/helpers.d.ts +1 -0
  30. package/dist/utils/helpers.d.ts.map +1 -1
  31. package/dist/utils/helpers.js +59 -13
  32. package/dist/utils/helpers.js.map +1 -1
  33. package/dist/utils/own-record.d.ts +2 -0
  34. package/dist/utils/own-record.d.ts.map +1 -0
  35. package/dist/utils/own-record.js +6 -0
  36. package/dist/utils/own-record.js.map +1 -0
  37. package/package.json +2 -1
@@ -1161,6 +1161,7 @@ export class SimpleIMAPService {
1161
1161
  if (fromPath === toPath) {
1162
1162
  throw new Error("Source and target paths are identical.");
1163
1163
  }
1164
+ await this.refuseSystemFolder(fromPath, "rename");
1164
1165
  const response = await this.mutateFolderWithReconnectCheck(async () => {
1165
1166
  const client = await this.ensureConnected();
1166
1167
  return client.mailboxRename(fromPath, toPath);
@@ -1191,27 +1192,30 @@ export class SimpleIMAPService {
1191
1192
  : undefined;
1192
1193
  return { path: response.path, newPath: response.newPath, folder, warning };
1193
1194
  }
1194
- async deleteFolder(path) {
1195
- const trimmed = path?.trim();
1196
- if (!trimmed) {
1197
- throw new Error("Folder path is required.");
1198
- }
1199
- // System folders, by name (any capitalisation, with or without surrounding slashes) and by the special-use
1200
- // the server itself reports. Compared on the normalised name: "inbox", "INBOX/" and "/Trash" are the same
1201
- // folders as "INBOX" and "Trash".
1195
+ // System folders, by name (any capitalisation, with or without surrounding slashes) and by the special-use
1196
+ // the server itself reports. Compared on the normalised name: "inbox", "INBOX/" and "/Trash" are the same
1197
+ // folders as "INBOX" and "Trash".
1198
+ async refuseSystemFolder(path, verb) {
1202
1199
  const reservedNames = new Set([
1203
1200
  "inbox", "drafts", "sent", "sent mail", "trash", "deleted messages", "spam", "junk", "archive",
1204
1201
  "all mail", "starred", "folders", "labels",
1205
1202
  ]);
1206
- const normalized = trimmed.replace(/^\/+|\/+$/g, "").trim().toLowerCase();
1203
+ const normalized = path.replace(/^\/+|\/+$/g, "").trim().toLowerCase();
1207
1204
  if (reservedNames.has(normalized)) {
1208
- throw new Error(`Refusing to delete reserved system folder ${trimmed}.`);
1205
+ throw new Error(`Refusing to ${verb} reserved system folder ${path}.`);
1209
1206
  }
1210
1207
  const known = await this.getFolders().catch(() => []);
1211
1208
  const target = known.find((entry) => entry.path.replace(/^\/+|\/+$/g, "").toLowerCase() === normalized);
1212
1209
  if (target?.specialUse) {
1213
- throw new Error(`Refusing to delete system folder ${trimmed} (it is the server's ${target.specialUse} folder).`);
1210
+ throw new Error(`Refusing to ${verb} system folder ${path} (it is the server's ${target.specialUse} folder).`);
1211
+ }
1212
+ }
1213
+ async deleteFolder(path) {
1214
+ const trimmed = path?.trim();
1215
+ if (!trimmed) {
1216
+ throw new Error("Folder path is required.");
1214
1217
  }
1218
+ await this.refuseSystemFolder(trimmed, "delete");
1215
1219
  const response = await this.mutateFolderWithReconnectCheck(async () => {
1216
1220
  const client = await this.ensureConnected();
1217
1221
  return client.mailboxDelete(trimmed);
@@ -2133,7 +2137,7 @@ export class SimpleIMAPService {
2133
2137
  return status?.uidValidity?.toString();
2134
2138
  }
2135
2139
  async emptyFolder(folder) {
2136
- if (folder.toUpperCase() === "INBOX") {
2140
+ if (folder.replace(/^\/+|\/+$/g, "").trim().toUpperCase() === "INBOX") {
2137
2141
  throw new Error("emptyFolder cannot be used on INBOX. Move messages to Trash first.");
2138
2142
  }
2139
2143
  let folderUidValidity;
@@ -3245,6 +3249,23 @@ export class SimpleIMAPService {
3245
3249
  const real = selectable.filter((entry) => !isVirtualMailView(entry));
3246
3250
  return (real.length > 0 ? real : selectable).map((entry) => entry.path);
3247
3251
  }
3252
+ // True when `path` is this account's Trash folder. Moving a message there is trashing it, whatever tool does
3253
+ // the move, so the move tools check this to apply the "trash" permission as well. A folder merely named
3254
+ // "Trash" under another path (Folders/Trash) is a different folder.
3255
+ async isTrashFolder(path) {
3256
+ const normalize = (value) => value.trim().replace(/^\/+|\/+$/g, "").trim().toLowerCase();
3257
+ const wanted = normalize(path);
3258
+ if (wanted === "trash" || wanted === "inbox.trash") {
3259
+ return true;
3260
+ }
3261
+ try {
3262
+ return normalize(await this.resolveSpecialFolder("\\Trash", ["Trash", "INBOX.Trash"])) === wanted;
3263
+ }
3264
+ catch {
3265
+ // The folder list could not be read, so it is not known whether this is the Trash folder.
3266
+ return undefined;
3267
+ }
3268
+ }
3248
3269
  async resolveSpecialFolder(specialUse, fallbacks) {
3249
3270
  const folders = await this.getFolderStructure();
3250
3271
  const bySpecialUse = folders.find((folder) => folder.specialUse === specialUse);