imapflow 1.0.144 → 1.0.146
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 +15 -0
- package/lib/commands/fetch.js +152 -135
- package/lib/commands/idle.js +2 -0
- package/lib/commands/list.js +5 -1
- package/lib/imap-flow.js +23 -14
- package/lib/special-use.js +9 -3
- package/lib/types.d.ts +2 -2
- package/package.json +8 -7
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.0.146](https://github.com/postalsys/imapflow/compare/v1.0.145...v1.0.146) (2023-10-26)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
* **throttling:** automatically retry throttled FETCH commands a few times ([07a9aea](https://github.com/postalsys/imapflow/commit/07a9aea37ae55ed885ccc4c0e3732b367ad82cd3))
|
|
9
|
+
|
|
10
|
+
## [1.0.145](https://github.com/postalsys/imapflow/compare/v1.0.144...v1.0.145) (2023-10-26)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### Bug Fixes
|
|
14
|
+
|
|
15
|
+
* **docs:** Fixed mailbox property name in AppendResponseObject ([ca6d789](https://github.com/postalsys/imapflow/commit/ca6d789b761d3117f733ed7b026122098f4d9142))
|
|
16
|
+
* **special-use:** support custom special use flags for the Archive folder ([17aa6a8](https://github.com/postalsys/imapflow/commit/17aa6a8baf180a7349fe30f897184eb8e359a498))
|
|
17
|
+
|
|
3
18
|
## [1.0.144](https://github.com/postalsys/imapflow/compare/v1.0.143...v1.0.144) (2023-09-13)
|
|
4
19
|
|
|
5
20
|
|
package/lib/commands/fetch.js
CHANGED
|
@@ -13,180 +13,197 @@ module.exports = async (connection, range, query, options) => {
|
|
|
13
13
|
|
|
14
14
|
let mailbox = connection.mailbox;
|
|
15
15
|
|
|
16
|
-
let messages = {
|
|
17
|
-
count: 0,
|
|
18
|
-
list: []
|
|
19
|
-
};
|
|
20
|
-
|
|
21
16
|
const commandKey = connection.capabilities.has('BINARY') && options.binary && !connection.disableBinary ? 'BINARY' : 'BODY';
|
|
22
17
|
|
|
23
|
-
let
|
|
24
|
-
|
|
25
|
-
let
|
|
18
|
+
let retryCount = 0;
|
|
19
|
+
while (retryCount < 4) {
|
|
20
|
+
let messages = {
|
|
21
|
+
count: 0,
|
|
22
|
+
list: []
|
|
23
|
+
};
|
|
26
24
|
|
|
27
|
-
let
|
|
25
|
+
let response;
|
|
26
|
+
try {
|
|
27
|
+
let attributes = [{ type: 'SEQUENCE', value: (range || '*').toString() }];
|
|
28
28
|
|
|
29
|
-
|
|
30
|
-
let bodyPeek = {
|
|
31
|
-
type: 'ATOM',
|
|
32
|
-
value: `${commandKey}.PEEK`,
|
|
33
|
-
section: [],
|
|
34
|
-
partial
|
|
35
|
-
};
|
|
29
|
+
let queryStructure = [];
|
|
36
30
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
31
|
+
let setBodyPeek = (attributes, partial) => {
|
|
32
|
+
let bodyPeek = {
|
|
33
|
+
type: 'ATOM',
|
|
34
|
+
value: `${commandKey}.PEEK`,
|
|
35
|
+
section: [],
|
|
36
|
+
partial
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
if (Array.isArray(attributes)) {
|
|
40
|
+
attributes.forEach(attribute => {
|
|
41
|
+
bodyPeek.section.push(attribute);
|
|
42
|
+
});
|
|
43
|
+
} else if (attributes) {
|
|
44
|
+
bodyPeek.section.push(attributes);
|
|
45
|
+
}
|
|
44
46
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
+
queryStructure.push(bodyPeek);
|
|
48
|
+
};
|
|
47
49
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
50
|
+
['all', 'fast', 'full', 'uid', 'flags', 'bodyStructure', 'envelope', 'internalDate'].forEach(key => {
|
|
51
|
+
if (query[key]) {
|
|
52
|
+
queryStructure.push({ type: 'ATOM', value: key.toUpperCase() });
|
|
53
|
+
}
|
|
54
|
+
});
|
|
53
55
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
56
|
+
if (query.size) {
|
|
57
|
+
queryStructure.push({ type: 'ATOM', value: 'RFC822.SIZE' });
|
|
58
|
+
}
|
|
57
59
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
60
|
+
if (query.source) {
|
|
61
|
+
let partial;
|
|
62
|
+
if (typeof query.source === 'object' && (query.source.start || query.source.maxLength)) {
|
|
63
|
+
partial = [Number(query.source.start) || 0];
|
|
64
|
+
if (query.source.maxLength && !isNaN(query.source.maxLength)) {
|
|
65
|
+
partial.push(Number(query.source.maxLength));
|
|
66
|
+
}
|
|
64
67
|
}
|
|
68
|
+
queryStructure.push({ type: 'ATOM', value: `${commandKey}.PEEK`, section: [], partial });
|
|
65
69
|
}
|
|
66
|
-
queryStructure.push({ type: 'ATOM', value: `${commandKey}.PEEK`, section: [], partial });
|
|
67
|
-
}
|
|
68
70
|
|
|
69
|
-
|
|
70
|
-
if (connection.capabilities.has('OBJECTID')) {
|
|
71
|
-
queryStructure.push({ type: 'ATOM', value: 'EMAILID' });
|
|
72
|
-
} else if (connection.capabilities.has('X-GM-EXT-1')) {
|
|
73
|
-
queryStructure.push({ type: 'ATOM', value: 'X-GM-MSGID' });
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
if (query.threadId) {
|
|
71
|
+
// if possible, always request for unique email id
|
|
77
72
|
if (connection.capabilities.has('OBJECTID')) {
|
|
78
|
-
queryStructure.push({ type: 'ATOM', value: '
|
|
73
|
+
queryStructure.push({ type: 'ATOM', value: 'EMAILID' });
|
|
79
74
|
} else if (connection.capabilities.has('X-GM-EXT-1')) {
|
|
80
|
-
queryStructure.push({ type: 'ATOM', value: 'X-GM-
|
|
75
|
+
queryStructure.push({ type: 'ATOM', value: 'X-GM-MSGID' });
|
|
81
76
|
}
|
|
82
|
-
}
|
|
83
77
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
78
|
+
if (query.threadId) {
|
|
79
|
+
if (connection.capabilities.has('OBJECTID')) {
|
|
80
|
+
queryStructure.push({ type: 'ATOM', value: 'THREADID' });
|
|
81
|
+
} else if (connection.capabilities.has('X-GM-EXT-1')) {
|
|
82
|
+
queryStructure.push({ type: 'ATOM', value: 'X-GM-THRID' });
|
|
83
|
+
}
|
|
87
84
|
}
|
|
88
|
-
}
|
|
89
85
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
86
|
+
if (query.labels) {
|
|
87
|
+
if (connection.capabilities.has('X-GM-EXT-1')) {
|
|
88
|
+
queryStructure.push({ type: 'ATOM', value: 'X-GM-LABELS' });
|
|
89
|
+
}
|
|
90
|
+
}
|
|
94
91
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
92
|
+
// always ask for modseq if possible
|
|
93
|
+
if (connection.enabled.has('CONDSTORE') && !mailbox.noModseq) {
|
|
94
|
+
queryStructure.push({ type: 'ATOM', value: 'MODSEQ' });
|
|
95
|
+
}
|
|
99
96
|
|
|
100
|
-
|
|
101
|
-
if (
|
|
102
|
-
|
|
103
|
-
} else {
|
|
104
|
-
setBodyPeek({ type: 'ATOM', value: 'HEADER' });
|
|
97
|
+
// always make sure to include UID in the request as well even though server might auto-add it itself
|
|
98
|
+
if (!query.uid) {
|
|
99
|
+
queryStructure.push({ type: 'ATOM', value: 'UID' });
|
|
105
100
|
}
|
|
106
|
-
}
|
|
107
101
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
102
|
+
if (query.headers) {
|
|
103
|
+
if (Array.isArray(query.headers)) {
|
|
104
|
+
setBodyPeek([{ type: 'ATOM', value: 'HEADER.FIELDS' }, query.headers.map(header => ({ type: 'ATOM', value: header }))]);
|
|
105
|
+
} else {
|
|
106
|
+
setBodyPeek({ type: 'ATOM', value: 'HEADER' });
|
|
112
107
|
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if (query.bodyParts && query.bodyParts.length) {
|
|
111
|
+
query.bodyParts.forEach(part => {
|
|
112
|
+
if (!part) {
|
|
117
113
|
return;
|
|
118
114
|
}
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
if (part.
|
|
123
|
-
|
|
115
|
+
let key;
|
|
116
|
+
let partial;
|
|
117
|
+
if (typeof part === 'object') {
|
|
118
|
+
if (!part.key || typeof part.key !== 'string') {
|
|
119
|
+
return;
|
|
124
120
|
}
|
|
121
|
+
key = part.key.toUpperCase();
|
|
122
|
+
if (part.start || part.maxLength) {
|
|
123
|
+
partial = [Number(part.start) || 0];
|
|
124
|
+
if (part.maxLength && !isNaN(part.maxLength)) {
|
|
125
|
+
partial.push(Number(part.maxLength));
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
} else if (typeof part === 'string') {
|
|
129
|
+
key = part.toUpperCase();
|
|
130
|
+
} else {
|
|
131
|
+
return;
|
|
125
132
|
}
|
|
126
|
-
} else if (typeof part === 'string') {
|
|
127
|
-
key = part.toUpperCase();
|
|
128
|
-
} else {
|
|
129
|
-
return;
|
|
130
|
-
}
|
|
131
133
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
134
|
+
setBodyPeek({ type: 'ATOM', value: key }, partial);
|
|
135
|
+
});
|
|
136
|
+
}
|
|
135
137
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
138
|
+
if (queryStructure.length === 1) {
|
|
139
|
+
queryStructure = queryStructure.pop();
|
|
140
|
+
}
|
|
139
141
|
|
|
140
|
-
|
|
142
|
+
attributes.push(queryStructure);
|
|
143
|
+
|
|
144
|
+
if (options.changedSince && connection.enabled.has('CONDSTORE') && !mailbox.noModseq) {
|
|
145
|
+
let changedSinceArgs = [
|
|
146
|
+
{
|
|
147
|
+
type: 'ATOM',
|
|
148
|
+
value: 'CHANGEDSINCE'
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
type: 'ATOM',
|
|
152
|
+
value: options.changedSince.toString()
|
|
153
|
+
}
|
|
154
|
+
];
|
|
141
155
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
},
|
|
148
|
-
{
|
|
149
|
-
type: 'ATOM',
|
|
150
|
-
value: options.changedSince.toString()
|
|
156
|
+
if (options.uid && connection.enabled.has('QRESYNC')) {
|
|
157
|
+
changedSinceArgs.push({
|
|
158
|
+
type: 'ATOM',
|
|
159
|
+
value: 'VANISHED'
|
|
160
|
+
});
|
|
151
161
|
}
|
|
152
|
-
];
|
|
153
162
|
|
|
154
|
-
|
|
155
|
-
changedSinceArgs.push({
|
|
156
|
-
type: 'ATOM',
|
|
157
|
-
value: 'VANISHED'
|
|
158
|
-
});
|
|
163
|
+
attributes.push(changedSinceArgs);
|
|
159
164
|
}
|
|
160
165
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
}
|
|
175
|
-
resolve();
|
|
176
|
-
}
|
|
166
|
+
response = await connection.exec(options.uid ? 'UID FETCH' : 'FETCH', attributes, {
|
|
167
|
+
untagged: {
|
|
168
|
+
FETCH: async untagged => {
|
|
169
|
+
messages.count++;
|
|
170
|
+
let formatted = await formatMessageResponse(untagged, mailbox);
|
|
171
|
+
if (typeof options.onUntaggedFetch === 'function') {
|
|
172
|
+
await new Promise((resolve, reject) => {
|
|
173
|
+
options.onUntaggedFetch(formatted, err => {
|
|
174
|
+
if (err) {
|
|
175
|
+
reject(err);
|
|
176
|
+
} else {
|
|
177
|
+
resolve();
|
|
178
|
+
}
|
|
179
|
+
});
|
|
177
180
|
});
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
|
|
181
|
+
} else {
|
|
182
|
+
messages.list.push(formatted);
|
|
183
|
+
}
|
|
181
184
|
}
|
|
182
185
|
}
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
response.next();
|
|
189
|
+
return messages;
|
|
190
|
+
} catch (err) {
|
|
191
|
+
if (err.code === 'ETHROTTLE') {
|
|
192
|
+
// retrying
|
|
193
|
+
connection.log.warn({
|
|
194
|
+
msg: 'Retrying throttled request',
|
|
195
|
+
cid: connection.id,
|
|
196
|
+
code: err.code,
|
|
197
|
+
response: err.responseText,
|
|
198
|
+
throttleReset: err.throttleReset,
|
|
199
|
+
retryCount
|
|
200
|
+
});
|
|
201
|
+
retryCount++;
|
|
202
|
+
continue;
|
|
183
203
|
}
|
|
184
|
-
});
|
|
185
204
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
connection.log.warn({ err, cid: connection.id });
|
|
190
|
-
return false;
|
|
205
|
+
connection.log.warn({ err, cid: connection.id });
|
|
206
|
+
return false;
|
|
207
|
+
}
|
|
191
208
|
}
|
|
192
209
|
};
|
package/lib/commands/idle.js
CHANGED
package/lib/commands/list.js
CHANGED
|
@@ -62,7 +62,11 @@ module.exports = async (connection, reference, mailbox, options) => {
|
|
|
62
62
|
let specialUseHints = {};
|
|
63
63
|
if (options.specialUseHints && typeof options.specialUseHints === 'object') {
|
|
64
64
|
for (let type of Object.keys(options.specialUseHints)) {
|
|
65
|
-
if (
|
|
65
|
+
if (
|
|
66
|
+
['sent', 'junk', 'trash', 'drafts', 'archive'].includes(type) &&
|
|
67
|
+
options.specialUseHints[type] &&
|
|
68
|
+
typeof options.specialUseHints[type] === 'string'
|
|
69
|
+
) {
|
|
66
70
|
specialUseHints[normalizePath(connection, options.specialUseHints[type])] = `\\${type.replace(/^./, c => c.toUpperCase())}`;
|
|
67
71
|
}
|
|
68
72
|
}
|
package/lib/imap-flow.js
CHANGED
|
@@ -562,25 +562,31 @@ class ImapFlow extends EventEmitter {
|
|
|
562
562
|
if (txt) {
|
|
563
563
|
err.responseText = txt;
|
|
564
564
|
|
|
565
|
+
let throttleDelay = false;
|
|
566
|
+
|
|
565
567
|
// MS365 throttling
|
|
566
568
|
// tag BAD Request is throttled. Suggested Backoff Time: 92415 milliseconds
|
|
567
569
|
if (/Request is throttled/i.test(txt) && /Backoff Time/i.test(txt)) {
|
|
568
570
|
let throttlingMatch = txt.match(/Backoff Time[:=\s]+(\d+)/i);
|
|
569
571
|
if (throttlingMatch && throttlingMatch[1] && !isNaN(throttlingMatch[1])) {
|
|
570
|
-
|
|
571
|
-
err.throttleReset = Number(throttlingMatch[1]);
|
|
572
|
-
|
|
573
|
-
let delayResponse = err.throttleReset;
|
|
574
|
-
if (delayResponse > 5 * 60 * 1000) {
|
|
575
|
-
// max delay cap
|
|
576
|
-
delayResponse = 5 * 60 * 1000;
|
|
577
|
-
}
|
|
578
|
-
if (delayResponse) {
|
|
579
|
-
this.log.warn({ msg: 'Throttling detected', err, cid: this.id, delayResponse });
|
|
580
|
-
await new Promise(r => setTimeout(r, delayResponse));
|
|
581
|
-
}
|
|
572
|
+
throttleDelay = Number(throttlingMatch[1]);
|
|
582
573
|
}
|
|
583
574
|
}
|
|
575
|
+
|
|
576
|
+
// Wait and return a throttling error
|
|
577
|
+
if (throttleDelay) {
|
|
578
|
+
err.code = 'ETHROTTLE';
|
|
579
|
+
err.throttleReset = throttleDelay;
|
|
580
|
+
|
|
581
|
+
let delayResponse = throttleDelay;
|
|
582
|
+
if (delayResponse > 5 * 60 * 1000) {
|
|
583
|
+
// max delay cap
|
|
584
|
+
delayResponse = 5 * 60 * 1000;
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
this.log.warn({ msg: 'Throttling detected', err, cid: this.id, throttleDelay, delayResponse });
|
|
588
|
+
await new Promise(r => setTimeout(r, delayResponse));
|
|
589
|
+
}
|
|
584
590
|
}
|
|
585
591
|
|
|
586
592
|
request.reject(err);
|
|
@@ -1939,7 +1945,7 @@ class ImapFlow extends EventEmitter {
|
|
|
1939
1945
|
/**
|
|
1940
1946
|
* @typedef {Object} AppendResponseObject
|
|
1941
1947
|
* @global
|
|
1942
|
-
* @property {String}
|
|
1948
|
+
* @property {String} destination full mailbox path where the message was uploaded to
|
|
1943
1949
|
* @property {BigInt} [uidValidity] mailbox `UIDVALIDITY` if server has `UIDPLUS` extension enabled
|
|
1944
1950
|
* @property {Number} [uid] UID of the uploaded message if server has `UIDPLUS` extension enabled
|
|
1945
1951
|
* @property {Number} [seq] sequence number of the uploaded message if path is currently selected mailbox
|
|
@@ -2736,7 +2742,10 @@ class ImapFlow extends EventEmitter {
|
|
|
2736
2742
|
|
|
2737
2743
|
let result = await handler(this, ...args);
|
|
2738
2744
|
|
|
2739
|
-
|
|
2745
|
+
if (command !== 'IDLE') {
|
|
2746
|
+
// do not autostart IDLE, if IDLE itself was stopped
|
|
2747
|
+
this.autoidle();
|
|
2748
|
+
}
|
|
2740
2749
|
|
|
2741
2750
|
return result;
|
|
2742
2751
|
}
|
package/lib/special-use.js
CHANGED
|
@@ -182,7 +182,7 @@ module.exports = {
|
|
|
182
182
|
'الرسائل العشوائية',
|
|
183
183
|
'هرزنامه',
|
|
184
184
|
'สแปม',
|
|
185
|
-
'
|
|
185
|
+
'垃圾郵件',
|
|
186
186
|
'垃圾邮件',
|
|
187
187
|
'垃圾電郵'
|
|
188
188
|
],
|
|
@@ -275,7 +275,9 @@ module.exports = {
|
|
|
275
275
|
'草稿',
|
|
276
276
|
'草稿',
|
|
277
277
|
'임시 보관함'
|
|
278
|
-
]
|
|
278
|
+
],
|
|
279
|
+
|
|
280
|
+
'\\Archive': ['archive']
|
|
279
281
|
},
|
|
280
282
|
|
|
281
283
|
specialUse(hasSpecialUseExtension, folder) {
|
|
@@ -289,7 +291,11 @@ module.exports = {
|
|
|
289
291
|
}
|
|
290
292
|
|
|
291
293
|
if (!result || !result.flag) {
|
|
292
|
-
let name = folder.name
|
|
294
|
+
let name = folder.name
|
|
295
|
+
.toLowerCase()
|
|
296
|
+
.replace(/\u200e/g, '')
|
|
297
|
+
.trim();
|
|
298
|
+
|
|
293
299
|
result = {
|
|
294
300
|
flag: Object.keys(module.exports.names).find(flag => module.exports.names[flag].includes(name)),
|
|
295
301
|
source: 'name'
|
package/lib/types.d.ts
CHANGED
|
@@ -805,13 +805,13 @@ declare type SearchObject = {
|
|
|
805
805
|
};
|
|
806
806
|
|
|
807
807
|
/**
|
|
808
|
-
* @property
|
|
808
|
+
* @property destination - full mailbox path where the message was uploaded to
|
|
809
809
|
* @property [uidValidity] - mailbox `UIDVALIDITY` if server has `UIDPLUS` extension enabled
|
|
810
810
|
* @property [uid] - UID of the uploaded message if server has `UIDPLUS` extension enabled
|
|
811
811
|
* @property [seq] - sequence number of the uploaded message if path is currently selected mailbox
|
|
812
812
|
*/
|
|
813
813
|
declare type AppendResponseObject = {
|
|
814
|
-
|
|
814
|
+
destination: string;
|
|
815
815
|
uidValidity?: bigint;
|
|
816
816
|
uid?: number;
|
|
817
817
|
seq?: number;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "imapflow",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.146",
|
|
4
4
|
"description": "IMAP Client for Node",
|
|
5
5
|
"main": "./lib/imap-flow.js",
|
|
6
6
|
"scripts": {
|
|
@@ -9,7 +9,8 @@
|
|
|
9
9
|
"docs": "rm -rf docs && mkdir -p docs && jsdoc lib/imap-flow.js -c jsdoc.json -R README.md --destination docs/ && cp assets/favicon.ico docs",
|
|
10
10
|
"dst": "node types.js",
|
|
11
11
|
"build": "npm run docs && npm run dst",
|
|
12
|
-
"st": "npm run docs && st -d docs -i index.html"
|
|
12
|
+
"st": "npm run docs && st -d docs -i index.html",
|
|
13
|
+
"update": "rm -rf node_modules package-lock.json && ncu -u && npm install"
|
|
13
14
|
},
|
|
14
15
|
"repository": {
|
|
15
16
|
"type": "git",
|
|
@@ -30,10 +31,10 @@
|
|
|
30
31
|
"@babel/eslint-parser": "7.22.15",
|
|
31
32
|
"@babel/eslint-plugin": "7.22.10",
|
|
32
33
|
"@babel/plugin-syntax-class-properties": "7.12.13",
|
|
33
|
-
"@babel/preset-env": "7.
|
|
34
|
-
"@types/node": "20.
|
|
34
|
+
"@babel/preset-env": "7.23.2",
|
|
35
|
+
"@types/node": "20.8.9",
|
|
35
36
|
"braintree-jsdoc-template": "3.3.0",
|
|
36
|
-
"eslint": "8.
|
|
37
|
+
"eslint": "8.52.0",
|
|
37
38
|
"eslint-config-nodemailer": "1.2.0",
|
|
38
39
|
"eslint-config-prettier": "9.0.0",
|
|
39
40
|
"grunt": "1.6.1",
|
|
@@ -51,8 +52,8 @@
|
|
|
51
52
|
"libmime": "5.2.1",
|
|
52
53
|
"libqp": "2.0.1",
|
|
53
54
|
"mailsplit": "5.4.0",
|
|
54
|
-
"nodemailer": "6.9.
|
|
55
|
-
"pino": "8.
|
|
55
|
+
"nodemailer": "6.9.7",
|
|
56
|
+
"pino": "8.16.1",
|
|
56
57
|
"socks": "2.7.1"
|
|
57
58
|
}
|
|
58
59
|
}
|