@bobfrankston/iflow-direct 0.1.8 → 0.1.9

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 (2) hide show
  1. package/imap-compat.js +36 -29
  2. package/package.json +1 -1
package/imap-compat.js CHANGED
@@ -73,44 +73,51 @@ export class CompatImapClient {
73
73
  }
74
74
  /** Detect special folders from folder list */
75
75
  getSpecialFolders(folders) {
76
- // Match IMAP special-use flags (RFC 6154) first, then fall back to exact
77
- // LEAF NAME match. Do NOT use substring matches on the full path —
78
- // "Drafts.Older" used to get tagged as the Drafts folder because of a
79
- // lower.includes("draft") test, which made it impossible to rename or
80
- // delete the subfolder.
76
+ // Two-pass detection so RFC 6154 \Drafts / \Sent / \Trash / \Junk /
77
+ // \Archive flags always win over name-based guesses. Previous single-pass
78
+ // `else if (flag || name)` could tag a stray folder named "DRAFT" as the
79
+ // drafts folder on Gmail, beating out [Imap]/Drafts which has the real
80
+ // \Drafts flag — Gmail then rejects APPEND to "DRAFT" as NONEXISTENT.
81
81
  const result = {};
82
82
  const leafName = (f) => {
83
83
  const delim = f.delimiter || ".";
84
84
  return (f.path.split(delim).pop() || f.path).toLowerCase();
85
85
  };
86
+ const flagsLower = (f) => f.flags.map(fl => fl.toLowerCase());
87
+ // Pass 1: RFC 6154 flags only — authoritative if present
86
88
  for (const f of folders) {
87
- const name = leafName(f);
88
- const flags = f.flags.map(fl => fl.toLowerCase());
89
- if (flags.includes("\\inbox") || name === "inbox") {
90
- if (!result.inbox)
91
- result.inbox = f.path;
92
- }
93
- else if (flags.includes("\\sent") || name === "sent" || name === "sent items" || name === "sent mail") {
94
- if (!result.sent)
95
- result.sent = f.path;
96
- }
97
- else if (flags.includes("\\trash") || name === "trash" || name === "deleted items" || name === "deleted") {
98
- if (!result.trash)
99
- result.trash = f.path;
100
- }
101
- else if (flags.includes("\\drafts") || name === "drafts" || name === "draft") {
102
- if (!result.drafts)
103
- result.drafts = f.path;
104
- }
105
- else if (flags.includes("\\junk") || flags.includes("\\spam") || name === "spam" || name === "junk" || name === "junk email" || name === "junk e-mail") {
106
- if (!result.junk)
107
- result.junk = f.path;
89
+ const flags = flagsLower(f);
90
+ if (!result.inbox && (flags.includes("\\inbox") || leafName(f) === "inbox"))
91
+ result.inbox = f.path;
92
+ if (!result.sent && flags.includes("\\sent"))
93
+ result.sent = f.path;
94
+ if (!result.trash && flags.includes("\\trash"))
95
+ result.trash = f.path;
96
+ if (!result.drafts && flags.includes("\\drafts"))
97
+ result.drafts = f.path;
98
+ if (!result.archive && flags.includes("\\archive"))
99
+ result.archive = f.path;
100
+ if (!result.junk && (flags.includes("\\junk") || flags.includes("\\spam"))) {
101
+ result.junk = f.path;
108
102
  if (!result.spam)
109
103
  result.spam = f.path;
110
104
  }
111
- else if (flags.includes("\\archive") || name === "archive" || name === "archives") {
112
- if (!result.archive)
113
- result.archive = f.path;
105
+ }
106
+ // Pass 2: exact leaf-name fallback for servers that don't advertise flags
107
+ for (const f of folders) {
108
+ const name = leafName(f);
109
+ if (!result.sent && (name === "sent" || name === "sent items" || name === "sent mail"))
110
+ result.sent = f.path;
111
+ if (!result.trash && (name === "trash" || name === "deleted items" || name === "deleted"))
112
+ result.trash = f.path;
113
+ if (!result.drafts && (name === "drafts" || name === "draft"))
114
+ result.drafts = f.path;
115
+ if (!result.archive && (name === "archive" || name === "archives"))
116
+ result.archive = f.path;
117
+ if (!result.junk && (name === "spam" || name === "junk" || name === "junk email" || name === "junk e-mail")) {
118
+ result.junk = f.path;
119
+ if (!result.spam)
120
+ result.spam = f.path;
114
121
  }
115
122
  }
116
123
  return result;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bobfrankston/iflow-direct",
3
- "version": "0.1.8",
3
+ "version": "0.1.9",
4
4
  "description": "Direct IMAP client — transport-agnostic, no Node.js dependencies, browser-ready",
5
5
  "main": "index.js",
6
6
  "types": "index.ts",