emailengine-app 2.68.1 → 2.70.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.
Files changed (95) hide show
  1. package/.github/workflows/deploy.yml +8 -3
  2. package/.github/workflows/release.yaml +6 -0
  3. package/CHANGELOG.md +59 -0
  4. package/Gruntfile.js +3 -1
  5. package/config/default.toml +2 -0
  6. package/data/google-crawlers.json +7 -1
  7. package/getswagger.sh +40 -4
  8. package/gettext-extract.js +163 -0
  9. package/lib/account.js +135 -72
  10. package/lib/api-routes/account-routes.js +684 -106
  11. package/lib/api-routes/blocklist-routes.js +344 -0
  12. package/lib/api-routes/chat-routes.js +32 -14
  13. package/lib/api-routes/delivery-test-routes.js +346 -0
  14. package/lib/api-routes/export-routes.js +28 -14
  15. package/lib/api-routes/gateway-routes.js +427 -0
  16. package/lib/api-routes/license-routes.js +156 -0
  17. package/lib/api-routes/mailbox-routes.js +344 -0
  18. package/lib/api-routes/message-routes.js +221 -187
  19. package/lib/api-routes/oauth2-app-routes.js +697 -0
  20. package/lib/api-routes/outbox-routes.js +185 -0
  21. package/lib/api-routes/pubsub-routes.js +102 -0
  22. package/lib/api-routes/route-helpers.js +58 -0
  23. package/lib/api-routes/settings-routes.js +357 -0
  24. package/lib/api-routes/stats-routes.js +111 -0
  25. package/lib/api-routes/submit-routes.js +461 -0
  26. package/lib/api-routes/template-routes.js +60 -75
  27. package/lib/api-routes/token-routes.js +297 -0
  28. package/lib/api-routes/webhook-route-routes.js +181 -0
  29. package/lib/autodetect-imap-settings.js +0 -2
  30. package/lib/consts.js +5 -0
  31. package/lib/email-client/base-client.js +28 -6
  32. package/lib/email-client/gmail-client.js +133 -112
  33. package/lib/email-client/imap/mailbox.js +34 -11
  34. package/lib/email-client/imap/subconnection.js +20 -13
  35. package/lib/email-client/imap/sync-operations.js +131 -3
  36. package/lib/email-client/imap-client.js +152 -75
  37. package/lib/email-client/notification-handler.js +1 -4
  38. package/lib/email-client/outlook-client.js +134 -75
  39. package/lib/export.js +97 -20
  40. package/lib/feature-flags.js +2 -2
  41. package/lib/gateway.js +4 -9
  42. package/lib/get-raw-email.js +5 -5
  43. package/lib/imapproxy/imap-core/lib/commands/starttls.js +18 -0
  44. package/lib/imapproxy/imap-core/lib/imap-command.js +6 -1
  45. package/lib/imapproxy/imap-core/lib/imap-connection.js +106 -24
  46. package/lib/imapproxy/imap-core/lib/imap-server.js +24 -0
  47. package/lib/imapproxy/imap-core/lib/imap-stream.js +26 -0
  48. package/lib/logger.js +24 -21
  49. package/lib/message-port-stream.js +113 -16
  50. package/lib/metrics-collector.js +0 -2
  51. package/lib/oauth2-apps.js +13 -4
  52. package/lib/outbox.js +24 -40
  53. package/lib/redis-operations.js +1 -1
  54. package/lib/reject-worker-calls.js +42 -0
  55. package/lib/routes-ui.js +37 -8778
  56. package/lib/schemas.js +429 -84
  57. package/lib/sentry.js +139 -0
  58. package/lib/settings.js +9 -3
  59. package/lib/stream-encrypt.js +1 -1
  60. package/lib/templates.js +1 -1
  61. package/lib/tokens.js +5 -3
  62. package/lib/tools.js +70 -4
  63. package/lib/ui-routes/account-routes.js +45 -212
  64. package/lib/ui-routes/admin-config-routes.js +928 -489
  65. package/lib/ui-routes/admin-entities-routes.js +1 -0
  66. package/lib/ui-routes/auth-routes.js +1339 -0
  67. package/lib/ui-routes/dashboard-routes.js +188 -0
  68. package/lib/ui-routes/document-store-routes.js +800 -0
  69. package/lib/ui-routes/export-routes.js +217 -0
  70. package/lib/ui-routes/internals-routes.js +354 -0
  71. package/lib/ui-routes/network-config-routes.js +759 -0
  72. package/lib/ui-routes/{oauth-routes.js → oauth-config-routes.js} +369 -91
  73. package/lib/ui-routes/route-helpers.js +314 -0
  74. package/lib/ui-routes/smtp-test-routes.js +236 -0
  75. package/lib/ui-routes/unsubscribe-routes.js +232 -0
  76. package/lib/webhook-request.js +36 -0
  77. package/lib/webhooks.js +8 -4
  78. package/package.json +13 -12
  79. package/sbom.json +1 -1
  80. package/server.js +222 -39
  81. package/static/licenses.html +160 -300
  82. package/translations/messages.pot +112 -132
  83. package/update-info.sh +19 -1
  84. package/views/config/logging.hbs +48 -0
  85. package/views/dashboard.hbs +7 -26
  86. package/views/internals/index.hbs +15 -0
  87. package/views/tokens/index.hbs +9 -0
  88. package/workers/api.js +200 -4424
  89. package/workers/documents.js +2 -22
  90. package/workers/export.js +103 -104
  91. package/workers/imap-proxy.js +3 -23
  92. package/workers/imap.js +32 -36
  93. package/workers/smtp.js +2 -22
  94. package/workers/submit.js +26 -35
  95. package/workers/webhooks.js +9 -43
