emailengine-app 2.63.4 → 2.65.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 (59) hide show
  1. package/.github/workflows/test.yml +4 -0
  2. package/CHANGELOG.md +70 -0
  3. package/copy-static-files.sh +1 -1
  4. package/data/google-crawlers.json +1 -1
  5. package/eslint.config.js +2 -0
  6. package/lib/account.js +13 -9
  7. package/lib/api-routes/account-routes.js +7 -1
  8. package/lib/consts.js +17 -1
  9. package/lib/email-client/gmail/gmail-api.js +1 -12
  10. package/lib/email-client/imap-client.js +5 -3
  11. package/lib/email-client/outlook/graph-api.js +9 -15
  12. package/lib/email-client/outlook-client.js +406 -177
  13. package/lib/export.js +17 -0
  14. package/lib/imapproxy/imap-server.js +3 -2
  15. package/lib/oauth/gmail.js +12 -1
  16. package/lib/oauth/outlook.js +99 -1
  17. package/lib/oauth/pubsub/google.js +253 -85
  18. package/lib/oauth2-apps.js +620 -389
  19. package/lib/outbox.js +1 -1
  20. package/lib/routes-ui.js +193 -238
  21. package/lib/schemas.js +189 -12
  22. package/lib/ui-routes/account-routes.js +7 -2
  23. package/lib/ui-routes/admin-entities-routes.js +3 -3
  24. package/lib/ui-routes/oauth-routes.js +27 -175
  25. package/package.json +21 -21
  26. package/sbom.json +1 -1
  27. package/server.js +54 -22
  28. package/static/licenses.html +30 -90
  29. package/translations/de.mo +0 -0
  30. package/translations/de.po +54 -42
  31. package/translations/en.mo +0 -0
  32. package/translations/en.po +55 -43
  33. package/translations/et.mo +0 -0
  34. package/translations/et.po +54 -42
  35. package/translations/fr.mo +0 -0
  36. package/translations/fr.po +54 -42
  37. package/translations/ja.mo +0 -0
  38. package/translations/ja.po +54 -42
  39. package/translations/messages.pot +93 -71
  40. package/translations/nl.mo +0 -0
  41. package/translations/nl.po +54 -42
  42. package/translations/pl.mo +0 -0
  43. package/translations/pl.po +54 -42
  44. package/views/config/oauth/app.hbs +12 -0
  45. package/views/config/oauth/edit.hbs +2 -0
  46. package/views/config/oauth/index.hbs +4 -1
  47. package/views/config/oauth/new.hbs +2 -0
  48. package/views/config/oauth/subscriptions.hbs +175 -0
  49. package/views/error.hbs +4 -4
  50. package/views/partials/oauth_form.hbs +179 -4
  51. package/views/partials/oauth_tabs.hbs +8 -0
  52. package/views/partials/scope_info.hbs +10 -0
  53. package/workers/api.js +174 -96
  54. package/workers/documents.js +1 -0
  55. package/workers/export.js +6 -2
  56. package/workers/imap.js +33 -49
  57. package/workers/smtp.js +1 -0
  58. package/workers/submit.js +1 -0
  59. package/workers/webhooks.js +42 -30
@@ -1,7 +1,7 @@
1
1
  msgid ""
2
2
  msgstr ""
3
3
  "Project-Id-Version: \n"
4
- "POT-Creation-Date: 2026-02-05 09:12+0000\n"
4
+ "POT-Creation-Date: 2026-03-10 13:39+0000\n"
5
5
  "PO-Revision-Date: \n"
6
6
  "Last-Translator: \n"
7
7
  "Language-Team: \n"
@@ -13,6 +13,22 @@ msgstr ""
13
13
  "|| n%100>14) ? 1 : 2);\n"
14
14
  "X-Generator: Poedit 3.8\n"
15
15
 
