emailengine-app 2.70.0 → 2.72.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 (60) hide show
  1. package/.github/workflows/codeql.yml +3 -0
  2. package/.github/workflows/e2e.yml +56 -0
  3. package/.github/workflows/test.yml +81 -12
  4. package/.ncurc.js +20 -20
  5. package/CHANGELOG.md +25 -0
  6. package/Gruntfile.js +19 -23
  7. package/bin/emailengine.js +8 -1
  8. package/config/default.toml +5 -0
  9. package/config/e2e.toml +35 -0
  10. package/config/test.toml +5 -0
  11. package/data/google-crawlers.json +1 -1
  12. package/getswagger.sh +4 -0
  13. package/lib/account.js +31 -25
  14. package/lib/api-routes/message-routes.js +125 -121
  15. package/lib/auth-token.js +83 -0
  16. package/lib/delivery-error.js +62 -0
  17. package/lib/document-store.js +22 -1
  18. package/lib/email-client/base-client.js +3 -2
  19. package/lib/email-client/gmail-client.js +33 -1
  20. package/lib/email-client/imap/mailbox.js +2 -2
  21. package/lib/email-client/notification-handler.js +2 -2
  22. package/lib/export.js +12 -0
  23. package/lib/feature-flags.js +6 -0
  24. package/lib/imap-proxy-auth.js +81 -0
  25. package/lib/imapproxy/imap-server.js +8 -103
  26. package/lib/license-beacon.js +367 -0
  27. package/lib/logger.js +11 -1
  28. package/lib/oauth/gmail.js +3 -0
  29. package/lib/oauth/outlook.js +3 -0
  30. package/lib/oauth2-apps.js +100 -11
  31. package/lib/routes-ui.js +2 -1
  32. package/lib/smtp-auth.js +70 -0
  33. package/lib/sub-script.js +8 -2
  34. package/lib/tools.js +26 -2
  35. package/lib/ui-routes/admin-config-routes.js +4 -3
  36. package/lib/ui-routes/document-store-routes.js +7 -1
  37. package/package.json +30 -24
  38. package/playwright.config.js +45 -0
  39. package/sbom.json +1 -1
  40. package/server.js +30 -8
  41. package/static/licenses.html +108 -128
  42. package/test-coverage-plan.md +233 -0
  43. package/translations/de.mo +0 -0
  44. package/translations/de.po +154 -142
  45. package/translations/et.mo +0 -0
  46. package/translations/et.po +129 -131
  47. package/translations/fr.mo +0 -0
  48. package/translations/fr.po +133 -136
  49. package/translations/ja.mo +0 -0
  50. package/translations/ja.po +126 -129
  51. package/translations/messages.pot +37 -37
  52. package/translations/nl.mo +0 -0
  53. package/translations/nl.po +128 -130
  54. package/translations/pl.mo +0 -0
  55. package/translations/pl.po +125 -128
  56. package/views/dashboard.hbs +22 -0
  57. package/workers/api.js +22 -5
  58. package/workers/export.js +58 -43
  59. package/workers/smtp.js +5 -85
  60. package/workers/submit.js +2 -12
@@ -22,6 +22,9 @@ on:
22
22
  jobs:
23
23
  analyze:
24
24
  name: Analyze (${{ matrix.language }})
25
+ # Skip release-please's auto-generated release PR: it only changes CHANGELOG/version,
26
+ # so there is no new code to scan. (Matches the guard in test.yml.)
27
+ if: ${{ !startsWith(github.ref_name, 'release-please--') && !startsWith(github.head_ref, 'release-please--') }}
25
28
  # Runner size impacts CodeQL analysis time. To learn more, please see:
26
29
  # - https://gh.io/recommended-hardware-resources-for-running-codeql
27
30
  # - https://gh.io/supported-runners-and-hardware-resources