@@ -1,10 +1,10 @@
1
1
  msgid ""
2
2
  msgstr ""
3
3
  "Content-Type: text/plain; charset=ascii\n"
4
- "POT-Creation-Date: 2026-06-01 09:16+0000\n"
4
+ "POT-Creation-Date: 2026-06-11 10:37+0000\n"
5
5
 
6
6
  #: views/error.hbs:4
7
- #: workers/api.js:7192
7
+ #: workers/api.js:2940
8
8
  msgid "Something went wrong"
9
9
  msgstr ""
10
10
 
@@ -21,7 +21,7 @@ msgid "Dashboard"
21
21
  msgstr ""
22
22
 
23
23
  #: views/config/license.hbs:45
24
- #: lib/routes-ui.js:2509
24
+ #: lib/ui-routes/oauth-config-routes.js:217
25
25
  msgid "%d day"
26
26
  msgid_plural "%d days"
27
27
  msgstr[0] ""
@@ -31,30 +31,6 @@ msgstr[1] ""
31
31
  msgid "Click <a href=\"%s\">here</a> to continue&mldr;"
32
32
  msgstr ""
33
33
 
34
- #: views/oauth-scope-error.hbs:2
35
- msgid "Insufficient Permissions"
36
- msgstr ""
37
-
38
- #: views/oauth-scope-error.hbs:8
39
- msgid ""
40
- "All requested permissions are required for this service to function "
41
- "properly. Some required permissions were not granted during sign-in."
42
- msgstr ""
43
-
44
- #: views/oauth-scope-error.hbs:12
45
- msgid "The following permissions were not granted:"
46
- msgstr ""
47
-
48
- #: views/oauth-scope-error.hbs:21
49
- msgid ""
50
- "Please try again and make sure all permission checkboxes are selected on "
51
- "the Google consent screen."
52
- msgstr ""
53
-
54
- #: views/oauth-scope-error.hbs:27
55
- msgid "Try Again"
56
- msgstr ""
57
-
58
34
  #: views/unsubscribe.hbs:3
59
35
  #: views/unsubscribe.hbs:62
60
36
  #: views/unsubscribe.hbs:85
@@ -126,12 +102,28 @@ msgstr ""
126
102
  msgid "Continue"
127
103
  msgstr ""
128
104
 
129
- #: views/accounts/register/index.hbs:2
130
- msgid "Choose your email account provider"
105
+ #: views/oauth-scope-error.hbs:2
106
+ msgid "Insufficient Permissions"
131
107
  msgstr ""
132
108
 
