imapflow 1.0.148 → 1.0.150
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/stale.yml +24 -0
- package/CHANGELOG.md +14 -0
- package/lib/imap-flow.js +81 -2
- package/lib/tools.js +46 -0
- package/lib/types.d.ts +21 -1
- package/package.json +9 -9
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
name: 'Close stale issues and PRs'
|
|
2
|
+
on:
|
|
3
|
+
schedule:
|
|
4
|
+
- cron: '30 1 * * *'
|
|
5
|
+
|
|
6
|
+
jobs:
|
|
7
|
+
stale:
|
|
8
|
+
runs-on: ubuntu-latest
|
|
9
|
+
steps:
|
|
10
|
+
- uses: actions/stale@v8
|
|
11
|
+
with:
|
|
12
|
+
stale-issue-message: 'This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 5 days.'
|
|
13
|
+
stale-pr-message: 'This PR is stale because it has been open 45 days with no activity. Remove stale label or comment or this will be closed in 10 days.'
|
|
14
|
+
close-issue-message: 'This issue was closed because it has been stalled for 15 days with no activity.'
|
|
15
|
+
close-pr-message: 'This PR was closed because it has been stalled for 20 days with no activity.'
|
|
16
|
+
days-before-issue-stale: 30
|
|
17
|
+
days-before-pr-stale: 45
|
|
18
|
+
days-before-issue-close: 15
|
|
19
|
+
days-before-pr-close: 20
|
|
20
|
+
stale-issue-label: 'no-issue-activity'
|
|
21
|
+
exempt-issue-labels: 'pending,work-in-progress'
|
|
22
|
+
stale-pr-label: 'no-pr-activity'
|
|
23
|
+
exempt-pr-labels: 'awaiting-approval,work-in-progress'
|
|
24
|
+
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.0.150](https://github.com/postalsys/imapflow/compare/v1.0.149...v1.0.150) (2024-02-01)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
* **deps:** Bumped Nodemailer version ([ee02764](https://github.com/postalsys/imapflow/commit/ee0276493494ecf08be557cc0c486fe309d359bf))
|
|
9
|
+
|
|
10
|
+
## [1.0.149](https://github.com/postalsys/imapflow/compare/v1.0.148...v1.0.149) (2024-01-31)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### Bug Fixes
|
|
14
|
+
|
|
15
|
+
* **flag-colors:** added a method to set Flag Color. The color is also included in the Fetch response structure ([d840951](https://github.com/postalsys/imapflow/commit/d8409513075b864e9131665af3f1670a0714d05c))
|
|
16
|
+
|
|
3
17
|
## [1.0.148](https://github.com/postalsys/imapflow/compare/v1.0.147...v1.0.148) (2024-01-16)
|
|
4
18
|
|
|
5
19
|
|
package/lib/imap-flow.js
CHANGED
|
@@ -29,7 +29,17 @@ const { PassThrough } = require('stream');
|
|
|
29
29
|
|
|
30
30
|
const { proxyConnection } = require('./proxy-connection');
|
|
31
31
|
|
|
32
|
-
const {
|
|
32
|
+
const {
|
|
33
|
+
comparePaths,
|
|
34
|
+
updateCapabilities,
|
|
35
|
+
getFolderTree,
|
|
36
|
+
formatMessageResponse,
|
|
37
|
+
getDecoder,
|
|
38
|
+
packMessageRange,
|
|
39
|
+
normalizePath,
|
|
40
|
+
expandRange,
|
|
41
|
+
getColorFlags
|
|
42
|
+
} = require('./tools');
|
|
33
43
|
|
|
34
44
|
const imapCommands = require('./imap-commands.js');
|
|
35
45
|
|
|
@@ -1177,6 +1187,10 @@ class ImapFlow extends EventEmitter {
|
|
|
1177
1187
|
|
|
1178
1188
|
updateEvent.flags = message.flags;
|
|
1179
1189
|
|
|
1190
|
+
if (message.flagColor) {
|
|
1191
|
+
updateEvent.flagColor = message.flagColor;
|
|
1192
|
+
}
|
|
1193
|
+
|
|
1180
1194
|
this.emit('flags', updateEvent);
|
|
1181
1195
|
}
|
|
1182
1196
|
}
|
|
@@ -1926,6 +1940,68 @@ class ImapFlow extends EventEmitter {
|
|
|
1926
1940
|
return await this.run('STORE', range, flags, queryOpts);
|
|
1927
1941
|
}
|
|
1928
1942
|
|
|
1943
|
+
/**
|
|
1944
|
+
* Sets a colored flag for an email. Only supported by mail clients like Apple Mail
|
|
1945
|
+
*
|
|
1946
|
+
* @param {SequenceString | Number[] | SearchObject} range Range to filter the messages
|
|
1947
|
+
* @param {string} The color to set. One of 'red', 'orange', 'yellow', 'green', 'blue', 'purple', and 'grey'
|
|
1948
|
+
* @param {Object} [options]
|
|
1949
|
+
* @param {Boolean} [options.uid] If `true` then uses UID {@link SequenceString} instead of sequence numbers
|
|
1950
|
+
* @param {BigInt} [options.unchangedSince] If set then only messages with a lower or equal `modseq` value are updated. Ignored if server does not support `CONDSTORE` extension.
|
|
1951
|
+
* @returns {Promise<Boolean>} Did the operation succeed or not
|
|
1952
|
+
*
|
|
1953
|
+
* @example
|
|
1954
|
+
* let mailbox = await client.mailboxOpen('INBOX');
|
|
1955
|
+
* // add a purple flag for all emails
|
|
1956
|
+
* await client.setFlagColor('1:*', 'Purple');
|
|
1957
|
+
*/
|
|
1958
|
+
async setFlagColor(range, color, options) {
|
|
1959
|
+
options = options || {};
|
|
1960
|
+
|
|
1961
|
+
range = await this.resolveRange(range, options);
|
|
1962
|
+
if (!range) {
|
|
1963
|
+
return false;
|
|
1964
|
+
}
|
|
1965
|
+
|
|
1966
|
+
let flagChanges = getColorFlags(color);
|
|
1967
|
+
if (!flagChanges) {
|
|
1968
|
+
return false;
|
|
1969
|
+
}
|
|
1970
|
+
|
|
1971
|
+
let addResults;
|
|
1972
|
+
let removeResults;
|
|
1973
|
+
|
|
1974
|
+
if (flagChanges.add && flagChanges.add.length) {
|
|
1975
|
+
let queryOpts = Object.assign(
|
|
1976
|
+
{
|
|
1977
|
+
operation: 'add'
|
|
1978
|
+
},
|
|
1979
|
+
options,
|
|
1980
|
+
{
|
|
1981
|
+
useLabels: false, // override if set
|
|
1982
|
+
// prevent triggering a premature Flags change notification
|
|
1983
|
+
silent: flagChanges.remove && flagChanges.remove.length
|
|
1984
|
+
}
|
|
1985
|
+
);
|
|
1986
|
+
|
|
1987
|
+
addResults = await this.run('STORE', range, flagChanges.add, queryOpts);
|
|
1988
|
+
}
|
|
1989
|
+
|
|
1990
|
+
if (flagChanges.remove && flagChanges.remove.length) {
|
|
1991
|
+
let queryOpts = Object.assign(
|
|
1992
|
+
{
|
|
1993
|
+
operation: 'remove'
|
|
1994
|
+
},
|
|
1995
|
+
options,
|
|
1996
|
+
{ useLabels: false } // override if set
|
|
1997
|
+
);
|
|
1998
|
+
|
|
1999
|
+
removeResults = await this.run('STORE', range, flagChanges.remove, queryOpts);
|
|
2000
|
+
}
|
|
2001
|
+
|
|
2002
|
+
return addResults || removeResults || false;
|
|
2003
|
+
}
|
|
2004
|
+
|
|
1929
2005
|
/**
|
|
1930
2006
|
* Delete messages from currently opened mailbox. Method does not indicate info about deleted messages,
|
|
1931
2007
|
* instead you should be using {@link ImapFlow#expunge} event for this
|
|
@@ -2077,7 +2153,7 @@ class ImapFlow extends EventEmitter {
|
|
|
2077
2153
|
* @typedef {Object} FetchQueryObject
|
|
2078
2154
|
* @global
|
|
2079
2155
|
* @property {Boolean} [uid] if `true` then include UID in the response
|
|
2080
|
-
* @property {Boolean} [flags] if `true` then include flags Set in the response
|
|
2156
|
+
* @property {Boolean} [flags] if `true` then include flags Set in the response. Also adds `flagColor` to the response if the message is flagged.
|
|
2081
2157
|
* @property {Boolean} [bodyStructure] if `true` then include parsed BODYSTRUCTURE object in the response
|
|
2082
2158
|
* @property {Boolean} [envelope] if `true` then include parsed ENVELOPE object in the response
|
|
2083
2159
|
* @property {Boolean} [internalDate] if `true` then include internal date value in the response
|
|
@@ -2148,6 +2224,7 @@ class ImapFlow extends EventEmitter {
|
|
|
2148
2224
|
* @property {Set<string>} [labels] a Set of labels. Only present if server supports `X-GM-EXT-1` extension
|
|
2149
2225
|
* @property {Number} [size] message size
|
|
2150
2226
|
* @property {Set<string>} [flags] a set of message flags
|
|
2227
|
+
* @property {String} [flagColor] flag color like "red", or "yellow". This value is derived from the `flags` Set and it uses the same color rules as Apple Mail
|
|
2151
2228
|
* @property {MessageEnvelopeObject} [envelope] message envelope
|
|
2152
2229
|
* @property {MessageStructureObject} [bodyStructure] message body structure
|
|
2153
2230
|
* @property {Date} [internalDate] message internal date
|
|
@@ -2171,6 +2248,8 @@ class ImapFlow extends EventEmitter {
|
|
|
2171
2248
|
* // fetch UID for all messages in a mailbox
|
|
2172
2249
|
* for await (let msg of client.fetch('1:*', {uid: true})){
|
|
2173
2250
|
* console.log(msg.uid);
|
|
2251
|
+
* // NB! You can not run any IMAP commands in this loop
|
|
2252
|
+
* // otherwise you will end up in a deadloop
|
|
2174
2253
|
* }
|
|
2175
2254
|
*/
|
|
2176
2255
|
async *fetch(range, query, options) {
|
package/lib/tools.js
CHANGED
|
@@ -8,6 +8,8 @@ const { createHash } = require('crypto');
|
|
|
8
8
|
const { JPDecoder } = require('./jp-decoder');
|
|
9
9
|
const iconv = require('iconv-lite');
|
|
10
10
|
|
|
11
|
+
const FLAG_COLORS = ['red', 'orange', 'yellow', 'green', 'blue', 'purple', 'grey'];
|
|
12
|
+
|
|
11
13
|
module.exports = {
|
|
12
14
|
encodePath(connection, path) {
|
|
13
15
|
path = (path || '').toString();
|
|
@@ -191,6 +193,43 @@ module.exports = {
|
|
|
191
193
|
return tree;
|
|
192
194
|
},
|
|
193
195
|
|
|
196
|
+
getFlagColor(flags) {
|
|
197
|
+
if (!flags.has('\\Flagged')) {
|
|
198
|
+
return null;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
const bit0 = flags.has('$MailFlagBit0') ? 1 : 0;
|
|
202
|
+
const bit1 = flags.has('$MailFlagBit1') ? 2 : 0;
|
|
203
|
+
const bit2 = flags.has('$MailFlagBit2') ? 4 : 0;
|
|
204
|
+
|
|
205
|
+
const color = bit0 | bit1 | bit2; // eslint-disable-line no-bitwise
|
|
206
|
+
|
|
207
|
+
return FLAG_COLORS[color] || 'red'; // default to red for the unused \b111
|
|
208
|
+
},
|
|
209
|
+
|
|
210
|
+
getColorFlags(color) {
|
|
211
|
+
const colorCode = color ? FLAG_COLORS.indexOf((color || '').toString().toLowerCase().trim()) : null;
|
|
212
|
+
if (colorCode < 0 && colorCode !== null) {
|
|
213
|
+
return null;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
const bits = [];
|
|
217
|
+
bits[0] = colorCode & 1; // eslint-disable-line no-bitwise
|
|
218
|
+
bits[1] = colorCode & 2; // eslint-disable-line no-bitwise
|
|
219
|
+
bits[2] = colorCode & 4; // eslint-disable-line no-bitwise
|
|
220
|
+
|
|
221
|
+
let result = { add: colorCode ? ['\\Flagged'] : [], remove: colorCode ? [] : ['\\Flagged'] };
|
|
222
|
+
|
|
223
|
+
for (let i = 0; i < bits.length; i++) {
|
|
224
|
+
if (bits[i]) {
|
|
225
|
+
result.add.push(`$MailFlagBit${i}`);
|
|
226
|
+
} else {
|
|
227
|
+
result.remove.push(`$MailFlagBit${i}`);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
return result;
|
|
231
|
+
},
|
|
232
|
+
|
|
194
233
|
async formatMessageResponse(untagged, mailbox) {
|
|
195
234
|
let map = {};
|
|
196
235
|
|
|
@@ -351,6 +390,13 @@ module.exports = {
|
|
|
351
390
|
map.id = map.emailId || createHash('md5').update([path, mailbox.uidValidity.toString(), map.uid.toString()].join(':')).digest('hex');
|
|
352
391
|
}
|
|
353
392
|
|
|
393
|
+
if (map.flags) {
|
|
394
|
+
let flagColor = module.exports.getFlagColor(map.flags);
|
|
395
|
+
if (flagColor) {
|
|
396
|
+
map.flagColor = flagColor;
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
|
|
354
400
|
return map;
|
|
355
401
|
},
|
|
356
402
|
|
package/lib/types.d.ts
CHANGED
|
@@ -364,6 +364,22 @@ declare module "imapflow" {
|
|
|
364
364
|
unchangedSince?: bigint;
|
|
365
365
|
useLabels?: boolean;
|
|
366
366
|
}): Promise<Boolean>;
|
|
367
|
+
/**
|
|
368
|
+
* Sets a colored flag for an email. Only supported by mail clients like Apple Mail
|
|
369
|
+
* @example
|
|
370
|
+
* let mailbox = await client.mailboxOpen('INBOX');
|
|
371
|
+
* // add a purple flag for all emails
|
|
372
|
+
* await client.setFlagColor('1:*', 'Purple');
|
|
373
|
+
* @param range - Range to filter the messages
|
|
374
|
+
* @param The - color to set. One of 'red', 'orange', 'yellow', 'green', 'blue', 'purple', and 'grey'
|
|
375
|
+
* @param [options.uid] - If `true` then uses UID {@link SequenceString} instead of sequence numbers
|
|
376
|
+
* @param [options.unchangedSince] - If set then only messages with a lower or equal `modseq` value are updated. Ignored if server does not support `CONDSTORE` extension.
|
|
377
|
+
* @returns Did the operation succeed or not
|
|
378
|
+
*/
|
|
379
|
+
setFlagColor(range: SequenceString | Number[] | SearchObject, The: string, options?: {
|
|
380
|
+
uid?: boolean;
|
|
381
|
+
unchangedSince?: bigint;
|
|
382
|
+
}): Promise<Boolean>;
|
|
367
383
|
/**
|
|
368
384
|
* Delete messages from currently opened mailbox. Method does not indicate info about deleted messages,
|
|
369
385
|
* instead you should be using {@link ImapFlow#expunge} event for this
|
|
@@ -447,6 +463,8 @@ declare module "imapflow" {
|
|
|
447
463
|
* // fetch UID for all messages in a mailbox
|
|
448
464
|
* for await (let msg of client.fetch('1:*', {uid: true})){
|
|
449
465
|
* console.log(msg.uid);
|
|
466
|
+
* // NB! You can not run any IMAP commands in this loop
|
|
467
|
+
* // otherwise you will end up in a deadloop
|
|
450
468
|
* }
|
|
451
469
|
* @param range - Range of messages to fetch
|
|
452
470
|
* @param query - Fetch query
|
|
@@ -832,7 +850,7 @@ declare type CopyResponseObject = {
|
|
|
832
850
|
|
|
833
851
|
/**
|
|
834
852
|
* @property [uid] - if `true` then include UID in the response
|
|
835
|
-
* @property [flags] - if `true` then include flags Set in the response
|
|
853
|
+
* @property [flags] - if `true` then include flags Set in the response. Also adds `flagColor` to the response if the message is flagged.
|
|
836
854
|
* @property [bodyStructure] - if `true` then include parsed BODYSTRUCTURE object in the response
|
|
837
855
|
* @property [envelope] - if `true` then include parsed ENVELOPE object in the response
|
|
838
856
|
* @property [internalDate] - if `true` then include internal date value in the response
|
|
@@ -935,6 +953,7 @@ declare type MessageStructureObject = {
|
|
|
935
953
|
* @property [labels] - a Set of labels. Only present if server supports `X-GM-EXT-1` extension
|
|
936
954
|
* @property [size] - message size
|
|
937
955
|
* @property [flags] - a set of message flags
|
|
956
|
+
* @property [flagColor] - flag color like "red", or "yellow". This value is derived from the `flags` Set and it uses the same color rules as Apple Mail
|
|
938
957
|
* @property [envelope] - message envelope
|
|
939
958
|
* @property [bodyStructure] - message body structure
|
|
940
959
|
* @property [internalDate] - message internal date
|
|
@@ -951,6 +970,7 @@ declare type FetchMessageObject = {
|
|
|
951
970
|
labels?: Set<string>;
|
|
952
971
|
size?: number;
|
|
953
972
|
flags?: Set<string>;
|
|
973
|
+
flagColor?: string;
|
|
954
974
|
envelope?: MessageEnvelopeObject;
|
|
955
975
|
bodyStructure?: MessageStructureObject;
|
|
956
976
|
internalDate?: Date;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "imapflow",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.150",
|
|
4
4
|
"description": "IMAP Client for Node",
|
|
5
5
|
"main": "./lib/imap-flow.js",
|
|
6
6
|
"scripts": {
|
|
@@ -28,14 +28,14 @@
|
|
|
28
28
|
},
|
|
29
29
|
"homepage": "https://imapflow.com/",
|
|
30
30
|
"devDependencies": {
|
|
31
|
-
"@babel/eslint-parser": "7.
|
|
32
|
-
"@babel/eslint-plugin": "7.
|
|
31
|
+
"@babel/eslint-parser": "7.23.10",
|
|
32
|
+
"@babel/eslint-plugin": "7.23.5",
|
|
33
33
|
"@babel/plugin-syntax-class-properties": "7.12.13",
|
|
34
|
-
"@babel/preset-env": "7.23.
|
|
35
|
-
"@types/node": "20.
|
|
36
|
-
"eslint": "8.
|
|
34
|
+
"@babel/preset-env": "7.23.9",
|
|
35
|
+
"@types/node": "20.11.15",
|
|
36
|
+
"eslint": "8.56.0",
|
|
37
37
|
"eslint-config-nodemailer": "1.2.0",
|
|
38
|
-
"eslint-config-prettier": "9.
|
|
38
|
+
"eslint-config-prettier": "9.1.0",
|
|
39
39
|
"grunt": "1.6.1",
|
|
40
40
|
"grunt-cli": "1.4.3",
|
|
41
41
|
"grunt-contrib-nodeunit": "5.0.0",
|
|
@@ -52,8 +52,8 @@
|
|
|
52
52
|
"libmime": "5.2.1",
|
|
53
53
|
"libqp": "2.0.1",
|
|
54
54
|
"mailsplit": "5.4.0",
|
|
55
|
-
"nodemailer": "6.9.
|
|
56
|
-
"pino": "8.
|
|
55
|
+
"nodemailer": "6.9.9",
|
|
56
|
+
"pino": "8.17.2",
|
|
57
57
|
"socks": "2.7.1"
|
|
58
58
|
}
|
|
59
59
|
}
|