imapkit 4.3.1 → 5.0.0
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/README.md +167 -51
- package/bin/help.txt +17 -3
- package/bin/imapkit.js +53 -23
- package/dist/cjs/commands/append.js +1 -1
- package/dist/cjs/commands/create.js +2 -2
- package/dist/cjs/commands/delete.js +2 -14
- package/dist/cjs/commands/handlers/flags.d.ts +3 -3
- package/dist/cjs/commands/handlers/flags.js +3 -3
- package/dist/cjs/commands/handlers/store.js +3 -3
- package/dist/cjs/commands/rename.js +6 -46
- package/dist/cjs/commands/select.js +1 -0
- package/dist/cjs/commands/subscribe.js +7 -8
- package/dist/cjs/commands/unsubscribe.js +3 -9
- package/dist/cjs/control.d.ts +430 -0
- package/dist/cjs/control.js +637 -0
- package/dist/cjs/index.d.ts +8 -1
- package/dist/cjs/index.js +9 -2
- package/dist/cjs/load-plugins.d.ts +1 -1
- package/dist/cjs/load-plugins.js +7 -2
- package/dist/cjs/plugins/acl.js +109 -42
- package/dist/cjs/plugins/condstore.js +7 -0
- package/dist/cjs/plugins/index.js +1 -3
- package/dist/cjs/plugins/metadata.js +140 -57
- package/dist/cjs/plugins/objectid.js +10 -0
- package/dist/cjs/plugins/quota.js +50 -2
- package/dist/cjs/plugins/savedate.js +1 -1
- package/dist/cjs/plugins/special-use.d.ts +0 -8
- package/dist/cjs/plugins/special-use.js +23 -0
- package/dist/cjs/quirks.d.ts +28 -0
- package/dist/cjs/quirks.js +124 -0
- package/dist/cjs/random.d.ts +10 -0
- package/dist/cjs/random.js +22 -0
- package/dist/cjs/rest.d.ts +50 -0
- package/dist/cjs/rest.js +561 -0
- package/dist/cjs/script.d.ts +33 -4
- package/dist/cjs/script.js +64 -4
- package/dist/cjs/server.d.ts +147 -8
- package/dist/cjs/server.js +398 -144
- package/dist/cjs/smtp-listener.d.ts +3 -2
- package/dist/cjs/smtp-listener.js +10 -6
- package/dist/cjs/storage-schema.d.ts +139 -0
- package/dist/cjs/storage-schema.js +215 -0
- package/dist/cjs/store-operations.d.ts +168 -0
- package/dist/cjs/store-operations.js +422 -0
- package/dist/cjs/types.d.ts +22 -1
- package/dist/esm/commands/append.js +1 -1
- package/dist/esm/commands/create.js +2 -2
- package/dist/esm/commands/delete.js +2 -14
- package/dist/esm/commands/handlers/flags.d.ts +3 -3
- package/dist/esm/commands/handlers/flags.js +3 -3
- package/dist/esm/commands/handlers/store.js +3 -3
- package/dist/esm/commands/rename.js +6 -46
- package/dist/esm/commands/select.js +1 -0
- package/dist/esm/commands/subscribe.js +7 -8
- package/dist/esm/commands/unsubscribe.js +3 -9
- package/dist/esm/control.d.ts +430 -0
- package/dist/esm/control.js +630 -0
- package/dist/esm/index.d.ts +8 -1
- package/dist/esm/index.js +5 -2
- package/dist/esm/load-plugins.d.ts +1 -1
- package/dist/esm/load-plugins.js +7 -2
- package/dist/esm/plugins/acl.js +109 -42
- package/dist/esm/plugins/condstore.js +7 -0
- package/dist/esm/plugins/index.js +1 -3
- package/dist/esm/plugins/metadata.js +140 -57
- package/dist/esm/plugins/objectid.js +10 -0
- package/dist/esm/plugins/quota.js +50 -2
- package/dist/esm/plugins/savedate.js +1 -1
- package/dist/esm/plugins/special-use.d.ts +0 -8
- package/dist/esm/plugins/special-use.js +23 -0
- package/dist/esm/quirks.d.ts +28 -0
- package/dist/esm/quirks.js +120 -0
- package/dist/esm/random.d.ts +10 -0
- package/dist/esm/random.js +19 -0
- package/dist/esm/rest.d.ts +50 -0
- package/dist/esm/rest.js +553 -0
- package/dist/esm/script.d.ts +33 -4
- package/dist/esm/script.js +63 -4
- package/dist/esm/server.d.ts +147 -8
- package/dist/esm/server.js +399 -145
- package/dist/esm/smtp-listener.d.ts +3 -2
- package/dist/esm/smtp-listener.js +10 -6
- package/dist/esm/storage-schema.d.ts +139 -0
- package/dist/esm/storage-schema.js +211 -0
- package/dist/esm/store-operations.d.ts +168 -0
- package/dist/esm/store-operations.js +407 -0
- package/dist/esm/types.d.ts +22 -1
- package/dist/plugin-help.json +0 -14
- package/package.json +11 -3
- package/dist/cjs/plugins/xtoybird.d.ts +0 -2
- package/dist/cjs/plugins/xtoybird.js +0 -236
- package/dist/esm/plugins/xtoybird.d.ts +0 -2
- package/dist/esm/plugins/xtoybird.js +0 -218
package/dist/cjs/script.js
CHANGED
|
@@ -4,14 +4,18 @@ exports.ServerScript = void 0;
|
|
|
4
4
|
exports.sendOutput = sendOutput;
|
|
5
5
|
exports.releaseDeferred = releaseDeferred;
|
|
6
6
|
exports.literalResponse = literalResponse;
|
|
7
|
+
exports.handleQuiet = handleQuiet;
|
|
7
8
|
exports.handleLine = handleLine;
|
|
8
|
-
const
|
|
9
|
+
const random_js_1 = require("./random.js");
|
|
10
|
+
const numbers_js_1 = require("./numbers.js");
|
|
11
|
+
const EVENTS = ['greeting', 'command', 'input', 'response', 'continuation', 'quiet'];
|
|
9
12
|
const OUTPUT_EVENTS = ['greeting', 'response', 'continuation'];
|
|
10
13
|
// the events where a key is valid, every other key is a typo and refused
|
|
11
14
|
const KEYS = {
|
|
12
15
|
on: EVENTS,
|
|
13
|
-
|
|
14
|
-
|
|
16
|
+
// a quiet event belongs to the command that waits for input (IDLE), if there is one
|
|
17
|
+
command: ['command', 'input', 'response', 'continuation', 'quiet'],
|
|
18
|
+
tag: ['command', 'input', 'response', 'continuation', 'quiet'],
|
|
15
19
|
description: ['response', 'continuation'],
|
|
16
20
|
session: EVENTS,
|
|
17
21
|
user: EVENTS,
|
|
@@ -22,6 +26,8 @@ const KEYS = {
|
|
|
22
26
|
when: EVENTS,
|
|
23
27
|
nth: EVENTS,
|
|
24
28
|
times: EVENTS,
|
|
29
|
+
chance: EVENTS,
|
|
30
|
+
quietFor: ['quiet'],
|
|
25
31
|
mutate: ['response', 'continuation'],
|
|
26
32
|
literals: ['response'],
|
|
27
33
|
defer: ['response'],
|
|
@@ -29,7 +35,7 @@ const KEYS = {
|
|
|
29
35
|
before: OUTPUT_EVENTS,
|
|
30
36
|
after: OUTPUT_EVENTS,
|
|
31
37
|
run: ['command', 'input'],
|
|
32
|
-
drop:
|
|
38
|
+
drop: ['greeting', 'command', 'input', 'response', 'continuation'],
|
|
33
39
|
delay: ['greeting', 'command', 'response', 'continuation'],
|
|
34
40
|
chunk: EVENTS,
|
|
35
41
|
chunkDelay: EVENTS,
|
|
@@ -77,6 +83,12 @@ function validateRule(rule) {
|
|
|
77
83
|
throw new TypeError('Script rule option "' + key + '" can not be used with "on": "' + rule.on + '"');
|
|
78
84
|
}
|
|
79
85
|
}
|
|
86
|
+
if (rule.on === 'quiet' && !(Number.isInteger(rule.quietFor) && rule.quietFor > 0)) {
|
|
87
|
+
throw new TypeError('A quiet rule needs "quietFor", a positive number of milliseconds');
|
|
88
|
+
}
|
|
89
|
+
if (rule.chance !== undefined && !(typeof rule.chance === 'number' && rule.chance >= 0 && rule.chance <= 1)) {
|
|
90
|
+
throw new TypeError('Script rule option "chance" must be a number from 0 to 1');
|
|
91
|
+
}
|
|
80
92
|
if (!ACTIONS.some(key => rule[key] !== undefined && rule[key] !== false)) {
|
|
81
93
|
throw new TypeError('A script rule needs an action (' + ACTIONS.join(', ') + ')');
|
|
82
94
|
}
|
|
@@ -99,6 +111,9 @@ function validateRule(rule) {
|
|
|
99
111
|
}
|
|
100
112
|
}
|
|
101
113
|
for (const key of ['delay', 'chunkDelay', 'truncate']) {
|
|
114
|
+
if (key === 'chunkDelay' && rule[key] === 'tick') {
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
102
117
|
if (rule[key] !== undefined && !(Number.isInteger(rule[key]) && rule[key] >= 0)) {
|
|
103
118
|
throw new TypeError('Script rule option "' + key + '" must be a non-negative integer');
|
|
104
119
|
}
|
|
@@ -157,6 +172,14 @@ class ServerScript {
|
|
|
157
172
|
constructor(server, rules) {
|
|
158
173
|
this.server = server;
|
|
159
174
|
this.entries = [];
|
|
175
|
+
this.ruleCounter = 0;
|
|
176
|
+
const seed = server.options.scriptSeed;
|
|
177
|
+
const seedRandom = () => {
|
|
178
|
+
this.random = (0, random_js_1.seededRandom)(typeof seed === 'number' ? seed : Math.floor(Math.random() * numbers_js_1.MAX_NUMBER));
|
|
179
|
+
};
|
|
180
|
+
seedRandom();
|
|
181
|
+
// control.reset() starts the same random sequence again
|
|
182
|
+
server.on('reset', seedRandom);
|
|
160
183
|
this.watched = new Set();
|
|
161
184
|
if (rules) {
|
|
162
185
|
this.add(rules);
|
|
@@ -206,6 +229,26 @@ class ServerScript {
|
|
|
206
229
|
setEntries(entries) {
|
|
207
230
|
this.entries = entries;
|
|
208
231
|
this.watched = new Set(entries.map(entry => entry.rule.on));
|
|
232
|
+
if (this.watched.has('quiet')) {
|
|
233
|
+
// sessions that are quiet already start counting now
|
|
234
|
+
this.server.connections?.forEach(connection => connection.watchQuiet());
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* The next quiet time a rule waits for, after the quiet time the rules were checked for already
|
|
239
|
+
*
|
|
240
|
+
* @param {Number} checked Milliseconds of quiet the rules were checked for
|
|
241
|
+
* @return {Number|null} the smallest `quietFor` above it, null if there is none
|
|
242
|
+
*/
|
|
243
|
+
nextQuiet(checked) {
|
|
244
|
+
let next = null;
|
|
245
|
+
for (const entry of this.entries) {
|
|
246
|
+
const quietFor = entry.rule.quietFor;
|
|
247
|
+
if (entry.rule.on === 'quiet' && quietFor !== undefined && quietFor > checked && (next === null || quietFor < next)) {
|
|
248
|
+
next = quietFor;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
return next;
|
|
209
252
|
}
|
|
210
253
|
addEntry(rule, match) {
|
|
211
254
|
// a copy, so that changing the caller's object later does not change the rule
|
|
@@ -219,6 +262,7 @@ class ServerScript {
|
|
|
219
262
|
}
|
|
220
263
|
}
|
|
221
264
|
const entry = {
|
|
265
|
+
id: ++this.ruleCounter,
|
|
222
266
|
rule: copy,
|
|
223
267
|
match,
|
|
224
268
|
sets,
|
|
@@ -245,6 +289,9 @@ class ServerScript {
|
|
|
245
289
|
if (entry.matched < (rule.nth || 1) || (rule.times !== undefined && entry.hits >= rule.times)) {
|
|
246
290
|
continue;
|
|
247
291
|
}
|
|
292
|
+
if (rule.chance !== undefined && this.random() >= rule.chance) {
|
|
293
|
+
continue;
|
|
294
|
+
}
|
|
248
295
|
entry.hits++;
|
|
249
296
|
this.server.emit('script', { rule, event: context.event, session: context.session, tag: context.tag, command: context.command });
|
|
250
297
|
return rule;
|
|
@@ -266,6 +313,9 @@ class ServerScript {
|
|
|
266
313
|
if (rule.untagged !== undefined && rule.untagged !== (!context.response || context.response.tag === '*')) {
|
|
267
314
|
return false;
|
|
268
315
|
}
|
|
316
|
+
if (rule.quietFor !== undefined && (context.quiet || 0) < rule.quietFor) {
|
|
317
|
+
return false;
|
|
318
|
+
}
|
|
269
319
|
if (entry.match && !entry.match.test(context.data)) {
|
|
270
320
|
return false;
|
|
271
321
|
}
|
|
@@ -460,6 +510,16 @@ function sendBytes(connection, rule, data, delay) {
|
|
|
460
510
|
close: rule.close || (rule.truncate === undefined ? undefined : true)
|
|
461
511
|
});
|
|
462
512
|
}
|
|
513
|
+
/**
|
|
514
|
+
* Handles a quiet event with the rule that matched it: sends the bytes of `send` and closes the connection with `close`
|
|
515
|
+
*
|
|
516
|
+
* @param {Object} connection IMAP connection
|
|
517
|
+
* @param {Object} rule Rule that matched
|
|
518
|
+
* @param {Object} context Event context
|
|
519
|
+
*/
|
|
520
|
+
function handleQuiet(connection, rule, context) {
|
|
521
|
+
sendBytes(connection, rule, resolveBytes(rule.send, context) || Buffer.alloc(0));
|
|
522
|
+
}
|
|
463
523
|
/**
|
|
464
524
|
* Handles a command or input line with the rule that matched it: sends the bytes of `send`, closes the connection,
|
|
465
525
|
* and processes the line as usual with `run` (or when the rule only delays it)
|
package/dist/cjs/server.d.ts
CHANGED
|
@@ -1,12 +1,28 @@
|
|
|
1
1
|
import { Stream } from 'node:stream';
|
|
2
2
|
import net from 'node:net';
|
|
3
|
+
import http from 'node:http';
|
|
3
4
|
import tls from 'node:tls';
|
|
4
5
|
import type { CompilerOptions, ParserOptions } from 'imap-handler';
|
|
5
6
|
import type { ResolvedCommandOptions } from './command-states.js';
|
|
7
|
+
import { Control } from './control.js';
|
|
8
|
+
import type { SessionInfo } from './control.js';
|
|
6
9
|
import { ServerScript } from './script.js';
|
|
7
10
|
import type { DeferredOutput, OutputOperation, ScriptContext, ScriptEvent, ScriptRule } from './script.js';
|
|
8
11
|
import type { AppendCheck, AppendCheckOptions, AppendDataHandler, AppendMessage, CapabilityCheck, CheckResult, ClosedCheck, CommandCheck, CommandContext, CommandOptions, CommandHandler, ConnectionHandler, ConnectionState, CopyHandler, FetchHandler, IMAPResponse, IMAPServerOptions, ListedMailbox, LiteralFilter, Mailbox, MailboxHandler, MailboxStatus, Message, MessageFilter, MessageHandler, MessageRange, Namespace, Notification, NotifyEvent, NotifyFilter, OutputHandler, ParsedCommand, RangeLimit, Refusal, SearchAccessCheck, SearchHandler, SearchLimit, ServerStorage, StatusHandler, StorageMailbox, StorageMessage, StoreHandler, SubscriptionStandIn, Transport, UrlAccessCheck, UserData } from './types.js';
|
|
9
12
|
declare const TAG_REGEX: RegExp;
|
|
13
|
+
/** The parts of a smtp-server SMTPServer that the server uses, smtp-server is an optional dependency */
|
|
14
|
+
interface SMTPListener {
|
|
15
|
+
close(callback: () => void): void;
|
|
16
|
+
once(event: 'error', listener: (err: Error) => void): unknown;
|
|
17
|
+
removeListener(event: 'error', listener: (err: Error) => void): unknown;
|
|
18
|
+
server: net.Server;
|
|
19
|
+
}
|
|
20
|
+
/** The command whose tagged response is pending, and the session state before it ran */
|
|
21
|
+
interface CommandStart {
|
|
22
|
+
tag: string;
|
|
23
|
+
command: string;
|
|
24
|
+
state: ConnectionState;
|
|
25
|
+
}
|
|
10
26
|
/**
|
|
11
27
|
* Creates a new IMAP server, call `listen()` on it to start accepting connections
|
|
12
28
|
*
|
|
@@ -64,7 +80,58 @@ declare class IMAPServer extends Stream {
|
|
|
64
80
|
script: ServerScript;
|
|
65
81
|
/** connections accepted so far, the number of a connection is `connection.sessionNumber` */
|
|
66
82
|
sessionCounter: number;
|
|
83
|
+
/** the control API, see src/control.ts */
|
|
84
|
+
control: Control;
|
|
85
|
+
/** the SMTP server that `start()` runs for the `smtp` option */
|
|
86
|
+
smtpServer: SMTPListener | null;
|
|
87
|
+
/** the HTTP server of the REST API that `start()` runs for the `rest` option */
|
|
88
|
+
restServer: http.Server | null;
|
|
67
89
|
constructor(options?: IMAPServerOptions);
|
|
90
|
+
/**
|
|
91
|
+
* Sets the users from the `users` option, or the default user. The users are deep copied, so that runtime changes
|
|
92
|
+
* never leak into the caller's objects or into other servers built from the same fixture. Without a prototype,
|
|
93
|
+
* user names like "__proto__" or "toString" are plain keys
|
|
94
|
+
*/
|
|
95
|
+
loadUsers(): void;
|
|
96
|
+
/**
|
|
97
|
+
* Builds the mailboxes from the `storage` option, a deep copy of it. Message and mailbox handlers of plugins run
|
|
98
|
+
* on every message and mailbox
|
|
99
|
+
*/
|
|
100
|
+
loadStorage(): void;
|
|
101
|
+
/**
|
|
102
|
+
* Starts accepting connections
|
|
103
|
+
*
|
|
104
|
+
* @param {Number} [port] Port to listen on, a free port if not set
|
|
105
|
+
* @param {String} [host] Address to listen on, all addresses if not set
|
|
106
|
+
* @return {Promise<Number>} resolves with the port the server listens on
|
|
107
|
+
*/
|
|
108
|
+
start(port?: number, host?: string): Promise<number>;
|
|
109
|
+
/**
|
|
110
|
+
* Starts the REST API of the `rest` option, see src/rest.ts
|
|
111
|
+
*
|
|
112
|
+
* @return {Promise<Number>} resolves with the HTTP port
|
|
113
|
+
*/
|
|
114
|
+
startRest(): Promise<number>;
|
|
115
|
+
/**
|
|
116
|
+
* Starts the SMTP server of the `smtp` option. smtp-server is an optional dependency, loaded only here
|
|
117
|
+
*
|
|
118
|
+
* @return {Promise<Number>} resolves with the SMTP port
|
|
119
|
+
*/
|
|
120
|
+
startSmtp(): Promise<number>;
|
|
121
|
+
/**
|
|
122
|
+
* Loads the SMTP listener, which needs the smtp-server package
|
|
123
|
+
*
|
|
124
|
+
* @return {Promise<Object>} the smtp-listener module
|
|
125
|
+
*/
|
|
126
|
+
loadSmtpListener(): Promise<{
|
|
127
|
+
startSMTPServer(port: number, server: IMAPServer, callback: (port: number) => void, host?: string): SMTPListener;
|
|
128
|
+
}>;
|
|
129
|
+
/**
|
|
130
|
+
* Stops the server and closes every connection
|
|
131
|
+
*
|
|
132
|
+
* @return {Promise} resolves when the server is closed
|
|
133
|
+
*/
|
|
134
|
+
stop(): Promise<void>;
|
|
68
135
|
/**
|
|
69
136
|
* Starts accepting connections, takes the arguments of `net.Server#listen()`
|
|
70
137
|
*/
|
|
@@ -72,6 +139,13 @@ declare class IMAPServer extends Stream {
|
|
|
72
139
|
listen(port: number, hostname: string, listeningListener?: () => void): void;
|
|
73
140
|
listen(options: net.ListenOptions, listeningListener?: () => void): void;
|
|
74
141
|
close(callback?: (err?: Error) => void): void;
|
|
142
|
+
/**
|
|
143
|
+
* Stops the SMTP and REST listeners of `start()`
|
|
144
|
+
*
|
|
145
|
+
* @param {Boolean} force true closes the open REST connections too, otherwise only the idle ones (a request that
|
|
146
|
+
* is answered, like POST /v1/shutdown, finishes first)
|
|
147
|
+
*/
|
|
148
|
+
closeListeners(force: boolean): void;
|
|
75
149
|
/**
|
|
76
150
|
* Returns TLS key and certificate. Without credentials in the options the
|
|
77
151
|
* bundled self-signed certificate for localhost is used.
|
|
@@ -144,13 +218,23 @@ declare class IMAPServer extends Stream {
|
|
|
144
218
|
*
|
|
145
219
|
* @param {String} type Kind of change
|
|
146
220
|
* @param {String} path Storage name of the mailbox
|
|
147
|
-
* @param {Object} [details] `{ oldPath, mailbox }`: the earlier name of a renamed mailbox, the mailbox
|
|
148
|
-
* object that a DELETE removed
|
|
221
|
+
* @param {Object} [details] `{ oldPath, mailbox, created }`: the earlier name of a renamed mailbox, the mailbox
|
|
222
|
+
* object that a DELETE removed, the mailboxes a CREATE made (superior levels first)
|
|
149
223
|
*/
|
|
150
224
|
mailboxChanged(type: string, path: string, details?: {
|
|
151
225
|
oldPath?: string | undefined;
|
|
152
226
|
mailbox?: Mailbox | undefined;
|
|
227
|
+
created?: string[] | undefined;
|
|
153
228
|
}): void;
|
|
229
|
+
/**
|
|
230
|
+
* Runs a change with `origin` as the session that caused it, the `origin` of the notifications and events it
|
|
231
|
+
* makes. Commands run with their session, the control API with null
|
|
232
|
+
*
|
|
233
|
+
* @param {Object|null} origin Session, or null for a change from outside
|
|
234
|
+
* @param {Function} fn Change
|
|
235
|
+
* @return {*} the result of fn
|
|
236
|
+
*/
|
|
237
|
+
withOrigin<T>(origin: IMAPConnection | null, fn: () => T): T;
|
|
154
238
|
/**
|
|
155
239
|
* Retrieves the handler of an IMAP command
|
|
156
240
|
*
|
|
@@ -286,6 +370,13 @@ declare class IMAPServer extends Stream {
|
|
|
286
370
|
* @param {Array} flags Flags of a message
|
|
287
371
|
*/
|
|
288
372
|
rememberFlags(mailbox: Mailbox, flags: string[]): void;
|
|
373
|
+
/**
|
|
374
|
+
* The current time for dates the server sets itself (INTERNALDATE of a message without one, SAVEDATE). The `now`
|
|
375
|
+
* option fixes it for repeatable tests: a Date, a timestamp, or a function that returns one
|
|
376
|
+
*
|
|
377
|
+
* @return {Date} current time
|
|
378
|
+
*/
|
|
379
|
+
now(): Date;
|
|
289
380
|
/**
|
|
290
381
|
* Converts a date-time value from storage or a client to the form it is sent in
|
|
291
382
|
*
|
|
@@ -510,11 +601,18 @@ declare class IMAPConnection {
|
|
|
510
601
|
} | undefined;
|
|
511
602
|
/** output that waits behind a delay of a script rule, null when output is written right away */
|
|
512
603
|
_outputQueue: OutputOperation[] | null;
|
|
513
|
-
_outputTimer: ReturnType<typeof setTimeout> | null;
|
|
604
|
+
_outputTimer: ReturnType<typeof setTimeout> | ReturnType<typeof setImmediate> | null;
|
|
605
|
+
/** a piece of a chunked write with chunkDelay 0 or "tick" waits until it was handed to the system */
|
|
606
|
+
_outputWaiting: boolean | undefined;
|
|
514
607
|
/** untagged responses that `defer` rules hold back, see releaseDeferred in src/script.ts */
|
|
515
608
|
_deferredOutput: DeferredOutput[] | null;
|
|
516
609
|
/** a script rule closes the connection with a RST, see closeNow */
|
|
517
610
|
_resetting: boolean | undefined;
|
|
611
|
+
/** time of the last input or output, and the timer of the quiet events of script rules, see watchQuiet */
|
|
612
|
+
_lastActivity: number | undefined;
|
|
613
|
+
_quietTimer: ReturnType<typeof setTimeout> | null | undefined;
|
|
614
|
+
/** the command whose tagged response is pending and the session before it ran, see commandCompleted */
|
|
615
|
+
_commandStart: CommandStart | null | undefined;
|
|
518
616
|
constructor(server: IMAPServer, socket: net.Socket);
|
|
519
617
|
/**
|
|
520
618
|
* Writes protocol output to the client, through the transport layer if there is one
|
|
@@ -542,8 +640,9 @@ declare class IMAPConnection {
|
|
|
542
640
|
*
|
|
543
641
|
* @param {Buffer} data Output
|
|
544
642
|
* @param {Object|null} transport Transport layer
|
|
643
|
+
* @param {Function} [callback] Called once the data was handed to the system (a transport: on the next turn)
|
|
545
644
|
*/
|
|
546
|
-
writeLayer(data: Buffer, transport: Transport | null): void;
|
|
645
|
+
writeLayer(data: Buffer, transport: Transport | null, callback?: () => void): void;
|
|
547
646
|
/**
|
|
548
647
|
* Sends output through the script rule that handles its event, if there is one
|
|
549
648
|
*
|
|
@@ -566,7 +665,19 @@ declare class IMAPConnection {
|
|
|
566
665
|
*
|
|
567
666
|
* @param {Buffer} data Data to send
|
|
568
667
|
*/
|
|
569
|
-
writeRaw(data: Buffer | string): void;
|
|
668
|
+
writeRaw(data: Buffer | string, callback?: () => void): void;
|
|
669
|
+
/**
|
|
670
|
+
* Notes input or output for the quiet events of script rules (#88)
|
|
671
|
+
*/
|
|
672
|
+
touch(): void;
|
|
673
|
+
/**
|
|
674
|
+
* Starts waiting for the next quiet event, if a rule waits for one and the session is not waiting already. When
|
|
675
|
+
* the time is up, the first rule that matches handles the event (`send`, `close`), the output it sends starts
|
|
676
|
+
* the next quiet time
|
|
677
|
+
*
|
|
678
|
+
* @param {Number} [checked] Quiet time the rules were checked for already, only longer ones are waited for
|
|
679
|
+
*/
|
|
680
|
+
watchQuiet(checked?: number): void;
|
|
570
681
|
/**
|
|
571
682
|
* Handles data from the socket, through the transport layer if there is one
|
|
572
683
|
*
|
|
@@ -949,6 +1060,34 @@ declare class IMAPConnection {
|
|
|
949
1060
|
* @param {Boolean} [scripted] The line comes from a script rule with `run`, it is next in the queue
|
|
950
1061
|
*/
|
|
951
1062
|
scheduleCommand(data: string, scripted?: boolean): void;
|
|
1063
|
+
/**
|
|
1064
|
+
* Emits the `command` event when the tagged response of a command goes out, and the `session` events "login"
|
|
1065
|
+
* (the command authenticated the session) and "logout" (back to Not Authenticated, UNAUTHENTICATE). Every command
|
|
1066
|
+
* that changes these does so before its tagged response. "select" and "unselect" come from SELECT and
|
|
1067
|
+
* closeMailbox(). Tests wait for these instead of polling
|
|
1068
|
+
*
|
|
1069
|
+
* @param {String} status OK, NO or BAD
|
|
1070
|
+
*/
|
|
1071
|
+
commandCompleted(status: string): void;
|
|
1072
|
+
/**
|
|
1073
|
+
* Emits a `session` event, `{ type, session, ...fields }`
|
|
1074
|
+
*
|
|
1075
|
+
* @param {String} type Event type
|
|
1076
|
+
* @param {Object} [fields] More fields of the event
|
|
1077
|
+
*/
|
|
1078
|
+
emitSession(type: string, fields?: Record<string, unknown>): void;
|
|
1079
|
+
/**
|
|
1080
|
+
* Describes the session without credentials or sockets, for the control API and the `session` events
|
|
1081
|
+
*
|
|
1082
|
+
* @return {Object} `{ session, user, state, mailbox, readOnly, enabled, secure, compressed, remoteAddress }`
|
|
1083
|
+
*/
|
|
1084
|
+
describe(): SessionInfo;
|
|
1085
|
+
/**
|
|
1086
|
+
* Checks if output can still be sent: the socket is open and the connection is not closing (BYE, LOGOUT)
|
|
1087
|
+
*
|
|
1088
|
+
* @return {Boolean} true for a live session
|
|
1089
|
+
*/
|
|
1090
|
+
isOpen(): boolean;
|
|
952
1091
|
/**
|
|
953
1092
|
* Handles a command line with the script rule that matched it, after the rule's delay. With `run` the line
|
|
954
1093
|
* goes through the parser and the command handler as usual afterwards
|
|
@@ -963,19 +1102,19 @@ declare class IMAPConnection {
|
|
|
963
1102
|
*
|
|
964
1103
|
* @param {Object} mailbox Mailbox to check for
|
|
965
1104
|
* @param {Boolean} [ignoreSelf] If set to true, does not send any notices to itself
|
|
966
|
-
* @param {Boolean} [
|
|
1105
|
+
* @param {Boolean} [ignoreExists] If set to true, does not send EXISTS notice to itself
|
|
967
1106
|
*/
|
|
968
1107
|
expungeDeleted(mailbox: Mailbox, ignoreSelf?: boolean, ignoreExists?: boolean): void;
|
|
969
1108
|
/**
|
|
970
1109
|
* Given a set of messages in a mailbox (possibly via getMessageRange), remove
|
|
971
|
-
* them from the mailbox and generate EXPUNGE notifications.
|
|
1110
|
+
* them from the mailbox and generate EXPUNGE notifications, see expungeMessages() in store-operations.ts
|
|
972
1111
|
*
|
|
973
1112
|
* @param {Object} mailbox Mailbox to check for
|
|
974
1113
|
* @param {Function|Array} messagesOrFilterFunc An Array of messages in the
|
|
975
1114
|
* folder that should be removed or a filtering function that indicates
|
|
976
1115
|
* messages to be removed by returning true.
|
|
977
1116
|
* @param {Boolean} [ignoreSelf] If set to true, does not send any notices to itself
|
|
978
|
-
* @param {Boolean} [
|
|
1117
|
+
* @param {Boolean} [ignoreExists] If set to true, does not send EXISTS notice to itself
|
|
979
1118
|
* @param {Boolean} [highestFirst] If set to true, the EXPUNGE responses go from the highest UID to the lowest
|
|
980
1119
|
* (MESSAGELIMIT, RFC 9738 section 3.1), otherwise from the lowest
|
|
981
1120
|
*/
|