133
- #: views/accounts/register/index.hbs:15
134
- msgid "Standard IMAP"
109
+ #: views/oauth-scope-error.hbs:8
110
+ msgid ""
111
+ "All requested permissions are required for this service to function "
112
+ "properly. Some required permissions were not granted during sign-in."
113
+ msgstr ""
114
+
115
+ #: views/oauth-scope-error.hbs:12
116
+ msgid "The following permissions were not granted:"
117
+ msgstr ""
118
+
119
+ #: views/oauth-scope-error.hbs:21
120
+ msgid ""
121
+ "Please try again and make sure all permission checkboxes are selected on "
122
+ "the Google consent screen."
123
+ msgstr ""
124
+
125
+ #: views/oauth-scope-error.hbs:27
126
+ msgid "Try Again"
135
127
  msgstr ""
136
128
 
137
129
  #: views/accounts/register/imap-server.hbs:19
@@ -249,169 +241,157 @@ msgstr ""
249
241
  msgid "Request failed."
250
242
  msgstr ""
251
243
 
252
- #: lib/routes-ui.js:385
253
- #: lib/ui-routes/account-routes.js:60
254
- msgid "Delegated"
255
- msgstr ""
256
-
257
- #: lib/routes-ui.js:386
258
- #: lib/ui-routes/account-routes.js:61
259
- msgid "Using credentials from \"%s\""
260
- msgstr ""
261
-
262
- #: lib/routes-ui.js:436
263
- #: lib/ui-routes/account-routes.js:111
264
- msgid ""
265
- "Connection timed out. This usually occurs if you are behind a firewall or "
266
- "connecting to the wrong port."
267
- msgstr ""
268
-
269
- #: lib/routes-ui.js:439
270
- #: lib/ui-routes/account-routes.js:114
271
- msgid "The server unexpectedly closed the connection."
244
+ #: views/accounts/register/index.hbs:2
245
+ msgid "Choose your email account provider"
272
246
  msgstr ""
273
247
 
274
- #: lib/routes-ui.js:442
275
- #: lib/ui-routes/account-routes.js:117
276
- msgid ""
277
- "The server unexpectedly closed the connection. This usually happens when "
278
- "attempting to connect to a TLS port without TLS enabled."
248
+ #: views/accounts/register/index.hbs:15
249
+ msgid "Standard IMAP"
279
250
  msgstr ""
280
251
 
281
- #: lib/routes-ui.js:447
282
- #: lib/ui-routes/account-routes.js:122
252
+ #: lib/autodetect-imap-settings.js:80
283
253
  msgid ""
284
- "The server refused the connection. This typically occurs if the server is "
285
- "not running, is overloaded, or you are connecting to the wrong host or port."
254
+ "Microsoft has disabled password-based sign-ins (including app passwords) "
255
+ "for Outlook.com, Hotmail.com, and Microsoft 365 email accounts. To "
256
+ "continue, please use the \"Sign in with Microsoft\" button to securely "
257
+ "connect your account."
286
258
  msgstr ""
287
259
 
288
- #: lib/routes-ui.js:574
289
- msgid "Invalid API key for OpenAI"
260
+ #: lib/tools.js:956
261
+ #: lib/ui-routes/unsubscribe-routes.js:28
262
+ msgid "Invalid input"
290
263
  msgstr ""
291
264
 
292
- #: lib/routes-ui.js:2502
293
- msgid "Unknown"
265
+ #: lib/tools.js:1723
266
+ msgid "Signature validation failed"
294
267
  msgstr ""
295
268
 
296
- #: lib/routes-ui.js:2511
297
- msgid "Indefinite"
269
+ #: lib/tools.js:1732
270
+ #: lib/tools.js:1737
271
+ msgid "Invalid or expired account setup URL"
298
272
  msgstr ""
299
273
 
300
- #: lib/routes-ui.js:5285
301
- #: lib/routes-ui.js:5320
302
- #: lib/routes-ui.js:5435
303
- #: lib/routes-ui.js:5482
304
- #: lib/routes-ui.js:5729
305
- #: lib/routes-ui.js:5765
306
- #: workers/api.js:2280
307
- #: workers/api.js:2608
308
- #: lib/ui-routes/account-routes.js:554
309
- #: lib/ui-routes/account-routes.js:590
310
- #: lib/ui-routes/account-routes.js:707
311
- #: lib/ui-routes/account-routes.js:754
312
- #: lib/ui-routes/account-routes.js:1003
313
- #: lib/ui-routes/account-routes.js:1039
274
+ #: lib/ui-routes/account-routes.js:402
275
+ #: lib/ui-routes/account-routes.js:437
276
+ #: lib/ui-routes/account-routes.js:552
277
+ #: lib/ui-routes/account-routes.js:599
278
+ #: lib/ui-routes/account-routes.js:846
279
+ #: lib/ui-routes/account-routes.js:882
280
+ #: workers/api.js:2158
281
+ #: workers/api.js:2486
314
282
  msgid "Email Account Setup"