@@ -0,0 +1,56 @@
1
+ name: E2E Tests
2
+
3
+ # Browser-driven happy-path end-to-end suite (test/e2e), kept separate from the unit and
4
+ # integration tiers so it is easy to re-run on its own and has its own requirements: it drives a
5
+ # real browser (Playwright/Chromium) and reaches external services (Ethereal for the test mailbox,
6
+ # postalsys.com for the 14-day trial). The trial rate limit is bypassed for the e2e serviceUrl
7
+ # (https://e2e.emailengine.app/) - see the postalsys-web trial allowlist.
8
+
9
+ on:
10
+ workflow_dispatch:
11
+ push:
12
+ branches: [master]
13
+
14
+ permissions:
15
+ contents: read
16
+
17
+ concurrency:
18
+ group: e2e-${{ github.ref }}
19
+ cancel-in-progress: true
20
+
21
+ jobs:
22
+ e2e:
23
+ name: E2E (Playwright)
24
+ timeout-minutes: 20
25
+ runs-on: ubuntu-24.04
26
+ services:
27
+ redis:
28
+ image: redis
29
+ options: >-
30
+ --health-cmd "redis-cli ping"
31
+ --health-interval 10s
32
+ --health-timeout 5s
33
+ --health-retries 5
34
+ ports:
35
+ - 6379:6379
36
+ steps:
37
+ - uses: actions/checkout@v6
38
+ - name: Use Node.js 24
39
+ uses: actions/setup-node@v6
40
+ with:
41
+ node-version: 24
42
+ cache: npm
43
+ - run: npm install
44
+ - name: Install Playwright browser
45
+ run: npx playwright install --with-deps chromium
46
+ - name: Run e2e tests
47
+ run: npm run test:e2e
48
+ env:
49
+ NODE_ENV: e2e
50
+ - name: Upload Playwright report
51
+ uses: actions/upload-artifact@v4
52
+ if: ${{ !cancelled() }}
53
+ with:
54
+ name: playwright-report
55
+ path: playwright-report/
56
+ retention-days: 7
@@ -12,8 +12,13 @@ concurrency:
12
12
  cancel-in-progress: true
13
13
 
14
14
  jobs:
15
+ # Skip CI for release-please's auto-generated release PR / branch: it only bumps the
16
+ # version + CHANGELOG (no code change), so re-running the suite is wasted work. This is
17
+ # gated per job rather than with [skip ci] in the release commit, because that text would
18
+ # ride the squash-merge into master and skip the Manage Release run, breaking releases.
15
19
  license_check:
16
20
  name: License Compliance Check
21
+ if: ${{ !startsWith(github.ref_name, 'release-please--') && !startsWith(github.head_ref, 'release-please--') }}
17
22
  runs-on: ubuntu-24.04
18
23
  # Service containers to run with `container-job`
19
24
  steps:
@@ -23,20 +28,83 @@ jobs:
23
28
  uses: actions/setup-node@v6
24
29
  with:
25
30
  node-version: 24
31
+ cache: npm
26
32
  - run: npm install
27
33
 
28
34
  - name: Run License Checks
29
35
  run: |
30
36
  npm run licenses
31
37
 
