emailengine-app 2.61.5 → 2.62.1

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.
Files changed (65) hide show
  1. package/CHANGELOG.md +88 -0
  2. package/data/google-crawlers.json +1 -1
  3. package/lib/account.js +20 -7
  4. package/lib/api-routes/account-routes.js +28 -5
  5. package/lib/api-routes/chat-routes.js +1 -1
  6. package/lib/api-routes/export-routes.js +316 -0
  7. package/lib/api-routes/message-routes.js +28 -23
  8. package/lib/api-routes/template-routes.js +28 -7
  9. package/lib/arf-detect.js +1 -1
  10. package/lib/autodetect-imap-settings.js +5 -5
  11. package/lib/consts.js +16 -0
  12. package/lib/db.js +3 -0
  13. package/lib/email-client/base-client.js +6 -4
  14. package/lib/email-client/gmail-client.js +205 -35
  15. package/lib/email-client/imap/mailbox.js +99 -8
  16. package/lib/email-client/imap/subconnection.js +5 -5
  17. package/lib/email-client/imap-client.js +76 -19
  18. package/lib/email-client/message-builder.js +3 -1
  19. package/lib/email-client/notification-handler.js +12 -9
  20. package/lib/email-client/outlook-client.js +364 -73
  21. package/lib/email-client/smtp-pool-manager.js +1 -1
  22. package/lib/export.js +528 -0
  23. package/lib/oauth/gmail.js +24 -16
  24. package/lib/oauth/mail-ru.js +26 -13
  25. package/lib/oauth/outlook.js +29 -19
  26. package/lib/oauth/pubsub/google.js +5 -0
  27. package/lib/routes-ui.js +268 -9
  28. package/lib/schemas.js +274 -81
  29. package/lib/stream-encrypt.js +263 -0
  30. package/lib/sub-script.js +2 -2
  31. package/lib/tools.js +194 -12
  32. package/lib/ui-routes/account-routes.js +23 -0
  33. package/lib/ui-routes/admin-config-routes.js +13 -6
  34. package/lib/ui-routes/admin-entities-routes.js +18 -0
  35. package/lib/webhooks.js +16 -20
  36. package/package.json +20 -20
  37. package/sbom.json +1 -1
  38. package/server.js +66 -7
  39. package/static/js/ace/ace.js +1 -1
  40. package/static/js/ace/ext-language_tools.js +1 -1
  41. package/static/licenses.html +118 -149
  42. package/translations/de.mo +0 -0
  43. package/translations/de.po +63 -36
  44. package/translations/en.mo +0 -0
  45. package/translations/en.po +64 -37
  46. package/translations/et.mo +0 -0
  47. package/translations/et.po +63 -36
  48. package/translations/fr.mo +0 -0
  49. package/translations/fr.po +63 -36
  50. package/translations/ja.mo +0 -0
  51. package/translations/ja.po +63 -36
  52. package/translations/messages.pot +84 -51
  53. package/translations/nl.mo +0 -0
  54. package/translations/nl.po +63 -36
  55. package/translations/pl.mo +0 -0
  56. package/translations/pl.po +63 -36
  57. package/views/accounts/account.hbs +375 -2
  58. package/views/config/network.hbs +45 -0
  59. package/views/config/service.hbs +35 -0
  60. package/workers/api.js +130 -47
  61. package/workers/documents.js +3 -2
  62. package/workers/export.js +933 -0
  63. package/workers/imap.js +34 -1
  64. package/workers/submit.js +33 -6
  65. package/workers/webhooks.js +20 -4
package/workers/api.js CHANGED
@@ -39,7 +39,8 @@ const {
39
39
  hasEnvValue,
40
40
  getBoolean,
41
41
  loadTlsConfig,
42
- retryAgent
42
+ httpAgent,
43
+ reloadHttpProxyAgent
43
44
  } = require('../lib/tools');
44
45
  const { matchIp, detectAutomatedRequest } = require('../lib/utils/network');
45
46
 
@@ -132,6 +133,7 @@ const chatRoutes = require('../lib/api-routes/chat-routes');
132
133
  const bullBoardRoutes = require('../lib/api-routes/bull-board-routes');
