imapflow 1.0.171 → 1.0.172

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/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.0.172](https://github.com/postalsys/imapflow/compare/v1.0.171...v1.0.172) (2025-01-03)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * **password-auth:** Added option auth.loginMethod to set specific authentication method ('LOGIN', 'AUTH=PLAIN', 'AUTH=LOGIN') ([ce3c339](https://github.com/postalsys/imapflow/commit/ce3c33908f5ad445b1a2fdcf2dfcbd4859413cf7))
9
+
3
10
  ## [1.0.171](https://github.com/postalsys/imapflow/compare/v1.0.170...v1.0.171) (2024-12-05)
4
11
 
5
12
 
@@ -137,7 +137,7 @@ async function authPlain(connection, username, password) {
137
137
  }
138
138
 
139
139
  // Authenticates user using LOGIN
140
- module.exports = async (connection, username, { accessToken, password }) => {
140
+ module.exports = async (connection, username, { accessToken, password, loginMethod }) => {
141
141
  if (connection.state !== connection.states.NOT_AUTHENTICATED) {
142
142
  // nothing to do here
143
143
  return;
@@ -151,10 +151,11 @@ module.exports = async (connection, username, { accessToken, password }) => {
151
151
  }
152
152
 
153
153
  if (password) {
154
- if (connection.capabilities.has('AUTH=PLAIN')) {
154
+ if ((!loginMethod && connection.capabilities.has('AUTH=PLAIN')) || loginMethod === 'AUTH=PLAIN') {
155
155
  return await authPlain(connection, username, password);
156
156
  }
157
- if (connection.capabilities.has('AUTH=LOGIN')) {
157
+
158
+ if ((!loginMethod && connection.capabilities.has('AUTH=LOGIN')) || loginMethod === 'AUTH=LOGIN') {
158
159
  return await authLogin(connection, username, password);
159
160
  }
160
161
  }
package/lib/imap-flow.js CHANGED
@@ -116,48 +116,110 @@ class ImapFlow extends EventEmitter {
116
116
  static version = packageInfo.version;
117
117
 
118
118
  /**
119
- * @param {Object} options IMAP connection options
120
- * @param {String} options.host Hostname of the IMAP server
121
- * @param {Number} options.port Port number for the IMAP server
122
- * @param {Boolean} [options.secure=false] Should the connection be established immediately and directly over TLS? Typically on port 993.
123
- * @param {Boolean} [options.doSTARTTLS=undefined] Should the connection be established using STARTTLS?
124
- * * If `true`, the connection is first established as unencrypted and then upgraded to TLS using STARTTLS, before authentication.
125
- * If the server does not advertize the `STARTTLS` `CAPABILITY`, or the upgrade fails for other reasons, then the connection fails.
126
- * Note: The combination `secure=true` (direct TLS) and `doSTARTTLS=true` is invalid.
127
- * * If `false`, then STARTTLS will not be used, even if the server advertizes it in IMAP `CAPABILITY`.
128
- * This helps with servers that have a broken TLS configuration.
129
- * If `doSTARTTLS=false` and `secure=false`, then a plain unencrypted socket is used.
130
- * Be sure to clearly warn the user about the consequences.
131
- * * If `undefined` (default) and `secure=false` (default), the connection is upgraded using STARTTLS before authentication, /only if possible/ .
132
- * If not possible, the connection will use an unencrypted plain socket.
133
- * This can mean TLS is used under normal circumstances, but a serious attacker can force an unencrypted connection and steal passwords,
134
- * called "downgrade attack". This can lead to a false sense of security. Be sure to warn the user.
135
- * @param {String} [options.servername] Servername for SNI (or when host is set to an IP address)
136
- * @param {Boolean} [options.disableCompression=false] if `true` then client does not try to use COMPRESS=DEFLATE extension
137
- * @param {Object} options.auth Authentication options. Authentication is requested automatically during <code>connect()</code>
138
- * @param {String} options.auth.user Usename
139
- * @param {String} [options.auth.pass] Password, if using regular authentication
140
- * @param {String} [options.auth.accessToken] OAuth2 Access Token, if using OAuth2 authentication
141
- * @param {IdInfoObject} [options.clientInfo] Client identification info
142
- * @param {Boolean} [options.disableAutoIdle=false] if `true` then IDLE is not started automatically. Useful if you only need to perform specific tasks over the connection
143
- * @param {Object} [options.tls] Additional TLS options (see [Node.js TLS connect](https://nodejs.org/api/tls.html#tls_tls_connect_options_callback) for all available options)
144
- * @param {Boolean} [options.tls.rejectUnauthorized=true] if `false` then client accepts self-signed and expired certificates from the server
145
- * @param {String} [options.tls.minVersion=TLSv1.2] To improvde security you might need to use something newer, eg *'TLSv1.2'*
146
- * @param {Number} [options.tls.minDHSize=1024] Minimum size of the DH parameter in bits to accept a TLS connection
147
- * @param {Object} [options.logger] Custom logger instance with `debug(obj)`, `info(obj)`, `warn(obj)` and `error(obj)` methods. If not provided then ImapFlow logs to console using pino format. Can be disabled by setting to `false`
148
- * @param {Boolean} [options.logRaw=false] If true then log data read from and written to socket encoded in base64
149
- * @param {Boolean} [options.emitLogs=false] If `true` then in addition of sending data to logger, ImapFlow emits 'log' events with the same data
150
- * @param {Boolean} [options.verifyOnly=false] If `true` then logs out automatically after successful authentication
151
- * @param {String} [options.proxy] Optional proxy URL. Supports HTTP CONNECT (`http://`, `https://`) and SOCKS (`socks://`, `socks4://`, `socks5://`) proxies
152
- * @param {Boolean} [options.qresync=false] If true, then enables QRESYNC support. EXPUNGE notifications will include `uid` property instead of `seq`
153
- * @param {Number} [options.maxIdleTime] If set, then breaks and restarts IDLE every maxIdleTime ms
154
- * @param {String} [options.missingIdleCommand="NOOP"] Which command to use if server does not support IDLE
155
- * @param {Boolean} [options.disableBinary=false] If true, then ignores the BINARY extension when making FETCH and APPEND calls
156
- * @param {Boolean} [options.disableAutoEnable] Do not enable supported extensions by default
157
- * @param {Number} [options.connectionTimeout=90000] how many milliseconds to wait for the connection to establish (default is 90 seconds)
158
- * @param {Number} [options.greetingTimeout=16000] how many milliseconds to wait for the greeting after connection is established (default is 16 seconds)
159
- * @param {Number} [options.socketTimeout=300000] how many milliseconds of inactivity to allow (default is 5 minutes)
119
+ * IMAP connection options
120
+ *
121
+ * @property {String} host
122
+ * Hostname of the IMAP server.
123
+ *
124
+ * @property {Number} port
125
+ * Port number for the IMAP server.
126
+ *
127
+ * @property {Boolean} [secure=false]
128
+ * If `true`, establishes the connection directly over TLS (commonly on port 993).
129
+ * If `false`, a plain (unencrypted) connection is used first and, if possible, the connection is upgraded to STARTTLS.
130
+ *
131
+ * @property {Boolean} [doSTARTTLS=undefined]
132
+ * Determines whether to upgrade the connection to TLS via STARTTLS:
133
+ * - **true**: Start unencrypted and upgrade to TLS using STARTTLS before authentication.
134
+ * The connection fails if the server does not support STARTTLS or the upgrade fails.
135
+ * Note that `secure=true` combined with `doSTARTTLS=true` is invalid.
136
+ * - **false**: Never use STARTTLS, even if the server advertises support.
137
+ * This is useful if the server has a broken TLS setup.
138
+ * Combined with `secure=false`, this results in a fully unencrypted connection.
139
+ * Make sure you warn users about the security risks.
140
+ * - **undefined** (default): If `secure=false` (default), attempt to upgrade to TLS via STARTTLS before authentication if the server supports it. If not supported, continue unencrypted. This may expose the connection to a downgrade attack.
141
+ *
142
+ * @property {String} [servername]
143
+ * Server name for SNI or when using an IP address as `host`.
144
+ *
145
+ * @property {Boolean} [disableCompression=false]
146
+ * If `true`, the client does not attempt to use the COMPRESS=DEFLATE extension.
147
+ *
148
+ * @property {Object} auth
149
+ * Authentication options. Authentication occurs automatically during {@link connect}.
150
+ *
151
+ * @property {String} auth.user
152
+ * Username for authentication.
153
+ *
154
+ * @property {String} [auth.pass]
155
+ * Password for regular authentication.
156
+ *
157
+ * @property {String} [auth.accessToken]
158
+ * OAuth2 access token, if using OAuth2 authentication.
159
+ *
160
+ * @property {String} [auth.loginMethod]
161
+ * Optional login method for password-based authentication (e.g., "LOGIN", "AUTH=LOGIN", or "AUTH=PLAIN").
162
+ * If not set, ImapFlow chooses based on available mechanisms.
163
+ *
164
+ * @property {IdInfoObject} [clientInfo]
165
+ * Client identification info sent to the server (via the ID command).
166
+ *
167
+ * @property {Boolean} [disableAutoIdle=false]
168
+ * If `true`, do not start IDLE automatically. Useful when only specific operations are needed.
169
+ *
170
+ * @property {Object} [tls]
171
+ * Additional TLS options. For details, see [Node.js TLS connect](https://nodejs.org/api/tls.html#tls_tls_connect_options_callback).
172
+ *
173
+ * @property {Boolean} [tls.rejectUnauthorized=true]
174
+ * If `false`, allows self-signed or expired certificates.
175
+ *
176
+ * @property {String} [tls.minVersion='TLSv1.2']
177
+ * Minimum accepted TLS version (e.g., `'TLSv1.2'`).
178
+ *
179
+ * @property {Number} [tls.minDHSize=1024]
180
+ * Minimum size (in bits) of the DH parameter for TLS connections.
181
+ *
182
+ * @property {Object|Boolean} [logger]
183
+ * Custom logger instance with `debug(obj)`, `info(obj)`, `warn(obj)`, and `error(obj)` methods.
184
+ * If `false`, logging is disabled. If not provided, ImapFlow logs to console in [pino format](https://getpino.io/).
185
+ *
186
+ * @property {Boolean} [logRaw=false]
187
+ * If `true`, logs all raw data (read and written) in base64 encoding. You can pipe such logs to [eerawlog](https://github.com/postalsys/eerawlog) command for readable output.
188
+ *
189
+ * @property {Boolean} [emitLogs=false]
190
+ * If `true`, emits `'log'` events with the same data passed to the logger.
191
+ *
192
+ * @property {Boolean} [verifyOnly=false]
193
+ * If `true`, disconnects after successful authentication without performing other actions.
194
+ *
195
+ * @property {String} [proxy]
196
+ * Proxy URL. Supports HTTP CONNECT (`http://`, `https://`) and SOCKS (`socks://`, `socks4://`, `socks5://`).
197
+ *
198
+ * @property {Boolean} [qresync=false]
199
+ * If `true`, enables QRESYNC support so that EXPUNGE notifications include `uid` instead of `seq`.
200
+ *
201
+ * @property {Number} [maxIdleTime]
202
+ * If set, breaks and restarts IDLE every `maxIdleTime` milliseconds.
203
+ *
204
+ * @property {String} [missingIdleCommand="NOOP"]
205
+ * Command to use if the server does not support IDLE.
206
+ *
207
+ * @property {Boolean} [disableBinary=false]
208
+ * If `true`, ignores the BINARY extension for FETCH and APPEND operations.
209
+ *
210
+ * @property {Boolean} [disableAutoEnable=false]
211
+ * If `true`, do not automatically enable supported IMAP extensions.
212
+ *
213
+ * @property {Number} [connectionTimeout=90000]
214
+ * Maximum time (in milliseconds) to wait for the connection to establish. Defaults to 90 seconds.
215
+ *
216
+ * @property {Number} [greetingTimeout=16000]
217
+ * Maximum time (in milliseconds) to wait for the server greeting after a connection is established. Defaults to 16 seconds.
218
+ *
219
+ * @property {Number} [socketTimeout=300000]
220
+ * Maximum period of inactivity (in milliseconds) before terminating the connection. Defaults to 5 minutes.
160
221
  */
222
+
161
223
  constructor(options) {
162
224
  super({ captureRejections: true });
163
225
 
@@ -277,10 +339,6 @@ class ImapFlow extends EventEmitter {
277
339
  */
278
340
  this.idling = false;
279
341
 
280
- /**
281
- * If `true` then in addition of sending data to logger, ImapFlow emits 'log' events with the same data
282
- * @type {Boolean}
283
- */
284
342
  this.emitLogs = !!this.options.emitLogs;
285
343
  // ordering number for emitted logs
286
344
  this.lo = 0;
@@ -986,11 +1044,13 @@ class ImapFlow extends EventEmitter {
986
1044
 
987
1045
  this.expectCapabilityUpdate = true;
988
1046
 
1047
+ let loginMethod = (this.options.auth.loginMethod || '').toString().trim().toUpperCase();
1048
+
989
1049
  if (this.options.auth.accessToken) {
990
1050
  this.authenticated = await this.run('AUTHENTICATE', this.options.auth.user, { accessToken: this.options.auth.accessToken });
991
1051
  } else if (this.options.auth.pass) {
992
- if (this.capabilities.has('AUTH=LOGIN') || this.capabilities.has('AUTH=PLAIN')) {
993
- this.authenticated = await this.run('AUTHENTICATE', this.options.auth.user, { password: this.options.auth.pass });
1052
+ if ((this.capabilities.has('AUTH=LOGIN') || this.capabilities.has('AUTH=PLAIN')) && loginMethod !== 'LOGIN') {
1053
+ this.authenticated = await this.run('AUTHENTICATE', this.options.auth.user, { password: this.options.auth.pass, loginMethod });
994
1054
  } else {
995
1055
  this.authenticated = await this.run('LOGIN', this.options.auth.user, this.options.auth.pass);
996
1056
  }
package/lib/types.d.ts CHANGED
@@ -4,83 +4,50 @@ declare module "imapflow" {
4
4
  import { EventEmitter } from "events";
5
5
 
6
6
  /**
7
- * IMAP client class for accessing IMAP mailboxes
8
- * @param options - IMAP connection options
9
- * @param options.host - Hostname of the IMAP server
10
- * @param options.port - Port number for the IMAP server
11
- * @param [options.secure = false] - Should the connection be established immediately and directly over TLS? Typically on port 993.
12
- * @param [options.doSTARTTLS] - Should the connection be established using STARTTLS?
13
- * * If `true`, the connection is first established as unencrypted and then upgraded to TLS using STARTTLS, before authentication.
14
- * If the server does not advertize the `STARTTLS` `CAPABILITY`, or the upgrade fails for other reasons, then the connection fails.
15
- * Note: The combination `secure=true` (direct TLS) and `doSTARTTLS=true` is invalid.
16
- * * If `false`, then STARTTLS will not be used, even if the server advertizes it in IMAP `CAPABILITY`.
17
- * This helps with servers that have a broken TLS configuration.
18
- * If `doSTARTTLS=false` and `secure=false`, then a plain unencrypted socket is used.
19
- * Be sure to clearly warn the user about the consequences.
20
- * * If `undefined` (default) and `secure=false` (default), the connection is upgraded using STARTTLS before authentication, /only if possible/ .
21
- * If not possible, the connection will use an unencrypted plain socket.
22
- * This can mean TLS is used under normal circumstances, but a serious attacker can force an unencrypted connection and steal passwords,
23
- * called "downgrade attack". This can lead to a false sense of security. Be sure to warn the user.
24
- * @param [options.servername] - Servername for SNI (or when host is set to an IP address)
25
- * @param [options.disableCompression = false] - if `true` then client does not try to use COMPRESS=DEFLATE extension
26
- * @param options.auth - Authentication options. Authentication is requested automatically during <code>connect()</code>
27
- * @param options.auth.user - Usename
28
- * @param [options.auth.pass] - Password, if using regular authentication
29
- * @param [options.auth.accessToken] - OAuth2 Access Token, if using OAuth2 authentication
30
- * @param [options.clientInfo] - Client identification info
31
- * @param [options.disableAutoIdle = false] - if `true` then IDLE is not started automatically. Useful if you only need to perform specific tasks over the connection
32
- * @param [options.tls] - Additional TLS options (see [Node.js TLS connect](https://nodejs.org/api/tls.html#tls_tls_connect_options_callback) for all available options)
33
- * @param [options.tls.rejectUnauthorized = true] - if `false` then client accepts self-signed and expired certificates from the server
34
- * @param [options.tls.minVersion = TLSv1.2] - To improvde security you might need to use something newer, eg *'TLSv1.2'*
35
- * @param [options.tls.minDHSize = 1024] - Minimum size of the DH parameter in bits to accept a TLS connection
36
- * @param [options.logger] - Custom logger instance with `debug(obj)`, `info(obj)`, `warn(obj)` and `error(obj)` methods. If not provided then ImapFlow logs to console using pino format. Can be disabled by setting to `false`
37
- * @param [options.logRaw = false] - If true then log data read from and written to socket encoded in base64
38
- * @param [options.emitLogs = false] - If `true` then in addition of sending data to logger, ImapFlow emits 'log' events with the same data
39
- * @param [options.verifyOnly = false] - If `true` then logs out automatically after successful authentication
40
- * @param [options.proxy] - Optional proxy URL. Supports HTTP CONNECT (`http://`, `https://`) and SOCKS (`socks://`, `socks4://`, `socks5://`) proxies
41
- * @param [options.qresync = false] - If true, then enables QRESYNC support. EXPUNGE notifications will include `uid` property instead of `seq`
42
- * @param [options.maxIdleTime] - If set, then breaks and restarts IDLE every maxIdleTime ms
43
- * @param [options.missingIdleCommand = "NOOP"] - Which command to use if server does not support IDLE
44
- * @param [options.disableBinary = false] - If true, then ignores the BINARY extension when making FETCH and APPEND calls
45
- * @param [options.disableAutoEnable] - Do not enable supported extensions by default
46
- * @param [options.connectionTimeout = 90000] - how many milliseconds to wait for the connection to establish (default is 90 seconds)
47
- * @param [options.greetingTimeout = 16000] - how many milliseconds to wait for the greeting after connection is established (default is 16 seconds)
48
- * @param [options.socketTimeout = 300000] - how many milliseconds of inactivity to allow (default is 5 minutes)
7
+ * IMAP connection options
8
+ * @property host - Hostname of the IMAP server.
9
+ * @property port - Port number for the IMAP server.
10
+ * @property [secure = false] - If `true`, establishes the connection directly over TLS (commonly on port 993).
11
+ * If `false`, a plain (unencrypted) connection is used first and, if possible, the connection is upgraded to STARTTLS.
12
+ * @property [doSTARTTLS] - Determines whether to upgrade the connection to TLS via STARTTLS:
13
+ * - **true**: Start unencrypted and upgrade to TLS using STARTTLS before authentication.
14
+ * The connection fails if the server does not support STARTTLS or the upgrade fails.
15
+ * Note that `secure=true` combined with `doSTARTTLS=true` is invalid.
16
+ * - **false**: Never use STARTTLS, even if the server advertises support.
17
+ * This is useful if the server has a broken TLS setup.
18
+ * Combined with `secure=false`, this results in a fully unencrypted connection.
19
+ * Make sure you warn users about the security risks.
20
+ * - **undefined** (default): If `secure=false` (default), attempt to upgrade to TLS via STARTTLS before authentication if the server supports it. If not supported, continue unencrypted. This may expose the connection to a downgrade attack.
21
+ * @property [servername] - Server name for SNI or when using an IP address as `host`.
22
+ * @property [disableCompression = false] - If `true`, the client does not attempt to use the COMPRESS=DEFLATE extension.
23
+ * @property auth - Authentication options. Authentication occurs automatically during {@link connect}.
24
+ * @property auth.user - Username for authentication.
25
+ * @property [auth.pass] - Password for regular authentication.
26
+ * @property [auth.accessToken] - OAuth2 access token, if using OAuth2 authentication.
27
+ * @property [auth.loginMethod] - Optional login method for password-based authentication (e.g., "LOGIN", "AUTH=LOGIN", or "AUTH=PLAIN").
28
+ * If not set, ImapFlow chooses based on available mechanisms.
29
+ * @property [clientInfo] - Client identification info sent to the server (via the ID command).
30
+ * @property [disableAutoIdle = false] - If `true`, do not start IDLE automatically. Useful when only specific operations are needed.
31
+ * @property [tls] - Additional TLS options. For details, see [Node.js TLS connect](https://nodejs.org/api/tls.html#tls_tls_connect_options_callback).
32
+ * @property [tls.rejectUnauthorized = true] - If `false`, allows self-signed or expired certificates.
33
+ * @property [tls.minVersion = 'TLSv1.2'] - Minimum accepted TLS version (e.g., `'TLSv1.2'`).
34
+ * @property [tls.minDHSize = 1024] - Minimum size (in bits) of the DH parameter for TLS connections.
35
+ * @property [logger] - Custom logger instance with `debug(obj)`, `info(obj)`, `warn(obj)`, and `error(obj)` methods.
36
+ * If `false`, logging is disabled. If not provided, ImapFlow logs to console in [pino format](https://getpino.io/).
37
+ * @property [logRaw = false] - If `true`, logs all raw data (read and written) in base64 encoding. You can pipe such logs to [eerawlog](https://github.com/postalsys/eerawlog) command for readable output.
38
+ * @property [emitLogs = false] - If `true`, emits `'log'` events with the same data passed to the logger.
39
+ * @property [verifyOnly = false] - If `true`, disconnects after successful authentication without performing other actions.
40
+ * @property [proxy] - Proxy URL. Supports HTTP CONNECT (`http://`, `https://`) and SOCKS (`socks://`, `socks4://`, `socks5://`).
41
+ * @property [qresync = false] - If `true`, enables QRESYNC support so that EXPUNGE notifications include `uid` instead of `seq`.
42
+ * @property [maxIdleTime] - If set, breaks and restarts IDLE every `maxIdleTime` milliseconds.
43
+ * @property [missingIdleCommand = "NOOP"] - Command to use if the server does not support IDLE.
44
+ * @property [disableBinary = false] - If `true`, ignores the BINARY extension for FETCH and APPEND operations.
45
+ * @property [disableAutoEnable = false] - If `true`, do not automatically enable supported IMAP extensions.
46
+ * @property [connectionTimeout = 90000] - Maximum time (in milliseconds) to wait for the connection to establish. Defaults to 90 seconds.
47
+ * @property [greetingTimeout = 16000] - Maximum time (in milliseconds) to wait for the server greeting after a connection is established. Defaults to 16 seconds.
48
+ * @property [socketTimeout = 300000] - Maximum period of inactivity (in milliseconds) before terminating the connection. Defaults to 5 minutes.
49
49
  */
50
50
  class ImapFlow extends EventEmitter {
51
- constructor(options: {
52
- host: string;
53
- port: number;
54
- secure?: boolean;
55
- doSTARTTLS?: boolean;
56
- servername?: string;
57
- disableCompression?: boolean;
58
- auth: {
59
- user: string;
60
- pass?: string;
61
- accessToken?: string;
62
- };
63
- clientInfo?: IdInfoObject;
64
- disableAutoIdle?: boolean;
65
- tls?: {
66
- rejectUnauthorized?: boolean;
67
- minVersion?: string;
68
- minDHSize?: number;
69
- };
70
- logger?: any;
71
- logRaw?: boolean;
72
- emitLogs?: boolean;
73
- verifyOnly?: boolean;
74
- proxy?: string;
75
- qresync?: boolean;
76
- maxIdleTime?: number;
77
- missingIdleCommand?: string;
78
- disableBinary?: boolean;
79
- disableAutoEnable?: boolean;
80
- connectionTimeout?: number;
81
- greetingTimeout?: number;
82
- socketTimeout?: number;
83
- });
84
51
  /**
85
52
  * Current module version as a static class property
86
53
  * @property version - Module version
@@ -130,10 +97,6 @@ declare module "imapflow" {
130
97
  * Is current mailbox idling (`true`) or not (`false`)
131
98
  */
132
99
  idling: boolean;
133
- /**
134
- * If `true` then in addition of sending data to logger, ImapFlow emits 'log' events with the same data
135
- */
136
- emitLogs: boolean;
137
100
  /**
138
101
  * Tries to upgrade the connection to TLS using STARTTLS.
139
102
  * @returns true, if the connection is now protected by TLS, either direct TLS or STARTTLS.
@@ -568,6 +531,117 @@ declare module "imapflow" {
568
531
  getMailboxLock(path: string | any[], options?: {
569
532
  readOnly?: boolean;
570
533
  }): Promise<MailboxLockObject>;
534
+ /**
535
+ * Hostname of the IMAP server.
536
+ */
537
+ host: string;
538
+ /**
539
+ * Port number for the IMAP server.
540
+ */
541
+ port: number;
542
+ /**
543
+ * If `true`, establishes the connection directly over TLS (commonly on port 993).
544
+ If `false`, a plain (unencrypted) connection is used first and, if possible, the connection is upgraded to STARTTLS.
545
+ */
546
+ secure?: boolean;
547
+ /**
548
+ * Determines whether to upgrade the connection to TLS via STARTTLS:
549
+ - **true**: Start unencrypted and upgrade to TLS using STARTTLS before authentication.
550
+ The connection fails if the server does not support STARTTLS or the upgrade fails.
551
+ Note that `secure=true` combined with `doSTARTTLS=true` is invalid.
552
+ - **false**: Never use STARTTLS, even if the server advertises support.
553
+ This is useful if the server has a broken TLS setup.
554
+ Combined with `secure=false`, this results in a fully unencrypted connection.
555
+ Make sure you warn users about the security risks.
556
+ - **undefined** (default): If `secure=false` (default), attempt to upgrade to TLS via STARTTLS before authentication if the server supports it. If not supported, continue unencrypted. This may expose the connection to a downgrade attack.
557
+ */
558
+ doSTARTTLS?: boolean;
559
+ /**
560
+ * Server name for SNI or when using an IP address as `host`.
561
+ */
562
+ servername?: string;
563
+ /**
564
+ * If `true`, the client does not attempt to use the COMPRESS=DEFLATE extension.
565
+ */
566
+ disableCompression?: boolean;
567
+ /**
568
+ * Authentication options. Authentication occurs automatically during {@link connect}.
569
+ */
570
+ auth: {
571
+ user: string;
572
+ pass?: string;
573
+ accessToken?: string;
574
+ loginMethod?: string;
575
+ };
576
+ /**
577
+ * Client identification info sent to the server (via the ID command).
578
+ */
579
+ clientInfo?: IdInfoObject;
580
+ /**
581
+ * If `true`, do not start IDLE automatically. Useful when only specific operations are needed.
582
+ */
583
+ disableAutoIdle?: boolean;
584
+ /**
585
+ * Additional TLS options. For details, see [Node.js TLS connect](https://nodejs.org/api/tls.html#tls_tls_connect_options_callback).
586
+ */
587
+ tls?: {
588
+ rejectUnauthorized?: boolean;
589
+ minVersion?: string;
590
+ minDHSize?: number;
591
+ };
592
+ /**
593
+ * Custom logger instance with `debug(obj)`, `info(obj)`, `warn(obj)`, and `error(obj)` methods.
594
+ If `false`, logging is disabled. If not provided, ImapFlow logs to console in [pino format](https://getpino.io/).
595
+ */
596
+ logger?: any | boolean;
597
+ /**
598
+ * If `true`, logs all raw data (read and written) in base64 encoding. You can pipe such logs to [eerawlog](https://github.com/postalsys/eerawlog) command for readable output.
599
+ */
600
+ logRaw?: boolean;
601
+ /**
602
+ * If `true`, emits `'log'` events with the same data passed to the logger.
603
+ */
604
+ emitLogs?: boolean;
605
+ /**
606
+ * If `true`, disconnects after successful authentication without performing other actions.
607
+ */
608
+ verifyOnly?: boolean;
609
+ /**
610
+ * Proxy URL. Supports HTTP CONNECT (`http://`, `https://`) and SOCKS (`socks://`, `socks4://`, `socks5://`).
611
+ */
612
+ proxy?: string;
613
+ /**
614
+ * If `true`, enables QRESYNC support so that EXPUNGE notifications include `uid` instead of `seq`.
615
+ */
616
+ qresync?: boolean;
617
+ /**
618
+ * If set, breaks and restarts IDLE every `maxIdleTime` milliseconds.
619
+ */
620
+ maxIdleTime?: number;
621
+ /**
622
+ * Command to use if the server does not support IDLE.
623
+ */
624
+ missingIdleCommand?: string;
625
+ /**
626
+ * If `true`, ignores the BINARY extension for FETCH and APPEND operations.
627
+ */
628
+ disableBinary?: boolean;
629
+ /**
630
+ * If `true`, do not automatically enable supported IMAP extensions.
631
+ */
632
+ disableAutoEnable?: boolean;
633
+ /**
634
+ * Maximum time (in milliseconds) to wait for the connection to establish. Defaults to 90 seconds.
635
+ */
636
+ connectionTimeout?: number;
637
+ /**
638
+ * Maximum time (in milliseconds) to wait for the server greeting after a connection is established. Defaults to 16 seconds.
639
+ */
640
+ greetingTimeout?: number;
641
+ /**
642
+ * Maximum period of inactivity (in milliseconds) before terminating the connection. Defaults to 5 minutes.
643
+ */
644
+ socketTimeout?: number;
571
645
  }
572
646
  }
573
647
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "imapflow",
3
- "version": "1.0.171",
3
+ "version": "1.0.172",
4
4
  "description": "IMAP Client for Node",
5
5
  "main": "./lib/imap-flow.js",
6
6
  "scripts": {
@@ -32,7 +32,7 @@
32
32
  "@babel/eslint-plugin": "7.25.9",
33
33
  "@babel/plugin-syntax-class-properties": "7.12.13",
34
34
  "@babel/preset-env": "7.26.0",
35
- "@types/node": "22.10.1",
35
+ "@types/node": "22.10.5",
36
36
  "eslint": "8.57.0",
37
37
  "eslint-config-nodemailer": "1.2.0",
38
38
  "eslint-config-prettier": "9.1.0",
@@ -53,7 +53,7 @@
53
53
  "libqp": "2.1.1",
54
54
  "mailsplit": "5.4.2",
55
55
  "nodemailer": "6.9.16",
56
- "pino": "9.5.0",
56
+ "pino": "9.6.0",
57
57
  "socks": "2.8.3"
58
58
  }
59
59
  }
@@ -1006,7 +1006,6 @@ module.exports['IMAP Parser, subfolder square bracket'] = test =>
1006
1006
  module.exports['IMAP Parser, FETCH with full range'] = test =>
1007
1007
  asyncWrapper(test, async test => {
1008
1008
  let parsed = await parser('* 32 FETCH (UID 32 RFC822.SIZE 3991 BODY[2.MIME] "(* 61B literal *)" BODY[2]<0.65536> "(* 6B literal *)")');
1009
- console.log(JSON.stringify(parsed.attributes));
1010
1009
  test.deepEqual(parsed.attributes, [
1011
1010
  {
1012
1011
  type: 'ATOM',
@@ -1061,3 +1060,180 @@ module.exports['IMAP Parser, FETCH with full range'] = test =>
1061
1060
  ]
1062
1061
  ]);
1063
1062
  });
1063
+
1064
+ module.exports['IMAP Parser, FETCH with BODYSTRUCTURE'] = test =>
1065
+ asyncWrapper(test, async test => {
1066
+ let parsed = await parser(
1067
+ '* 1013 FETCH (UID 2986 MODSEQ (4960) BODYSTRUCTURE (("text" "plain" ("charset" "us-ascii") NIL NIL "7bit" 16 1 NIL NIL NIL NIL)("message" "rfc822" ("name" "Tellimuse Microsoft 365 Business Standard arve vaatamine.eml") NIL NIL "7bit" 370684 ("Mon, 16 Dec 2024 03:28:28 +0000" "Tellimuse Microsoft 365 Business Standard arve vaatamine" (("Microsoft" NIL "microsoft-noreply" "microsoft.com")) (("Microsoft" NIL "microsoft-noreply" "microsoft.com")) (("Microsoft" NIL "microsoft-noreply" "microsoft.com")) ((NIL NIL "andris.reinman" "gmail.com")) NIL NIL NIL "<58710631-775f-4c07-96ff-28a776f44d90@az.eastus2.microsoft.com>") ((("text" "plain" ("charset" "utf-8") NIL NIL "quoted-printable" 2866 80 NIL NIL NIL NIL)("text" "html" ("charset" "utf-8") NIL NIL "quoted-printable" 78392 1770 NIL NIL NIL NIL) "alternative" ("boundary" "=-EcWGOW6mwE+0T4lm385OWw==") NIL NIL NIL)("application" "octet-stream" ("name" "52482541500.pdf") NIL NIL "base64" 279430 NIL ("attachment" ("filename" "52482541500.pdf")) NIL NIL) "mixed" ("boundary" "=-1wJq2CLBJ6H+Zk2GPX9FKw==") NIL NIL NIL) 5580 NIL ("attachment" ("filename" "Tellimuse Microsoft 365 Business Standard arve vaatamine.eml")) NIL NIL) "mixed" ("boundary" "Apple-Mail=_F700EE9B-43B1-4EF1-95EE-CAA13391B333") NIL NIL NIL))'
1068
+ );
1069
+
1070
+ test.deepEqual(parsed.attributes, [
1071
+ { type: 'ATOM', value: 'FETCH' },
1072
+ [
1073
+ { type: 'ATOM', value: 'UID' },
1074
+ { type: 'ATOM', value: '2986' },
1075
+ { type: 'ATOM', value: 'MODSEQ' },
1076
+ [{ type: 'ATOM', value: '4960' }],
1077
+ { type: 'ATOM', value: 'BODYSTRUCTURE' },
1078
+ [
1079
+ [
1080
+ { type: 'STRING', value: 'text' },
1081
+ { type: 'STRING', value: 'plain' },
1082
+ [
1083
+ { type: 'STRING', value: 'charset' },
1084
+ { type: 'STRING', value: 'us-ascii' }
1085
+ ],
1086
+ null,
1087
+ null,
1088
+ { type: 'STRING', value: '7bit' },
1089
+ { type: 'ATOM', value: '16' },
1090
+ { type: 'ATOM', value: '1' },
1091
+ null,
1092
+ null,
1093
+ null,
1094
+ null
1095
+ ],
1096
+ [
1097
+ { type: 'STRING', value: 'message' },
1098
+ { type: 'STRING', value: 'rfc822' },
1099
+ [
1100
+ { type: 'STRING', value: 'name' },
1101
+ { type: 'STRING', value: 'Tellimuse Microsoft 365 Business Standard arve vaatamine.eml' }
1102
+ ],
1103
+ null,
1104
+ null,
1105
+ { type: 'STRING', value: '7bit' },
1106
+ { type: 'ATOM', value: '370684' },
1107
+ [
1108
+ { type: 'STRING', value: 'Mon, 16 Dec 2024 03:28:28 +0000' },
1109
+ { type: 'STRING', value: 'Tellimuse Microsoft 365 Business Standard arve vaatamine' },
1110
+ [
1111
+ [
1112
+ { type: 'STRING', value: 'Microsoft' },
1113
+ null,
1114
+ { type: 'STRING', value: 'microsoft-noreply' },
1115
+ { type: 'STRING', value: 'microsoft.com' }
1116
+ ]
1117
+ ],
1118
+ [
1119
+ [
1120
+ { type: 'STRING', value: 'Microsoft' },
1121
+ null,
1122
+ { type: 'STRING', value: 'microsoft-noreply' },
1123
+ { type: 'STRING', value: 'microsoft.com' }
1124
+ ]
1125
+ ],
1126
+ [
1127
+ [
1128
+ { type: 'STRING', value: 'Microsoft' },
1129
+ null,
1130
+ { type: 'STRING', value: 'microsoft-noreply' },
1131
+ { type: 'STRING', value: 'microsoft.com' }
1132
+ ]
1133
+ ],
1134
+ [[null, null, { type: 'STRING', value: 'andris.reinman' }, { type: 'STRING', value: 'gmail.com' }]],
1135
+ null,
1136
+ null,
1137
+ null,
1138
+ { type: 'STRING', value: '<58710631-775f-4c07-96ff-28a776f44d90@az.eastus2.microsoft.com>' }
1139
+ ],
1140
+ [
1141
+ [
1142
+ [
1143
+ { type: 'STRING', value: 'text' },
1144
+ { type: 'STRING', value: 'plain' },
1145
+ [
1146
+ { type: 'STRING', value: 'charset' },
1147
+ { type: 'STRING', value: 'utf-8' }
1148
+ ],
1149
+ null,
1150
+ null,
1151
+ { type: 'STRING', value: 'quoted-printable' },
1152
+ { type: 'ATOM', value: '2866' },
1153
+ { type: 'ATOM', value: '80' },
1154
+ null,
1155
+ null,
1156
+ null,
1157
+ null
1158
+ ],
1159
+ [
1160
+ { type: 'STRING', value: 'text' },
1161
+ { type: 'STRING', value: 'html' },
1162
+ [
1163
+ { type: 'STRING', value: 'charset' },
1164
+ { type: 'STRING', value: 'utf-8' }
1165
+ ],
1166
+ null,
1167
+ null,
1168
+ { type: 'STRING', value: 'quoted-printable' },
1169
+ { type: 'ATOM', value: '78392' },
1170
+ { type: 'ATOM', value: '1770' },
1171
+ null,
1172
+ null,
1173
+ null,
1174
+ null
1175
+ ],
1176
+ { type: 'STRING', value: 'alternative' },
1177
+ [
1178
+ { type: 'STRING', value: 'boundary' },
1179
+ { type: 'STRING', value: '=-EcWGOW6mwE+0T4lm385OWw==' }
1180
+ ],
1181
+ null,
1182
+ null,
1183
+ null
1184
+ ],
1185
+ [
1186
+ { type: 'STRING', value: 'application' },
1187
+ { type: 'STRING', value: 'octet-stream' },
1188
+ [
1189
+ { type: 'STRING', value: 'name' },
1190
+ { type: 'STRING', value: '52482541500.pdf' }
1191
+ ],
1192
+ null,
1193
+ null,
1194
+ { type: 'STRING', value: 'base64' },
1195
+ { type: 'ATOM', value: '279430' },
1196
+ null,
1197
+ [
1198
+ { type: 'STRING', value: 'attachment' },
1199
+ [
1200
+ { type: 'STRING', value: 'filename' },
1201
+ { type: 'STRING', value: '52482541500.pdf' }
1202
+ ]
1203
+ ],
1204
+ null,
1205
+ null
1206
+ ],
1207
+ { type: 'STRING', value: 'mixed' },
1208
+ [
1209
+ { type: 'STRING', value: 'boundary' },
1210
+ { type: 'STRING', value: '=-1wJq2CLBJ6H+Zk2GPX9FKw==' }
1211
+ ],
1212
+ null,
1213
+ null,
1214
+ null
1215
+ ],
1216
+ { type: 'ATOM', value: '5580' },
1217
+ null,
1218
+ [
1219
+ { type: 'STRING', value: 'attachment' },
1220
+ [
1221
+ { type: 'STRING', value: 'filename' },
1222
+ { type: 'STRING', value: 'Tellimuse Microsoft 365 Business Standard arve vaatamine.eml' }
1223
+ ]
1224
+ ],
1225
+ null,
1226
+ null
1227
+ ],
1228
+ { type: 'STRING', value: 'mixed' },
1229
+ [
1230
+ { type: 'STRING', value: 'boundary' },
1231
+ { type: 'STRING', value: 'Apple-Mail=_F700EE9B-43B1-4EF1-95EE-CAA13391B333' }
1232
+ ],
1233
+ null,
1234
+ null,
1235
+ null
1236
+ ]
1237
+ ]
1238
+ ]);
1239
+ });