@gera2ld/imap 0.0.1 → 0.0.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 (2) hide show
  1. package/dist/index.js +520 -623
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -1,642 +1,539 @@
1
- import { EventEmitter as S } from "node:events";
2
- import * as T from "node:net";
3
- import * as $ from "node:tls";
4
- const b = "=", w = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
5
- let g;
6
- function I() {
7
- return g ||= O(w), g;
1
+ import { EventEmitter as e } from "node:events";
2
+ import * as t from "node:net";
3
+ import * as n from "node:tls";
4
+ //#region ../../node_modules/.pnpm/@gera2ld+common@file+packages+common/node_modules/@gera2ld/common/dist/index.js
5
+ var r = "=", i = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", a;
6
+ function o() {
7
+ return a ||= s(i), a;
8
8
  }
9
- function O(r) {
10
- const t = new Array(255);
11
- for (let e = 0; e < r.length; e += 1)
12
- t[r.charCodeAt(e)] = e;
13
- return t;
9
+ function s(e) {
10
+ let t = Array(255);
11
+ for (let n = 0; n < e.length; n += 1) t[e.charCodeAt(n)] = n;
12
+ return t;
14
13
  }
15
- function M(r, t) {
16
- const e = t[r];
17
- if (e == null) throw new Error("Unable to parse base64 string.");
18
- return e;
14
+ function c(e, t) {
15
+ let n = t[e];
16
+ if (n == null) throw Error("Unable to parse base64 string.");
17
+ return n;
19
18
  }
20
- function D(r, t, e) {
21
- let s = "", n = 0;
22
- for (; n < r.length; ) {
23
- const o = r[n++], i = r[n++], a = r[n++];
24
- if (s += t[o >> 2], s += t[(o & 3) << 4 | (i || 0) >> 4], i == null ? s += b : s += t[(i & 15) << 2 | (a || 0) >> 6], a == null) {
25
- s += b;
26
- break;
27
- }
28
- s += t[a & 63];
29
- }
30
- return s;
19
+ function l(e, t, n) {
20
+ let i = "", a = 0;
21
+ for (; a < e.length;) {
22
+ let o = e[a++], s = e[a++], c = e[a++];
23
+ if (i += t[o >> 2], i += t[(o & 3) << 4 | (s || 0) >> 4], s == null ? n && (i += r) : i += t[(s & 15) << 2 | (c || 0) >> 6], c == null) {
24
+ n && (i += r);
25
+ break;
26
+ }
27
+ i += t[c & 63];
28
+ }
29
+ return i;
31
30
  }
32
- function v(r, t) {
33
- let e = r.length;
34
- for (; e > 0 && r[e - 1] === "="; ) e -= 1;
35
- const s = Math.ceil(e / 4), n = new Uint8Array(3 * s);
36
- let o = 0, i = 0, a = 0;
37
- for (i = 0; i < s; i += 1) {
38
- let l = 0;
39
- for (a = 0; a < 4; a += 1) {
40
- o = i * 4 + a;
41
- const f = r[o];
42
- if (!f || f === b) break;
43
- l |= M(r.charCodeAt(o), t) << (3 - a) * 6;
44
- }
45
- n[i * 3] = l >> 16, n[i * 3 + 1] = l >> 8 & 255, n[i * 3 + 2] = l & 255;
46
- }
47
- if (o < e - 1 || a === 1) throw new Error("Invalid base64 string");
48
- let c = 3 * s;
49
- for (; a < 4; a += 1) c -= 1;
50
- return n.subarray(0, c);
31
+ function u(e, t) {
32
+ let n = e.length;
33
+ for (; n > 0 && e[n - 1] === "=";) --n;
34
+ let i = Math.ceil(n / 4), a = new Uint8Array(3 * i), o = 0, s = 0, l = 0;
35
+ for (s = 0; s < i; s += 1) {
36
+ let n = 0;
37
+ for (l = 0; l < 4; l += 1) {
38
+ o = s * 4 + l;
39
+ let i = e[o];
40
+ if (!i || i === r) break;
41
+ n |= c(e.charCodeAt(o), t) << (3 - l) * 6;
42
+ }
43
+ a[s * 3] = n >> 16, a[s * 3 + 1] = n >> 8 & 255, a[s * 3 + 2] = n & 255;
44
+ }
45
+ if (o < n - 1 || l === 1) throw Error("Invalid base64 string");
46
+ let u = 3 * i;
47
+ for (; l < 4; l += 1) --u;
48
+ return a.subarray(0, u);
51
49
  }
52
- function U(r) {
53
- return D(r, w);
50
+ function d(e) {
51
+ return l(e, i, !0);
54
52
  }
55
- function y(r) {
56
- return v(r, I());
53
+ function f(e) {
54
+ return u(e, o());
57
55
  }
58
- function N(r) {
59
- return new TextEncoder().encode(r);
56
+ function p(e) {
57
+ return new TextEncoder().encode(e);
60
58
  }
61
- function E(r) {
62
- return new TextDecoder().decode(r);
59
+ function m(e) {
60
+ return new TextDecoder().decode(e);
63
61
  }
64
- function m() {
65
- const r = {
66
- status: "pending"
67
- };
68
- return r.promise = new Promise((t, e) => {
69
- r.resolve = t, r.reject = e;
70
- }), r.promise.then(
71
- () => {
72
- r.status = "resolved";
73
- },
74
- () => {
75
- r.status = "rejected";
76
- }
77
- ), r;
62
+ function h() {
63
+ let e = { status: "pending" };
64
+ return e.promise = new Promise((t, n) => {
65
+ e.resolve = t, e.reject = n;
66
+ }), e.promise.then(() => {
67
+ e.status = "resolved";
68
+ }, () => {
69
+ e.status = "rejected";
70
+ }), e;
78
71
  }
79
- const F = new Uint8Array([13, 10]);
80
- class L {
81
- buffer = new Uint8Array(0);
82
- requests = [];
83
- isClosed = !1;
84
- read(t = 8192) {
85
- const e = m();
86
- return this.requests.push({
87
- deferred: e,
88
- handle: () => {
89
- const s = Math.min(t, this.buffer.length), n = this.buffer.subarray(0, s);
90
- return this.buffer = this.buffer.subarray(s), e.resolve(n), !0;
91
- }
92
- }), this.processBuffer(), e.promise;
93
- }
94
- readExact(t) {
95
- const e = m();
96
- return this.requests.push({
97
- deferred: e,
98
- handle: () => {
99
- if (t > this.buffer.length) return !1;
100
- const s = this.buffer.subarray(0, t);
101
- return this.buffer = this.buffer.subarray(t), e.resolve(s), !0;
102
- }
103
- }), this.processBuffer(), e.promise;
104
- }
105
- readUntil(t = F) {
106
- typeof t == "string" && (t = N(t));
107
- const e = m();
108
- return this.requests.push({
109
- deferred: e,
110
- handle: () => {
111
- const s = P(this.buffer, t);
112
- if (s < 0) return !1;
113
- const n = s + t.length, o = this.buffer.subarray(0, n);
114
- return this.buffer = this.buffer.subarray(n), e.resolve(o), !0;
115
- }
116
- }), this.processBuffer(), e.promise;
117
- }
118
- feed(t) {
119
- if (this.isClosed) throw new Error("Buffer is closed");
120
- this.buffer = B(this.buffer, t), this.processBuffer();
121
- }
122
- close() {
123
- this.isClosed = !0, this.processBuffer();
124
- }
125
- processBuffer() {
126
- for (; this.requests.length; ) {
127
- const t = this.requests[0];
128
- if (!t.handle())
129
- if (this.isClosed)
130
- t.deferred.reject(new Error("Buffer is closed"));
131
- else break;
132
- this.requests.shift();
133
- }
134
- }
135
- }
136
- function B(r, t) {
137
- const e = new Uint8Array(r.length + t.length);
138
- return e.set(r, 0), e.set(t, r.length), e;
139
- }
140
- function P(r, t) {
141
- if (!t.length) return 0;
142
- for (let e = 0; e <= r.length - t.length; e += 1) {
143
- let s;
144
- for (s = 0; s < t.length && r[e + s] === t[s]; s += 1)
145
- ;
146
- if (s === t.length) return e;
147
- }
148
- return -1;
149
- }
150
- class R {
151
- options;
152
- _socket = null;
153
- reader = new L();
154
- isConnected = !1;
155
- constructor(t) {
156
- this.options = t;
157
- }
158
- async connect(t) {
159
- return new Promise((e, s) => {
160
- const n = this.options.secure ? $.connect({
161
- host: this.options.host,
162
- port: this.options.port,
163
- rejectUnauthorized: !1
164
- }) : T.connect({
165
- host: this.options.host,
166
- port: this.options.port
167
- });
168
- this._socket = n, n.on("data", (o) => {
169
- this.reader.feed(o);
170
- }), n.on("connect", () => {
171
- this.isConnected = !0, e();
172
- }), n.on("error", (o) => {
173
- t?.onError?.(o), s(o);
174
- }), n.on("close", () => {
175
- this.isConnected = !1, t?.onClose?.();
176
- });
177
- });
178
- }
179
- write(t) {
180
- if (!this._socket)
181
- throw new Error("Not connected");
182
- this._socket.write(t);
183
- }
184
- disconnect() {
185
- this._socket && (this._socket.end(), this._socket.destroy(), this._socket = null);
186
- }
72
+ var g = new Uint8Array([13, 10]), _ = class {
73
+ buffer = new Uint8Array();
74
+ requests = [];
75
+ isClosed = !1;
76
+ read(e = 8192) {
77
+ let t = h();
78
+ return this.requests.push({
79
+ deferred: t,
80
+ handle: () => {
81
+ let n = Math.min(e, this.buffer.length), r = this.buffer.subarray(0, n);
82
+ return this.buffer = this.buffer.subarray(n), t.resolve(r), !0;
83
+ }
84
+ }), this.processBuffer(), t.promise;
85
+ }
86
+ readExact(e) {
87
+ let t = h();
88
+ return this.requests.push({
89
+ deferred: t,
90
+ handle: () => {
91
+ if (e > this.buffer.length) return !1;
92
+ let n = this.buffer.subarray(0, e);
93
+ return this.buffer = this.buffer.subarray(e), t.resolve(n), !0;
94
+ }
95
+ }), this.processBuffer(), t.promise;
96
+ }
97
+ readUntil(e = g) {
98
+ typeof e == "string" && (e = p(e));
99
+ let t = h();
100
+ return this.requests.push({
101
+ deferred: t,
102
+ handle: () => {
103
+ let n = y(this.buffer, e);
104
+ if (n < 0) return !1;
105
+ let r = n + e.length, i = this.buffer.subarray(0, r);
106
+ return this.buffer = this.buffer.subarray(r), t.resolve(i), !0;
107
+ }
108
+ }), this.processBuffer(), t.promise;
109
+ }
110
+ feed(e) {
111
+ if (this.isClosed) throw Error("Buffer is closed");
112
+ this.buffer = v(this.buffer, e), this.processBuffer();
113
+ }
114
+ close() {
115
+ this.isClosed = !0, this.processBuffer();
116
+ }
117
+ processBuffer() {
118
+ for (; this.requests.length;) {
119
+ let e = this.requests[0];
120
+ if (!e.handle()) if (this.isClosed) e.deferred.reject(/* @__PURE__ */ Error("Buffer is closed"));
121
+ else break;
122
+ this.requests.shift();
123
+ }
124
+ }
125
+ };
126
+ function v(e, t) {
127
+ let n = new Uint8Array(e.length + t.length);
128
+ return n.set(e, 0), n.set(t, e.length), n;
187
129
  }
188
- class j {
189
- decode(t) {
190
- return new TextDecoder().decode(t);
191
- }
192
- async *parse(t) {
193
- for (; ; ) {
194
- const e = await t.readUntil();
195
- if (e.length === 0) break;
196
- const s = this.decode(e);
197
- if (s.startsWith("+ "))
198
- yield {
199
- symbol: "+",
200
- text: s.slice(2)
201
- };
202
- else {
203
- const n = s.split(" ");
204
- let o = "", i, a;
205
- s.startsWith("* ") ? (o = "*", n.shift(), isNaN(+n[0]) ? a = n.shift() : a = n.splice(1, 1)[0]) : (i = n.shift(), a = n.shift());
206
- let c = n.join(" ");
207
- const l = {
208
- command: a,
209
- stack: [[]],
210
- brackets: []
211
- };
212
- for (; c; ) {
213
- this.parseAttributes(l, c);
214
- const f = l.stack.at(-1), h = f.at(-1), p = typeof h == "string" && h.match(/^\{(\d+)\}\r\n$/);
215
- if (p) {
216
- const x = +p[1], A = this.decode(await t.readExact(x));
217
- f.pop(), f.push(A);
218
- }
219
- if (!l.brackets.length) break;
220
- c = this.decode(await t.readUntil());
221
- }
222
- yield o ? {
223
- symbol: o,
224
- command: a,
225
- attributes: l.stack[0]
226
- } : {
227
- symbol: "",
228
- tag: i,
229
- command: a,
230
- attributes: l.stack[0]
231
- };
232
- }
233
- }
234
- }
235
- parseAttributes(t, e) {
236
- let s = !1, n = !0, o = !1, i = "";
237
- const a = () => {
238
- if (!i) return;
239
- let c;
240
- isNaN(+i) ? i.toLowerCase() === "nil" ? c = null : c = i : c = +i, t.stack.at(-1).push(c), i = "";
241
- };
242
- for (let c = 0; c < e.length; c += 1) {
243
- const l = e[c];
244
- if (s)
245
- l === '"' ? (s = !1, a()) : (l === "\\" && (c += 1), i += e[c]);
246
- else if (l === '"')
247
- s = !0;
248
- else if (l === " ")
249
- a();
250
- else if ((n ? "([" : "(").includes(l)) {
251
- t.brackets.push(l);
252
- const f = [];
253
- t.stack.at(-1).push(f), t.stack.push(f), l === "[" && (o = !0);
254
- } else if ((o ? "])" : ")").includes(l)) {
255
- const f = t.brackets.pop();
256
- if (!["()", "[]"].includes(f + l))
257
- throw new Error("Invalid bracket");
258
- a(), t.stack.pop(), l === "]" && (o = !1);
259
- } else
260
- i += e[c];
261
- n = !1;
262
- }
263
- a();
264
- }
130
+ function y(e, t) {
131
+ if (!t.length) return 0;
132
+ for (let n = 0; n <= e.length - t.length; n += 1) {
133
+ let r;
134
+ for (r = 0; r < t.length && e[n + r] === t[r]; r += 1);
135
+ if (r === t.length) return n;
136
+ }
137
+ return -1;
265
138
  }
266
- const k = [
267
- "Jan",
268
- "Feb",
269
- "Mar",
270
- "Apr",
271
- "May",
272
- "Jun",
273
- "Jul",
274
- "Aug",
275
- "Sep",
276
- "Oct",
277
- "Nov",
278
- "Dec"
139
+ //#endregion
140
+ //#region src/connector.ts
141
+ var b = class {
142
+ options;
143
+ _socket = null;
144
+ reader = new _();
145
+ isConnected = !1;
146
+ constructor(e) {
147
+ this.options = e;
148
+ }
149
+ async connect(e) {
150
+ return new Promise((r, i) => {
151
+ let a = this.options.secure ? n.connect({
152
+ host: this.options.host,
153
+ port: this.options.port,
154
+ rejectUnauthorized: !1
155
+ }) : t.connect({
156
+ host: this.options.host,
157
+ port: this.options.port
158
+ });
159
+ this._socket = a, a.on("data", (e) => {
160
+ this.reader.feed(e);
161
+ }), a.on("connect", () => {
162
+ this.isConnected = !0, r();
163
+ }), a.on("error", (t) => {
164
+ e?.onError?.(t), i(t);
165
+ }), a.on("close", () => {
166
+ this.isConnected = !1, e?.onClose?.();
167
+ });
168
+ });
169
+ }
170
+ write(e) {
171
+ if (!this._socket) throw Error("Not connected");
172
+ this._socket.write(e);
173
+ }
174
+ disconnect() {
175
+ this._socket &&= (this._socket.end(), this._socket.destroy(), null);
176
+ }
177
+ }, x = class {
178
+ decode(e) {
179
+ return new TextDecoder().decode(e);
180
+ }
181
+ async *parse(e) {
182
+ for (;;) {
183
+ let t = await e.readUntil();
184
+ if (t.length === 0) break;
185
+ let n = this.decode(t);
186
+ if (n.startsWith("+ ")) yield {
187
+ symbol: "+",
188
+ text: n.slice(2)
189
+ };
190
+ else {
191
+ let t = n.split(" "), r = "", i, a;
192
+ n.startsWith("* ") ? (r = "*", t.shift(), a = isNaN(+t[0]) ? t.shift() : t.splice(1, 1)[0]) : (i = t.shift(), a = t.shift());
193
+ let o = t.join(" "), s = {
194
+ command: a,
195
+ stack: [[]],
196
+ brackets: []
197
+ };
198
+ for (; o;) {
199
+ this.parseAttributes(s, o);
200
+ let t = s.stack.at(-1), n = t.at(-1), r = typeof n == "string" && n.match(/^\{(\d+)\}\r\n$/);
201
+ if (r) {
202
+ let n = +r[1], i = this.decode(await e.readExact(n));
203
+ t.pop(), t.push(i);
204
+ }
205
+ if (!s.brackets.length) break;
206
+ o = this.decode(await e.readUntil());
207
+ }
208
+ yield r ? {
209
+ symbol: r,
210
+ command: a,
211
+ attributes: s.stack[0]
212
+ } : {
213
+ symbol: "",
214
+ tag: i,
215
+ command: a,
216
+ attributes: s.stack[0]
217
+ };
218
+ }
219
+ }
220
+ }
221
+ parseAttributes(e, t) {
222
+ let n = !1, r = !0, i = !1, a = "", o = () => {
223
+ if (!a) return;
224
+ let t;
225
+ t = isNaN(+a) ? a.toLowerCase() === "nil" ? null : a : +a, e.stack.at(-1).push(t), a = "";
226
+ };
227
+ for (let s = 0; s < t.length; s += 1) {
228
+ let c = t[s];
229
+ if (n) c === "\"" ? (n = !1, o()) : (c === "\\" && (s += 1), a += t[s]);
230
+ else if (c === "\"") n = !0;
231
+ else if (c === " ") o();
232
+ else if ((r ? "([" : "(").includes(c)) {
233
+ e.brackets.push(c);
234
+ let t = [];
235
+ e.stack.at(-1).push(t), e.stack.push(t), c === "[" && (i = !0);
236
+ } else if ((i ? "])" : ")").includes(c)) {
237
+ let t = e.brackets.pop();
238
+ if (!["()", "[]"].includes(t + c)) throw Error("Invalid bracket");
239
+ o(), e.stack.pop(), c === "]" && (i = !1);
240
+ } else a += t[s];
241
+ r = !1;
242
+ }
243
+ o();
244
+ }
245
+ }, S = [
246
+ "Jan",
247
+ "Feb",
248
+ "Mar",
249
+ "Apr",
250
+ "May",
251
+ "Jun",
252
+ "Jul",
253
+ "Aug",
254
+ "Sep",
255
+ "Oct",
256
+ "Nov",
257
+ "Dec"
279
258
  ];
280
- function H(r) {
281
- const t = String(r.getDate()).padStart(2, "0"), e = k[r.getMonth()], s = r.getFullYear();
282
- return `${t}-${e}-${s}`;
283
- }
284
- function z(r) {
285
- const t = String(r.getDate()).padStart(2, "0"), e = k[r.getMonth()], s = r.getFullYear(), n = String(r.getHours()).padStart(2, "0"), o = String(r.getMinutes()).padStart(2, "0"), i = String(r.getSeconds()).padStart(2, "0"), a = -r.getTimezoneOffset(), c = a >= 0 ? "+" : "-", l = Math.abs(a), f = String(Math.floor(l / 60)).padStart(
286
- 2,
287
- "0"
288
- ), h = String(l % 60).padStart(2, "0"), p = `${c}${f}${h}`;
289
- return `${t}-${e}-${s} ${n}:${o}:${i} ${p}`;
259
+ function C(e) {
260
+ return `${String(e.getDate()).padStart(2, "0")}-${S[e.getMonth()]}-${e.getFullYear()}`;
290
261
  }
291
- function d(r) {
292
- return !Array.isArray(r) || r.length < 4 ? {} : {
293
- name: C(r[0] ?? "") || void 0,
294
- adl: r[1] ?? void 0,
295
- mailbox: r[2] ?? void 0,
296
- host: r[3] ?? void 0
297
- };
262
+ function w(e) {
263
+ let t = String(e.getDate()).padStart(2, "0"), n = S[e.getMonth()], r = e.getFullYear(), i = String(e.getHours()).padStart(2, "0"), a = String(e.getMinutes()).padStart(2, "0"), o = String(e.getSeconds()).padStart(2, "0"), s = -e.getTimezoneOffset(), c = s >= 0 ? "+" : "-", l = Math.abs(s);
264
+ return `${t}-${n}-${r} ${i}:${a}:${o} ${`${c}${String(Math.floor(l / 60)).padStart(2, "0")}${String(l % 60).padStart(2, "0")}`}`;
298
265
  }
299
- function C(r) {
300
- return r.split(/\s+/).map((t) => {
301
- if (t.startsWith("=?") && t.endsWith("?=")) {
302
- const [e, s, n] = t.slice(2, -2).split("?");
303
- if (e.toLowerCase() !== "utf-8")
304
- throw new Error(`Charset is not supported: ${e}`);
305
- let o;
306
- if (s === "B")
307
- o = y(n);
308
- else {
309
- const i = [];
310
- for (let a = 0; a < n.length; a += 1)
311
- if (n[a] === "=") {
312
- const c = n.slice(a + 1, a + 3);
313
- i.push(parseInt(c, 16)), a += 2;
314
- } else
315
- i.push(n.charCodeAt(a));
316
- o = new Uint8Array(i);
317
- }
318
- return E(o);
319
- }
320
- return t;
321
- }).join("");
266
+ function T(e) {
267
+ return !Array.isArray(e) || e.length < 4 ? {} : {
268
+ name: E(e[0] ?? "") || void 0,
269
+ adl: e[1] ?? void 0,
270
+ mailbox: e[2] ?? void 0,
271
+ host: e[3] ?? void 0
272
+ };
322
273
  }
323
- const u = { uid: !0 };
324
- function _(r, t) {
325
- const e = `user=${r}auth=Bearer ${t}`;
326
- return U(new TextEncoder().encode(e));
274
+ function E(e) {
275
+ return e.split(/\s+/).map((e) => {
276
+ if (e.startsWith("=?") && e.endsWith("?=")) {
277
+ let [t, n, r] = e.slice(2, -2).split("?");
278
+ if (t.toLowerCase() !== "utf-8") throw Error(`Charset is not supported: ${t}`);
279
+ let i;
280
+ if (n === "B") i = f(r);
281
+ else {
282
+ let e = [];
283
+ for (let t = 0; t < r.length; t += 1) if (r[t] === "=") {
284
+ let n = r.slice(t + 1, t + 3);
285
+ e.push(parseInt(n, 16)), t += 2;
286
+ } else e.push(r.charCodeAt(t));
287
+ i = new Uint8Array(e);
288
+ }
289
+ return m(i);
290
+ }
291
+ return e;
292
+ }).join("");
327
293
  }
328
- class G extends S {
329
- options;
330
- connector;
331
- parser;
332
- tagCounter = 0;
333
- tagPrefix = "A";
334
- pendingCommand = null;
335
- constructor(t) {
336
- super(), this.options = t, this.parser = new j(), this.connector = new R({
337
- host: t.host,
338
- port: t.port,
339
- secure: t.secure
340
- });
341
- }
342
- nextTag() {
343
- return this.tagPrefix + this.tagCounter++;
344
- }
345
- /**
346
- * Register a pending command and return a promise that resolves when the response arrives.
347
- * Throws if another command is already pending.
348
- */
349
- registerPendingCommand(t, e, s) {
350
- if (this.pendingCommand)
351
- throw new Error(
352
- `Cannot execute ${e} command while another operation ("${this.pendingCommand.command}") is in progress.`
353
- );
354
- const n = m();
355
- return this.pendingCommand = {
356
- tag: t,
357
- command: e,
358
- callback: s,
359
- deferred: n
360
- }, n.promise.finally(() => {
361
- this.pendingCommand = null;
362
- }), n.promise;
363
- }
364
- /**
365
- * Send a raw command to the server.
366
- */
367
- sendCommand(t) {
368
- this.emit("send", t), this.connector.write(`${t}\r
369
- `);
370
- }
371
- /**
372
- * Execute a command and wait for its response.
373
- * Processes matching untagged responses as they arrive via onResponse, filters out nulls.
374
- * Non-matching responses are emitted as events.
375
- *
376
- * @param command - The IMAP command to send (e.g., 'LIST "" "*"', 'UID SEARCH ALL')
377
- * @param matchCommand - Optional command name to match in responses (e.g., 'LIST', 'SEARCH', 'FETCH'). Required when onResponse is provided.
378
- * @param onResponse - Optional function to transform each matching untagged response as it arrives. Return null to skip.
379
- * @returns Promise with tagged response and array of transformed items
380
- */
381
- async executeCommand(t, e) {
382
- const s = this.nextTag(), n = t.split(" ");
383
- let o = n.shift();
384
- if (o === "UID" && (o = n.shift()), !o) throw new Error("Invalid command");
385
- const i = this.registerPendingCommand(s, o, e);
386
- this.sendCommand(`${s} ${t}`), await i;
387
- }
388
- /**
389
- * Handle incoming data lines from the connector.
390
- */
391
- handleResponse(t) {
392
- this.emit("response", t);
393
- const e = this.pendingCommand, s = () => {
394
- t.symbol === "*" && this.handleAsyncNotification(t);
395
- };
396
- if (e) {
397
- const n = () => {
398
- t.symbol === "" && t.tag === e.tag ? t.command === "OK" ? e.deferred.resolve() : e.deferred.reject(new Error(t.command)) : s();
399
- };
400
- e.callback ? e.callback({
401
- response: t,
402
- pending: e,
403
- next: s,
404
- fallback: n
405
- }) : n();
406
- } else
407
- s();
408
- }
409
- handleAsyncNotification(t) {
410
- switch (t.command) {
411
- case "EXISTS":
412
- this.emit("newmail", { count: t.attributes[0] });
413
- break;
414
- case "EXPUNGE":
415
- this.emit("expunge", { seq: t.attributes[0] });
416
- break;
417
- case "RECENT":
418
- this.emit("recent", { count: t.attributes[0] });
419
- break;
420
- case "FLAGS":
421
- this.emit("flags", { flags: t.attributes[0] });
422
- break;
423
- }
424
- }
425
- parseFetchAttributes(t, e) {
426
- const s = { seq: t };
427
- if (Array.isArray(e))
428
- for (let n = 0; n < e.length; n += 2) {
429
- const o = e[n]?.toUpperCase(), i = e[n + 1];
430
- switch (o) {
431
- case "UID":
432
- s.uid = i;
433
- break;
434
- case "FLAGS":
435
- s.flags = Array.isArray(i) ? i : [i];
436
- break;
437
- case "ENVELOPE":
438
- s.envelope = {
439
- date: i?.[0],
440
- subject: C(i?.[1]),
441
- from: i?.[2]?.map(d) ?? [],
442
- sender: i?.[3]?.map(d) ?? [],
443
- replyTo: i?.[4]?.map(d) ?? [],
444
- to: i?.[5]?.map(d) ?? [],
445
- cc: i?.[6]?.map(d) ?? [],
446
- bcc: i?.[7]?.map(d) ?? [],
447
- inReplyTo: i?.[8],
448
- messageId: i?.[9]
449
- };
450
- break;
451
- case "INTERNALDATE":
452
- s.internalDate = i;
453
- break;
454
- case "RFC822.SIZE":
455
- s.size = i;
456
- break;
457
- case "BODY[]":
458
- s.body = i;
459
- break;
460
- case "RFC822.TEXT":
461
- case "BODY[TEXT]":
462
- s.text = i;
463
- break;
464
- case "BODY[HTML]":
465
- s.html = i;
466
- break;
467
- default:
468
- s.attributes ||= {}, s.attributes[o] = i;
469
- break;
470
- }
471
- }
472
- return s;
473
- }
474
- /**
475
- * Connect to the IMAP server and authenticate.
476
- */
477
- async connect() {
478
- await this.connector.connect({
479
- onError: (t) => this.emit("error", t),
480
- onClose: () => this.emit("close")
481
- }), this.processResponses(), await this.registerPendingCommand("", "", ({ response: t, pending: e, next: s }) => {
482
- t.symbol === "*" && t.command === "OK" ? e.deferred.resolve() : s();
483
- }), await this.login();
484
- }
485
- async processResponses() {
486
- for await (const t of this.parser.parse(this.connector.reader))
487
- this.handleResponse(t);
488
- }
489
- /**
490
- * Authenticate with the server.
491
- */
492
- async login() {
493
- if (this.options.accessToken) {
494
- const t = typeof this.options.accessToken == "function" ? await this.options.accessToken() : this.options.accessToken, e = _(this.options.user, t);
495
- await this.executeCommand(
496
- `AUTHENTICATE XOAUTH2 ${e}`,
497
- ({ response: s, pending: n, fallback: o }) => {
498
- s.symbol === "+" ? n.deferred.reject(
499
- new Error(E(y(s.text)))
500
- ) : o();
501
- }
502
- );
503
- } else if (this.options.password)
504
- await this.executeCommand(
505
- `LOGIN "${this.options.user}" "${this.options.password}"`
506
- );
507
- else
508
- throw new Error("Either password or accessToken must be provided");
509
- }
510
- /**
511
- * List all mailboxes.
512
- */
513
- async listMailboxes() {
514
- const t = [];
515
- return await this.executeCommand('LIST "" "*"', ({ response: e, fallback: s }) => {
516
- if (e.symbol === "*" && e.command === "LIST") {
517
- const n = {
518
- attributes: e.attributes[0],
519
- delimiter: e.attributes[1],
520
- name: e.attributes[2]
521
- };
522
- t.push(n);
523
- } else
524
- s();
525
- }), t;
526
- }
527
- /**
528
- * Select a mailbox.
529
- */
530
- async selectMailbox(t) {
531
- await this.executeCommand(`SELECT "${t}"`);
532
- }
533
- /**
534
- * Search messages.
535
- */
536
- async searchMessages(t, e) {
537
- const n = { ...u, ...e }.uid ? "UID " : "";
538
- let o = [];
539
- return await this.executeCommand(
540
- `${n}SEARCH ${t}`,
541
- ({ response: i, fallback: a }) => {
542
- i.symbol === "*" && i.command === "SEARCH" ? o = [...o, ...i.attributes] : a();
543
- }
544
- ), o;
545
- }
546
- /**
547
- * Fetch messages.
548
- */
549
- async fetchMessages(t, e = ["UID", "ENVELOPE", "FLAGS"], s) {
550
- const i = `${{ ...u, ...s }.uid ? "UID " : ""}FETCH ${t} (${e.join(" ")})`, a = [];
551
- return await this.executeCommand(i, ({ response: c, fallback: l }) => {
552
- if (c.symbol === "*" && c.command === "FETCH") {
553
- const f = c.attributes[0], h = c.attributes[1];
554
- a.push(this.parseFetchAttributes(f, h));
555
- } else
556
- l();
557
- }), a;
558
- }
559
- /**
560
- * Set flags on messages.
561
- */
562
- async setFlags(t, e, s, n) {
563
- const i = { ...u, ...n }.uid ? "UID " : "", a = s.join(" ");
564
- await this.executeCommand(
565
- `${i}STORE ${t} ${e}FLAGS (${a})`
566
- );
567
- }
568
- /**
569
- * Mark messages as seen.
570
- */
571
- async markAsSeen(t, e) {
572
- const s = { ...u, ...e };
573
- await this.setFlags(t, "+", ["\\Seen"], s);
574
- }
575
- /**
576
- * Mark messages as unseen.
577
- */
578
- async markAsUnseen(t, e) {
579
- const s = { ...u, ...e };
580
- await this.setFlags(t, "-", ["\\Seen"], s);
581
- }
582
- /**
583
- * Delete messages.
584
- */
585
- async deleteMessages(t, e) {
586
- const s = { ...u, ...e };
587
- await this.setFlags(t, "+", ["\\Deleted"], s), await this.executeCommand("EXPUNGE");
588
- }
589
- /**
590
- * Move messages to another mailbox.
591
- */
592
- async moveMessages(t, e, s) {
593
- const o = { ...u, ...s }.uid ? "UID " : "";
594
- await this.executeCommand(
595
- `${o}MOVE ${t} "${e}"`
596
- );
597
- }
598
- /**
599
- * Start IDLE mode.
600
- */
601
- async startIdle() {
602
- const t = m();
603
- let e = !1;
604
- return this.executeCommand("IDLE", ({ response: s, pending: n, fallback: o }) => {
605
- if (e)
606
- o();
607
- else if (s.symbol === "+")
608
- e = !0, t.resolve();
609
- else {
610
- const i = new Error(s.command);
611
- t.reject(i), n.deferred.resolve(t.promise);
612
- }
613
- }), t.promise;
614
- }
615
- /**
616
- * Stop IDLE mode.
617
- */
618
- async stopIdle() {
619
- if (this.pendingCommand?.command !== "IDLE")
620
- throw new Error("IDLE mode is not active");
621
- return this.sendCommand("DONE"), this.pendingCommand.deferred.promise;
622
- }
623
- /**
624
- * Disconnect from the server.
625
- */
626
- async disconnect() {
627
- if (this.pendingCommand?.command === "IDLE")
628
- try {
629
- await this.stopIdle();
630
- } catch {
631
- }
632
- this.connector.disconnect();
633
- }
294
+ //#endregion
295
+ //#region src/client.ts
296
+ var D = { uid: !0 };
297
+ function O(e, t) {
298
+ let n = `user=${e}\x01auth=Bearer ${t}\x01\x01`;
299
+ return d(new TextEncoder().encode(n));
634
300
  }
635
- export {
636
- G as ImapClient,
637
- j as ImapParser,
638
- C as decodeRfc2047,
639
- H as formatDateForImap,
640
- z as formatDateTimeForImap,
641
- d as parseAddress
301
+ var k = class extends e {
302
+ options;
303
+ connector;
304
+ parser;
305
+ tagCounter = 0;
306
+ tagPrefix = "A";
307
+ pendingCommand = null;
308
+ constructor(e) {
309
+ super(), this.options = e, this.parser = new x(), this.connector = new b({
310
+ host: e.host,
311
+ port: e.port,
312
+ secure: e.secure
313
+ });
314
+ }
315
+ nextTag() {
316
+ return this.tagPrefix + this.tagCounter++;
317
+ }
318
+ registerPendingCommand(e, t, n) {
319
+ if (this.pendingCommand) throw Error(`Cannot execute ${t} command while another operation ("${this.pendingCommand.command}") is in progress.`);
320
+ let r = h();
321
+ return this.pendingCommand = {
322
+ tag: e,
323
+ command: t,
324
+ callback: n,
325
+ deferred: r
326
+ }, r.promise.finally(() => {
327
+ this.pendingCommand = null;
328
+ }), r.promise;
329
+ }
330
+ sendCommand(e) {
331
+ this.emit("send", e), this.connector.write(`${e}\r\n`);
332
+ }
333
+ async executeCommand(e, t) {
334
+ let n = this.nextTag(), r = e.split(" "), i = r.shift();
335
+ if (i === "UID" && (i = r.shift()), !i) throw Error("Invalid command");
336
+ let a = this.registerPendingCommand(n, i, t);
337
+ this.sendCommand(`${n} ${e}`), await a;
338
+ }
339
+ handleResponse(e) {
340
+ this.emit("response", e);
341
+ let t = this.pendingCommand, n = () => {
342
+ e.symbol === "*" && this.handleAsyncNotification(e);
343
+ };
344
+ if (t) {
345
+ let r = () => {
346
+ e.symbol === "" && e.tag === t.tag ? e.command === "OK" ? t.deferred.resolve() : t.deferred.reject(Error(e.command)) : n();
347
+ };
348
+ t.callback ? t.callback({
349
+ response: e,
350
+ pending: t,
351
+ next: n,
352
+ fallback: r
353
+ }) : r();
354
+ } else n();
355
+ }
356
+ handleAsyncNotification(e) {
357
+ switch (e.command) {
358
+ case "EXISTS":
359
+ this.emit("newmail", { count: e.attributes[0] });
360
+ break;
361
+ case "EXPUNGE":
362
+ this.emit("expunge", { seq: e.attributes[0] });
363
+ break;
364
+ case "RECENT":
365
+ this.emit("recent", { count: e.attributes[0] });
366
+ break;
367
+ case "FLAGS":
368
+ this.emit("flags", { flags: e.attributes[0] });
369
+ break;
370
+ }
371
+ }
372
+ parseFetchAttributes(e, t) {
373
+ let n = { seq: e };
374
+ if (Array.isArray(t)) for (let e = 0; e < t.length; e += 2) {
375
+ let r = t[e]?.toUpperCase(), i = t[e + 1];
376
+ switch (r) {
377
+ case "UID":
378
+ n.uid = i;
379
+ break;
380
+ case "FLAGS":
381
+ n.flags = Array.isArray(i) ? i : [i];
382
+ break;
383
+ case "ENVELOPE":
384
+ n.envelope = {
385
+ date: i?.[0],
386
+ subject: E(i?.[1]),
387
+ from: i?.[2]?.map(T) ?? [],
388
+ sender: i?.[3]?.map(T) ?? [],
389
+ replyTo: i?.[4]?.map(T) ?? [],
390
+ to: i?.[5]?.map(T) ?? [],
391
+ cc: i?.[6]?.map(T) ?? [],
392
+ bcc: i?.[7]?.map(T) ?? [],
393
+ inReplyTo: i?.[8],
394
+ messageId: i?.[9]
395
+ };
396
+ break;
397
+ case "INTERNALDATE":
398
+ n.internalDate = i;
399
+ break;
400
+ case "RFC822.SIZE":
401
+ n.size = i;
402
+ break;
403
+ case "BODY[]":
404
+ n.body = i;
405
+ break;
406
+ case "RFC822.TEXT":
407
+ case "BODY[TEXT]":
408
+ n.text = i;
409
+ break;
410
+ case "BODY[HTML]":
411
+ n.html = i;
412
+ break;
413
+ default:
414
+ n.attributes ||= {}, n.attributes[r] = i;
415
+ break;
416
+ }
417
+ }
418
+ return n;
419
+ }
420
+ async connect() {
421
+ await this.connector.connect({
422
+ onError: (e) => this.emit("error", e),
423
+ onClose: () => this.emit("close")
424
+ }), this.processResponses(), await this.registerPendingCommand("", "", ({ response: e, pending: t, next: n }) => {
425
+ e.symbol === "*" && e.command === "OK" ? t.deferred.resolve() : n();
426
+ }), await this.login();
427
+ }
428
+ async processResponses() {
429
+ for await (let e of this.parser.parse(this.connector.reader)) this.handleResponse(e);
430
+ }
431
+ async login() {
432
+ if (this.options.accessToken) {
433
+ let e = typeof this.options.accessToken == "function" ? await this.options.accessToken() : this.options.accessToken, t = O(this.options.user, e);
434
+ await this.executeCommand(`AUTHENTICATE XOAUTH2 ${t}`, ({ response: e, pending: t, fallback: n }) => {
435
+ e.symbol === "+" ? t.deferred.reject(Error(m(f(e.text)))) : n();
436
+ });
437
+ } else if (this.options.password) await this.executeCommand(`LOGIN "${this.options.user}" "${this.options.password}"`);
438
+ else throw Error("Either password or accessToken must be provided");
439
+ }
440
+ async listMailboxes() {
441
+ let e = [];
442
+ return await this.executeCommand("LIST \"\" \"*\"", ({ response: t, fallback: n }) => {
443
+ if (t.symbol === "*" && t.command === "LIST") {
444
+ let n = {
445
+ attributes: t.attributes[0],
446
+ delimiter: t.attributes[1],
447
+ name: t.attributes[2]
448
+ };
449
+ e.push(n);
450
+ } else n();
451
+ }), e;
452
+ }
453
+ async selectMailbox(e) {
454
+ await this.executeCommand(`SELECT "${e}"`);
455
+ }
456
+ async searchMessages(e, t) {
457
+ let n = {
458
+ ...D,
459
+ ...t
460
+ }.uid ? "UID " : "", r = [];
461
+ return await this.executeCommand(`${n}SEARCH ${e}`, ({ response: e, fallback: t }) => {
462
+ e.symbol === "*" && e.command === "SEARCH" ? r = [...r, ...e.attributes] : t();
463
+ }), r;
464
+ }
465
+ async fetchMessages(e, t = [
466
+ "UID",
467
+ "ENVELOPE",
468
+ "FLAGS"
469
+ ], n) {
470
+ let r = `${{
471
+ ...D,
472
+ ...n
473
+ }.uid ? "UID " : ""}FETCH ${e} (${t.join(" ")})`, i = [];
474
+ return await this.executeCommand(r, ({ response: e, fallback: t }) => {
475
+ if (e.symbol === "*" && e.command === "FETCH") {
476
+ let t = e.attributes[0], n = e.attributes[1];
477
+ i.push(this.parseFetchAttributes(t, n));
478
+ } else t();
479
+ }), i;
480
+ }
481
+ async setFlags(e, t, n, r) {
482
+ let i = {
483
+ ...D,
484
+ ...r
485
+ }.uid ? "UID " : "", a = n.join(" ");
486
+ await this.executeCommand(`${i}STORE ${e} ${t}FLAGS (${a})`);
487
+ }
488
+ async markAsSeen(e, t) {
489
+ let n = {
490
+ ...D,
491
+ ...t
492
+ };
493
+ await this.setFlags(e, "+", ["\\Seen"], n);
494
+ }
495
+ async markAsUnseen(e, t) {
496
+ let n = {
497
+ ...D,
498
+ ...t
499
+ };
500
+ await this.setFlags(e, "-", ["\\Seen"], n);
501
+ }
502
+ async deleteMessages(e, t) {
503
+ let n = {
504
+ ...D,
505
+ ...t
506
+ };
507
+ await this.setFlags(e, "+", ["\\Deleted"], n), await this.executeCommand("EXPUNGE");
508
+ }
509
+ async moveMessages(e, t, n) {
510
+ let r = {
511
+ ...D,
512
+ ...n
513
+ }.uid ? "UID " : "";
514
+ await this.executeCommand(`${r}MOVE ${e} "${t}"`);
515
+ }
516
+ async startIdle() {
517
+ let e = h(), t = !1;
518
+ return this.executeCommand("IDLE", ({ response: n, pending: r, fallback: i }) => {
519
+ if (t) i();
520
+ else if (n.symbol === "+") t = !0, e.resolve();
521
+ else {
522
+ let t = Error(n.command);
523
+ e.reject(t), r.deferred.resolve(e.promise);
524
+ }
525
+ }), e.promise;
526
+ }
527
+ async stopIdle() {
528
+ if (this.pendingCommand?.command !== "IDLE") throw Error("IDLE mode is not active");
529
+ return this.sendCommand("DONE"), this.pendingCommand.deferred.promise;
530
+ }
531
+ async disconnect() {
532
+ if (this.pendingCommand?.command === "IDLE") try {
533
+ await this.stopIdle();
534
+ } catch {}
535
+ this.connector.disconnect();
536
+ }
642
537
  };
538
+ //#endregion
539
+ export { k as ImapClient, x as ImapParser, E as decodeRfc2047, C as formatDateForImap, w as formatDateTimeForImap, T as parseAddress };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gera2ld/imap",
3
- "version": "0.0.1",
3
+ "version": "0.0.3",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": {
@@ -20,7 +20,7 @@
20
20
  "registry": "https://registry.npmjs.org/"
21
21
  },
22
22
  "devDependencies": {
23
- "@gera2ld/common": "^0.0.1"
23
+ "@gera2ld/common": "^0.0.3"
24
24
  },
25
25
  "scripts": {
26
26
  "clean": "del-cli dist tsconfig.tsbuildinfo",