133
134
  const accountRoutes = require('../lib/api-routes/account-routes');
134
135
  const messageRoutes = require('../lib/api-routes/message-routes');
136
+ const exportRoutes = require('../lib/api-routes/export-routes');
135
137
 
136
138
  const {
137
139
  settingsSchema,
@@ -174,7 +176,8 @@ const AccountTypeSchema = Joi.string()
174
176
  .valid(...['imap'].concat(Object.keys(OAUTH_PROVIDERS)).concat('oauth2'))
175
177
  .example('outlook')
176
178
  .description('Account type')
177
- .required();
179
+ .required()
180
+ .label('AccountType');
178
181
 
179
182
  const SUPPORTED_LOCALES = locales.map(locale => locale.locale);
180
183
 
@@ -289,7 +292,7 @@ class ResponseStream extends Transform {
289
292
  this._finalized = false;
290
293
 
291
294
  // Ensure cleanup on all stream end scenarios
292
- this.once('error', () => this.finalize());
295
+ this.on('error', () => this.finalize());
293
296
  this.once('close', () => this.finalize());
294
297
  this.once('end', () => this.finalize());
295
298
  }
@@ -297,6 +300,7 @@ class ResponseStream extends Transform {
297
300
  updateTimer() {
298
301
  clearTimeout(this.periodicKeepAliveTimer);
299
302
  this.periodicKeepAliveTimer = setTimeout(() => {
303
+ if (this._finalized || this.destroyed) return;
300
304
  this.write(': still here\n\n');
301
305
  if (this._compressor) {
302
306
  this._compressor.flush();
@@ -311,6 +315,7 @@ class ResponseStream extends Transform {
311
315
  }
312
316
 
313
317
  sendMessage(payload) {
318
+ if (this._finalized || this.destroyed) return;
314
319
  let sendData = JSON.stringify(payload);
315
320
  this.write('event: message\ndata:' + sendData + '\n\n');
316
321
  if (this._compressor) {
@@ -325,6 +330,10 @@ class ResponseStream extends Transform {
325
330
 
326
331
  clearTimeout(this.periodicKeepAliveTimer);
327
332
  registeredPublishers.delete(this);
333
+
334
+ if (!this.destroyed) {
335
+ this.destroy();
336
+ }
328
337
  }
329
338
 
330
339
  _transform(data, encoding, done) {
@@ -914,6 +923,8 @@ Include your token in requests using one of these methods:
914
923
 
915
924
  security: [{ bearerAuth: [] }],
916
925
 
926
+ definitionPrefix: 'useLabel',
927
+
917
928
  cors: !!CORS_CONFIG,
918
929
  cache: {
919
930
  expiresIn: 7 * 24 * 60 * 60 * 1000
@@ -1008,6 +1019,11 @@ Include your token in requests using one of these methods:
1008
1019
  {
1009
1020
  name: 'Multi Message Actions',
1010
1021
  description: 'Perform bulk operations on multiple messages simultaneously, such as marking as read, moving, or deleting'
1022
+ },
1023
+ {
1024
+ name: 'Export (Beta)',
1025
+ description:
1026
+ 'Bulk export messages from email accounts. This feature is in beta and the API may change in future releases. Export files are encrypted at rest when a service secret is configured.'
1011
1027
  }
1012
1028
  ],
1013
1029
 
@@ -2027,10 +2043,10 @@ Include your token in requests using one of these methods:
2027
2043
  }
2028
2044
 
2029
2045
  // Validate nonce format: 16 bytes base64url encoded = 21-22 characters
2046
+ // Also accept base64 encoding (+, /, =) for backward compatibility with old cached nonces
2030
2047
  const stateNonce = request.query.state.slice('account:add:'.length);
2031
- if (!/^[A-Za-z0-9_-]{21,22}$/.test(stateNonce)) {
2032
- let error = Boom.boomify(new Error(`Oauth failed: invalid state format`), { statusCode: 400 });
2033
- throw error;
2048
+ if (!/^[A-Za-z0-9_\-+/]{21,22}={0,2}$/.test(stateNonce)) {
2049
+ throw Boom.badRequest('Oauth failed: invalid state format');
2034
2050
  }
2035
2051
 
2036
2052
  let [[, accountData]] = await redis.multi().get(`${REDIS_PREFIX}${request.query.state}`).del(`${REDIS_PREFIX}${request.query.state}`).exec();
@@ -3314,7 +3330,7 @@ Include your token in requests using one of these methods:
3314
3330
 
3315
3331
  envelope: Joi.object({
3316
3332
  from: Joi.string().email().allow('').example('sender@example.com'),
3317
- to: Joi.array().items(Joi.string().email().required().example('recipient@example.com')).single()
3333
+ to: Joi.array().items(Joi.string().email().required().example('recipient@example.com')).single().label('SmtpEnvelopeTo')
3318
3334
  })
3319
3335
  .description(
3320
3336
  "An optional object specifying the SMTP envelope used during email transmission. If not provided, the envelope is automatically derived from the email's message headers. This is useful when you need the envelope addresses to differ from those in the email headers."
@@ -3386,7 +3402,11 @@ Include your token in requests using one of these methods:
3386
3402
  template: Joi.string().max(256).example('example').description('Stored template ID to load the email content from'),
3387
3403
 
3388
3404
  render: Joi.object({
3389
- format: Joi.string().valid('html', 'markdown').default('html').description('Markup language for HTML ("html" or "markdown")'),
3405
+ format: Joi.string()
3406
+ .valid('html', 'markdown')
3407
+ .default('html')
3408
+ .description('Markup language for HTML ("html" or "markdown")')
3409
+ .label('RenderFormat'),
3390
3410
  params: Joi.object().label('RenderValues').description('An object of variables for the template renderer')
3391
3411
  })
3392
3412
  .allow(false)
@@ -3432,9 +3452,9 @@ Include your token in requests using one of these methods:
3432
3452
  }),
3433
3453
 
3434
3454
  contentType: Joi.string().lowercase().max(256).example('image/gif'),
3435
- contentDisposition: Joi.string().lowercase().valid('inline', 'attachment'),
3455
+ contentDisposition: Joi.string().lowercase().valid('inline', 'attachment').label('AttachmentContentDisposition'),
3436
3456
  cid: Joi.string().max(256).example('unique-image-id@localhost').description('Content-ID value for embedded images'),
3437
- encoding: Joi.string().valid('base64').default('base64'),
3457
+ encoding: Joi.string().valid('base64').default('base64').label('AttachmentEncoding'),
3438
3458
 
3439
3459
  reference: Joi.string()
3440
3460
  .base64({ paddingRequired: false, urlSafe: true })
@@ -3444,6 +3464,7 @@ Include your token in requests using one of these methods:
3444
3464
  .description(
3445
3465
  'References an existing attachment by its ID instead of providing new attachment content. If this field is set, the `content` field must not be included. If not set, the `content` field is required.'
3446
3466
  )
3467
+ .label('AttachmentReference')
3447
3468
  }).label('UploadAttachment')
3448
3469
  )
3449
3470
  .description('List of attachments')
@@ -3475,7 +3496,7 @@ Include your token in requests using one of these methods:
3475
3496
  .example('Sent Mail')
3476
3497
  .description("Upload sent message to this folder. By default the account's Sent Mail folder is used."),
3477
3498
 
3478
- locale: Joi.string().empty('').max(100).example('fr').description('Optional locale'),
3499
+ locale: Joi.string().empty('').max(100).example('fr').description('Optional locale').label('MessageLocale'),
3479
3500
  tz: Joi.string().empty('').max(100).example('Europe/Tallinn').description('Optional timezone'),
3480
3501
 
3481
3502
  sendAt: Joi.date().iso().example('2021-07-08T07:06:34.336Z').description('Send message at specified time'),
@@ -3483,7 +3504,7 @@ Include your token in requests using one of these methods:
3483
3504
  .integer()
3484
3505
  .example(10)
3485
3506
  .description('How many delivery attempts to make until message is considered as failed'),
3486
- gateway: Joi.string().max(256).example('example').description('Optional SMTP gateway ID for message routing'),
3507
+ gateway: Joi.string().max(256).example('example').description('Optional SMTP gateway ID for message routing').label('MessageGateway'),
3487
3508
 
3488
3509
  listId: Joi.string()
3489
3510
  .hostname()
@@ -3505,11 +3526,13 @@ Include your token in requests using one of these methods:
3505
3526
  .empty('')
3506
3527
  .valid('headers', 'full')
3507
3528
  .required()
3508
- .description('Specifies if only headers or the entire body of the message should be included in the response (RET)'),
3529
+ .description('Specifies if only headers or the entire body of the message should be included in the response (RET)')
3530
+ .label('DsnReturn'),
3509
3531
  notify: Joi.array()
3510
3532
  .single()
3511
3533
  .items(Joi.string().valid('never', 'success', 'failure', 'delay').label('NotifyEntry'))
3512
- .description('Defines the conditions under which a DSN response should be sent'),
3534
+ .description('Defines the conditions under which a DSN response should be sent')
3535
+ .label('DsnNotify'),
3513
3536
  recipient: Joi.string().trim().empty('').email().description('The email address the DSN should be sent (ORCPT)')
3514
3537
  })
3515
3538
  .description('Request DSN notifications')
@@ -3636,7 +3659,9 @@ Include your token in requests using one of these methods:
3636
3659
  skipped: Joi.object({
3637
3660
  reason: Joi.string().example('unsubscribe').description('Why this message was skipped'),
3638
3661
  listId: Joi.string().example('test-list')
3639
- }).description('Info about skipped message. If this value is set, then the message was not sent')
3662
+ })
3663
+ .description('Info about skipped message. If this value is set, then the message was not sent')
3664
+ .label('SkippedMessageInfo')
3640
3665
  })