315
283
  msgstr ""
316
284
 
317
- #: lib/routes-ui.js:5345
318
- #: lib/routes-ui.js:5378
319
- #: lib/routes-ui.js:8338
320
- #: lib/ui-routes/account-routes.js:615
321
- #: lib/ui-routes/account-routes.js:649
285
+ #: lib/ui-routes/account-routes.js:462
286
+ #: lib/ui-routes/account-routes.js:495
287
+ #: lib/ui-routes/unsubscribe-routes.js:65
322
288
  msgid "Invalid request. Check your input and try again."
323
289
  msgstr ""
324
290
 
325
- #: lib/routes-ui.js:5538
326
- #: lib/routes-ui.js:5549
327
- #: lib/ui-routes/account-routes.js:811
328
- #: lib/ui-routes/account-routes.js:822
291
+ #: lib/ui-routes/account-routes.js:592
292
+ #: lib/ui-routes/account-routes.js:875
293
+ msgid "Couldn't set up account. Try again."
294
+ msgstr ""
295
+
296
+ #: lib/ui-routes/account-routes.js:655
297
+ #: lib/ui-routes/account-routes.js:666
329
298
  #: lib/ui-routes/admin-entities-routes.js:2020
330
299
  msgid "Server hostname was not found"
331
300
  msgstr ""
332
301
 
333
- #: lib/routes-ui.js:5541
334
- #: lib/routes-ui.js:5552
335
- #: lib/ui-routes/account-routes.js:814
336
- #: lib/ui-routes/account-routes.js:825
302
+ #: lib/ui-routes/account-routes.js:658
303
+ #: lib/ui-routes/account-routes.js:669
337
304
  #: lib/ui-routes/admin-entities-routes.js:2023
338
305
  msgid "Invalid username or password"
339
306
  msgstr ""
340
307
 
341
- #: lib/routes-ui.js:5555
342
- #: lib/ui-routes/account-routes.js:828
308
+ #: lib/ui-routes/account-routes.js:672
343
309
  #: lib/ui-routes/admin-entities-routes.js:2026
344
310
  msgid "Authentication credentials were not provided"
345
311
  msgstr ""
346
312
 
347
- #: lib/routes-ui.js:5558
348
- #: lib/ui-routes/account-routes.js:831
313
+ #: lib/ui-routes/account-routes.js:675
349
314
  #: lib/ui-routes/admin-entities-routes.js:2029
350
315
  msgid "OAuth2 authentication failed"
351
316
  msgstr ""
352
317
 
353
- #: lib/routes-ui.js:5561
354
- #: lib/routes-ui.js:5565
355
- #: lib/ui-routes/account-routes.js:834
356
- #: lib/ui-routes/account-routes.js:838
318
+ #: lib/ui-routes/account-routes.js:678
319
+ #: lib/ui-routes/account-routes.js:682
357
320
  #: lib/ui-routes/admin-entities-routes.js:2032
358
321
  #: lib/ui-routes/admin-entities-routes.js:2036
359
322
  msgid "TLS protocol error"
360
323
  msgstr ""
361
324
 
362
- #: lib/routes-ui.js:5569
363
- #: lib/ui-routes/account-routes.js:842
325
+ #: lib/ui-routes/account-routes.js:686
364
326
  #: lib/ui-routes/admin-entities-routes.js:2040
365
327
  msgid "Connection timed out"
366
328
  msgstr ""
367
329
 
368
- #: lib/routes-ui.js:5572
369
- #: lib/ui-routes/account-routes.js:845
330
+ #: lib/ui-routes/account-routes.js:689
370
331
  #: lib/ui-routes/admin-entities-routes.js:2043
371
332
  msgid "Could not connect to server"
372
333
  msgstr ""
373
334
 
