imapflow 1.0.72 → 1.0.76
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/.eslintrc +2 -1
- package/CHANGELOG.md +5 -0
- package/lib/commands/append.js +2 -1
- package/lib/commands/idle.js +69 -31
- package/lib/commands/noop.js +1 -1
- package/lib/imap-flow.js +52 -17
- package/package.json +11 -11
package/.eslintrc
CHANGED
package/CHANGELOG.md
CHANGED
package/lib/commands/append.js
CHANGED
|
@@ -86,7 +86,8 @@ module.exports = async (connection, destination, content, flags, idate) => {
|
|
|
86
86
|
EXISTS: async untagged => {
|
|
87
87
|
map.seq = Number(untagged.command);
|
|
88
88
|
}
|
|
89
|
-
}
|
|
89
|
+
},
|
|
90
|
+
comment: 'Sequence not found from APPEND output'
|
|
90
91
|
});
|
|
91
92
|
response.next();
|
|
92
93
|
} catch (err) {
|
package/lib/commands/idle.js
CHANGED
|
@@ -13,61 +13,99 @@ module.exports = async connection => {
|
|
|
13
13
|
let response;
|
|
14
14
|
|
|
15
15
|
let preCheckWaitQueue = [];
|
|
16
|
-
|
|
17
16
|
try {
|
|
18
17
|
connection.idling = true;
|
|
19
18
|
|
|
20
|
-
let
|
|
19
|
+
//let idleSent = false;
|
|
20
|
+
let doneRequested = false;
|
|
21
|
+
let doneSent = false;
|
|
22
|
+
let canEnd = false;
|
|
23
|
+
|
|
24
|
+
let preCheck = () => {
|
|
25
|
+
doneRequested = true;
|
|
26
|
+
if (canEnd && !doneSent) {
|
|
27
|
+
connection.log.debug({
|
|
28
|
+
src: 'c',
|
|
29
|
+
msg: `DONE`,
|
|
30
|
+
comment: `breaking IDLE`,
|
|
31
|
+
lockId: connection.currentLockId,
|
|
32
|
+
path: connection.mailbox && connection.mailbox.path
|
|
33
|
+
});
|
|
34
|
+
connection.write('DONE');
|
|
35
|
+
doneSent = true;
|
|
36
|
+
|
|
37
|
+
connection.idling = false;
|
|
38
|
+
connection.preCheck = false; // unset itself
|
|
39
|
+
|
|
40
|
+
while (preCheckWaitQueue.length) {
|
|
41
|
+
let { resolve } = preCheckWaitQueue.shift();
|
|
42
|
+
resolve();
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
|
|
21
47
|
connection.preCheck = () => {
|
|
22
|
-
let
|
|
48
|
+
let handler = new Promise((resolve, reject) => {
|
|
23
49
|
preCheckWaitQueue.push({ resolve, reject });
|
|
24
50
|
});
|
|
25
51
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
console.log('RESOLVING IDLE');
|
|
38
|
-
let entry = preCheckWaitQueue.shift();
|
|
39
|
-
entry.resolve();
|
|
40
|
-
}
|
|
41
|
-
});
|
|
42
|
-
}
|
|
52
|
+
connection.log.trace({
|
|
53
|
+
msg: 'Requesting IDLE break',
|
|
54
|
+
lockId: connection.currentLockId,
|
|
55
|
+
path: connection.mailbox && connection.mailbox.path,
|
|
56
|
+
queued: preCheckWaitQueue.length,
|
|
57
|
+
doneRequested,
|
|
58
|
+
canEnd,
|
|
59
|
+
doneSent
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
preCheck();
|
|
43
63
|
|
|
44
|
-
return
|
|
64
|
+
return handler;
|
|
45
65
|
};
|
|
46
66
|
|
|
47
67
|
response = await connection.exec('IDLE', false, {
|
|
48
68
|
onPlusTag: async () => {
|
|
49
69
|
connection.log.debug({ msg: `Initiated IDLE, waiting for server input` });
|
|
70
|
+
canEnd = true;
|
|
71
|
+
if (doneRequested) {
|
|
72
|
+
preCheck();
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
onSend: () => {
|
|
76
|
+
//idleSent = true;
|
|
50
77
|
}
|
|
51
78
|
});
|
|
52
79
|
|
|
53
80
|
// unset before response.next()
|
|
54
|
-
connection.preCheck
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
81
|
+
if (typeof connection.preCheck === 'function') {
|
|
82
|
+
connection.log.trace({
|
|
83
|
+
msg: 'Clearing pre-check function',
|
|
84
|
+
lockId: connection.currentLockId,
|
|
85
|
+
path: connection.mailbox && connection.mailbox.path,
|
|
86
|
+
queued: preCheckWaitQueue.length,
|
|
87
|
+
doneRequested,
|
|
88
|
+
canEnd,
|
|
89
|
+
doneSent
|
|
90
|
+
});
|
|
91
|
+
connection.preCheck = false;
|
|
92
|
+
while (preCheckWaitQueue.length) {
|
|
93
|
+
let { resolve } = preCheckWaitQueue.shift();
|
|
94
|
+
resolve();
|
|
95
|
+
}
|
|
59
96
|
}
|
|
60
97
|
|
|
61
98
|
response.next();
|
|
62
99
|
return;
|
|
63
100
|
} catch (err) {
|
|
64
101
|
connection.preCheck = false;
|
|
65
|
-
|
|
66
|
-
let entry = preCheckWaitQueue.shift();
|
|
67
|
-
entry.reject(err);
|
|
68
|
-
}
|
|
102
|
+
connection.idling = false;
|
|
69
103
|
|
|
70
104
|
connection.log.warn({ err, cid: connection.id });
|
|
105
|
+
while (preCheckWaitQueue.length) {
|
|
106
|
+
let { reject } = preCheckWaitQueue.shift();
|
|
107
|
+
reject(err);
|
|
108
|
+
}
|
|
71
109
|
return false;
|
|
72
110
|
}
|
|
73
111
|
}
|
|
@@ -85,7 +123,7 @@ module.exports = async connection => {
|
|
|
85
123
|
};
|
|
86
124
|
|
|
87
125
|
let idleCheck = async () => {
|
|
88
|
-
let response = await connection.exec('NOOP');
|
|
126
|
+
let response = await connection.exec('NOOP', false, { comment: 'IDLE not supported' });
|
|
89
127
|
response.next();
|
|
90
128
|
};
|
|
91
129
|
|
package/lib/commands/noop.js
CHANGED
package/lib/imap-flow.js
CHANGED
|
@@ -331,8 +331,14 @@ class ImapFlow extends EventEmitter {
|
|
|
331
331
|
isLogging: true
|
|
332
332
|
});
|
|
333
333
|
|
|
334
|
-
|
|
334
|
+
let options = data.options || {};
|
|
335
|
+
|
|
336
|
+
this.log.debug({ src: 's', msg: logCompiled.toString(), cid: this.id, comment: options.comment });
|
|
335
337
|
this.write(Buffer.from(this.commandParts.shift()));
|
|
338
|
+
|
|
339
|
+
if (typeof options.onSend === 'function') {
|
|
340
|
+
options.onSend();
|
|
341
|
+
}
|
|
336
342
|
}
|
|
337
343
|
|
|
338
344
|
async trySend() {
|
|
@@ -344,7 +350,8 @@ class ImapFlow extends EventEmitter {
|
|
|
344
350
|
await this.send({
|
|
345
351
|
tag: this.currentRequest.tag,
|
|
346
352
|
command: this.currentRequest.command,
|
|
347
|
-
attributes: this.currentRequest.attributes
|
|
353
|
+
attributes: this.currentRequest.attributes,
|
|
354
|
+
options: this.currentRequest.options
|
|
348
355
|
});
|
|
349
356
|
}
|
|
350
357
|
|
|
@@ -1024,7 +1031,7 @@ class ImapFlow extends EventEmitter {
|
|
|
1024
1031
|
* await client.connect();
|
|
1025
1032
|
*/
|
|
1026
1033
|
async connect() {
|
|
1027
|
-
let connector = this.
|
|
1034
|
+
let connector = this.secureConnection ? tls : net;
|
|
1028
1035
|
|
|
1029
1036
|
let opts = Object.assign(
|
|
1030
1037
|
{
|
|
@@ -2018,7 +2025,13 @@ class ImapFlow extends EventEmitter {
|
|
|
2018
2025
|
return {};
|
|
2019
2026
|
}
|
|
2020
2027
|
|
|
2021
|
-
options =
|
|
2028
|
+
options = Object.assign(
|
|
2029
|
+
{
|
|
2030
|
+
chunkSize: 64 * 1024,
|
|
2031
|
+
maxBytes: Infinity
|
|
2032
|
+
},
|
|
2033
|
+
options || {}
|
|
2034
|
+
);
|
|
2022
2035
|
|
|
2023
2036
|
let hasMore = true;
|
|
2024
2037
|
let processed = 0;
|
|
@@ -2028,6 +2041,28 @@ class ImapFlow extends EventEmitter {
|
|
|
2028
2041
|
|
|
2029
2042
|
let uid = false;
|
|
2030
2043
|
|
|
2044
|
+
if (part === '1') {
|
|
2045
|
+
// First part has special conditions for single node emails as
|
|
2046
|
+
// the mime parts for root node are not 1 and 1.MIME but TEXT and HEADERS
|
|
2047
|
+
let response = await this.fetchOne(range, { uid: true, bodyStructure: true }, options);
|
|
2048
|
+
|
|
2049
|
+
if (!response) {
|
|
2050
|
+
return { response: false, chunk: false };
|
|
2051
|
+
}
|
|
2052
|
+
|
|
2053
|
+
if (!uid && response.uid) {
|
|
2054
|
+
uid = response.uid;
|
|
2055
|
+
// force UID from now on even if first range was a sequence number
|
|
2056
|
+
range = uid;
|
|
2057
|
+
options.uid = true;
|
|
2058
|
+
}
|
|
2059
|
+
|
|
2060
|
+
if (!response.bodyStructure.childNodes) {
|
|
2061
|
+
// single text message
|
|
2062
|
+
part = 'TEXT';
|
|
2063
|
+
}
|
|
2064
|
+
}
|
|
2065
|
+
|
|
2031
2066
|
let getNextPart = async query => {
|
|
2032
2067
|
query = query || {};
|
|
2033
2068
|
|
|
@@ -2045,10 +2080,15 @@ class ImapFlow extends EventEmitter {
|
|
|
2045
2080
|
query.bodyParts = [];
|
|
2046
2081
|
}
|
|
2047
2082
|
|
|
2048
|
-
if (query.size
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2083
|
+
if (query.size) {
|
|
2084
|
+
if (/^[\d.]+$/.test(part)) {
|
|
2085
|
+
// fetch meta as well
|
|
2086
|
+
mimeKey = part + '.mime';
|
|
2087
|
+
query.bodyParts.push(mimeKey);
|
|
2088
|
+
} else if (part === 'text') {
|
|
2089
|
+
mimeKey = 'header';
|
|
2090
|
+
query.bodyParts.push(mimeKey);
|
|
2091
|
+
}
|
|
2052
2092
|
}
|
|
2053
2093
|
|
|
2054
2094
|
query.bodyParts.push({
|
|
@@ -2085,15 +2125,10 @@ class ImapFlow extends EventEmitter {
|
|
|
2085
2125
|
}
|
|
2086
2126
|
|
|
2087
2127
|
if (query.bodyParts) {
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
let mimeResponse = await this.fetchOne(range, { bodyParts: ['header'] }, options);
|
|
2093
|
-
if (!mimeResponse) {
|
|
2094
|
-
return { response: false, chunk: false };
|
|
2095
|
-
}
|
|
2096
|
-
result.mime = mimeResponse.headers;
|
|
2128
|
+
if (mimeKey === 'header') {
|
|
2129
|
+
result.mime = response.headers;
|
|
2130
|
+
} else {
|
|
2131
|
+
result.mime = response.bodyParts.get(mimeKey);
|
|
2097
2132
|
}
|
|
2098
2133
|
}
|
|
2099
2134
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "imapflow",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.76",
|
|
4
4
|
"description": "IMAP Client for Node",
|
|
5
5
|
"main": "./lib/imap-flow.js",
|
|
6
6
|
"scripts": {
|
|
@@ -26,19 +26,19 @@
|
|
|
26
26
|
},
|
|
27
27
|
"homepage": "https://imapflow.com/",
|
|
28
28
|
"devDependencies": {
|
|
29
|
-
"@babel/eslint-parser": "
|
|
30
|
-
"@babel/eslint-plugin": "
|
|
31
|
-
"@babel/plugin-syntax-class-properties": "
|
|
32
|
-
"@babel/preset-env": "
|
|
33
|
-
"@types/node": "16.
|
|
29
|
+
"@babel/eslint-parser": "7.15.8",
|
|
30
|
+
"@babel/eslint-plugin": "7.14.5",
|
|
31
|
+
"@babel/plugin-syntax-class-properties": "7.12.13",
|
|
32
|
+
"@babel/preset-env": "7.15.8",
|
|
33
|
+
"@types/node": "16.11.1",
|
|
34
34
|
"braintree-jsdoc-template": "3.3.0",
|
|
35
|
-
"eslint": "
|
|
35
|
+
"eslint": "8.0.1",
|
|
36
36
|
"eslint-config-nodemailer": "1.2.0",
|
|
37
37
|
"eslint-config-prettier": "8.3.0",
|
|
38
38
|
"grunt": "1.4.1",
|
|
39
39
|
"grunt-cli": "1.4.3",
|
|
40
|
-
"grunt-contrib-nodeunit": "
|
|
41
|
-
"grunt-eslint": "
|
|
40
|
+
"grunt-contrib-nodeunit": "4.0.0",
|
|
41
|
+
"grunt-eslint": "24.0.0",
|
|
42
42
|
"jsdoc": "3.6.7",
|
|
43
43
|
"tsd-jsdoc": "2.5.0"
|
|
44
44
|
},
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
"libbase64": "1.2.1",
|
|
49
49
|
"libmime": "5.0.0",
|
|
50
50
|
"libqp": "1.1.0",
|
|
51
|
-
"mailsplit": "5.
|
|
52
|
-
"pino": "
|
|
51
|
+
"mailsplit": "5.3.1",
|
|
52
|
+
"pino": "7.0.2"
|
|
53
53
|
}
|
|
54
54
|
}
|