imapflow 1.0.192 → 1.0.193
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 +7 -0
- package/lib/imap-flow.js +12 -12
- package/package.json +1 -1
- package/test/authentication-test.js +83 -0
- package/test/commands-test.js +73 -0
- package/test/connection-test.js +162 -0
- package/test/integration-test.js +83 -0
- package/test/search-compiler-test.js +81 -0
- package/test/special-use-test.js +49 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.0.193](https://github.com/postalsys/imapflow/compare/v1.0.192...v1.0.193) (2025-07-31)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
* Improved exception handling ([0eb77ac](https://github.com/postalsys/imapflow/commit/0eb77ac28a0f36b085769b6f9a20fd89d9214060))
|
|
9
|
+
|
|
3
10
|
## [1.0.192](https://github.com/postalsys/imapflow/compare/v1.0.191...v1.0.192) (2025-07-31)
|
|
4
11
|
|
|
5
12
|
|
package/lib/imap-flow.js
CHANGED
|
@@ -4,10 +4,6 @@
|
|
|
4
4
|
* @module imapflow
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
// TODO:
|
|
8
|
-
// * Use buffers for compiled commands
|
|
9
|
-
// * OAuth2 authentication
|
|
10
|
-
|
|
11
7
|
const tls = require('tls');
|
|
12
8
|
const net = require('net');
|
|
13
9
|
const crypto = require('crypto');
|
|
@@ -377,7 +373,6 @@ class ImapFlow extends EventEmitter {
|
|
|
377
373
|
}
|
|
378
374
|
|
|
379
375
|
this.log.error({ err, cid: this.id });
|
|
380
|
-
setImmediate(() => this.close());
|
|
381
376
|
this.emitError(err);
|
|
382
377
|
});
|
|
383
378
|
|
|
@@ -386,6 +381,12 @@ class ImapFlow extends EventEmitter {
|
|
|
386
381
|
}
|
|
387
382
|
|
|
388
383
|
emitError(err) {
|
|
384
|
+
if (!err) {
|
|
385
|
+
return;
|
|
386
|
+
}
|
|
387
|
+
err._connId = err._connId || this.id;
|
|
388
|
+
|
|
389
|
+
setImmediate(() => this.close());
|
|
389
390
|
this.emit('error', err);
|
|
390
391
|
}
|
|
391
392
|
|
|
@@ -761,7 +762,6 @@ class ImapFlow extends EventEmitter {
|
|
|
761
762
|
this._socketError ||
|
|
762
763
|
(err => {
|
|
763
764
|
this.log.error({ err, cid: this.id });
|
|
764
|
-
setImmediate(() => this.close());
|
|
765
765
|
this.emitError(err);
|
|
766
766
|
});
|
|
767
767
|
this._socketClose =
|
|
@@ -790,6 +790,10 @@ class ImapFlow extends EventEmitter {
|
|
|
790
790
|
err.code = 'ETIMEOUT';
|
|
791
791
|
|
|
792
792
|
if (this.idling) {
|
|
793
|
+
if (!this.usable || !this.socket || this.socket.destroyed) {
|
|
794
|
+
this.emitError(err);
|
|
795
|
+
return;
|
|
796
|
+
}
|
|
793
797
|
// Attempt to recover IDLE connections
|
|
794
798
|
this.run('NOOP')
|
|
795
799
|
.then(() => this.idle())
|
|
@@ -797,8 +801,7 @@ class ImapFlow extends EventEmitter {
|
|
|
797
801
|
} else {
|
|
798
802
|
// Close immediately for non-IDLE operations
|
|
799
803
|
this.log.debug({ msg: 'Socket timeout', cid: this.id });
|
|
800
|
-
this.
|
|
801
|
-
this.close();
|
|
804
|
+
this.emitError(err);
|
|
802
805
|
}
|
|
803
806
|
});
|
|
804
807
|
|
|
@@ -1175,10 +1178,7 @@ class ImapFlow extends EventEmitter {
|
|
|
1175
1178
|
}
|
|
1176
1179
|
|
|
1177
1180
|
// ALWAYS emit the error so users can handle it
|
|
1178
|
-
|
|
1179
|
-
this.emit('error', err);
|
|
1180
|
-
this.close();
|
|
1181
|
-
});
|
|
1181
|
+
this.emitError(err);
|
|
1182
1182
|
});
|
|
1183
1183
|
}
|
|
1184
1184
|
|
package/package.json
CHANGED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { ImapFlow } = require('../lib/imap-flow');
|
|
4
|
+
const { AuthenticationFailure } = require('../lib/tools');
|
|
5
|
+
|
|
6
|
+
module.exports['Authentication: Password auth configuration'] = test => {
|
|
7
|
+
let client = new ImapFlow({
|
|
8
|
+
host: 'imap.example.com',
|
|
9
|
+
auth: {
|
|
10
|
+
user: 'testuser',
|
|
11
|
+
pass: 'testpass'
|
|
12
|
+
}
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
test.equal(client.options.auth.user, 'testuser');
|
|
16
|
+
test.equal(client.options.auth.pass, 'testpass');
|
|
17
|
+
test.done();
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
module.exports['Authentication: OAuth2 auth configuration'] = test => {
|
|
21
|
+
let client = new ImapFlow({
|
|
22
|
+
host: 'imap.example.com',
|
|
23
|
+
auth: {
|
|
24
|
+
user: 'testuser',
|
|
25
|
+
accessToken: 'oauth2_token_here'
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
test.equal(client.options.auth.user, 'testuser');
|
|
30
|
+
test.equal(client.options.auth.accessToken, 'oauth2_token_here');
|
|
31
|
+
test.done();
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
module.exports['Authentication: Login method specification'] = test => {
|
|
35
|
+
let client = new ImapFlow({
|
|
36
|
+
host: 'imap.example.com',
|
|
37
|
+
auth: {
|
|
38
|
+
user: 'testuser',
|
|
39
|
+
pass: 'testpass',
|
|
40
|
+
loginMethod: 'AUTH=PLAIN'
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
test.equal(client.options.auth.loginMethod, 'AUTH=PLAIN');
|
|
45
|
+
test.done();
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
module.exports['Authentication: AuthenticationFailure error structure'] = test => {
|
|
49
|
+
let error = new AuthenticationFailure('Invalid credentials');
|
|
50
|
+
|
|
51
|
+
test.ok(error instanceof Error);
|
|
52
|
+
test.equal(error.constructor.name, 'AuthenticationFailure');
|
|
53
|
+
test.equal(error.message, 'Invalid credentials');
|
|
54
|
+
test.done();
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
module.exports['Authentication: Verify-only mode'] = test => {
|
|
58
|
+
let client = new ImapFlow({
|
|
59
|
+
host: 'imap.example.com',
|
|
60
|
+
auth: {
|
|
61
|
+
user: 'testuser',
|
|
62
|
+
pass: 'testpass'
|
|
63
|
+
},
|
|
64
|
+
verifyOnly: true
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
test.equal(client.options.verifyOnly, true);
|
|
68
|
+
test.done();
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
module.exports['Authentication: Disable auto IDLE'] = test => {
|
|
72
|
+
let client = new ImapFlow({
|
|
73
|
+
host: 'imap.example.com',
|
|
74
|
+
auth: {
|
|
75
|
+
user: 'testuser',
|
|
76
|
+
pass: 'testpass'
|
|
77
|
+
},
|
|
78
|
+
disableAutoIdle: true
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
test.equal(client.options.disableAutoIdle, true);
|
|
82
|
+
test.done();
|
|
83
|
+
};
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { ImapFlow } = require('../lib/imap-flow');
|
|
4
|
+
|
|
5
|
+
module.exports['Commands: Client instantiation'] = test => {
|
|
6
|
+
let client = new ImapFlow({
|
|
7
|
+
host: 'imap.example.com',
|
|
8
|
+
auth: { user: 'test', pass: 'test' }
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
test.ok(client);
|
|
12
|
+
test.equal(typeof client.exec, 'function');
|
|
13
|
+
test.done();
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
module.exports['Commands: Method availability'] = test => {
|
|
17
|
+
let client = new ImapFlow({
|
|
18
|
+
host: 'imap.example.com',
|
|
19
|
+
auth: { user: 'test', pass: 'test' }
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
// Check that key IMAP methods exist
|
|
23
|
+
test.equal(typeof client.connect, 'function');
|
|
24
|
+
test.equal(typeof client.logout, 'function');
|
|
25
|
+
test.equal(typeof client.list, 'function');
|
|
26
|
+
test.equal(typeof client.mailboxOpen, 'function');
|
|
27
|
+
test.equal(typeof client.mailboxClose, 'function');
|
|
28
|
+
test.equal(typeof client.search, 'function');
|
|
29
|
+
test.equal(typeof client.fetch, 'function');
|
|
30
|
+
test.done();
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
module.exports['Commands: State management methods'] = test => {
|
|
34
|
+
let client = new ImapFlow({
|
|
35
|
+
host: 'imap.example.com',
|
|
36
|
+
auth: { user: 'test', pass: 'test' }
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
test.equal(typeof client.mailboxCreate, 'function');
|
|
40
|
+
test.equal(typeof client.mailboxDelete, 'function');
|
|
41
|
+
test.equal(typeof client.mailboxRename, 'function');
|
|
42
|
+
test.equal(typeof client.mailboxSubscribe, 'function');
|
|
43
|
+
test.equal(typeof client.mailboxUnsubscribe, 'function');
|
|
44
|
+
test.done();
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
module.exports['Commands: Message operation methods'] = test => {
|
|
48
|
+
let client = new ImapFlow({
|
|
49
|
+
host: 'imap.example.com',
|
|
50
|
+
auth: { user: 'test', pass: 'test' }
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
test.equal(typeof client.messageFlagsSet, 'function');
|
|
54
|
+
test.equal(typeof client.messageFlagsAdd, 'function');
|
|
55
|
+
test.equal(typeof client.messageFlagsRemove, 'function');
|
|
56
|
+
test.equal(typeof client.messageCopy, 'function');
|
|
57
|
+
test.equal(typeof client.messageMove, 'function');
|
|
58
|
+
test.equal(typeof client.messageDelete, 'function');
|
|
59
|
+
test.done();
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
module.exports['Commands: Utility methods'] = test => {
|
|
63
|
+
let client = new ImapFlow({
|
|
64
|
+
host: 'imap.example.com',
|
|
65
|
+
auth: { user: 'test', pass: 'test' }
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
test.equal(typeof client.noop, 'function');
|
|
69
|
+
test.equal(typeof client.getQuota, 'function');
|
|
70
|
+
test.equal(typeof client.stats, 'function');
|
|
71
|
+
test.equal(typeof client.getRandomId, 'function');
|
|
72
|
+
test.done();
|
|
73
|
+
};
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { ImapFlow } = require('../lib/imap-flow');
|
|
4
|
+
|
|
5
|
+
module.exports['Connection: Basic connection options'] = test => {
|
|
6
|
+
let client = new ImapFlow({
|
|
7
|
+
host: 'imap.example.com',
|
|
8
|
+
port: 993,
|
|
9
|
+
auth: { user: 'test', pass: 'test' }
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
test.equal(client.host, 'imap.example.com');
|
|
13
|
+
test.equal(client.port, 993);
|
|
14
|
+
test.done();
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
module.exports['Connection: Default options'] = test => {
|
|
18
|
+
let client = new ImapFlow({
|
|
19
|
+
host: 'imap.example.com',
|
|
20
|
+
auth: { user: 'test', pass: 'test' }
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
test.equal(client.port, 110);
|
|
24
|
+
test.equal(client.secureConnection, false);
|
|
25
|
+
test.done();
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
module.exports['Connection: Secure connection defaults'] = test => {
|
|
29
|
+
let client = new ImapFlow({
|
|
30
|
+
host: 'imap.example.com',
|
|
31
|
+
port: 993,
|
|
32
|
+
auth: { user: 'test', pass: 'test' }
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
test.equal(client.secureConnection, true);
|
|
36
|
+
test.done();
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
module.exports['Connection: TLS options'] = test => {
|
|
40
|
+
let client = new ImapFlow({
|
|
41
|
+
host: 'imap.example.com',
|
|
42
|
+
auth: { user: 'test', pass: 'test' },
|
|
43
|
+
tls: {
|
|
44
|
+
rejectUnauthorized: false,
|
|
45
|
+
minVersion: 'TLSv1.3'
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
test.equal(client.options.tls.rejectUnauthorized, false);
|
|
50
|
+
test.equal(client.options.tls.minVersion, 'TLSv1.3');
|
|
51
|
+
test.done();
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
module.exports['Connection: Authentication options'] = test => {
|
|
55
|
+
let client = new ImapFlow({
|
|
56
|
+
host: 'imap.example.com',
|
|
57
|
+
auth: {
|
|
58
|
+
user: 'testuser',
|
|
59
|
+
pass: 'testpass',
|
|
60
|
+
accessToken: 'token123'
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
test.equal(client.options.auth.user, 'testuser');
|
|
65
|
+
test.equal(client.options.auth.pass, 'testpass');
|
|
66
|
+
test.equal(client.options.auth.accessToken, 'token123');
|
|
67
|
+
test.done();
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
module.exports['Connection: Proxy configuration'] = test => {
|
|
71
|
+
let client = new ImapFlow({
|
|
72
|
+
host: 'imap.example.com',
|
|
73
|
+
auth: { user: 'test', pass: 'test' },
|
|
74
|
+
proxy: 'socks5://proxy.example.com:1080'
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
test.equal(client.options.proxy, 'socks5://proxy.example.com:1080');
|
|
78
|
+
test.done();
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
module.exports['Connection: Client info'] = test => {
|
|
82
|
+
let clientInfo = {
|
|
83
|
+
name: 'Test Client',
|
|
84
|
+
version: '1.0.0',
|
|
85
|
+
vendor: 'Test Corp'
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
let client = new ImapFlow({
|
|
89
|
+
host: 'imap.example.com',
|
|
90
|
+
auth: { user: 'test', pass: 'test' },
|
|
91
|
+
clientInfo
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
test.equal(client.clientInfo.name, 'Test Client');
|
|
95
|
+
test.equal(client.clientInfo.version, '1.0.0');
|
|
96
|
+
test.equal(client.clientInfo.vendor, 'Test Corp');
|
|
97
|
+
test.done();
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
module.exports['Connection: Logger configuration'] = test => {
|
|
101
|
+
let client = new ImapFlow({
|
|
102
|
+
host: 'imap.example.com',
|
|
103
|
+
auth: { user: 'test', pass: 'test' },
|
|
104
|
+
logger: false
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
test.equal(client.options.logger, false);
|
|
108
|
+
test.done();
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
module.exports['Connection: Stats tracking'] = test => {
|
|
112
|
+
let client = new ImapFlow({
|
|
113
|
+
host: 'imap.example.com',
|
|
114
|
+
auth: { user: 'test', pass: 'test' }
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
let stats = client.stats();
|
|
118
|
+
test.ok(Object.prototype.hasOwnProperty.call(stats, 'sent'));
|
|
119
|
+
test.ok(Object.prototype.hasOwnProperty.call(stats, 'received'));
|
|
120
|
+
test.equal(typeof stats.sent, 'number');
|
|
121
|
+
test.equal(typeof stats.received, 'number');
|
|
122
|
+
test.done();
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
module.exports['Connection: Random ID generation'] = test => {
|
|
126
|
+
let client = new ImapFlow({
|
|
127
|
+
host: 'imap.example.com',
|
|
128
|
+
auth: { user: 'test', pass: 'test' }
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
let id1 = client.getRandomId();
|
|
132
|
+
let id2 = client.getRandomId();
|
|
133
|
+
|
|
134
|
+
test.ok(typeof id1 === 'string' && id1.length > 0);
|
|
135
|
+
test.ok(typeof id2 === 'string' && id2.length > 0);
|
|
136
|
+
test.notEqual(id1, id2, 'IDs should be unique');
|
|
137
|
+
test.done();
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
module.exports['Connection: State management'] = test => {
|
|
141
|
+
let client = new ImapFlow({
|
|
142
|
+
host: 'imap.example.com',
|
|
143
|
+
auth: { user: 'test', pass: 'test' }
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
test.equal(client.state, client.states.NOT_AUTHENTICATED);
|
|
147
|
+
test.equal(client.authenticated, false);
|
|
148
|
+
test.ok(client.capabilities instanceof Map);
|
|
149
|
+
test.done();
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
module.exports['Connection: Event emitter setup'] = test => {
|
|
153
|
+
let client = new ImapFlow({
|
|
154
|
+
host: 'imap.example.com',
|
|
155
|
+
auth: { user: 'test', pass: 'test' }
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
test.equal(typeof client.on, 'function');
|
|
159
|
+
test.equal(typeof client.emit, 'function');
|
|
160
|
+
test.equal(typeof client.removeListener, 'function');
|
|
161
|
+
test.done();
|
|
162
|
+
};
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { ImapFlow } = require('../lib/imap-flow');
|
|
4
|
+
|
|
5
|
+
module.exports['Integration: Basic client creation'] = test => {
|
|
6
|
+
let client = new ImapFlow({
|
|
7
|
+
host: 'imap.example.com',
|
|
8
|
+
auth: { user: 'test', pass: 'test' }
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
test.ok(client);
|
|
12
|
+
test.equal(client.state, client.states.NOT_AUTHENTICATED);
|
|
13
|
+
test.equal(client.authenticated, false);
|
|
14
|
+
test.done();
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
module.exports['Integration: Multiple client instances'] = test => {
|
|
18
|
+
let client1 = new ImapFlow({
|
|
19
|
+
host: 'imap1.example.com',
|
|
20
|
+
auth: { user: 'test1', pass: 'test1' }
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
let client2 = new ImapFlow({
|
|
24
|
+
host: 'imap2.example.com',
|
|
25
|
+
auth: { user: 'test2', pass: 'test2' }
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
test.ok(client1);
|
|
29
|
+
test.ok(client2);
|
|
30
|
+
test.notEqual(client1.id, client2.id);
|
|
31
|
+
test.done();
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
module.exports['Integration: Client configuration'] = test => {
|
|
35
|
+
let client = new ImapFlow({
|
|
36
|
+
host: 'imap.example.com',
|
|
37
|
+
port: 993,
|
|
38
|
+
secure: true,
|
|
39
|
+
auth: { user: 'test', pass: 'test' },
|
|
40
|
+
logger: false
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
test.equal(client.host, 'imap.example.com');
|
|
44
|
+
test.equal(client.port, 993);
|
|
45
|
+
test.equal(client.secureConnection, true);
|
|
46
|
+
test.done();
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
module.exports['Integration: Event emitter functionality'] = test => {
|
|
50
|
+
let client = new ImapFlow({
|
|
51
|
+
host: 'imap.example.com',
|
|
52
|
+
auth: { user: 'test', pass: 'test' }
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
let eventFired = false;
|
|
56
|
+
client.on('test-event', () => {
|
|
57
|
+
eventFired = true;
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
client.emit('test-event');
|
|
61
|
+
|
|
62
|
+
setTimeout(() => {
|
|
63
|
+
test.ok(eventFired);
|
|
64
|
+
test.done();
|
|
65
|
+
}, 10);
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
module.exports['Integration: Stats functionality'] = test => {
|
|
69
|
+
let client = new ImapFlow({
|
|
70
|
+
host: 'imap.example.com',
|
|
71
|
+
auth: { user: 'test', pass: 'test' }
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
let stats = client.stats();
|
|
75
|
+
test.ok(typeof stats === 'object');
|
|
76
|
+
test.ok(Object.prototype.hasOwnProperty.call(stats, 'sent'));
|
|
77
|
+
test.ok(Object.prototype.hasOwnProperty.call(stats, 'received'));
|
|
78
|
+
|
|
79
|
+
// Reset stats
|
|
80
|
+
let resetStats = client.stats(true);
|
|
81
|
+
test.ok(typeof resetStats === 'object');
|
|
82
|
+
test.done();
|
|
83
|
+
};
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { searchCompiler } = require('../lib/search-compiler');
|
|
4
|
+
|
|
5
|
+
// Mock connection for testing
|
|
6
|
+
let createMockConnection = () => ({
|
|
7
|
+
capabilities: new Map([
|
|
8
|
+
['IMAP4rev1', true],
|
|
9
|
+
['UTF8=ACCEPT', true]
|
|
10
|
+
]),
|
|
11
|
+
enabled: new Set(['UTF8=ACCEPT'])
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
// Mock mailbox for testing
|
|
15
|
+
let createMockMailbox = () => ({
|
|
16
|
+
flags: new Set(['\\Seen', '\\Answered', '\\Flagged', '\\Deleted', '\\Draft']),
|
|
17
|
+
permanentFlags: new Set(['\\*'])
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
module.exports['Search Compiler: Basic functionality'] = test => {
|
|
21
|
+
let connection = createMockConnection();
|
|
22
|
+
let mailbox = createMockMailbox();
|
|
23
|
+
|
|
24
|
+
test.doesNotThrow(() => {
|
|
25
|
+
let compiled = searchCompiler(connection, { seen: false }, mailbox);
|
|
26
|
+
test.ok(Array.isArray(compiled));
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
test.done();
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
module.exports['Search Compiler: Text searches'] = test => {
|
|
33
|
+
let connection = createMockConnection();
|
|
34
|
+
let mailbox = createMockMailbox();
|
|
35
|
+
|
|
36
|
+
let compiled = searchCompiler(connection, {
|
|
37
|
+
from: 'user@example.com',
|
|
38
|
+
subject: 'Test'
|
|
39
|
+
}, mailbox);
|
|
40
|
+
|
|
41
|
+
test.ok(Array.isArray(compiled));
|
|
42
|
+
test.ok(compiled.length > 0);
|
|
43
|
+
test.done();
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
module.exports['Search Compiler: Flag searches'] = test => {
|
|
47
|
+
let connection = createMockConnection();
|
|
48
|
+
let mailbox = createMockMailbox();
|
|
49
|
+
|
|
50
|
+
let compiled = searchCompiler(connection, {
|
|
51
|
+
seen: true,
|
|
52
|
+
answered: false
|
|
53
|
+
}, mailbox);
|
|
54
|
+
|
|
55
|
+
test.ok(Array.isArray(compiled));
|
|
56
|
+
test.ok(compiled.length > 0);
|
|
57
|
+
test.done();
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
module.exports['Search Compiler: Date searches'] = test => {
|
|
61
|
+
let connection = createMockConnection();
|
|
62
|
+
let mailbox = createMockMailbox();
|
|
63
|
+
|
|
64
|
+
let compiled = searchCompiler(connection, {
|
|
65
|
+
since: new Date('2023-01-01')
|
|
66
|
+
}, mailbox);
|
|
67
|
+
|
|
68
|
+
test.ok(Array.isArray(compiled));
|
|
69
|
+
test.ok(compiled.length > 0);
|
|
70
|
+
test.done();
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
module.exports['Search Compiler: Empty query'] = test => {
|
|
74
|
+
let connection = createMockConnection();
|
|
75
|
+
let mailbox = createMockMailbox();
|
|
76
|
+
|
|
77
|
+
let compiled = searchCompiler(connection, {}, mailbox);
|
|
78
|
+
|
|
79
|
+
test.ok(Array.isArray(compiled));
|
|
80
|
+
test.done();
|
|
81
|
+
};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const specialUse = require('../lib/special-use');
|
|
4
|
+
|
|
5
|
+
module.exports['Special Use: flags array'] = test => {
|
|
6
|
+
test.ok(Array.isArray(specialUse.flags));
|
|
7
|
+
test.ok(specialUse.flags.includes('\\Sent'));
|
|
8
|
+
test.ok(specialUse.flags.includes('\\Drafts'));
|
|
9
|
+
test.ok(specialUse.flags.includes('\\Trash'));
|
|
10
|
+
test.ok(specialUse.flags.includes('\\Archive'));
|
|
11
|
+
test.done();
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
module.exports['Special Use: names object'] = test => {
|
|
15
|
+
test.ok(typeof specialUse.names === 'object');
|
|
16
|
+
test.ok(specialUse.names['\\Sent']);
|
|
17
|
+
test.ok(Array.isArray(specialUse.names['\\Sent']));
|
|
18
|
+
test.ok(specialUse.names['\\Sent'].includes('sent'));
|
|
19
|
+
test.done();
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
module.exports['Special Use: Sent folder names'] = test => {
|
|
23
|
+
let sentNames = specialUse.names['\\Sent'];
|
|
24
|
+
test.ok(sentNames.includes('sent'));
|
|
25
|
+
test.ok(sentNames.includes('sent items'));
|
|
26
|
+
test.ok(sentNames.includes('sent messages'));
|
|
27
|
+
test.done();
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
module.exports['Special Use: Drafts folder names'] = test => {
|
|
31
|
+
let draftsNames = specialUse.names['\\Drafts'];
|
|
32
|
+
test.ok(draftsNames.includes('drafts'));
|
|
33
|
+
test.done();
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
module.exports['Special Use: Trash folder names'] = test => {
|
|
37
|
+
let trashNames = specialUse.names['\\Trash'];
|
|
38
|
+
test.ok(trashNames.includes('trash'));
|
|
39
|
+
test.ok(trashNames.includes('deleted items'));
|
|
40
|
+
test.ok(trashNames.includes('deleted messages'));
|
|
41
|
+
test.done();
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
module.exports['Special Use: Junk folder names'] = test => {
|
|
45
|
+
let junkNames = specialUse.names['\\Junk'];
|
|
46
|
+
test.ok(junkNames.includes('spam'));
|
|
47
|
+
test.ok(junkNames.includes('junk'));
|
|
48
|
+
test.done();
|
|
49
|
+
};
|