32
- test:
33
- name: Test Suite
34
- timeout-minutes: 15 # Increased timeout for Gmail API tests
35
- strategy:
36
- matrix:
37
- node: [24.x]
38
- os: [ubuntu-24.04]
39
- runs-on: ${{ matrix.os }}
38
+ lint:
39
+ name: Lint
40
+ if: ${{ !startsWith(github.ref_name, 'release-please--') && !startsWith(github.head_ref, 'release-please--') }}
41
+ runs-on: ubuntu-24.04
42
+ timeout-minutes: 10
43
+ steps:
44
+ - uses: actions/checkout@v6
45
+ - name: Use Node.js 24
46
+ uses: actions/setup-node@v6
47
+ with:
48
+ node-version: 24
49
+ cache: npm
50
+ - run: npm install
51
+ - name: Run ESLint
52
+ run: |
53
+ npm run lint
54
+
55
+ unit:
56
+ name: Unit Tests
57
+ if: ${{ !startsWith(github.ref_name, 'release-please--') && !startsWith(github.head_ref, 'release-please--') }}
58
+ timeout-minutes: 10
59
+ runs-on: ubuntu-24.04
60
+ # Service containers to run with `container-job`
61
+ services:
62
+ # Label used to access the service container
63
+ redis:
64
+ # Docker Hub image
65
+ image: redis
66
+ # Set health checks to wait until redis has started
67
+ options: >-
68
+ --health-cmd "redis-cli ping"
69
+ --health-interval 10s
70
+ --health-timeout 5s
71
+ --health-retries 5
72
+ ports:
73
+ - 6379:6379
74
+ steps:
75
+ - uses: actions/checkout@v6
76
+ - name: Use Node.js 24
77
+ uses: actions/setup-node@v6
78
+ with:
79
+ node-version: 24
80
+ cache: npm
81
+ - name: Setup Redis CLI
82
+ uses: shogo82148/actions-setup-redis@v1
83
+ with:
84
+ redis-version: '7.x'
85
+ auto-start: 'false'
86
+ - run: npm install
87
+ - name: Run unit tests
88
+ run: |
89
+ npm run test:unit
90
+ env:
91
+ NODE_ENV: test
92
+ # account-revoke-on-delete-test.js runs against live Gmail when
93
+ # these are present and skips itself when they are not
94
+ GMAIL_API_PROJECT_ID: ${{ secrets.TEST_GMAIL_API_PROJECT_ID }}
95
+ GMAIL_API_CLIENT_ID: ${{ secrets.TEST_GMAIL_API_CLIENT_ID }}
96
+ GMAIL_API_CLIENT_SECRET: ${{ secrets.TEST_GMAIL_API_CLIENT_SECRET }}
97
+ GMAIL_API_SERVICE_EMAIL: ${{ secrets.TEST_GMAIL_API_SERVICE_EMAIL }}
98
+ GMAIL_API_SERVICE_CLIENT: ${{ secrets.TEST_GMAIL_API_SERVICE_CLIENT }}
99
+ GMAIL_API_SERVICE_KEY: ${{ secrets.TEST_GMAIL_API_SERVICE_KEY }}
100
+ GMAIL_API_ACCOUNT_EMAIL_1: ${{ secrets.TEST_GMAIL_API_ACCOUNT_EMAIL_1 }}
101
+ GMAIL_API_ACCOUNT_REFRESH_1: ${{ secrets.TEST_GMAIL_API_ACCOUNT_REFRESH_1 }}
102
+
103
+ integration:
104
+ name: Integration Tests
105
+ if: ${{ !startsWith(github.ref_name, 'release-please--') && !startsWith(github.head_ref, 'release-please--') }}
106
+ timeout-minutes: 15 # Increased timeout for Gmail API tests
107
+ runs-on: ubuntu-24.04
40
108
  # Service containers to run with `container-job`
41
109
  services:
42
110
  # Label used to access the service container
@@ -53,19 +121,20 @@ jobs:
53
121
  - 6379:6379
54
122
  steps:
55
123
  - uses: actions/checkout@v6
56
- - name: Use Node.js ${{ matrix.node }}
124
+ - name: Use Node.js 24
57
125
  uses: actions/setup-node@v6
58
126
  with:
59
- node-version: ${{ matrix.node }}
127
+ node-version: 24
128
+ cache: npm
60
129
  - name: Setup Redis CLI
61
130
  uses: shogo82148/actions-setup-redis@v1
62
131
  with:
63
132
  redis-version: '7.x'
64
133
  auto-start: 'false'
65
134
  - run: npm install
66
- - name: Run tests
135
+ - name: Run integration tests
67
136
  run: |