3641
3666
  .label('BulkResponseEntry')
3642
3667
  .example({
@@ -3752,6 +3777,9 @@ Include your token in requests using one of these methods:
3752
3777
  }
3753
3778
 
3754
3779
  notify('settings', request.payload);
3780
+ if ('httpProxyEnabled' in request.payload || 'httpProxyUrl' in request.payload) {
3781
+ reloadHttpProxyAgent().catch(err => logger.error({ msg: 'Failed to reload HTTP proxy agent', err }));
3782
+ }
3755
3783
  return { updated };
3756
3784
  },
3757
3785
  options: {
@@ -3856,13 +3884,27 @@ Include your token in requests using one of these methods:
3856
3884
  failAction,
3857
3885
 
3858
3886
  params: Joi.object({
3859
- queue: Joi.string().empty('').trim().valid('notify', 'submit', 'documents').required().example('notify').description('Queue ID')
3887
+ queue: Joi.string()
3888
+ .empty('')
3889
+ .trim()
3890
+ .valid('notify', 'submit', 'documents')
3891
+ .required()
3892
+ .example('notify')
3893
+ .description('Queue ID')
3894
+ .label('QueueId')
3860
3895
  })
3861
3896
  },
3862
3897
 
3863
3898
  response: {
3864
3899
  schema: Joi.object({
3865
- queue: Joi.string().empty('').trim().valid('notify', 'submit', 'documents').required().example('notify').description('Queue ID'),
3900
+ queue: Joi.string()
3901
+ .empty('')
3902
+ .trim()
3903
+ .valid('notify', 'submit', 'documents')
3904
+ .required()
3905
+ .example('notify')
3906
+ .description('Queue ID')
3907
+ .label('QueueIdResponse'),
3866
3908
  jobs: Joi.object({
3867
3909
  active: Joi.number().integer().example(123).description('Jobs that are currently being processed'),
3868
3910
  delayed: Joi.number().integer().example(123).description('Jobs that are processed in the future'),
@@ -3946,7 +3988,14 @@ Include your token in requests using one of these methods:
3946
3988
  failAction,
3947
3989
 
3948
3990
  params: Joi.object({
3949
- queue: Joi.string().empty('').trim().valid('notify', 'submit', 'documents').required().example('notify').description('Queue ID')
3991
+ queue: Joi.string()
3992
+ .empty('')
3993
+ .trim()
3994
+ .valid('notify', 'submit', 'documents')
3995
+ .required()
3996
+ .example('notify')
3997
+ .description('Queue ID')
3998
+ .label('QueueIdParam')
3950
3999
  }),
3951
4000
 
3952
4001
  payload: Joi.object({
@@ -3956,7 +4005,14 @@ Include your token in requests using one of these methods:
3956
4005
 
3957
4006
  response: {
3958
4007
  schema: Joi.object({
3959
- queue: Joi.string().empty('').trim().valid('notify', 'submit', 'documents').required().example('notify').description('Queue ID'),
4008
+ queue: Joi.string()
4009
+ .empty('')
4010
+ .trim()
4011
+ .valid('notify', 'submit', 'documents')
4012
+ .required()
4013
+ .example('notify')
4014
+ .description('Queue ID')
4015
+ .label('QueueIdPutResponse'),
3960
4016
  paused: Joi.boolean().example(false).description('Is the queue paused or not')
3961
4017
  }).label('SettingsPutQueueResponse'),
3962
4018
  failAction: 'log'
@@ -4108,7 +4164,7 @@ Include your token in requests using one of these methods:
4108
4164
  failAction,
4109
4165
 
4110
4166
  payload: Joi.object({
4111
- mailboxes: Joi.boolean().example(false).description('Include mailbox listing in response').default(false),
4167
+ mailboxes: Joi.boolean().example(false).description('Include mailbox listing in response').default(false).label('IncludeMailboxes'),
4112
4168
  imap: Joi.object(imapSchema).allow(false).description('IMAP configuration').label('ImapConfiguration'),
4113
4169
  smtp: Joi.object(smtpSchema).allow(false).description('SMTP configuration').label('SmtpConfiguration'),
4114
4170
  proxy: settingsSchema.proxyUrl,
@@ -4127,7 +4183,7 @@ Include your token in requests using one of these methods:
4127
4183
  .example('ERR_SSL_WRONG_VERSION_NUMBER')
4128
4184
  .description('Error code. Only present if success=false')
4129
4185
  .label('VerifyImapCode')
4130
- }),
4186
+ }).label('VerifyImapResult'),
4131
4187
  smtp: Joi.object({
4132
4188
  success: Joi.boolean().example(true).description('Was SMTP account verified').label('VerifySmtpSuccess'),
4133
4189
  error: Joi.string()
@@ -4138,7 +4194,7 @@ Include your token in requests using one of these methods:
4138
4194
  .example('ERR_SSL_WRONG_VERSION_NUMBER')
4139
4195
  .description('Error code. Only present if success=false')
4140
4196
  .label('VerifySmtpCode')
4141
- }),
4197
+ }).label('VerifySmtpResult'),
4142
4198
  mailboxes: shortMailboxesSchema
4143
4199
  }).label('VerifyAccountResponse'),
4144
4200
  failAction: 'log'
@@ -4597,6 +4653,12 @@ Include your token in requests using one of these methods:
4597
4653
  MAX_PAYLOAD_TIMEOUT
4598
4654
  });