16
+ #: views/error.hbs:4 workers/api.js:7043
17
+ msgid "Something went wrong"
18
+ msgstr "Ups... Coś poszlo nie tak"
19
+
20
+ #: views/error.hbs:6
21
+ msgid "Error code: %s"
22
+ msgstr "Kod bledu: %s"
23
+
24
+ #: views/error.hbs:14
25
+ msgid "Go back"
26
+ msgstr "Wstecz"
27
+
28
+ #: views/error.hbs:17
29
+ msgid "Dashboard"
30
+ msgstr "Pulpit"
31
+
16
32
  #: views/config/license.hbs:45
17
33
  msgid "%d day"
18
34
  msgid_plural "%d days"
@@ -20,10 +36,6 @@ msgstr[0] "%d dzień"
20
36
  msgstr[1] "%d dni"
21
37
  msgstr[2] "%d dni"
22
38
 
23
- #: views/redirect.hbs:1
24
- msgid "Click <a href=\"%s\">here</a> to continue&mldr;"
25
- msgstr "Kliknij <a href=\"%s\">tutaj</a>, aby kontynuować&mldr;"
26
-
27
39
  #: views/unsubscribe.hbs:3 views/unsubscribe.hbs:62 views/unsubscribe.hbs:85
28
40
  msgid "Unsubscribe"
29
41
  msgstr "Wypisz się"
@@ -69,6 +81,10 @@ msgstr "Adres e-mail"
69
81
  msgid "Enter your email address"
70
82
  msgstr "Wprowadź swój adres e-mail"
71
83
 
84
+ #: views/redirect.hbs:1
85
+ msgid "Click <a href=\"%s\">here</a> to continue&mldr;"
86
+ msgstr "Kliknij <a href=\"%s\">tutaj</a>, aby kontynuować&mldr;"
87
+
72
88
  #: views/accounts/register/imap.hbs:11
73
89
  msgid "Your name"
74
90
  msgstr "Twoje imię"
@@ -91,14 +107,6 @@ msgstr "Wprowadź hasło do konta"
91
107
  msgid "Continue"
92
108
  msgstr "Kontynuuj"
93
109
 
94
- #: views/accounts/register/index.hbs:2
95
- msgid "Choose your email account provider"
96
- msgstr "Wybierz dostawcę konta e-mail"
97
-
98
- #: views/accounts/register/index.hbs:15
99
- msgid "Standard IMAP"
100
- msgstr "Standardowy IMAP"
101
-
102
110
  #: views/accounts/register/imap-server.hbs:19
103
111
  msgid "IMAP"
104
112
  msgstr "IMAP"
@@ -220,15 +228,23 @@ msgstr "Nie udalo sie polaczyc z serwerem SMTP"
220
228
  msgid "Request failed."
221
229
  msgstr "Zadanie nie powiodlo sie."
222
230
 
223
- #: lib/routes-ui.js:520 lib/ui-routes/account-routes.js:60
231
+ #: views/accounts/register/index.hbs:2
232
+ msgid "Choose your email account provider"
233
+ msgstr "Wybierz dostawcę konta e-mail"
234
+
235
+ #: views/accounts/register/index.hbs:15
236
+ msgid "Standard IMAP"
237
+ msgstr "Standardowy IMAP"
238
+
239
+ #: lib/routes-ui.js:523 lib/ui-routes/account-routes.js:60
224
240
  msgid "Delegated"
225
241
  msgstr "Delegowany"
226
242
 
227
- #: lib/routes-ui.js:521 lib/ui-routes/account-routes.js:61
243
+ #: lib/routes-ui.js:524 lib/ui-routes/account-routes.js:61
228
244
  msgid "Using credentials from \"%s\""
229
245
  msgstr "Używanie poświadczeń z \"%s\""
230
246
 
231
- #: lib/routes-ui.js:571 lib/ui-routes/account-routes.js:111
247
+ #: lib/routes-ui.js:574 lib/ui-routes/account-routes.js:111
232
248
  msgid ""
233
249
  "Connection timed out. This usually occurs if you are behind a firewall or "
234
250
  "connecting to the wrong port."
@@ -236,11 +252,11 @@ msgstr ""
236
252
  "Przekroczono limit czasu połączenia. Zwykle dzieje się tak, gdy użytkownik "
237
253
  "znajduje się za zaporą sieciową lub łączy się z niewłaściwym portem."
238
254
 