374
- #: lib/routes-ui.js:5575
375
- #: lib/ui-routes/account-routes.js:848
335
+ #: lib/ui-routes/account-routes.js:692
376
336
  #: lib/ui-routes/admin-entities-routes.js:2046
377
337
  msgid "Unexpected server response"
378
338
  msgstr ""
379
339
 
380
- #: lib/routes-ui.js:8301
381
- #: lib/tools.js:950
382
- msgid "Invalid input"
340
+ #: lib/ui-routes/admin-config-routes.js:144
341
+ msgid "Invalid API key for OpenAI"
383
342
  msgstr ""
384
343
 
385
- #: lib/routes-ui.js:8311
386
- #: lib/routes-ui.js:8429
387
- #: lib/routes-ui.js:8446
388
- #: lib/routes-ui.js:8482
389
- msgid "Subscription Management"
344
+ #: lib/ui-routes/oauth-config-routes.js:210
345
+ msgid "Unknown"
390
346
  msgstr ""
391
347
 
392
- #: workers/api.js:7191
393
- #: workers/api.js:7308
394
- msgid "Requested page not found"
348
+ #: lib/ui-routes/oauth-config-routes.js:219
349
+ msgid "Indefinite"
395
350
  msgstr ""
396
351
 
397
- #: lib/tools.js:1653
398
- msgid "Signature validation failed"
352
+ #: lib/ui-routes/route-helpers.js:81
353
+ msgid "Delegated"
399
354
  msgstr ""
400
355
 
401
- #: lib/tools.js:1662
402
- #: lib/tools.js:1667
403
- msgid "Invalid or expired account setup URL"
356
+ #: lib/ui-routes/route-helpers.js:82
357
+ msgid "Using credentials from \"%s\""
404
358
  msgstr ""
405
359
 
406
- #: lib/autodetect-imap-settings.js:80
360
+ #: lib/ui-routes/route-helpers.js:132
407
361
  msgid ""
408
- "Microsoft has disabled password-based sign-ins (including app passwords) "
409
- "for Outlook.com, Hotmail.com, and Microsoft 365 email accounts. To "
410
- "continue, please use the \"Sign in with Microsoft\" button to securely "
411
- "connect your account."
362
+ "Connection timed out. This usually occurs if you are behind a firewall or "
363
+ "connecting to the wrong port."
412
364
  msgstr ""
413
365
 
414
- #: lib/ui-routes/account-routes.js:747
415
- #: lib/ui-routes/account-routes.js:1032
416
- msgid "Couldn't set up account. Try again."
417
- msgstr ""
366
+ #: lib/ui-routes/route-helpers.js:135
367
+ msgid "The server unexpectedly closed the connection."
368
+ msgstr ""
369
+
370
+ #: lib/ui-routes/route-helpers.js:138
371
+ msgid ""
372
+ "The server unexpectedly closed the connection. This usually happens when "
373
+ "attempting to connect to a TLS port without TLS enabled."
374
+ msgstr ""
375
+
376
+ #: lib/ui-routes/route-helpers.js:143
377
+ msgid ""
378
+ "The server refused the connection. This typically occurs if the server is "
379
+ "not running, is overloaded, or you are connecting to the wrong host or port."
380
+ msgstr ""
381
+
382
+ #: lib/ui-routes/unsubscribe-routes.js:38
383
+ #: lib/ui-routes/unsubscribe-routes.js:156
384
+ #: lib/ui-routes/unsubscribe-routes.js:173
385
+ #: lib/ui-routes/unsubscribe-routes.js:209
386
+ msgid "Subscription Management"
387
+ msgstr ""
388
+
389
+ #: lib/ui-routes/unsubscribe-routes.js:167
390
+ #: lib/ui-routes/unsubscribe-routes.js:202
391
+ msgid "Couldn't process request. Try again."
392
+ msgstr ""
393
+
394
+ #: workers/api.js:2939
395
+ #: workers/api.js:3054
396
+ msgid "Requested page not found"
397
+ msgstr ""
package/update-info.sh CHANGED
@@ -1,6 +1,24 @@
1
1
  #!/bin/sh
2
2
 