4599
4655
 
4656
+ // setup export routes
4657
+ await exportRoutes({
4658
+ server,
4659
+ CORS_CONFIG
4660
+ });
4661
+
4600
4662
  server.route({
4601
4663
  method: 'GET',
4602
4664
  path: '/v1/webhookRoutes',
@@ -4867,7 +4929,8 @@ Include your token in requests using one of these methods:
4867
4929
 
4868
4930
  clientId: Joi.string()
4869
4931
  .example('4f05f488-d858-4f2c-bd12-1039062612fe')
4870
- .description('Client or Application ID for 3-legged OAuth2 applications'),
4932
+ .description('Client or Application ID for 3-legged OAuth2 applications')
4933
+ .label('OAuth2AppListClientId'),
4871
4934
  clientSecret: Joi.string()
4872
4935
  .example('******')
4873
4936
  .description('Client secret for 3-legged OAuth2 applications. Actual value is not revealed.'),
@@ -4878,9 +4941,13 @@ Include your token in requests using one of these methods:
4878
4941
  allowRelative: false
4879
4942
  })
4880
4943
  .example('https://myservice.com/oauth')
4881
- .description('Redirect URL for 3-legged OAuth2 applications'),
4944
+ .description('Redirect URL for 3-legged OAuth2 applications')
4945
+ .label('OAuth2AppListRedirectUrl'),
4882
4946
 
