imapflow 1.4.9 → 1.6.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/.github/workflows/test.yml +20 -0
- package/.release-please-manifest.json +1 -1
- package/CHANGELOG.md +22 -0
- package/CLAUDE.md +3 -5
- package/lib/commands/fetch.js +18 -14
- package/lib/commands/idle.js +197 -104
- package/lib/commands/list.js +19 -8
- package/lib/commands/quota.js +3 -0
- package/lib/commands/select.js +5 -0
- package/lib/commands/status.js +10 -1
- package/lib/connection-deadline.js +98 -0
- package/lib/handler/imap-compiler.js +20 -14
- package/lib/handler/imap-stream.js +141 -50
- package/lib/handler/limits.js +43 -0
- package/lib/handler/token-parser.js +38 -1
- package/lib/imap-flow.d.ts +47 -5
- package/lib/imap-flow.js +594 -283
- package/lib/proxy-connection.js +393 -98
- package/lib/special-use.js +660 -51
- package/lib/tools.js +52 -3
- package/package.json +2 -2
- package/test/commands-branches-test.js +17 -1
- package/test/commands-integration-test.js +353 -2
- package/test/connection-edge-cases-test.js +4 -40
- package/test/fixtures/fake-timers.js +115 -0
- package/test/handler-branches-test.js +4 -28
- package/test/idle-polling-test.js +349 -0
- package/test/imap-compiler-test.js +85 -0
- package/test/imap-flow-compress-test.js +12 -0
- package/test/imap-flow-coverage-test.js +3 -3
- package/test/imap-flow-fetch-download-test.js +56 -0
- package/test/imap-flow-internals-test.js +23 -0
- package/test/imap-flow-proxy-paths-test.js +151 -0
- package/test/imap-flow-secure-test.js +182 -9
- package/test/imap-flow-server-test.js +229 -0
- package/test/imap-parser-test.js +112 -1
- package/test/imap-stream-test.js +46 -0
- package/test/integration/README.md +17 -5
- package/test/integration/rev2-live-test.js +125 -0
- package/test/integration/run-rev2-tests.sh +14 -0
- package/test/parser-limits-test.js +274 -0
- package/test/proxy-connection-test.js +553 -442
- package/test/reliability-improvements-test.js +87 -0
- package/test/search-compiler-test.js +17 -0
- package/test/special-use-test.js +337 -0
- package/test/tag-correlation-test.js +333 -0
- package/test/timer-policy-test.js +214 -0
- package/test/tools-test.js +42 -4
package/lib/imap-flow.d.ts
CHANGED
|
@@ -42,7 +42,22 @@ export interface ImapFlowOptions {
|
|
|
42
42
|
verifyOnly?: boolean;
|
|
43
43
|
/** If true and verifyOnly is set, lists mailboxes */
|
|
44
44
|
includeMailboxes?: boolean;
|
|
45
|
-
/**
|
|
45
|
+
/**
|
|
46
|
+
* Proxy URL. Supports HTTP CONNECT (http:, https:) and SOCKS (socks:, socks4:, socks4a:,
|
|
47
|
+
* socks5:) proxies. IPv6 proxy endpoints are given in URL form, e.g. `socks5://[2001:db8::1]:1080`.
|
|
48
|
+
*
|
|
49
|
+
* DNS behaviour depends on the proxy protocol:
|
|
50
|
+
* - `http:`/`https:` - the destination hostname is sent to the proxy unresolved
|
|
51
|
+
* - `socks4:` - destination hostnames are resolved locally to IPv4 (SOCKS4 has no IPv6
|
|
52
|
+
* destination address type; IPv6 destinations are rejected)
|
|
53
|
+
* - `socks4a:` - destination hostnames are sent to the proxy for remote DNS (IPv6
|
|
54
|
+
* destinations are rejected)
|
|
55
|
+
* - `socks:`/`socks5:` - destination hostnames are sent to the proxy for remote DNS, IPv4
|
|
56
|
+
* and IPv6 literals are passed through
|
|
57
|
+
*
|
|
58
|
+
* The proxy endpoint itself is never resolved by ImapFlow; a hostname endpoint is handed to
|
|
59
|
+
* Node as-is. Proxy DNS and negotiation run inside `connectionTimeout`.
|
|
60
|
+
*/
|
|
46
61
|
proxy?: string;
|
|
47
62
|
/** If true, then use QRESYNC instead of CONDSTORE. EXPUNGE notifications will include UID instead of sequence number */
|
|
48
63
|
qresync?: boolean;
|
|
@@ -56,7 +71,11 @@ export interface ImapFlowOptions {
|
|
|
56
71
|
disableAutoEnable?: boolean;
|
|
57
72
|
/** If true, do not enable IMAP4rev2 mode even if the server supports it */
|
|
58
73
|
disableIMAP4rev2?: boolean;
|
|
59
|
-
/**
|
|
74
|
+
/**
|
|
75
|
+
* How long to wait for a usable transport, covering DNS resolution, proxy negotiation and the
|
|
76
|
+
* TCP/TLS handshake as a single budget. Defaults to 90 seconds. An expiry in any of those
|
|
77
|
+
* phases rejects with error code `CONNECT_TIMEOUT`.
|
|
78
|
+
*/
|
|
60
79
|
connectionTimeout?: number;
|
|
61
80
|
/** How long to wait for the greeting. Defaults to 16 seconds */
|
|
62
81
|
greetingTimeout?: number;
|
|
@@ -65,12 +84,17 @@ export interface ImapFlowOptions {
|
|
|
65
84
|
/**
|
|
66
85
|
* Maximum allowed length in bytes of a single response line (a response without a literal).
|
|
67
86
|
* Guards against a malicious or broken server that never sends a line terminator. Defaults to
|
|
68
|
-
* 1GB.
|
|
87
|
+
* 1GB. The line terminator counts towards the limit and a line exactly at the limit is
|
|
88
|
+
* accepted. Exceeding it is terminal: the connection fails with error code `LineTooLarge` and
|
|
89
|
+
* no further input is parsed.
|
|
69
90
|
*/
|
|
70
91
|
maxLineLength?: number;
|
|
71
92
|
/**
|
|
72
93
|
* Maximum allowed size in bytes of a single IMAP literal block. Bounds peak memory allocation
|
|
73
|
-
* against a malicious or broken server announcing an oversized literal. Defaults to 1GB.
|
|
94
|
+
* against a malicious or broken server announcing an oversized literal. Defaults to 1GB. A
|
|
95
|
+
* literal exactly at the limit is accepted. Exceeding it is terminal: the connection fails
|
|
96
|
+
* with error code `LiteralTooLarge`, and neither the marker line nor any byte of the rejected
|
|
97
|
+
* literal is interpreted as protocol.
|
|
74
98
|
*/
|
|
75
99
|
maxLiteralSize?: number;
|
|
76
100
|
/**
|
|
@@ -184,6 +208,8 @@ export interface ListResponse {
|
|
|
184
208
|
flags: Set<string>;
|
|
185
209
|
/** One of special-use flags (if applicable) */
|
|
186
210
|
specialUse?: string;
|
|
211
|
+
/** How specialUse was determined: "user" (from specialUseHints), "extension" (SPECIAL-USE or XLIST flag reported by the server) or "name" (matched against known localized folder names) */
|
|
212
|
+
specialUseSource?: 'user' | 'extension' | 'name';
|
|
187
213
|
/** True if mailbox was found from the output of LIST command */
|
|
188
214
|
listed: boolean;
|
|
189
215
|
/** True if the mailbox is subscribed - reported by LSUB or by LIST RETURN (SUBSCRIBED) on LIST-EXTENDED/IMAP4rev2 servers */
|
|
@@ -207,6 +233,10 @@ export interface ListOptions {
|
|
|
207
233
|
unseen?: boolean;
|
|
208
234
|
/** If true request last known modseq value */
|
|
209
235
|
highestModseq?: boolean;
|
|
236
|
+
/** If true request total mailbox size in octets (requires STATUS=SIZE or IMAP4rev2) */
|
|
237
|
+
size?: boolean;
|
|
238
|
+
/** If true request count of messages with \Deleted flag (requires IMAP4rev2) */
|
|
239
|
+
deleted?: boolean;
|
|
210
240
|
};
|
|
211
241
|
/** Set specific paths as special use folders */
|
|
212
242
|
specialUseHints?: {
|
|
@@ -218,6 +248,8 @@ export interface ListOptions {
|
|
|
218
248
|
junk?: string;
|
|
219
249
|
/** Path to "Drafts" folder */
|
|
220
250
|
drafts?: string;
|
|
251
|
+
/** Path to "Archive" folder */
|
|
252
|
+
archive?: string;
|
|
221
253
|
};
|
|
222
254
|
}
|
|
223
255
|
|
|
@@ -282,6 +314,10 @@ export interface StatusObject {
|
|
|
282
314
|
unseen?: number;
|
|
283
315
|
/** Last known modseq value (if CONDSTORE extension is enabled) */
|
|
284
316
|
highestModseq?: bigint;
|
|
317
|
+
/** Total size of the mailbox in octets (only if requested and the server supports STATUS=SIZE or IMAP4rev2) */
|
|
318
|
+
size?: number;
|
|
319
|
+
/** Count of messages with \Deleted flag (only if requested and IMAP4rev2 is active) */
|
|
320
|
+
deleted?: number;
|
|
285
321
|
}
|
|
286
322
|
|
|
287
323
|
export type SequenceString = string | number | bigint;
|
|
@@ -493,6 +529,8 @@ export interface FetchMessageObject {
|
|
|
493
529
|
internalDate?: Date | string;
|
|
494
530
|
/** A Map of message body parts where key is requested part identifier and value is a Buffer */
|
|
495
531
|
bodyParts?: Map<string, Buffer>;
|
|
532
|
+
/** Part identifiers from bodyParts that arrived via FETCH BINARY, i.e. with the content-transfer-encoding already decoded by the server */
|
|
533
|
+
binaryParts?: Set<string>;
|
|
496
534
|
/** Requested header lines as Buffer */
|
|
497
535
|
headers?: Buffer;
|
|
498
536
|
/** Account unique ID for this email */
|
|
@@ -755,6 +793,10 @@ export class ImapFlow extends EventEmitter {
|
|
|
755
793
|
uidValidity?: boolean;
|
|
756
794
|
unseen?: boolean;
|
|
757
795
|
highestModseq?: boolean;
|
|
796
|
+
/** Requires STATUS=SIZE or IMAP4rev2 */
|
|
797
|
+
size?: boolean;
|
|
798
|
+
/** Requires IMAP4rev2 */
|
|
799
|
+
deleted?: boolean;
|
|
758
800
|
}
|
|
759
801
|
): Promise<StatusObject>;
|
|
760
802
|
|
|
@@ -861,7 +903,7 @@ export class ImapFlow extends EventEmitter {
|
|
|
861
903
|
/** Mailbox was opened */
|
|
862
904
|
on(event: 'mailboxOpen', listener: (mailbox: MailboxObject) => void): this;
|
|
863
905
|
|
|
864
|
-
/** Mailbox was closed */
|
|
906
|
+
/** Mailbox was closed, either explicitly or because the connection went away while a mailbox was still selected */
|
|
865
907
|
on(event: 'mailboxClose', listener: (mailbox: MailboxObject) => void): this;
|
|
866
908
|
|
|
867
909
|
/** Log event if emitLogs=true */
|