3
- COMMIT_HASH=$(cat .git/refs/heads/master)
3
+ # Resolve the commit hash for version-info.json:
4
+ # 1. EE_COMMIT_HASH is the explicit override, set by the deploy workflow and
5
+ # by release builds that run from a git export without a .git directory
6
+ # 2. git rev-parse works in any normal checkout, also when refs are packed;
7
+ # the toplevel check makes sure the hash comes from this repository and
8
+ # not from an unrelated parent repository when this directory is not a
9
+ # git repository itself
10
+ # 3. the plain ref file is the fallback for the Docker image build, which
11
+ # only copies .git/refs/heads/master into the build context
12
+ if [ -n "$EE_COMMIT_HASH" ]; then
13
+ COMMIT_HASH="$EE_COMMIT_HASH"
14
+ elif [ "$(git rev-parse --show-toplevel 2>/dev/null)" = "$(pwd -P)" ] && git rev-parse HEAD >/dev/null 2>&1; then
15
+ COMMIT_HASH=$(git rev-parse HEAD)
16
+ elif [ -f .git/refs/heads/master ]; then
17
+ COMMIT_HASH=$(cat .git/refs/heads/master)
18
+ else
19
+ COMMIT_HASH=""
20
+ fi
21
+
4
22
  TIMESTAMP=$(node -e 'console.log(Date.now())')
5
23
  cat >version-info.json <<EOL