4883
- serviceClient: Joi.string().example('9103965568215821627203').description('Service client ID for 2-legged OAuth2 applications'),
4947
+ serviceClient: Joi.string()
4948
+ .example('9103965568215821627203')
4949
+ .description('Service client ID for 2-legged OAuth2 applications')
4950
+ .label('OAuth2AppListServiceClient'),
4884
4951
 
4885
4952
  googleProjectId: googleProjectIdSchema,
4886
4953
  googleWorkspaceAccounts: googleWorkspaceAccountsSchema,
@@ -5002,7 +5069,8 @@ Include your token in requests using one of these methods:
5002
5069
 
5003
5070
  clientId: Joi.string()
5004
5071
  .example('4f05f488-d858-4f2c-bd12-1039062612fe')
5005
- .description('Client or Application ID for 3-legged OAuth2 applications'),
5072
+ .description('Client or Application ID for 3-legged OAuth2 applications')
5073
+ .label('OAuth2AppGetClientId'),
5006
5074
  clientSecret: Joi.string().example('******').description('Client secret for 3-legged OAuth2 applications. Actual value is not revealed.'),
5007
5075
  authority: Joi.string().example('common').description('Authorization tenant value for Outlook OAuth2 applications'),
5008
5076
  redirectUrl: Joi.string()