68
- npm test
137
+ npm run test:integration
69
138
  env:
70
139
  NODE_ENV: test
71
140
  GMAIL_API_PROJECT_ID: ${{ secrets.TEST_GMAIL_API_PROJECT_ID }}
package/.ncurc.js CHANGED
@@ -1,30 +1,30 @@
1
1
  module.exports = {
2
2
  upgrade: true,
3
+ // Packages capped inside their current major: the next major is ESM-only (this codebase is
4
+ // CommonJS and is bundled into a binary with pkg) or it breaks a peer dependency. Using 'minor'
5
+ // instead of a blanket reject so these still receive security/patch updates within the safe
6
+ // major instead of being frozen at one exact version. Verified against Node 20 (Docker) 2026-06-17.
7
+ target: name => (['joi', 'nanoid', 'ical.js', 'gettext-parser', 'xgettext-template', 'chai', 'undici', 'marked'].includes(name) ? 'minor' : 'latest'),
8
+ // joi - hapi-swagger (repo archived 2026-02-04) peer-requires joi 17.x; permanent ceiling
9
+ // nanoid - 4.x dropped the CommonJS require export (ESM-only)
10
+ // ical.js - 2.x is ESM-only
11
+ // gettext-parser - 8.x is ESM-only
12
+ // xgettext-template - 6.x is ESM-only (translation build tool)
13
+ // chai - 5.x is ESM-only (only used by the vendored imap-core tests)
14
+ // undici - 8.x requires Node >=22.19 and crashes at require() on Node 20; EmailEngine supports Node 20+
15
+ // marked - 16.x dropped the CommonJS build (ESM-only, needs require(esm)/Node >=20.19); 15.x is the
16
+ // last require()-compatible line. 15.0.12 verified on Node 20-24 and in a yao/pkg node24 build.
3
17
  reject: [
4
- // Block package upgrades that moved to ESM
5
- 'nanoid',
6
- 'gettext-parser',
7
- 'xgettext-template',
8
- 'chai',
9
- 'js-beautify',
10
- 'ical.js',
18
+ // 8.16+ pulls apache-arrow (ESM) into the pkg bundle; 9.x drops it but is a major bump for
19
+ // the deprecated, default-off Document Store. Even the 8.19 minor is unsafe to bundle.
11
20
  '@elastic/elasticsearch',
12
21
 
13
- 'pino-pretty',
14
-
15
- // no support for Node 16
16
- 'marked',
17
-
18
- // some kind of CVE in later versions. Only needed for license reference, so the actual version does not matter anyway
22
+ // v4.x adds vulnerable jquery + bootstrap runtime dependencies; v3.3.7 has none. Used only
23
+ // for the generated software-license listing, never executed at runtime.
19
24
  'startbootstrap-sb-admin-2',
20
25
 
21
- // Keep joi at version 17.x for hapi-swagger compatibility
22
- 'joi',
23
-
24
26
  // @asamuzakjp/css-color >=4.1.2 pulls in @csstools/* v4 which are pure ESM and break pkg bundling
25
- '@asamuzakjp/css-color',
26
-
27
- // undici >=8.0.0 requires Node >=22.19.0; pin to last Node 20-compatible release
28
- 'undici'
27
+ // (transitive via @postalsys/email-text-tools -> jsdom -> cssstyle; also pinned in package.json "overrides").
28
+ '@asamuzakjp/css-color'
29
29
  ]
30
30
  };
package/CHANGELOG.md CHANGED
@@ -1,5 +1,30 @@
1
1
  # Changelog
2
2
 