6
24
  {
@@ -49,6 +49,54 @@
49
49
  </div>
50
50
  </div>
51
51
 
52
+ <div class="card mb-4">
53
+ <div class="card-header py-3">
54
+ <h6 class="m-0 font-weight-bold text-primary">Error Reporting</h6>
55
+ </div>
56
+ <div class="card-body">
57
+
58
+ {{#if sentryEnvManaged}}
59
+ <div class="alert alert-info">Error reporting is currently managed by the <code>SENTRY_DSN</code>
60
+ environment variable. The settings below are ignored until that variable is removed.</div>
61
+ {{/if}}
62
+
63
+ <div class="form-group form-check">
64
+
65
+ <div class="text-muted float-right code-link">[<a href="/admin/swagger#/Settings/postV1Settings"
66
+ target="_blank" rel="noopener noreferrer">sentryEnabled</a>]</div>
67
+
68
+ <input type="checkbox" class="form-check-input {{#if errors.sentryEnabled}}is-invalid{{/if}}"
69
+ id="settingsSentryEnabled" name="sentryEnabled" {{#if values.sentryEnabled}}checked{{/if}}
70
+ {{#if sentryEnvManaged}}disabled{{/if}} />
71
+ <label class="form-check-label" for="settingsSentryEnabled">Report Unhandled Errors to Sentry</label>
72
+ {{#if errors.sentryEnabled}}
73
+ <span class="invalid-feedback">{{errors.sentryEnabled}}</span>
74
+ {{/if}}
75
+ <small class="form-text text-muted">Send unhandled errors to a Sentry server. Reports include stack
76
+ traces, account IDs, and error details, but never credentials or message content. Changes apply
77
+ within a minute - no restart needed.</small>
78
+ </div>
79
+
80
+ <div class="form-group">
81
+
82
+ <div class="text-muted float-right code-link">[<a href="/admin/swagger#/Settings/postV1Settings"
83
+ target="_blank" rel="noopener noreferrer">sentryDsn</a>]</div>
84
+
85
+ <label for="settingsSentryDsn">Sentry DSN</label>
86
+ <input type="text" class="form-control {{#if errors.sentryDsn}}is-invalid{{/if}}"
87
+ id="settingsSentryDsn" name="sentryDsn" placeholder="https://public-key@sentry.example.com/1"
88
+ value="{{values.sentryDsn}}" {{#if sentryEnvManaged}}disabled{{/if}} />
89
+ {{#if errors.sentryDsn}}
90
+ <span class="invalid-feedback">{{errors.sentryDsn}}</span>
91
+ {{/if}}
92
+ <small class="form-text text-muted">Leave empty to send reports to the Sentry instance run by the
93
+ EmailEngine developers (sentry.emailengine.dev). Enabling this temporarily during a support case
94
+ helps to debug problems with your installation. Set your own DSN to keep reports
95
+ in-house.</small>
96
+ </div>
97
+ </div>
98
+ </div>
99
+
52
100
  <div class="mb-4">
53
101
  <button type="submit" class="btn btn-primary btn-icon-split">
54
102
  <span class="icon text-white-50">
@@ -5,16 +5,16 @@
5
5
  </div>
6
6
 
7
7
 
8
- {{#if isElastiCache}}
9
- <div class="card border-left-danger mt-4">
8
+ {{#each redisWarnings}}
9
+ <div class="card border-left-{{color}} mt-4">
10
10
  <div class="card-body">
11
11
  <div class="row no-gutters align-items-center">
12
12
  <div class="col mr-2">
13
- <div class="text-xs font-weight-bold text-danger text-uppercase mb-1">Compatibility warning
13
+ <div class="text-xs font-weight-bold text-{{color}} text-uppercase mb-1">{{title}}
14
14
  </div>
15
- <p>EmailEngine is incompatible with Amazon ElastiCache as the database backend.</p>
16
- <p>Please switch to a standard Redis instance. Using ElastiCache with EmailEngine can result in data
17
- loss and some features may not work correctly.</p>
15
+ {{#each details}}
16
+ <p>{{this}}</p>
17
+ {{/each}}
18
18
  </div>
19
19
  <div class="col-auto">
20
20
  <i class="fas fa-exclamation-circle fa-2x text-gray-300"></i>
@@ -22,26 +22,7 @@
22
22
  </div>
23
23
  </div>
24
24
  </div>
25
- {{/if}}
26
-
27
-
28
- {{#if isRedisCluster}}
29
- <div class="card border-left-danger mt-4">
30
- <div class="card-body">
31
- <div class="row no-gutters align-items-center">
32
- <div class="col mr-2">
33
- <div class="text-xs font-weight-bold text-danger text-uppercase mb-1">Compatibility warning
34
- </div>
35
- <p>EmailEngine is incompatible with Redis Cluster setup.</p>
36
- <p>Please switch to a standard Redis primary instance.</p>
37
- </div>
38
- <div class="col-auto">
39
- <i class="fas fa-exclamation-circle fa-2x text-gray-300"></i>
40
- </div>
41
- </div>
42
- </div>
43
- </div>
44
- {{/if}}
25
+ {{/each}}
45
26
 
46
27
 
47
28
  {{#unless hasAccounts}}
@@ -5,6 +5,21 @@
5
5
  </h1>
6
6
  </div>
7
7
 
8
+ {{#if apiWorkerWarning}}
9
+ <div class="alert alert-warning mt-4" role="alert">
10
+ <i class="fas fa-exclamation-triangle"></i>
11
+ <strong>Multiple API workers are not active.</strong>
12
+ {{#equals apiWorkerWarning.reason "port"}}
13
+ <code>EENGINE_WORKERS_API</code> is set to {{apiWorkerWarning.requested}}, but EmailEngine could not verify
14
+ <code>SO_REUSEPORT</code> support because the API port was unavailable while probing at startup, so only a single
15
+ API worker was started. This is usually a transient conflict and may clear on the next restart.
16
+ {{else}}
17
+ <code>EENGINE_WORKERS_API</code> is set to {{apiWorkerWarning.requested}}, but this platform does not support
18
+ <code>SO_REUSEPORT</code> (requires Linux with Node.js 23.1 or newer), so only a single API worker was started.
19
+ {{/equals}}
20
+ </div>
21
+ {{/if}}
22
+
8
23
  <div class="card mb-4 mt-4">
9
24
 
10
25
  <div class="table-responsive">
@@ -34,6 +34,9 @@
34
34
  <th class="p-0">
35
35
  <div class="p-2">Scopes</div>
36
36
  </th>
37
+ <th class="p-0">
38
+ <div class="p-2">Token ID</div>
39
+ </th>
37
40
  <th class="p-0">
38
41
  <div class="p-2">Last used</div>
39
42
  </th>
@@ -56,6 +59,12 @@
56
59
  {{/if}}
57
60
  </td>
58
61
 
62
+ <td class="p-2">
63
+ {{#if idShort}}
64
+ <code data-toggle="tooltip" data-placement="top" title="{{id}}" style="cursor: help;">{{idShort}}</code>
65
+ {{/if}}
66
+ </td>
67
+
59
68
  <td class="p-2">
60
69
  {{#if access.timeStr}}
61
70
  <span class="relative-time" data-time="{{access.timeStr}}"></span>