@@ -5011,7 +5079,8 @@ Include your token in requests using one of these methods:
5011
5079
  allowRelative: false
5012
5080
  })
5013
5081
  .example('https://myservice.com/oauth')
5014
- .description('Redirect URL for 3-legged OAuth2 applications'),
5082
+ .description('Redirect URL for 3-legged OAuth2 applications')
5083
+ .label('OAuth2AppGetRedirectUrl'),
5015
5084
 
5016
5085
  googleProjectId: googleProjectIdSchema,
5017
5086
  googleWorkspaceAccounts: googleWorkspaceAccountsSchema,
@@ -5023,7 +5092,10 @@ Include your token in requests using one of these methods:
5023
5092
  .example('name@project-123.iam.gserviceaccount.com')
5024
5093
  .description('Service Client Email for 2-legged OAuth2 applications'),
5025
5094
 
5026
- serviceClient: Joi.string().example('9103965568215821627203').description('Service client ID for 2-legged OAuth2 applications'),
5095
+ serviceClient: Joi.string()
5096
+ .example('9103965568215821627203')
5097
+ .description('Service client ID for 2-legged OAuth2 applications')
5098
+ .label('OAuth2AppGetServiceClient'),
5027
5099
 
5028
5100
  serviceKey: Joi.string()
5029
5101
  .example('******')
@@ -5163,7 +5235,8 @@ Include your token in requests using one of these methods:
5163
5235
  .allow('', null, false)
5164
5236
  .max(256)
5165
5237
  .example('52422112755-3uov8bjwlrullq122rdm6l8ui25ho7qf.apps.googleusercontent.com')
5166
- .description('Client or Application ID for 3-legged OAuth2 applications'),
5238
+ .description('Client or Application ID for 3-legged OAuth2 applications')
5239
+ .label('UpdateOAuth2ClientId'),
5167
5240
 
5168
5241
  clientSecret: Joi.string()
5169
5242
  .trim()
@@ -5177,18 +5250,26 @@ Include your token in requests using one of these methods:
5177
5250
  .base64({ paddingRequired: false, urlSafe: true })
5178
5251
  .max(512)
5179
5252
  .example('AAAAAQAACnA')
5180
- .description('Cloud Pub/Sub app for Gmail API webhooks'),
5253
+ .description('Cloud Pub/Sub app for Gmail API webhooks')
5254
+ .label('UpdatePubSubAppId'),
5181
5255
 
5182
- extraScopes: Joi.array().items(Joi.string().trim().max(255).example('User.Read')).description('OAuth2 Extra Scopes'),
5256
+ extraScopes: Joi.array()
5257
+ .items(Joi.string().trim().max(255).example('User.Read').label('UpdateExtraScopeEntry'))
5258
+ .description('OAuth2 Extra Scopes')
5259
+ .label('UpdateOAuth2ExtraScopes'),
5183
5260
 
