emailengine-app 2.61.5 → 2.62.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/CHANGELOG.md +78 -0
- package/data/google-crawlers.json +1 -1
- package/lib/account.js +20 -7
- package/lib/api-routes/account-routes.js +28 -5
- package/lib/api-routes/chat-routes.js +1 -1
- package/lib/api-routes/export-routes.js +316 -0
- package/lib/api-routes/message-routes.js +28 -23
- package/lib/api-routes/template-routes.js +28 -7
- package/lib/arf-detect.js +1 -1
- package/lib/consts.js +16 -0
- package/lib/db.js +3 -0
- package/lib/email-client/base-client.js +6 -4
- package/lib/email-client/gmail-client.js +204 -33
- package/lib/email-client/imap/mailbox.js +99 -8
- package/lib/email-client/imap/subconnection.js +5 -5
- package/lib/email-client/imap-client.js +76 -16
- package/lib/email-client/message-builder.js +3 -1
- package/lib/email-client/notification-handler.js +12 -9
- package/lib/email-client/outlook-client.js +362 -69
- package/lib/email-client/smtp-pool-manager.js +1 -1
- package/lib/export.js +528 -0
- package/lib/oauth/gmail.js +21 -13
- package/lib/oauth/mail-ru.js +23 -10
- package/lib/oauth/outlook.js +26 -16
- package/lib/oauth/pubsub/google.js +5 -0
- package/lib/routes-ui.js +235 -1
- package/lib/schemas.js +260 -80
- package/lib/stream-encrypt.js +263 -0
- package/lib/tools.js +30 -4
- package/lib/ui-routes/account-routes.js +23 -0
- package/lib/ui-routes/admin-config-routes.js +11 -4
- package/lib/ui-routes/admin-entities-routes.js +18 -0
- package/lib/webhooks.js +16 -20
- package/package.json +16 -16
- package/sbom.json +1 -1
- package/server.js +41 -5
- package/static/js/ace/ace.js +1 -1
- package/static/js/ace/ext-language_tools.js +1 -1
- package/static/licenses.html +52 -62
- package/translations/de.mo +0 -0
- package/translations/de.po +63 -36
- package/translations/en.mo +0 -0
- package/translations/en.po +64 -37
- package/translations/et.mo +0 -0
- package/translations/et.po +63 -36
- package/translations/fr.mo +0 -0
- package/translations/fr.po +63 -36
- package/translations/ja.mo +0 -0
- package/translations/ja.po +63 -36
- package/translations/messages.pot +80 -47
- package/translations/nl.mo +0 -0
- package/translations/nl.po +63 -36
- package/translations/pl.mo +0 -0
- package/translations/pl.po +63 -36
- package/views/accounts/account.hbs +375 -2
- package/views/config/service.hbs +35 -0
- package/workers/api.js +123 -44
- package/workers/documents.js +1 -0
- package/workers/export.js +926 -0
- package/workers/imap.js +29 -0
- package/workers/submit.js +25 -5
- package/workers/webhooks.js +11 -2
package/server.js
CHANGED
|
@@ -131,7 +131,7 @@ if (readEnvValue('BUGSNAG_API_KEY')) {
|
|
|
131
131
|
|
|
132
132
|
// Import additional dependencies
|
|
133
133
|
const pathlib = require('path');
|
|
134
|
-
const { redis, queueConf } = require('./lib/db');
|
|
134
|
+
const { redis, queueConf, notifyQueue, submitQueue, documentsQueue, exportQueue } = require('./lib/db');
|
|
135
135
|
const promClient = require('prom-client');
|
|
136
136
|
const fs = require('fs').promises;
|
|
137
137
|
const crypto = require('crypto');
|
|
@@ -302,6 +302,7 @@ const THREAD_NAMES = {
|
|
|
302
302
|
webhooks: 'Webhook worker',
|
|
303
303
|
api: 'HTTP and API server',
|
|
304
304
|
submit: 'Email sending worker',
|
|
305
|
+
export: 'Export worker',
|
|
305
306
|
documents: 'Document store indexing worker',
|
|
306
307
|
imapProxy: 'IMAP proxy server',
|
|
307
308
|
smtp: 'SMTP proxy server'
|
|
@@ -314,7 +315,8 @@ const THREAD_NAMES = {
|
|
|
314
315
|
const THREAD_CONFIG_VALUES = {
|
|
315
316
|
imap: { key: 'EENGINE_WORKERS', value: config.workers.imap },
|
|
316
317
|
submit: { key: 'EENGINE_WORKERS_SUBMIT', value: config.workers.submit },
|
|
317
|
-
webhooks: { key: 'EENGINE_WORKERS_WEBHOOKS', value: config.workers.webhooks }
|
|
318
|
+
webhooks: { key: 'EENGINE_WORKERS_WEBHOOKS', value: config.workers.webhooks },
|
|
319
|
+
export: { key: 'EENGINE_WORKERS_EXPORT', value: config.workers.export || 1 }
|
|
318
320
|
};
|
|
319
321
|
|
|
320
322
|
// Queue event handlers for different job queues
|
|
@@ -2618,10 +2620,13 @@ async function onCommand(worker, message) {
|
|
|
2618
2620
|
break;
|
|
2619
2621
|
|
|
2620
2622
|
// IMAP operations - forward to assigned worker
|
|
2623
|
+
case 'submitMessage':
|
|
2624
|
+
case 'queueMessage':
|
|
2621
2625
|
case 'listMessages':
|
|
2622
2626
|
case 'getRawMessage':
|
|
2623
2627
|
case 'getText':
|
|
2624
2628
|
case 'getMessage':
|
|
2629
|
+
case 'getMessages':
|
|
2625
2630
|
case 'updateMessage':
|
|
2626
2631
|
case 'updateMessages':
|
|
2627
2632
|
case 'listMailboxes':
|
|
@@ -2633,8 +2638,6 @@ async function onCommand(worker, message) {
|
|
|
2633
2638
|
case 'createMailbox':
|
|
2634
2639
|
case 'modifyMailbox':
|
|
2635
2640
|
case 'deleteMailbox':
|
|
2636
|
-
case 'submitMessage':
|
|
2637
|
-
case 'queueMessage':
|
|
2638
2641
|
case 'uploadMessage':
|
|
2639
2642
|
case 'getAttachment':
|
|
2640
2643
|
case 'listSignatures': {
|
|
@@ -2649,7 +2652,6 @@ async function onCommand(worker, message) {
|
|
|
2649
2652
|
if (['getRawMessage', 'getAttachment'].includes(message.cmd) && message.port) {
|
|
2650
2653
|
transferList.push(message.port);
|
|
2651
2654
|
}
|
|
2652
|
-
|
|
2653
2655
|
if (['submitMessage', 'queueMessage'].includes(message.cmd) && typeof message.raw === 'object') {
|
|
2654
2656
|
transferList.push(message.raw);
|
|
2655
2657
|
}
|
|
@@ -2779,6 +2781,10 @@ const closeQueues = cb => {
|
|
|
2779
2781
|
proms.push(queueEvents.documents.close());
|
|
2780
2782
|
}
|
|
2781
2783
|
|
|
2784
|
+
if (queueEvents.export) {
|
|
2785
|
+
proms.push(queueEvents.export.close());
|
|
2786
|
+
}
|
|
2787
|
+
|
|
2782
2788
|
if (!proms.length) {
|
|
2783
2789
|
return setImmediate(() => cb());
|
|
2784
2790
|
}
|
|
@@ -3105,6 +3111,11 @@ const startApplication = async () => {
|
|
|
3105
3111
|
await spawnWorker('submit');
|
|
3106
3112
|
}
|
|
3107
3113
|
|
|
3114
|
+
// Start export workers
|
|
3115
|
+
for (let i = 0; i < (config.workers.export || 1); i++) {
|
|
3116
|
+
await spawnWorker('export');
|
|
3117
|
+
}
|
|
3118
|
+
|
|
3108
3119
|
// Start document processing worker
|
|
3109
3120
|
await spawnWorker('documents');
|
|
3110
3121
|
|
|
@@ -3187,6 +3198,31 @@ startApplication()
|
|
|
3187
3198
|
queueEvents.notify = new QueueEvents('notify', Object.assign({}, queueConf));
|
|
3188
3199
|
queueEvents.submit = new QueueEvents('submit', Object.assign({}, queueConf));
|
|
3189
3200
|
queueEvents.documents = new QueueEvents('documents', Object.assign({}, queueConf));
|
|
3201
|
+
queueEvents.export = new QueueEvents('export', Object.assign({}, queueConf));
|
|
3202
|
+
|
|
3203
|
+
// Periodic queue cleanup (every 6 hours)
|
|
3204
|
+
const QUEUE_CLEANUP_INTERVAL = 6 * 60 * 60 * 1000;
|
|
3205
|
+
|
|
3206
|
+
async function cleanupQueues() {
|
|
3207
|
+
const queues = [notifyQueue, submitQueue, documentsQueue, exportQueue];
|
|
3208
|
+
for (const queue of queues) {
|
|
3209
|
+
try {
|
|
3210
|
+
// Clean completed jobs older than 24 hours
|
|
3211
|
+
await queue.clean(24 * 60 * 60 * 1000, 10000, 'completed');
|
|
3212
|
+
// Clean failed jobs older than 7 days
|
|
3213
|
+
await queue.clean(7 * 24 * 60 * 60 * 1000, 10000, 'failed');
|
|
3214
|
+
logger.trace({ msg: 'Queue cleanup completed', queue: queue.name });
|
|
3215
|
+
} catch (err) {
|
|
3216
|
+
logger.error({ msg: 'Queue cleanup failed', queue: queue.name, err });
|
|
3217
|
+
}
|
|
3218
|
+
}
|
|
3219
|
+
}
|
|
3220
|
+
|
|
3221
|
+
const queueCleanupTimer = setInterval(cleanupQueues, QUEUE_CLEANUP_INTERVAL);
|
|
3222
|
+
queueCleanupTimer.unref();
|
|
3223
|
+
|
|
3224
|
+
// Initial cleanup 5 minutes after startup
|
|
3225
|
+
setTimeout(cleanupQueues, 5 * 60 * 1000).unref();
|
|
3190
3226
|
})
|
|
3191
3227
|
.catch(err => {
|
|
3192
3228
|
logger.fatal({ msg: 'Application startup failed', err });
|