239
- #: lib/routes-ui.js:574 lib/ui-routes/account-routes.js:114
255
+ #: lib/routes-ui.js:577 lib/ui-routes/account-routes.js:114
240
256
  msgid "The server unexpectedly closed the connection."
241
257
  msgstr "Serwer nieoczekiwanie zamknął połączenie."
242
258
 
243
- #: lib/routes-ui.js:577 lib/ui-routes/account-routes.js:117
259
+ #: lib/routes-ui.js:580 lib/ui-routes/account-routes.js:117
244
260
  msgid ""
245
261
  "The server unexpectedly closed the connection. This usually happens when "
246
262
  "attempting to connect to a TLS port without TLS enabled."
@@ -248,7 +264,7 @@ msgstr ""
248
264
  "Serwer nieoczekiwanie zamknął połączenie. Zwykle dzieje się tak podczas "
249
265
  "próby połączenia z portem TLS bez włączonego protokołu TLS."
250
266
 
251
- #: lib/routes-ui.js:582 lib/ui-routes/account-routes.js:122
267
+ #: lib/routes-ui.js:585 lib/ui-routes/account-routes.js:122
252
268
  msgid ""
253
269
  "The server refused the connection. This typically occurs if the server is "
254
270
  "not running, is overloaded, or you are connecting to the wrong host or port."
@@ -256,90 +272,86 @@ msgstr ""
256
272
  "Serwer odmówił połączenia. Zwykle dzieje się tak, gdy serwer nie działa, "
257
273
  "jest przeciążony lub łączysz się z niewłaściwym hostem lub portem."
258
274
 
259
- #: lib/routes-ui.js:709
275
+ #: lib/routes-ui.js:712
260
276
  msgid "Invalid API key for OpenAI"
261
277
  msgstr "Nieprawidłowy klucz API dla OpenAI"
262
278
 
263
- #: lib/routes-ui.js:4671 lib/routes-ui.js:4706 lib/routes-ui.js:4821
264
- #: lib/routes-ui.js:4868 lib/routes-ui.js:5115 lib/routes-ui.js:5151
265
- #: workers/api.js:2413 lib/ui-routes/account-routes.js:549
279
+ #: lib/routes-ui.js:4754 lib/routes-ui.js:4789 lib/routes-ui.js:4904
280
+ #: lib/routes-ui.js:4951 lib/routes-ui.js:5198 lib/routes-ui.js:5234
281
+ #: workers/api.js:2557 lib/ui-routes/account-routes.js:549
266
282
  #: lib/ui-routes/account-routes.js:585 lib/ui-routes/account-routes.js:702
267
283
  #: lib/ui-routes/account-routes.js:749 lib/ui-routes/account-routes.js:998
268
284
  #: lib/ui-routes/account-routes.js:1034
269
285
  msgid "Email Account Setup"
270
286
  msgstr "Konfiguracja konta e-mail"
271
287
 
272
- #: lib/routes-ui.js:4731 lib/routes-ui.js:4764 lib/routes-ui.js:7701
288
+ #: lib/routes-ui.js:4814 lib/routes-ui.js:4847 lib/routes-ui.js:7807
273
289
  #: lib/ui-routes/account-routes.js:610 lib/ui-routes/account-routes.js:644
274
290
  msgid "Invalid request. Check your input and try again."
275
291
  msgstr "Nie udało się zweryfikować argumentów żądania."
276
292
 
277
- #: lib/routes-ui.js:4924 lib/routes-ui.js:4935
293
+ #: lib/routes-ui.js:5007 lib/routes-ui.js:5018
278
294
  #: lib/ui-routes/account-routes.js:806 lib/ui-routes/account-routes.js:817
279
295
  #: lib/ui-routes/admin-entities-routes.js:2020
280
296
  msgid "Server hostname was not found"
281
297
  msgstr "Nie znaleziono nazwy hosta serwera"
282
298
 
283
- #: lib/routes-ui.js:4927 lib/routes-ui.js:4938
299
+ #: lib/routes-ui.js:5010 lib/routes-ui.js:5021
284
300
  #: lib/ui-routes/account-routes.js:809 lib/ui-routes/account-routes.js:820