5184
- skipScopes: Joi.array().items(Joi.string().trim().max(255).example('SMTP.Send')).description('OAuth2 scopes to skip from the base set'),
5261
+ skipScopes: Joi.array()
5262
+ .items(Joi.string().trim().max(255).example('SMTP.Send').label('UpdateSkipScopeEntry'))
5263
+ .description('OAuth2 scopes to skip from the base set')
5264
+ .label('UpdateOAuth2SkipScopes'),
5185
5265
 
5186
5266
  serviceClient: Joi.string()
5187
5267
  .trim()
5188
5268
  .allow('', null, false)
5189
5269
  .max(256)
5190
5270
  .example('7103296518315821565203')
5191
- .description('Service client ID for 2-legged OAuth2 applications'),
5271
+ .description('Service client ID for 2-legged OAuth2 applications')
5272
+ .label('UpdateServiceClient'),
5192
5273
 
5193
5274
  googleProjectId: googleProjectIdSchema,
5194
5275
  googleWorkspaceAccounts: googleWorkspaceAccountsSchema,
@@ -5230,6 +5311,7 @@ Include your token in requests using one of these methods:
5230
5311
  .uri({ scheme: ['http', 'https'], allowRelative: false })
5231
5312
  .example('https://myservice.com/oauth')
5232
5313
  .description('Redirect URL for 3-legged OAuth2 applications')
5314
+ .label('UpdateOAuth2RedirectUrl')
5233
5315
  }).label('UpdateOAuthApp')
5234
5316
  },
5235
5317
 
@@ -5465,7 +5547,7 @@ Include your token in requests using one of these methods:
5465
5547
  .default(false)
5466
5548
  .example(true)
5467
5549
  .description('Should connection use TLS. Usually true for port 465')
5468
- .label('TLS'),
5550
+ .label('GatewayTlsOptions'),
5469
5551
 
5470
5552
  lastError: lastErrorSchema.allow(null)
5471
5553
  }).label('GatewayResponse'),
@@ -5542,7 +5624,7 @@ Include your token in requests using one of these methods:
5542
5624
  .default(false)
5543
5625
  .example(true)
5544
5626
  .description('Should connection use TLS. Usually true for port 465')
5545
- .label('TLS')
5627
+ .label('GatewayCreateTlsOptions')
5546
5628
  }).label('CreateGateway')
5547
5629
  },
5548
5630
 
@@ -5628,7 +5710,7 @@ Include your token in requests using one of these methods:
5628
5710
  .falsy('N', 'false', 0, '')
5629
5711
  .example(true)
5630
5712
  .description('Should connection use TLS. Usually true for port 465')
5631
- .label('TLS')
5713
+ .label('GatewayUpdateTlsOptions')
5632
5714
  }).label('UpdateGateway')
5633
5715
  },
5634
5716
 
@@ -5696,7 +5778,7 @@ Include your token in requests using one of these methods:
5696
5778
  schema: Joi.object({
5697
5779
  gateway: Joi.string().max(256).required().example('example').description('Gateway ID'),
5698
5780
  deleted: Joi.boolean().truthy('Y', 'true', '1').falsy('N', 'false', 0).default(true).description('Was the gateway deleted')
5699
- }).label('DeleteRequestResponse'),
5781
+ }).label('DeleteGatewayResponse'),
5700
5782
  failAction: 'log'
5701
5783
  }
5702
5784
  }
@@ -5778,7 +5860,7 @@ Include your token in requests using one of these methods:
5778
5860
  schema: Joi.object({
5779
5861
  account: accountIdSchema.required(),
5780
5862
  user: Joi.string().max(256).required().example('user@example.com').description('Username'),
5781
- accessToken: Joi.string().max(256).required().example('aGVsbG8gd29ybGQ=').description('Access Token'),
5863
+ accessToken: Joi.string().max(256).required().example('aGVsbG8gd29ybGQ=').description('Access Token').label('OAuthAccessToken'),
5782
5864
  provider: OAuth2ProviderSchema
5783
5865
  }).label('AccountTokenResponse'),