3
+ ## [2.72.0](https://github.com/postalsys/emailengine/compare/v2.71.0...v2.72.0) (2026-06-18)
4
+
5
+
6
+ ### Features
7
+
8
+ * adopt pre-existing Gmail Pub/Sub resources with ownership tracking ([fe43fad](https://github.com/postalsys/emailengine/commit/fe43fadad624025a56139382428256eb810f9e08))
9
+
10
+ ## [2.71.0](https://github.com/postalsys/emailengine/compare/v2.70.0...v2.71.0) (2026-06-15)
11
+
12
+
13
+ ### Features
14
+
15
+ * add anonymized feature beacon to license validation ([954d92a](https://github.com/postalsys/emailengine/commit/954d92a9d8e7c5fff6f1b8c711dfd228f556387a))
16
+ * disable deprecated Document Store by default behind a feature gate ([8790f75](https://github.com/postalsys/emailengine/commit/8790f7538ba2ee8d6ec73d1f3bbc221c2f54f0fe))
17
+
18
+
19
+ ### Bug Fixes
20
+
21
+ * defer export worker job consumption until startup recovery completes ([a21b0a5](https://github.com/postalsys/emailengine/commit/a21b0a50fdb98d13a2227a020069129d23fe225b))
22
+ * fail export when a folder cannot be indexed ([36c9c9d](https://github.com/postalsys/emailengine/commit/36c9c9d536540cd5a61b16b69af5e8e84c194ee6))
23
+ * filter transient fetch failures from Sentry and retry DNS errors ([883b9b4](https://github.com/postalsys/emailengine/commit/883b9b487e3580c5b1240d28cd519d190c402b47))
24
+ * retry transient errors in API-account batch export path ([6cba7c7](https://github.com/postalsys/emailengine/commit/6cba7c72658a037f68867cf2464f7d3420a79507))
25
+ * translate OAuth scope error page across 6 languages ([4ae1919](https://github.com/postalsys/emailengine/commit/4ae19199fe628f8a4f7177d53db1f05167077e3e))
26
+ * upgrade joi to 17.13.4 and @postalsys/certs to 1.0.15 (GHSA-q7cg-457f-vx79) ([6ec77e5](https://github.com/postalsys/emailengine/commit/6ec77e50b288b14550cd09b724f5aab59d17ced4))
27
+
3
28
  ## [2.70.0](https://github.com/postalsys/emailengine/compare/v2.69.0...v2.70.0) (2026-06-11)
4
29
 
5
30
 
package/Gruntfile.js CHANGED
@@ -5,22 +5,11 @@ const config = require('@zone-eu/wild-config');
5
5
  module.exports = function (grunt) {
6
6
  // Project configuration.
7
7
  grunt.initConfig({
8
- wait: {
9
- server: {
10
- options: {
11
- delay: 20 * 1000 // Increased from 12s to 20s for Gmail API operations
12
- }
13
- }
14
- },
15
-
16
8
  shell: {
17
9
  eslint: {
18
10
  // Globs are quoted so eslint expands them itself - unquoted, sh (no globstar)
19
11
  // expands lib/**/*.js to depth-2 files only and skips most of lib/
20
- command: "npx eslint 'lib/**/*.js' 'workers/**/*.js' server.js Gruntfile.js",
21
- options: {
22
- async: false
23
- }
12
+ command: "npx eslint 'lib/**/*.js' 'workers/**/*.js' server.js Gruntfile.js"
24
13
  },
25
14
  server: {
26
15
  command: 'node server.js',
@@ -29,16 +18,22 @@ module.exports = function (grunt) {
29
18
  }
30
19
  },
31
20
  flush: {
32
- command: `redis-cli -u "${config.dbs.redis}" flushdb`,
33
- options: {
34
- async: false
35
- }
21
+ command: `redis-cli -u "${config.dbs.redis}" flushdb`
36
22
  },
37
- test: {
38
- command: 'node --test --test-concurrency=1 --test-timeout=180000 test/*.js', // Added 3-minute timeout for tests
39
- options: {
40
- async: false
41
- }
23
+ waitServer: {
24
+ // Polls /health until the server reports ready (all IMAP workers up,
25
+ // Redis responding) instead of sleeping for a fixed delay
26
+ command: 'node test/helpers/wait-for-server.js'
27
+ },
28
+ testUnit: {
29
+ // Self-contained tests - need Redis but not the live server.
30
+ // Run with default --test concurrency; the suite is verified to pass in parallel.
31
+ // The *-test.js pattern keeps helper modules out of the test runner
32
+ command: 'node --test --test-timeout=180000 test/*-test.js'
33
+ },
34
+ testIntegration: {
35
+ // Tests that run against the live server started by shell:server
36
+ command: 'node --test --test-concurrency=1 --test-timeout=180000 test/integration/*-test.js'
42
37
  },
43
38
  options: {
44
39
  stdout: data => console.log(data.toString().trim()),
@@ -50,10 +45,11 @@ module.exports = function (grunt) {
50
45
 
51
46
  // Load the plugin(s)
52
47
  grunt.loadNpmTasks('grunt-shell-spawn');
53
- grunt.loadNpmTasks('grunt-wait');
54
48
 
55
49
  // Tasks
56
- grunt.registerTask('test', ['shell:flush', 'shell:server', 'wait:server', 'shell:test', 'shell:server:kill']);
50
+ grunt.registerTask('test-unit', ['shell:flush', 'shell:testUnit']);
51
+ grunt.registerTask('test-integration', ['shell:flush', 'shell:server', 'shell:waitServer', 'shell:testIntegration', 'shell:server:kill']);
52
+ grunt.registerTask('test', ['test-unit', 'test-integration']);
57
53
 
58
54
  grunt.registerTask('default', ['shell:eslint', 'test']);
59
55
  };
@@ -105,7 +105,14 @@ const GLOBAL_OPTIONS = [
105
105
  { name: '--smtp.host', description: 'SMTP server bind address', type: 'string', default: '127.0.0.1', group: 'SMTP server' },
106
106
  { name: '--smtp.port', description: 'SMTP server port', type: 'number', default: 2525, group: 'SMTP server' },
107
107
  { name: '--smtp.proxy', description: 'Enable HAProxy PROXY protocol', type: 'boolean', default: false, group: 'SMTP server' },
108
- { name: '--smtp.maxMessageSize', description: 'Maximum email size', type: 'number/string', default: '25M', group: 'SMTP server' }
108
+ { name: '--smtp.maxMessageSize', description: 'Maximum email size', type: 'number/string', default: '25M', group: 'SMTP server' },
109
+ {
110
+ name: '--documentStore.enabled',
111
+ description: 'Enable the deprecated Document Store (ElasticSearch) feature',
112
+ type: 'boolean',
113
+ default: false,
114
+ group: 'Document Store (deprecated)'
115
+ }
109
116
  ];
110
117
 
111
118
  // Help formatting functions
@@ -31,6 +31,11 @@ secret = "" # client password, if not set allows any password
31
31
  proxy = false # Set to true if using HAProxy with send-proxy option
32
32
  #maxMessageSize = "25M" # maximum message size accepted by SMTP server (default: 25MB)
33
33
 
34
+ [documentStore]
35
+ # Deprecated Document Store (ElasticSearch) feature. Disabled by default; the worker and
36
+ # all document-store API/UI endpoints are only available when this is enabled.
37
+ enabled = false
38
+
34
39
  [dbs]
35
40
  # redis connection
36
41
  redis = "redis://127.0.0.1:6379/8"
@@ -0,0 +1,35 @@
1
+ # End-to-end overrides, merged over default.toml by @zone-eu/wild-config when NODE_ENV=e2e.
2
+ # Boots a fresh EmailEngine for the Playwright happy-path suite (test/e2e): enable auth,
3
+ # activate a 14-day trial (hits postalsys.com), register an Ethereal account, send + read back.
4
+ #
5
+ # Uses an isolated Redis DB so the suite can flush it for a clean fresh-instance run without
6
+ # touching dev (db 9), test (db 13), or default (db 8) data. No preparedToken / preparedPassword /
7
+ # preparedLicense here on purpose - the suite enables auth and activates the trial through the UI.
8
+
9
+ # JSON formatted settings, seeded on startup.
10
+ # serviceUrl is the recognizable e2e URL that postalsys-web allowlists to skip the trial rate
11
+ # limit. It is only used as the trial request's `url`; the browser and API talk to 127.0.0.1:7099.
12
+ settings = '''
13
+ {
14
+ "serviceUrl": "https://e2e.emailengine.app/",
15
+ "ignoreMailCertErrors": true
16
+ }
17
+ '''
18
+
19
+ [service]
20
+ # Fixed encryption secret for the throwaway e2e instance (Redis is flushed on every run).
21
+ secret = "e2e encryption secret"
22
+
23
+ [workers]
24
+ imap = 1
25
+
26
+ [log]
27
+ level = "warn"
28
+
29
+ [dbs]
30
+ # Isolated Redis DB for e2e; flushed before each run by test/e2e/flush-redis.js
31
+ redis = "redis://127.0.0.1:6379/14"
32
+
33
+ [api]
34
+ host = "127.0.0.1"
35
+ port = 7099
package/config/test.toml CHANGED
@@ -43,3 +43,8 @@ port = 7077
43
43
 
44
44
  [webhooksServer]
45
45
  port = 7078
46
+
47
+ # Keep the deprecated Document Store feature available during tests so the existing
48
+ # document-store API/UI endpoints stay covered. Disabled by default in production.
49
+ [documentStore]
50
+ enabled = true
@@ -1,5 +1,5 @@
1
1
  {
2
- "creationTime": "2026-06-10T14:45:48.000000",
2
+ "creationTime": "2026-06-18T14:46:19.000000",
3
3
  "prefixes": [
4
4
  {
5
5
  "ipv6Prefix": "2001:4860:4801:2008::/64"
package/getswagger.sh CHANGED
@@ -4,6 +4,10 @@ set -e
4
4
 
5
5
  export EENGINE_PORT=5678
6
6
 
7
+ # Keep the deprecated Document Store endpoints in the generated spec; they are only
8
+ # registered when the feature is enabled.
9
+ export EENGINE_DOCUMENT_STORE_ENABLED=true
10
+
7
11
  # refuse to run if something is already listening on the port, otherwise the
8
12
  # polling loop below would silently fetch swagger.json from a stale instance
9
13
  if (exec 3<>"/dev/tcp/127.0.0.1/${EENGINE_PORT}") 2>/dev/null; then
package/lib/account.js CHANGED
@@ -20,6 +20,7 @@ const { deepStrictEqual, strictEqual } = require('assert');
20
20
  const { encrypt, decrypt } = require('./encrypt');
21
21
  const { oauth2Apps, LEGACY_KEYS, isApiBasedApp } = require('./oauth2-apps');
22
22
  const settings = require('./settings');
23
+ const { isDocumentStoreEnabled, documentStoreFeatureEnabled } = require('./document-store');
23
24
  const redisScanDelete = require('./redis-scan-delete');
24
25
  const { customAlphabet } = require('nanoid');
25
26
  const Lock = require('ioredfour');
@@ -1048,28 +1049,33 @@ class Account {
1048
1049
  };
1049
1050
  }
1050
1051
 
1051
- try {
1052
- let queueKeep = (await settings.get('queueKeep')) || true;
1053
- let serviceUrl = (await settings.get('serviceUrl')) || null;
1052
+ // Only notify the documents queue when the deprecated Document Store feature is enabled.
1053
+ // When it is off the documents worker is not running, so an enqueued job would never be
1054
+ // consumed and would pile up in Redis.
1055
+ if (documentStoreFeatureEnabled) {
1056
+ try {
1057
+ let queueKeep = (await settings.get('queueKeep')) || true;
1058
+ let serviceUrl = (await settings.get('serviceUrl')) || null;
1054
1059
 
1055
- let payload = {
1056
- serviceUrl,
1057
- account: this.account,
1058
- date: new Date().toISOString(),
1059
- event: ACCOUNT_DELETED_NOTIFY
1060
- };
1060
+ let payload = {
1061
+ serviceUrl,
1062
+ account: this.account,
1063
+ date: new Date().toISOString(),
1064
+ event: ACCOUNT_DELETED_NOTIFY
1065
+ };
1061
1066
 
1062
- await this.documentsQueue.add(ACCOUNT_DELETED_NOTIFY, payload, {
1063
- removeOnComplete: queueKeep,
1064
- removeOnFail: queueKeep,
1065
- attempts: 10,
1066
- backoff: {
1067
- type: 'exponential',
1068
- delay: 5000
1069
- }
1070
- });
1071
- } catch (err) {
1072
- this.logger.error({ msg: 'Failed to add entry to documents queue', err });
1067
+ await this.documentsQueue.add(ACCOUNT_DELETED_NOTIFY, payload, {
1068
+ removeOnComplete: queueKeep,
1069
+ removeOnFail: queueKeep,
1070
+ attempts: 10,
1071
+ backoff: {
1072
+ type: 'exponential',
1073
+ delay: 5000
1074
+ }
1075
+ });
1076
+ } catch (err) {
1077
+ this.logger.error({ msg: 'Failed to add entry to documents queue', err });
1078
+ }
1073
1079
  }
1074
1080
 
1075
1081
  await this.call({
@@ -1458,7 +1464,7 @@ class Account {
1458
1464
  }
1459
1465
 
1460
1466
  async getText(text, options) {
1461
- if (options.documentStore && (await settings.get('documentStoreEnabled'))) {
1467
+ if (options.documentStore && (await isDocumentStoreEnabled())) {
1462
1468
  await this.loadAccountData(this.account, false);
1463
1469
 
1464
1470
  const { index, client } = this.esClient;
@@ -1516,7 +1522,7 @@ class Account {
1516
1522
  options.preProcessHtml = true;
1517
1523
  }
1518
1524
 
1519
- if (options.documentStore && (await settings.get('documentStoreEnabled'))) {
1525
+ if (options.documentStore && (await isDocumentStoreEnabled())) {
1520
1526
  await this.loadAccountData(this.account, false);
1521
1527
 
1522
1528
  const { index, client } = this.esClient;
@@ -1700,7 +1706,7 @@ class Account {
1700
1706
  }
1701
1707
 
1702
1708
  async listMessages(query) {
1703
- if (query.documentStore && (await settings.get('documentStoreEnabled'))) {
1709
+ if (query.documentStore && (await isDocumentStoreEnabled())) {
1704
1710
  await this.loadAccountData(this.account, false);
1705
1711
 
1706
1712
  const { index, client } = this.esClient;
@@ -1836,7 +1842,7 @@ class Account {
1836
1842
 
1837
1843
  async searchMessages(query, searchOpts) {
1838
1844
  searchOpts = searchOpts || {};
1839
- if (query.documentStore && (await settings.get('documentStoreEnabled'))) {
1845
+ if (query.documentStore && (await isDocumentStoreEnabled())) {
1840
1846
  if (!searchOpts.unified) {
1841
1847
  await this.loadAccountData(this.account, false);
1842
1848
  }
@@ -2401,7 +2407,7 @@ class Account {
2401
2407
  // scan and delete keys
2402
2408
  await redisScanDelete(this.redis, this.logger, `${REDIS_PREFIX}iam:${this.account}:*`);
2403
2409
 
2404
- if (await settings.get('documentStoreEnabled')) {
2410
+ if (await isDocumentStoreEnabled()) {
2405
2411
  // Flush ElasticSearch index for this account
2406
2412
  const { index, client } = this.esClient;
2407
2413
  if (!client) {