285
301
  #: lib/ui-routes/admin-entities-routes.js:2023
286
302
  msgid "Invalid username or password"
287
303
  msgstr "Nieprawidłowa nazwa użytkownika lub hasło"
288
304
 
289
- #: lib/routes-ui.js:4941 lib/ui-routes/account-routes.js:823
305
+ #: lib/routes-ui.js:5024 lib/ui-routes/account-routes.js:823
290
306
  #: lib/ui-routes/admin-entities-routes.js:2026
291
307
  msgid "Authentication credentials were not provided"
292
308
  msgstr "Nie podano danych uwierzytelniających"
293
309
 
294
- #: lib/routes-ui.js:4944 lib/ui-routes/account-routes.js:826
310
+ #: lib/routes-ui.js:5027 lib/ui-routes/account-routes.js:826
295
311
  #: lib/ui-routes/admin-entities-routes.js:2029
296
312
  msgid "OAuth2 authentication failed"
297
313
  msgstr "Uwierzytelnianie OAuth2 nie powiodło się"
298
314
 
299
- #: lib/routes-ui.js:4947 lib/routes-ui.js:4951
315
+ #: lib/routes-ui.js:5030 lib/routes-ui.js:5034
300
316
  #: lib/ui-routes/account-routes.js:829 lib/ui-routes/account-routes.js:833
301
317
  #: lib/ui-routes/admin-entities-routes.js:2032
302
318
  #: lib/ui-routes/admin-entities-routes.js:2036
303
319
  msgid "TLS protocol error"
304
320
  msgstr "Błąd protokołu TLS"
305
321
 
306
- #: lib/routes-ui.js:4955 lib/ui-routes/account-routes.js:837
322
+ #: lib/routes-ui.js:5038 lib/ui-routes/account-routes.js:837
307
323
  #: lib/ui-routes/admin-entities-routes.js:2040
308
324
  msgid "Connection timed out"
309
325
  msgstr "Przekroczono limit czasu połączenia"
310
326
 
311
- #: lib/routes-ui.js:4958 lib/ui-routes/account-routes.js:840
327
+ #: lib/routes-ui.js:5041 lib/ui-routes/account-routes.js:840
312
328
  #: lib/ui-routes/admin-entities-routes.js:2043
313
329
  msgid "Could not connect to server"
314
330
  msgstr "Nie można połączyć się z serwerem"
315
331
 
316
- #: lib/routes-ui.js:4961 lib/ui-routes/account-routes.js:843
332
+ #: lib/routes-ui.js:5044 lib/ui-routes/account-routes.js:843
317
333
  #: lib/ui-routes/admin-entities-routes.js:2046
318
334
  msgid "Unexpected server response"
319
335
  msgstr "Nieoczekiwana odpowiedź serwera"
320
336
 
321
- #: lib/routes-ui.js:7664 lib/tools.js:778
337
+ #: lib/routes-ui.js:7770 lib/tools.js:950
322
338
  msgid "Invalid input"
323
339
  msgstr "Nieprawidłowe dane wejściowe"
324
340
 
325
- #: lib/routes-ui.js:7674 lib/routes-ui.js:7792 lib/routes-ui.js:7809
326
- #: lib/routes-ui.js:7845
341
+ #: lib/routes-ui.js:7780 lib/routes-ui.js:7898 lib/routes-ui.js:7915
342
+ #: lib/routes-ui.js:7951
327
343
  msgid "Subscription Management"
328
344
  msgstr "Zarządzanie subskrypcjami"
329
345
 
330
- #: workers/api.js:6904 workers/api.js:7020
346
+ #: workers/api.js:7042 workers/api.js:7159
331
347
  msgid "Requested page not found"
332
348
  msgstr "Nie znaleziono żądanej strony"
333
349
 
334
- #: workers/api.js:6905
335
- msgid "Something went wrong"
336
- msgstr "Ups... Coś poszlo nie tak"
337
-
338
- #: lib/tools.js:1477
350
+ #: lib/tools.js:1653
339
351
  msgid "Signature validation failed"
