@brickert/kerio-connect-api 0.0.7 → 0.0.8

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/index.d.ts CHANGED
@@ -83,6 +83,7 @@ export interface GenericResponse {
83
83
  result?: Array;
84
84
  token?: string;
85
85
  detail?: string;
86
+ deleteItems?: number;
86
87
  }
87
88
  };
88
89
  }
@@ -109,6 +110,7 @@ export class Kerio extends WebClient {
109
110
  Logs: Logs;
110
111
  Domains: Domains;
111
112
  Users: Users;
113
+ MessageQueues: MessageQueues;
112
114
 
113
115
  login(user: KerioUser): void;
114
116
 
@@ -404,4 +406,100 @@ export interface KerioUserStatistic {
404
406
  xmpp: number;
405
407
  xmpps: number;
406
408
  }
407
- }
409
+ }
410
+
411
+ export class MessageQueues extends KerioModules {
412
+ /**
413
+ * Get a Mapped Array of KerioMessageItems indexed by their ID for messages that are pending to be processed
414
+ * @returns {Promise<Map<import('../index.d.ts').KerioMessageID, import('../index.d.ts').KerioMessageItem>>}
415
+ */
416
+ pending(): Promise<Map<KerioMessageID, KerioMessageItem>>;
417
+
418
+ /**
419
+ * Remove select message(s) that are held in queue/processing queue.
420
+ * @param messageId Single or Array of KerioMessageID(s)
421
+ * @returns {Promise<number>} Number of successfully removed messages
422
+ */
423
+ removeFromQueue(messageId: KerioMessageID | Array<KerioMessageID>): Promise<number>;
424
+
425
+ /**
426
+ * Remove all message(s) in the queue pending to be processed
427
+ * @returns {Promise<number>} Number of successfully removed messages
428
+ */
429
+ flushQueue(): Promise<number>;
430
+
431
+ /**
432
+ * Manually trigger sending these message(s) before their scheduled re-attempt
433
+ * @param messageId Single or Array of KerioMessageID(s)
434
+ * @returns {Promise<void>} Returns void. Access Kerio.MessageQueues.pending() to see any changes, messages not listed there are successfully being placed into the processed queue.
435
+ */
436
+ trySendingNow(messageId: KerioMessageID | Array<KerioMessageID>): Promise<void>;
437
+
438
+ /**
439
+ * Get a Mapped Array of KerioMessageItems indexed by their ID for a snapshot of the server's activity on processing messages
440
+ * @returns {Promise<Map<import('../index.d.ts').KerioMessageID, import('../index.d.ts').KerioMessageProcessedItem>>}
441
+ */
442
+ processing(): Promise<Map<KerioMessageID, KerioMessageProcessedItem>>;
443
+
444
+ /**
445
+ * Manually process message(s) now from their current stage.
446
+ * @returns {Promise<void>} Returns void. Access Kerio.MessageQueues.procesing() to see any changes, messages not listed there are successfully delivered to the destination server.
447
+ */
448
+ tryProcessingNow(): Promise<void>;
449
+ }
450
+
451
+ /**
452
+ * @example "1a2b3c4d-00000"
453
+ */
454
+ export type KerioMessageID = string;
455
+
456
+ export interface KerioMessageItem {
457
+ id: KerioMessageID;
458
+ status: string;
459
+ time: {
460
+ creationTime: string; //YYYY-MM-DD HH:MM of server's timezone
461
+ nextTry: string; //YYYY-MM-DD HH:MM of server's timezone
462
+ };
463
+ messageSize: {
464
+ value: number;
465
+ units: "Bytes"
466
+ };
467
+ headers: {
468
+ from: string;
469
+ to: string;
470
+ };
471
+ authSender: {
472
+ address: string; //Authorized SMTP user email address
473
+ ip: string; //Authorized SMTP user ip address
474
+ }
475
+ }
476
+
477
+ export interface KerioMessageProcessedItem {
478
+ id: KerioMessageID;
479
+ status: {
480
+ progress: number; //Current progress in the current status stage
481
+ stage: KerioMessageProcessStatusEnum;
482
+ timeInCurrentStatus: string; //in HH:MM:SS format
483
+ };
484
+ messageSize: {
485
+ value: number;
486
+ units: "Bytes"
487
+ };
488
+ headers: {
489
+ from: string;
490
+ to: string;
491
+ destination: string; //Target SMTP server FQDN
492
+ };
493
+
494
+ }
495
+
496
+ /**
497
+ * msExecuting: General execution/starting state.
498
+ * msBackup: Message is being backed up.
499
+ * msContentFiltering: Passing through content/spam filters.
500
+ * msAntivirusControl: Being scanned for viruses.
501
+ * msLocalDelivering: Delivering to a mailbox on the local server.
502
+ * msSmtpDelivering: Attempting delivery to the next hop SMTP server.
503
+ * msFinishing: Finalizing the delivery/cleanup process.
504
+ */
505
+ export type KerioMessageProcessStatusEnum = "msExecuting" | "msBackup" | "msContentFiltering" | "msAntivirusControl" | "msLocalDelivering" | "msSmtpDelivering" | "msFinishing";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brickert/kerio-connect-api",
3
- "version": "0.0.7",
3
+ "version": "0.0.8",
4
4
  "description": "An unofficial API wrapper for Kerio Connect Mail Server jsonrpc Admin API.",