5784
5866
  failAction: 'log'
@@ -5848,7 +5930,7 @@ Include your token in requests using one of these methods:
5848
5930
  }).label('SignatureResponseItem')
5849
5931
  )
5850
5932
  .label('SignatureEntries')
5851
- }).label('AccountTokenResponse'),
5933
+ }).label('AccountSignaturesResponse'),
5852
5934
  failAction: 'log'
5853
5935
  }
5854
5936
  }
@@ -5884,7 +5966,7 @@ Include your token in requests using one of these methods:
5884
5966
  requestor: '@postalsys/emailengine-app'
5885
5967
  }),
5886
5968
  headers,
5887
- dispatcher: retryAgent
5969
+ dispatcher: httpAgent.retry
5888
5970
  });
5889
5971
 
5890
5972
  if (!res.ok) {
@@ -5995,7 +6077,7 @@ ${now}`,
5995
6077
  }),
5996
6078
 
5997
6079
  payload: Joi.object({
5998
- gateway: Joi.string().allow(false, null).empty('').max(256).example(false).description('Optional gateway ID')
6080
+ gateway: Joi.string().allow(false, null).empty('').max(256).example(false).description('Optional gateway ID').label('DeliveryTestGateway')
5999
6081
  }).label('DeliveryStartRequest')
6000
6082
  },
6001
6083
 
@@ -6037,7 +6119,7 @@ ${now}`,
6037
6119
  let res = await fetchCmd(`${SMTP_TEST_HOST}/test-address/${request.params.deliveryTest}`, {
6038
6120
  method: 'get',
6039
6121
  headers,
6040
- dispatcher: retryAgent
6122
+ dispatcher: httpAgent.retry
6041
6123
  });
6042
6124
 
6043
6125
  if (!res.ok) {
@@ -6141,14 +6223,15 @@ ${now}`,
6141
6223
  response: {
6142
6224
  schema: Joi.object({
6143
6225
  success: Joi.boolean().example(true).description('Was the test completed').label('ResponseDeliveryCheckSuccess'),
6144
- dkim: Joi.object().unknown().description('DKIM results'),
6145
- spf: Joi.object().unknown().description('SPF results'),
6146
- dmarc: Joi.object().unknown().description('DMARC results'),
6147
- bimi: Joi.object().unknown().description('BIMI results'),
6148
- arc: Joi.object().unknown().description('ARC results'),
6226
+ dkim: Joi.object().unknown().description('DKIM results').label('DkimResults'),
6227
+ spf: Joi.object().unknown().description('SPF results').label('SpfResults'),
6228
+ dmarc: Joi.object().unknown().description('DMARC results').label('DmarcResults'),
6229
+ bimi: Joi.object().unknown().description('BIMI results').label('BimiResults'),
6230
+ arc: Joi.object().unknown().description('ARC results').label('ArcResults'),
6149
6231
  mainSig: Joi.object()
6150
6232
  .unknown()
6151
6233
  .description('Primary DKIM signature. `status.aligned` should be set, otherwise DKIM check should not be considered as passed.')
6234
+ .label('MainSignature')
6152
6235
  }).label('DeliveryCheckResponse'),
6153
6236
  failAction: 'log'
6154
6237
  }
@@ -241,7 +241,7 @@ const documentsWorker = new Worker(
241
241
  return;
242
242
  }
243
243
 
244
- let deleteResult = null;
244
+ let deleteResult;
245
245
 
246
246
  let filterQuery = {
247
247
  bool: {
@@ -612,7 +612,7 @@ const documentsWorker = new Worker(
612
612
  return;
613
613
  }
614
614
 
615
- let deleteResult = null;
615
+ let deleteResult;
616
616
 
617
617
  try {
618
618
  let messageIdHeader;
@@ -912,6 +912,7 @@ if( ctx._source.bounces != null) {
912
912
  Object.assign(
913
913
  {
914
914
  concurrency: 1,
915
+ lockDuration: 2 * 60 * 1000, // 2 minutes for ES operations
915
916
  maxStalledCount: 5,
916
917
  stalledInterval: 60 * 1000
917
918
  },