340
352
  msgstr "Walidacja podpisu nie powiodła się"
341
353
 
342
- #: lib/tools.js:1486 lib/tools.js:1491
354
+ #: lib/tools.js:1662 lib/tools.js:1667
343
355
  msgid "Invalid or expired account setup URL"
344
356
  msgstr "Nieprawidłowy lub wygasły adres URL konfiguracji konta"
345
357
 
@@ -87,6 +87,18 @@
87
87
  <hr>
88
88
  {{/if}}
89
89
 
90
+ {{#if app.meta.ttlWarning}}
91
+ <div class="alert alert-warning">{{app.meta.ttlWarning.message}}
92
+ {{#if app.meta.ttlWarning.description}}
93
+ <hr>
94
+ <p class="mb-0">
95
+ <small>{{app.meta.ttlWarning.description}}</small>
96
+ </p>
97
+ {{/if}}
98
+ </div>
99
+ <hr>
100
+ {{/if}}
101
+
90
102
  <dl class="row">
91
103
  <dt class="col-sm-3">Provider ID</dt>
92
104
  <dd class="col-sm-9">
@@ -8,6 +8,7 @@
8
8
  </ol>
9
9
  </nav>
10
10
 
11
+ {{#unless activeOutlook}}{{#unless activeGmailService}}{{#unless activeOutlookService}}
11
12
  {{#if providerData.tutorialUrl}}
12
13
  <div class="card border-left-info shadow mb-4">
13
14
  <div class="card-body">
@@ -27,6 +28,7 @@
27
28
  </div>
28
29
  </div>
29
30
  {{/if}}
31
+ {{/unless}}{{/unless}}{{/unless}}
30
32
 
31
33
  <form method="post" action="/admin/config/oauth/edit" class="pending-form">
32
34
  <input type="hidden" name="crumb" id="crumb" value="{{crumb}}" />
@@ -6,7 +6,8 @@
6
6
  <div class="dropdown-menu">
7
7
  <a class="dropdown-item" href="{{newLink}}?provider=gmail">Gmail</a>
8
8
  <a class="dropdown-item" href="{{newLink}}?provider=gmailService">Gmail Service Accounts</a>
9
- <a class="dropdown-item" href="{{newLink}}?provider=outlook">Outlook</a>
9
+ <a class="dropdown-item" href="{{newLink}}?provider=outlook">Outlook (delegated)</a>
10
+ <a class="dropdown-item" href="{{newLink}}?provider=outlookService">Outlook (application)</a>
10
11
  <a class="dropdown-item" href="{{newLink}}?provider=mailRu">Mail.ru</a>
11
12
  </div>
12
13
  </div>
@@ -14,6 +15,8 @@
14
15
 
15
16
  {{> oauth_config_header}}
16
17
 
18
+ {{> oauth_tabs}}
19
+
17
20
  {{#if apps}}
18
21
  <div class="card mt-4 mb-4">
19
22
  <div class="table-responsive">
@@ -7,6 +7,7 @@
7
7
  </ol>
8
8
  </nav>
9
9
 
10
+ {{#unless activeOutlook}}{{#unless activeGmailService}}{{#unless activeOutlookService}}
10
11
  {{#if providerData.tutorialUrl}}
11
12
  <div class="card border-left-info shadow mb-4">
12
13
  <div class="card-body">
@@ -26,6 +27,7 @@
26
27
  </div>
27
28
  </div>
28
29
  {{/if}}
30
+ {{/unless}}{{/unless}}{{/unless}}
29
31
 
30
32
  <form method="post" action="/admin/config/oauth/new" class="pending-form">
31
33
  <input type="hidden" name="crumb" id="crumb" value="{{crumb}}" />
@@ -0,0 +1,175 @@
1
+ {{> oauth_config_header}}
2
+
3
+ {{> oauth_tabs}}
4
+
5
+ {{#if apps}}
6
+ <div class="card mt-4 mb-4">
7
+ <div class="table-responsive">
8
+ <table class="table table-hover">
9
+ <thead>
10
+ <tr>
11
+ <th class="p-0">
12
+ <div class="p-2">Name</div>
13
+ </th>
14
+ <th class="p-0">
15
+ <div class="p-2">Project ID</div>
16
+ </th>
17
+ <th class="p-0">
18
+ <div class="p-2">Topic</div>
19
+ </th>
20
+ <th class="p-0">
21
+ <div class="p-2">Subscription</div>
22
+ </th>
23
+ <th class="p-0">
24
+ <div class="p-2">Expiration</div>
25
+ </th>
26
+ <th class="p-0">
27
+ <div class="p-2">Status</div>
28
+ </th>
29
+ </tr>
30
+ </thead>
31
+
32
+ <tbody>
33
+ {{#each apps}}
34
+ <tr>
35
+ <td class="p-0">
36
+ <div class="position-relative p-2">
37
+ <a href="/admin/config/oauth/app/{{id}}"
38
+ class="stretched-link"></a><strong>{{name}}</strong>
39
+ </div>
40
+ </td>
41
+
42
+ <td class="p-0">
43
+ <div class="position-relative p-2">
44
+ <a href="/admin/config/oauth/app/{{id}}" class="stretched-link"></a>{{googleProjectId}}
45
+ </div>
46
+ </td>
47
+
48
+ <td class="p-0">
49
+ <div class="position-relative p-2">
50
+ <a href="/admin/config/oauth/app/{{id}}" class="stretched-link"></a>
51
+ {{#if pubSubTopic}}
52
+ <span class="badge badge-success">Created</span>
53
+ {{else}}
54
+ <span class="badge badge-secondary">Not set</span>
55
+ {{/if}}
56
+ </div>
57
+ </td>
58
+
59
+ <td class="p-0">
60
+ <div class="position-relative p-2">
61
+ <a href="/admin/config/oauth/app/{{id}}" class="stretched-link"></a>
62
+ {{#if pubSubSubscription}}
63
+ <span class="badge badge-success">Created</span>
64
+ {{else}}
65
+ <span class="badge badge-secondary">Not set</span>
66
+ {{/if}}
67
+ </div>
68
+ </td>
69
+
70
+ <td class="p-0">
71
+ <div class="position-relative p-2">
72
+ <a href="/admin/config/oauth/app/{{id}}" class="stretched-link"></a>
73
+ {{#if expirationLabel}}
74
+ {{expirationLabel}}
75
+ {{else}}
76
+ <span class="text-muted">-</span>
77
+ {{/if}}
78
+ </div>
79
+ </td>
80
+
81
+ <td class="p-0">
82
+ <div class="position-relative p-2">
83
+ <a href="/admin/config/oauth/app/{{id}}" class="stretched-link"></a>
84
+ {{#if meta.pubSubFlag}}
85
+ <span class="badge badge-danger" title="{{meta.pubSubFlag.message}}">Error</span>
86
+ {{else if meta.authFlag}}
87
+ <span class="badge badge-warning" title="{{meta.authFlag.message}}">Setup Failed</span>
88
+ {{else if meta.ttlWarning}}
89
+ <span class="badge badge-warning" title="{{meta.ttlWarning.message}}">TTL Update Failed</span>
90
+ {{else if pubSubSubscription}}
91
+ <span class="badge badge-success">OK</span>
92
+ {{else}}
93
+ <span class="badge badge-warning">Pending</span>
94
+ {{/if}}
95
+ </div>
96
+ </td>
97
+ </tr>
98
+ {{/each}}
99
+ </tbody>
100
+ </table>
101
+ </div>
102
+
103
+ {{#if showPaging}}
104
+ <div class="card-footer">
105
+
106
+ <nav aria-label="Page navigation">
107
+ <ul class="pagination" style="flex-wrap: wrap;">
108
+
109
+ {{#if prevPage}}
110
+ <li class="page-item"><a class="page-link" href="{{prevPage}}">Previous</a></li>
111
+ {{else}}
112
+ <li class="page-item disabled"><a class="page-link" href="#">Previous</a></li>
113
+ {{/if}}
114
+
115
+ {{#each pageLinks}}
116
+ <li class="page-item {{#if active}}active{{/if}}"><a class="page-link" href="{{url}}">{{title}}</a>
117
+ </li>
118
+ {{/each}}
119
+
120
+ {{#if nextPage}}
121
+ <li class="page-item"><a class="page-link" href="{{nextPage}}">Next</a></li>
122
+ {{else}}
123
+ <li class="page-item disabled"><a class="page-link" href="#">Next</a></li>
124
+ {{/if}}
125
+
126
+ </ul>
127
+ </nav>
128
+ </div>
129
+ {{/if}}
130
+ </div>
131
+ {{else}}
132
+ <div class="list-group mt-4 mb-4">
133
+ <div class="list-group-item">
134
+ <p>
135
+ {{#if firstPage}}
136
+ No Gmail Pub/Sub apps have been registered yet.
137
+ {{else}}
138
+ No Gmail Pub/Sub apps found.
139
+ {{/if}}
140
+ </p>
141
+ </div>
142
+ </div>
143
+ {{/if}}
144
+
145
+ <div class="card mt-4 mb-4">
146
+ <div class="card-header py-3">
147
+ <h6 class="m-0 font-weight-bold text-primary">Subscription Settings</h6>
148
+ </div>
149
+ <div class="card-body">
150
+ <form method="post" action="/admin/config/oauth/subscriptions">
151
+ <input type="hidden" name="crumb" value="{{crumb}}" />
152
+ <div class="form-group row">
153
+ <label for="gmailSubscriptionTtl" class="col-sm-3 col-form-label">Subscription TTL</label>
154
+ <div class="col-sm-9">
155
+ <input type="number" class="form-control" id="gmailSubscriptionTtl"
156
+ name="gmailSubscriptionTtl" value="{{values.gmailSubscriptionTtl}}"
157
+ placeholder="31" min="0" max="365" />
158
+ <small class="form-text text-muted">
159
+ Inactivity expiration in days. Leave empty for Google's default (31 days). Set to 0 to disable expiration.
160
+ </small>
161
+ </div>
162
+ </div>
163
+ <button type="submit" class="btn btn-primary">Update</button>
164
+ </form>
165
+
166
+ <div class="alert alert-info mt-3 mb-0">
167
+ <strong>Note:</strong> Google automatically deletes Pub/Sub subscriptions that receive no activity
168
+ for a set period. This setting controls that period for both new and existing subscriptions.
169
+ Changes take effect the next time an OAuth app is created, updated, or its subscription is recovered.
170
+ If a subscription does expire, EmailEngine detects this and recreates it automatically.
171
+ No messages are lost during the gap because EmailEngine also polls the Gmail API every 10 minutes
172
+ and uses the History API to catch up on any missed changes.
173
+ </div>
174
+ </div>
175
+ </div>
package/views/error.hbs CHANGED
@@ -1,9 +1,9 @@
1
1
  <div class="container mt-4">
2
2
  <div class="card border-left-danger">
3
3
  <div class="card-body">
4
- <h1 class="h4 mb-3">Something went wrong</h1>
4
+ <h1 class="h4 mb-3">{{_ "Something went wrong" templateLocale}}</h1>
5
5
  <p class="mb-2">{{message}}</p>
6
- <p class="text-muted small mb-3">Error code: {{statusCode}}</p>
6
+ <p class="text-muted small mb-3">{{_ "Error code: %s" templateLocale statusCode}}</p>
7
7
  {{#if details}}
8
8
  {{#each details}}
9
9
  <div class="alert alert-danger mb-2">{{this}}</div>
@@ -11,10 +11,10 @@
11
11
  {{/if}}
12
12
  <div class="mt-3">
13
13
  <a href="javascript:history.back()" class="btn btn-secondary btn-sm">
14
- <i class="fas fa-arrow-left"></i> Go back
14
+ <i class="fas fa-arrow-left"></i> {{_ "Go back" templateLocale}}
15
15
  </a>
16
16
  <a href="/admin" class="btn btn-primary btn-sm ml-2">
17
- <i class="fas fa-home"></i> Dashboard
17
+ <i class="fas fa-home"></i> {{_ "Dashboard" templateLocale}}
18
18
  </a>
19
19
  </div>
20
20
  </div>