5
5
  "keywords": [
6
6
  "kerio",
package/src/kerio.js CHANGED
@@ -3,6 +3,7 @@ import { Logs } from "./logs.js";
3
3
  import { Session } from "./session.js";
4
4
  import { Domains } from "./domains.js";
5
5
  import { Users } from "./users.js";
6
+ import { MessageQueues } from "./msgqueues.js";
6
7
  import { WebClient } from "./client.js";
7
8
  import { CronJob } from 'cron';
8
9
  import pino from 'pino';
@@ -27,6 +28,7 @@ export class Kerio extends WebClient {
27
28
  this.Session = new Session(this);
28
29
  this.Domains = new Domains(this);
29
30
  this.Users = new Users(this);
31
+ this.MessageQueues = new MessageQueues(this);
30
32
 
31
33
  this.logger = pino({
32
34
  level: "debug",
@@ -0,0 +1,469 @@
1
+ import { KerioModules } from './modules.js';
2
+
3
+ export class MessageQueues extends KerioModules {
4
+
5
+ /**
6
+ * Get a Mapped Array of KerioMessageItems indexed by their ID for messages that are pending to be processed
7
+ * @returns {Promise<Map<import('../index.d.ts').KerioMessageID, import('../index.d.ts').KerioMessageItem>>}
8
+ */
9
+ async pending() {
10
+ try {
11
+ if (!this.instance.logged_in) {
12
+
13
+ this.reset();
14
+
15
+ throw {
16
+ name: "KerioClientSessionError",
17
+ message: `Kerio session invalid. Try logging in again.`,
18
+ type: 'Kerio',
19
+ from: "Kerio.MessageQueues.queued"
20
+ }
21
+ }
22
+
23
+ let queue_response = await this.sessionedRequest({
24
+ http_method: 'POST',
25
+ api_method: 'Queue.get',
26
+ auth: {
27
+ cookie: this.instance.session_cookie,
28
+ token: this.instance.x_token
29
+ },
30
+ body_params: {
31
+ query: {
32
+ }
33
+ }
34
+ });
35
+
36
+ let response_body = queue_response._body;
37
+
38
+ if (!response_body.result?.errors && !response_body?.error) {
39
+
40
+ var queueMsgsResult = new Map();
41
+
42
+ if (response_body.result.list.length > 0) {
43
+ response_body.result.list.forEach(msg => {
44
+
45
+ queueMsgsResult.set(msg.id, {
46
+ id: msg.id,
47
+ status: msg.status,
48
+ time: {
49
+ created: msg.creationTime,
50
+ nextTry: msg.nextTry
51
+ },
52
+ messageSize: {
53
+ value: msg.messageSize.value,
54
+ units: msg.messageSize.units
55
+ },
56
+ headers: {
57
+ from: msg.from,
58
+ to: msg.to
59
+ },
60
+ authSender: {
61
+ address: msg.authSender,
62
+ ip: msg.senderIp
63
+ }
64
+ });
65
+ });
66
+ }
67
+
68
+ this.instance.logger.debug({
69
+ name: "KerioQueuedMessagesPending",
70
+ message: `listed ${queueMsgsResult.size} queued messages pending to be processed`,
71
+ type: "Kerio",
72
+ from: "Kerio.MessageQueues.queued"
73
+ });
74
+
75
+ return queueMsgsResult;
76
+
77
+ } else {
78
+ throw {
79
+ name: "KerioRequestError",
80
+ message: `Error occured while fetching results from API method 'Queue.get'`,
81
+ type: 'Kerio',
82
+ from: "Kerio.MessageQueues.list"
83
+ }
84
+ }
85
+
86
+ } catch (e) {
87
+ this.instance.logger.error(e);
88
+ throw e;
89
+ }
90
+ }
91
+
92
+ /**
93
+ * Remove select message(s) that are held in the list of queue/processing queue.
94
+ * @param messageId Single or Array of KerioMessageID(s)
95
+ * @returns {Promise<number>} Number of successfully removed messages
96
+ */
97
+ async removeFromQueue(messageId = null) {
98
+ try {
99
+ if (!this.instance.logged_in) {
100
+
101
+ this.reset();
102
+
103
+ throw {
104
+ name: "KerioClientSessionError",
105
+ message: `Kerio session invalid. Try logging in again.`,
106
+ type: 'Kerio',
107
+ from: "Kerio.MessageQueues.removeFromQueue"
108
+ }
109
+ }
110
+
111
+ if (!messageId || (Array.isArray(messageId) && messageId.length == 0)) {
112
+ throw {
113
+ name: "KerioMessageIdError",
114
+ message: `Invalid message ID or array of message IDs while processing API method 'Queue.remove'`,
115
+ type: 'Kerio',
116
+ from: "Kerio.MessageQueues.removeFromQueue"
117
+ }
118
+ }
119
+
120
+ //If single message ID string, convert to array of one element
121
+ if (!Array.isArray(messageId)) {
122
+ messageId = [messageId];
123
+ }
124
+
125
+ let queue_remove_response = await this.sessionedRequest({
126
+ http_method: 'POST',
127
+ api_method: 'Queue.remove',
128
+ auth: {
129
+ cookie: this.instance.session_cookie,
130
+ token: this.instance.x_token
131
+ },
132
+ body_params: {
133
+ query: {
134
+ },
135
+ messageIds: messageId
136
+ }
137
+ });
138
+
139
+ let response_body = queue_remove_response._body;
140
+
141
+ if (!response_body.result?.errors && !response_body?.error) {
142
+
143
+ this.instance.logger.debug({
144
+ name: "KerioQueuedMessagesRemoved",
145
+ message: `Removed ${response_body.result.deleteItems} queued messages that were pending to be processed`,
146
+ type: "Kerio",
147
+ from: "Kerio.MessageQueues.removeFromQueue"
148
+ });
149
+
150
+ return response_body.result.deleteItems;
151
+
152
+ } else {
153
+ throw {
154
+ name: "KerioRequestError",
155
+ message: `Error occured while fetching results from API method 'Queue.remove'`,
156
+ type: 'Kerio',
157
+ from: "Kerio.MessageQueues.removeFromQueue"
158
+ }
159
+ }
160
+
161
+ } catch (e) {
162
+ this.instance.logger.error(e);
163
+ throw e;
164
+ }
165
+ }
166
+
167
+ /**
168
+ * Remove all message(s) in the queue pending to be processed
169
+ * @returns {Promise<number>} Number of successfully removed messages
170
+ */
171
+ async flushQueue() {
172
+ try {
173
+ if (!this.instance.logged_in) {
174
+
175
+ this.reset();
176
+
177
+ throw {
178
+ name: "KerioClientSessionError",
179
+ message: `Kerio session invalid. Try logging in again.`,
180
+ type: 'Kerio',
181
+ from: "Kerio.MessageQueues.flushQueue"
182
+ }
183
+ }
184
+
185
+ let queue_response = await this.sessionedRequest({
186
+ http_method: 'POST',
187
+ api_method: 'Queue.removeAll',
188
+ auth: {
189
+ cookie: this.instance.session_cookie,
190
+ token: this.instance.x_token
191
+ },
192
+ body_params: {
193
+ query: {
194
+ }
195
+ }
196
+ });
197
+
198
+ let response_body = queue_response._body;
199
+
200
+ if (!response_body.result?.errors && !response_body?.error) {
201
+
202
+ this.instance.logger.debug({
203
+ name: "KerioQueuedMessagesFlush",
204
+ message: `Flushed ${response_body.result.deleteItems} queued messages pending to be processed`,
205
+ type: "Kerio",
206
+ from: "Kerio.MessageQueues.flushQueue"
207
+ });
208
+
209
+ return response_body.result.deleteItems;
210
+
211
+ } else {
212
+ throw {
213
+ name: "KerioRequestError",
214
+ message: `Error occured while fetching results from API method 'Queue.removeAll'`,
215
+ type: 'Kerio',
216
+ from: "Kerio.MessageQueues.flushQueue"
217
+ }
218
+ }
219
+
220
+ } catch (e) {
221
+ this.instance.logger.error(e);
222
+ throw e;
223
+ }
224
+ }
225
+
226
+ /**
227
+ * Manually trigger sending these message(s) before their scheduled re-attempt
228
+ * @param messageId Single or Array of KerioMessageID(s)
229
+ * @returns {Promise<void>} Returns void. Access Kerio.MessageQueues.queued() to see any changes, messages not listed there are successfully being placed into the processed queue.
230
+ */
231
+ async trySendingNow(messageId = null) {
232
+ try {
233
+ if (!this.instance.logged_in) {
234
+
235
+ this.reset();
236
+
237
+ throw {
238
+ name: "KerioClientSessionError",
239
+ message: `Kerio session invalid. Try logging in again.`,
240
+ type: 'Kerio',
241
+ from: "Kerio.MessageQueues.trySendingNow"
242
+ }
243
+ }
244
+
245
+ if (!messageId || (Array.isArray(messageId) && messageId.length == 0)) {
246
+ throw {
247
+ name: "KerioMessageIdError",
248
+ message: `Invalid message ID or array of message IDs while processing API method 'Queue.tryToSend'`,
249
+ type: 'Kerio',
250
+ from: "Kerio.MessageQueues.trySendingNow"
251
+ }
252
+ }
253
+
254
+ //If single message ID string, convert to array of one element
255
+ if (!Array.isArray(messageId)) {
256
+ messageId = [messageId];
257
+ }
258
+
259
+ let try_sending_response = await this.sessionedRequest({
260
+ http_method: 'POST',
261
+ api_method: 'Queue.tryToSend',
262
+ auth: {
263
+ cookie: this.instance.session_cookie,
264
+ token: this.instance.x_token
265
+ },
266
+ body_params: {
267
+ query: {
268
+ },
269
+ messageIds: messageId
270
+ }
271
+ });
272
+
273
+ let response_body = try_sending_response._body;
274
+
275
+ if (!response_body.result?.errors && !response_body?.error) {
276
+
277
+ let debug_msg = "";
278
+
279
+ if (Array.isArray(messageId)) {
280
+ debug_msg = `Processing ${messageId.length} specified queued messages right now. Message IDs of '${messageId.join(', ')}'`;
281
+ } else {
282
+ debug_msg = `Processing queued message right now. Message ID of '${messageId}'`;
283
+ }
284
+
285
+ this.instance.logger.debug({
286
+ name: "KerioQueueTrySendingNowAttempt",
287
+ message: debug_msg,
288
+ type: "Kerio",
289
+ from: "Kerio.MessageQueues.trySendingNow"
290
+ });
291
+
292
+ return;
293
+
294
+ } else {
295
+
296
+ if (response_body?.error?.code) {
297
+ switch (response_body?.error?.code) {
298
+ case 1000:
299
+ // One or more Message Ids don't exist or already processed
300
+ // Safe to silently error and return as you are intended to do Kerio.MessageQueues.pending() to check the status after.
301
+ return;
302
+ default:
303
+ throw {
304
+ name: "KerioRequestError",
305
+ message: `Error occured while fetching results from API method 'Queue.tryToSend'`,
306
+ type: 'Kerio',
307
+ from: "Kerio.MessageQueues.trySendingNow"
308
+ }
309
+ }
310
+ }
311
+
312
+ throw {
313
+ name: "KerioRequestError",
314
+ message: `Error occured while fetching results from API method 'Queue.tryToSend'`,
315
+ type: 'Kerio',
316
+ from: "Kerio.MessageQueues.trySendingNow"
317
+ }
318
+ }
319
+
320
+ } catch (e) {
321
+ this.instance.logger.error(e);
322
+ throw e;
323
+ }
324
+ }
325
+
326
+ /**
327
+ * Get a Mapped Array of KerioMessageItems indexed by their ID for a snapshot of the server's activity on processing messages
328
+ * @returns {Promise<Map<import('../index.d.ts').KerioMessageID, import('../index.d.ts').KerioMessageProcessedItem>>}
329
+ */
330
+ async processing() {
331
+ try {
332
+ if (!this.instance.logged_in) {
333
+
334
+ this.reset();
335
+
336
+ throw {
337
+ name: "KerioClientSessionError",
338
+ message: `Kerio session invalid. Try logging in again.`,
339
+ type: 'Kerio',
340
+ from: "Kerio.MessageQueues.processing"
341
+ }
342
+ }
343
+
344
+ let process_response = await this.sessionedRequest({
345
+ http_method: 'POST',
346
+ api_method: 'Queue.getProcessed',
347
+ auth: {
348
+ cookie: this.instance.session_cookie,
349
+ token: this.instance.x_token
350
+ },
351
+ body_params: {
352
+ query: {
353
+ }
354
+ }
355
+ });
356
+
357
+ let response_body = process_response._body;
358
+
359
+ if (!response_body.result?.errors && !response_body?.error) {
360
+
361
+ var processMsgsResult = new Map();
362
+
363
+ if (response_body.result.list.length > 0) {
364
+ response_body.result.list.forEach(msg => {
365
+
366
+ processMsgsResult.set(msg.id, {
367
+ id: msg.id,
368
+ status: {
369
+ progress: msg.percentage,
370
+ stage: msg.status,
371
+ timeInCurrentStatus: msg.time
372
+ },
373
+ messageSize: {
374
+ value: msg.messageSize.value,
375
+ units: msg.messageSize.units
376
+ },
377
+ headers: {
378
+ from: msg.from,
379
+ to: msg.to,
380
+ destination: msg.server
381
+ }
382
+ });
383
+ });
384
+ }
385
+
386
+ this.instance.logger.debug({
387
+ name: "KerioQueuedMessages",
388
+ message: `listed ${processMsgsResult.size} processing messages`,
389
+ type: "Kerio",
390
+ from: "Kerio.MessageQueues.processing"
391
+ });
392
+
393
+ return processMsgsResult;
394
+
395
+ } else {
396
+ throw {
397
+ name: "KerioRequestError",
398
+ message: `Error occured while fetching results from API method 'Queue.get'`,
399
+ type: 'Kerio',
400
+ from: "Kerio.MessageQueues.list"
401
+ }
402
+ }
403
+
404
+ } catch (e) {
405
+ this.instance.logger.error(e);
406
+ throw e;
407
+ }
408
+ }
409
+
410
+ /**
411
+ * Manually process message(s) now from their current stage.
412
+ * @returns {Promise<void>} Returns void. Access Kerio.MessageQueues.procesing() to see any changes, messages not listed there are successfully delivered to the destination server.
413
+ */
414
+ async tryProcessingNow() {
415
+ try {
416
+ if (!this.instance.logged_in) {
417
+
418
+ this.reset();
419
+
420
+ throw {
421
+ name: "KerioClientSessionError",
422
+ message: `Kerio session invalid. Try logging in again.`,
423
+ type: 'Kerio',
424
+ from: "Kerio.MessageQueues.tryProcessingNow"
425
+ }
426
+ }
427
+
428
+ let try_process_response = await this.sessionedRequest({
429
+ http_method: 'POST',
430
+ api_method: 'Queue.run',
431
+ auth: {
432
+ cookie: this.instance.session_cookie,
433
+ token: this.instance.x_token
434
+ },
435
+ body_params: {
436
+ query: {
437
+ }
438
+ }
439
+ });
440
+
441
+ let response_body = try_process_response._body;
442
+
443
+ if (!response_body.result?.errors && !response_body?.error) {
444
+
445
+ this.instance.logger.debug({
446
+ name: "KerioQueueProcessingNow",
447
+ message: `Force processing messages`,
448
+ type: "Kerio",
449
+ from: "Kerio.MessageQueues.tryProcessingNow"
450
+ });
451
+
452
+ return;
453
+
454
+ } else {
455
+ throw {
456
+ name: "KerioRequestError",
457
+ message: `Error occured while fetching results from API method 'Queue.run'`,
458
+ type: 'Kerio',
459
+ from: "Kerio.MessageQueues.tryProcessingNow"
460
+ }
461
+ }
462
+
463
+ } catch (e) {
464
+ this.instance.logger.error(e);
465
+ throw e;
466
+ }
467
+ }
468
+
469
+ }