emailengine-app 2.61.1 → 2.61.3

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 (136) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/data/google-crawlers.json +1 -1
  3. package/lib/account/account-state.js +248 -0
  4. package/lib/account.js +45 -193
  5. package/lib/api-routes/account-routes.js +1023 -0
  6. package/lib/api-routes/message-routes.js +1377 -0
  7. package/lib/consts.js +12 -2
  8. package/lib/email-client/base-client.js +282 -771
  9. package/lib/email-client/gmail/gmail-api.js +243 -0
  10. package/lib/email-client/gmail-client.js +145 -53
  11. package/lib/email-client/imap/mailbox.js +24 -698
  12. package/lib/email-client/imap/sync-operations.js +812 -0
  13. package/lib/email-client/imap-client.js +1 -1
  14. package/lib/email-client/message-builder.js +566 -0
  15. package/lib/email-client/notification-handler.js +314 -0
  16. package/lib/email-client/outlook/graph-api.js +326 -0
  17. package/lib/email-client/outlook-client.js +159 -113
  18. package/lib/email-client/smtp-pool-manager.js +196 -0
  19. package/lib/imapproxy/imap-server.js +3 -12
  20. package/lib/oauth/gmail.js +4 -4
  21. package/lib/oauth/mail-ru.js +30 -5
  22. package/lib/oauth/outlook.js +57 -3
  23. package/lib/oauth/pubsub/google.js +30 -11
  24. package/lib/oauth/scope-checker.js +202 -0
  25. package/lib/oauth2-apps.js +8 -4
  26. package/lib/redis-operations.js +484 -0
  27. package/lib/routes-ui.js +283 -2582
  28. package/lib/tools.js +4 -196
  29. package/lib/ui-routes/account-routes.js +1931 -0
  30. package/lib/ui-routes/admin-config-routes.js +1233 -0
  31. package/lib/ui-routes/admin-entities-routes.js +2367 -0
  32. package/lib/ui-routes/oauth-routes.js +992 -0
  33. package/lib/utils/network.js +237 -0
  34. package/package.json +10 -10
  35. package/sbom.json +1 -1
  36. package/static/js/app.js +5 -5
  37. package/static/licenses.html +79 -19
  38. package/translations/de.mo +0 -0
  39. package/translations/de.po +97 -86
  40. package/translations/en.mo +0 -0
  41. package/translations/en.po +80 -75
  42. package/translations/et.mo +0 -0
  43. package/translations/et.po +96 -86
  44. package/translations/fr.mo +0 -0
  45. package/translations/fr.po +97 -86
  46. package/translations/ja.mo +0 -0
  47. package/translations/ja.po +96 -86
  48. package/translations/messages.pot +105 -91
  49. package/translations/nl.mo +0 -0
  50. package/translations/nl.po +98 -86
  51. package/translations/pl.mo +0 -0
  52. package/translations/pl.po +96 -86
  53. package/views/account/security.hbs +4 -4
  54. package/views/accounts/account.hbs +13 -13
  55. package/views/accounts/register/imap-server.hbs +12 -12
  56. package/views/config/document-store/pre-processing/index.hbs +4 -2
  57. package/views/config/oauth/app.hbs +6 -7
  58. package/views/config/oauth/index.hbs +2 -2
  59. package/views/config/service.hbs +3 -4
  60. package/views/dashboard.hbs +5 -7
  61. package/views/error.hbs +22 -7
  62. package/views/gateways/gateway.hbs +2 -2
  63. package/views/partials/add_account_modal.hbs +7 -10
  64. package/views/partials/document_store_header.hbs +1 -1
  65. package/views/partials/editor_scope_info.hbs +0 -1
  66. package/views/partials/oauth_config_header.hbs +1 -1
  67. package/views/partials/side_menu.hbs +3 -3
  68. package/views/partials/webhook_form.hbs +2 -2
  69. package/views/templates/index.hbs +1 -1
  70. package/views/templates/template.hbs +8 -8
  71. package/views/tokens/index.hbs +6 -6
  72. package/views/tokens/new.hbs +1 -1
  73. package/views/webhooks/index.hbs +4 -4
  74. package/views/webhooks/webhook.hbs +7 -7
  75. package/workers/api.js +148 -2436
  76. package/workers/smtp.js +2 -1
  77. package/lib/imapproxy/imap-core/test/client.js +0 -46
  78. package/lib/imapproxy/imap-core/test/fixtures/append.eml +0 -1196
  79. package/lib/imapproxy/imap-core/test/fixtures/chunks.js +0 -44
  80. package/lib/imapproxy/imap-core/test/fixtures/fix1.eml +0 -6
  81. package/lib/imapproxy/imap-core/test/fixtures/fix2.eml +0 -599
  82. package/lib/imapproxy/imap-core/test/fixtures/fix3.eml +0 -32
  83. package/lib/imapproxy/imap-core/test/fixtures/fix4.eml +0 -6
  84. package/lib/imapproxy/imap-core/test/fixtures/mimetorture.eml +0 -599
  85. package/lib/imapproxy/imap-core/test/fixtures/mimetorture.js +0 -2740
  86. package/lib/imapproxy/imap-core/test/fixtures/mimetorture.json +0 -1411
  87. package/lib/imapproxy/imap-core/test/fixtures/mimetree.js +0 -85
  88. package/lib/imapproxy/imap-core/test/fixtures/nodemailer.eml +0 -582
  89. package/lib/imapproxy/imap-core/test/fixtures/ryan_finnie_mime_torture.eml +0 -599
  90. package/lib/imapproxy/imap-core/test/fixtures/simple.eml +0 -42
  91. package/lib/imapproxy/imap-core/test/fixtures/simple.json +0 -164
  92. package/lib/imapproxy/imap-core/test/imap-compile-stream-test.js +0 -671
  93. package/lib/imapproxy/imap-core/test/imap-compiler-test.js +0 -272
  94. package/lib/imapproxy/imap-core/test/imap-indexer-test.js +0 -236
  95. package/lib/imapproxy/imap-core/test/imap-parser-test.js +0 -922
  96. package/lib/imapproxy/imap-core/test/memory-notifier.js +0 -129
  97. package/lib/imapproxy/imap-core/test/prepare.sh +0 -74
  98. package/lib/imapproxy/imap-core/test/protocol-test.js +0 -1756
  99. package/lib/imapproxy/imap-core/test/search-test.js +0 -1356
  100. package/lib/imapproxy/imap-core/test/test-client.js +0 -152
  101. package/lib/imapproxy/imap-core/test/test-server.js +0 -623
  102. package/lib/imapproxy/imap-core/test/tools-test.js +0 -22
  103. package/test/api-test.js +0 -899
  104. package/test/autoreply-test.js +0 -327
  105. package/test/bounce-test.js +0 -151
  106. package/test/complaint-test.js +0 -256
  107. package/test/fixtures/autoreply/LICENSE +0 -27
  108. package/test/fixtures/autoreply/rfc3834-01.eml +0 -23
  109. package/test/fixtures/autoreply/rfc3834-02.eml +0 -24
  110. package/test/fixtures/autoreply/rfc3834-03.eml +0 -26
  111. package/test/fixtures/autoreply/rfc3834-04.eml +0 -48
  112. package/test/fixtures/autoreply/rfc3834-05.eml +0 -19
  113. package/test/fixtures/autoreply/rfc3834-06.eml +0 -59
  114. package/test/fixtures/bounces/163.eml +0 -2521
  115. package/test/fixtures/bounces/fastmail.eml +0 -242
  116. package/test/fixtures/bounces/gmail.eml +0 -252
  117. package/test/fixtures/bounces/hotmail.eml +0 -655
  118. package/test/fixtures/bounces/mailru.eml +0 -121
  119. package/test/fixtures/bounces/outlook.eml +0 -1107
  120. package/test/fixtures/bounces/postfix.eml +0 -101
  121. package/test/fixtures/bounces/rambler.eml +0 -116
  122. package/test/fixtures/bounces/workmail.eml +0 -142
  123. package/test/fixtures/bounces/yahoo.eml +0 -139
  124. package/test/fixtures/bounces/zoho.eml +0 -83
  125. package/test/fixtures/bounces/zonemta.eml +0 -100
  126. package/test/fixtures/complaints/LICENSE +0 -27
  127. package/test/fixtures/complaints/amazonses.eml +0 -72
  128. package/test/fixtures/complaints/dmarc.eml +0 -59
  129. package/test/fixtures/complaints/hotmail.eml +0 -49
  130. package/test/fixtures/complaints/optout.eml +0 -40
  131. package/test/fixtures/complaints/standard-arf.eml +0 -68
  132. package/test/fixtures/complaints/yahoo.eml +0 -68
  133. package/test/oauth2-apps-test.js +0 -301
  134. package/test/sendonly-test.js +0 -160
  135. package/test/test-config.js +0 -34
  136. package/test/webhooks-server.js +0 -39
@@ -1,327 +0,0 @@
1
- 'use strict';
2
-
3
- // Test fixtures in fixtures/autoreply/ are from:
4
- // https://github.com/sisimai/set-of-emails/
5
- // Licensed under BSD 2-Clause License, Copyright (C) 2014, azumakuniyuki
6
-
7
- const test = require('node:test');
8
- const assert = require('node:assert').strict;
9
-
10
- const { simpleParser } = require('mailparser');
11
- const fs = require('fs');
12
- const Path = require('path');
13
-
14
- const path = fname => Path.join(__dirname, 'fixtures', 'autoreply', fname);
15
-
16
- // Replicate isAutoreply logic from base-client.js for testing
17
- function isAutoreply(messageData) {
18
- // Check subject patterns - these are strong autoreply indicators
19
- // Note: "Automatic reply:" and "Auto reply:" (with space) are common variants
20
- // "Out of the Office" is also valid (with "the")
21
- if (/^(auto(matic)?\s*(reply|response)|Out of(?: the)? Office|OOF:|OOO:)/i.test(messageData.subject)) {
22
- return true;
23
- }
24
-
25
- // Weaker subject patterns require inReplyTo as confirmation
26
- if (/^auto:/i.test(messageData.subject) && messageData.inReplyTo) {
27
- return true;
28
- }
29
-
30
- if (!messageData.headers) {
31
- return false;
32
- }
33
-
34
- // Check Precedence header
35
- if (messageData.headers.precedence && messageData.headers.precedence.some(e => /auto[_-]?reply/.test(e))) {
36
- return true;
37
- }
38
-
39
- // Check Auto-Submitted header (RFC 3834)
40
- if (messageData.headers['auto-submitted'] && messageData.headers['auto-submitted'].some(e => /auto[_-]?replied/.test(e))) {
41
- return true;
42
- }
43
-
44
- // Check X-Auto-Response-Suppress header (Microsoft Exchange)
45
- // Values like "All", "OOF", "AutoReply" indicate this is an autoreply
46
- if (messageData.headers['x-auto-response-suppress'] && messageData.headers['x-auto-response-suppress'].length) {
47
- return true;
48
- }
49
-
50
- // Check various vendor-specific headers
51
- for (let headerKey of ['x-autoresponder', 'x-autorespond', 'x-autoreply']) {
52
- if (messageData.headers[headerKey] && messageData.headers[headerKey].length) {
53
- return true;
54
- }
55
- }
56
-
57
- return false;
58
- }
59
-
60
- // Convert parsed email headers to the format expected by isAutoreply
61
- function convertHeaders(parsed) {
62
- const headers = {};
63
- if (parsed.headers) {
64
- for (let [key, value] of parsed.headers) {
65
- let normalizedKey = key.toLowerCase();
66
- if (!headers[normalizedKey]) {
67
- headers[normalizedKey] = [];
68
- }
69
- headers[normalizedKey].push(value);
70
- }
71
- }
72
- return headers;
73
- }
74
-
75
- // Helper to parse email and prepare messageData for isAutoreply
76
- async function parseForAutoreply(filePath) {
77
- const content = await fs.promises.readFile(filePath);
78
- const parsed = await simpleParser(content);
79
-
80
- return {
81
- subject: parsed.subject || '',
82
- inReplyTo: parsed.inReplyTo || null,
83
- headers: convertHeaders(parsed)
84
- };
85
- }
86
-
87
- test('RFC 3834 autoreply detection tests', async t => {
88
- await t.test('Auto-Submitted header detection (rfc3834-01)', async () => {
89
- const messageData = await parseForAutoreply(path('rfc3834-01.eml'));
90
- const result = isAutoreply(messageData);
91
-
92
- // Has Auto-Submitted: auto-replied header
93
- assert.strictEqual(result, true);
94
- assert.ok(messageData.headers['auto-submitted']);
95
- assert.ok(messageData.headers['auto-submitted'].some(e => /auto-replied/.test(e)));
96
- });
97
-
98
- await t.test('Automatic reply subject with X-Auto-Response-Suppress (rfc3834-02)', async () => {
99
- const messageData = await parseForAutoreply(path('rfc3834-02.eml'));
100
- const result = isAutoreply(messageData);
101
-
102
- // Has subject "Automatic reply:" and X-Auto-Response-Suppress: All
103
- assert.strictEqual(result, true);
104
- assert.ok(/^Automatic reply:/i.test(messageData.subject));
105
- });
106
-
107
- await t.test('Auto reply subject with In-Reply-To (rfc3834-03)', async () => {
108
- const messageData = await parseForAutoreply(path('rfc3834-03.eml'));
109
- const result = isAutoreply(messageData);
110
-
111
- // Has subject "Auto reply:" with In-Reply-To header
112
- assert.strictEqual(result, true);
113
- assert.ok(/^Auto reply:/i.test(messageData.subject));
114
- assert.ok(messageData.inReplyTo);
115
- });
116
-
117
- await t.test('Microsoft Exchange automatic reply (rfc3834-04)', async () => {
118
- const messageData = await parseForAutoreply(path('rfc3834-04.eml'));
119
- const result = isAutoreply(messageData);
120
-
121
- // Has subject "Automatic reply:" and X-Auto-Response-Suppress: All
122
- assert.strictEqual(result, true);
123
- assert.ok(messageData.headers['x-auto-response-suppress']);
124
- });
125
-
126
- await t.test('Auto-Submitted with random subject (rfc3834-05)', async () => {
127
- const messageData = await parseForAutoreply(path('rfc3834-05.eml'));
128
- const result = isAutoreply(messageData);
129
-
130
- // Has Auto-Submitted: auto-replied with non-standard subject
131
- assert.strictEqual(result, true);
132
- assert.ok(messageData.headers['auto-submitted']);
133
- });
134
-
135
- await t.test('Mimecast auto-response (rfc3834-06)', async () => {
136
- const messageData = await parseForAutoreply(path('rfc3834-06.eml'));
137
- const result = isAutoreply(messageData);
138
-
139
- // Has Auto-Submitted and X-Auto-Response-Suppress headers
140
- assert.strictEqual(result, true);
141
- assert.ok(messageData.headers['auto-submitted']);
142
- assert.ok(messageData.headers['x-auto-response-suppress']);
143
- });
144
- });
145
-
146
- test('isAutoreply heuristics', async t => {
147
- await t.test('Detects Out of Office subject', async () => {
148
- const messageData = {
149
- subject: 'Out of Office: I am away',
150
- inReplyTo: null,
151
- headers: {}
152
- };
153
- assert.strictEqual(isAutoreply(messageData), true);
154
- });
155
-
156
- await t.test('Detects Out of the Office subject (with "the")', async () => {
157
- const messageData = {
158
- subject: 'Out of the Office: Mailtrain Newsletter',
159
- inReplyTo: null,
160
- headers: {}
161
- };
162
- assert.strictEqual(isAutoreply(messageData), true);
163
- });
164
-
165
- await t.test('Detects OOF prefix', async () => {
166
- const messageData = {
167
- subject: 'OOF: Automatic Reply',
168
- inReplyTo: null,
169
- headers: {}
170
- };
171
- assert.strictEqual(isAutoreply(messageData), true);
172
- });
173
-
174
- await t.test('Detects OOO prefix', async () => {
175
- const messageData = {
176
- subject: 'OOO: Out of Office',
177
- inReplyTo: null,
178
- headers: {}
179
- };
180
- assert.strictEqual(isAutoreply(messageData), true);
181
- });
182
-
183
- await t.test('Detects Automatic reply subject', async () => {
184
- const messageData = {
185
- subject: 'Automatic reply: Your message',
186
- inReplyTo: null,
187
- headers: {}
188
- };
189
- assert.strictEqual(isAutoreply(messageData), true);
190
- });
191
-
192
- await t.test('Detects Auto reply subject (with space)', async () => {
193
- const messageData = {
194
- subject: 'Auto reply: Thanks',
195
- inReplyTo: null,
196
- headers: {}
197
- };
198
- assert.strictEqual(isAutoreply(messageData), true);
199
- });
200
-
201
- await t.test('Detects Automatic response subject', async () => {
202
- const messageData = {
203
- subject: 'Automatic response: Meeting',
204
- inReplyTo: null,
205
- headers: {}
206
- };
207
- assert.strictEqual(isAutoreply(messageData), true);
208
- });
209
-
210
- await t.test('Requires inReplyTo for weak auto: subject', async () => {
211
- const messageData = {
212
- subject: 'auto: Something',
213
- inReplyTo: null,
214
- headers: {}
215
- };
216
- assert.strictEqual(isAutoreply(messageData), false);
217
-
218
- messageData.inReplyTo = '<some-message-id@example.com>';
219
- assert.strictEqual(isAutoreply(messageData), true);
220
- });
221
-
222
- await t.test('Detects Precedence: auto_reply header', async () => {
223
- const messageData = {
224
- subject: 'Some subject',
225
- inReplyTo: null,
226
- headers: {
227
- precedence: ['auto_reply']
228
- }
229
- };
230
- assert.strictEqual(isAutoreply(messageData), true);
231
- });
232
-
233
- await t.test('Detects Precedence: auto-reply header', async () => {
234
- const messageData = {
235
- subject: 'Some subject',
236
- inReplyTo: null,
237
- headers: {
238
- precedence: ['auto-reply']
239
- }
240
- };
241
- assert.strictEqual(isAutoreply(messageData), true);
242
- });
243
-
244
- await t.test('Detects Auto-Submitted: auto-replied header', async () => {
245
- const messageData = {
246
- subject: 'Some subject',
247
- inReplyTo: null,
248
- headers: {
249
- 'auto-submitted': ['auto-replied']
250
- }
251
- };
252
- assert.strictEqual(isAutoreply(messageData), true);
253
- });
254
-
255
- await t.test('Detects X-Auto-Response-Suppress header', async () => {
256
- const messageData = {
257
- subject: 'Some subject',
258
- inReplyTo: null,
259
- headers: {
260
- 'x-auto-response-suppress': ['All']
261
- }
262
- };
263
- assert.strictEqual(isAutoreply(messageData), true);
264
- });
265
-
266
- await t.test('Detects X-Autoresponder header', async () => {
267
- const messageData = {
268
- subject: 'Some subject',
269
- inReplyTo: null,
270
- headers: {
271
- 'x-autoresponder': ['true']
272
- }
273
- };
274
- assert.strictEqual(isAutoreply(messageData), true);
275
- });
276
-
277
- await t.test('Detects X-Autorespond header', async () => {
278
- const messageData = {
279
- subject: 'Some subject',
280
- inReplyTo: null,
281
- headers: {
282
- 'x-autorespond': ['yes']
283
- }
284
- };
285
- assert.strictEqual(isAutoreply(messageData), true);
286
- });
287
-
288
- await t.test('Detects X-Autoreply header', async () => {
289
- const messageData = {
290
- subject: 'Some subject',
291
- inReplyTo: null,
292
- headers: {
293
- 'x-autoreply': ['yes']
294
- }
295
- };
296
- assert.strictEqual(isAutoreply(messageData), true);
297
- });
298
-
299
- await t.test('Rejects regular email', async () => {
300
- const messageData = {
301
- subject: 'Weekly Newsletter',
302
- inReplyTo: null,
303
- headers: {
304
- from: ['newsletter@example.com']
305
- }
306
- };
307
- assert.strictEqual(isAutoreply(messageData), false);
308
- });
309
-
310
- await t.test('Rejects email with similar but non-matching subject', async () => {
311
- const messageData = {
312
- subject: 'Automatic update notification',
313
- inReplyTo: null,
314
- headers: {}
315
- };
316
- assert.strictEqual(isAutoreply(messageData), false);
317
- });
318
-
319
- await t.test('Handles missing headers gracefully', async () => {
320
- const messageData = {
321
- subject: 'Test',
322
- inReplyTo: null,
323
- headers: null
324
- };
325
- assert.strictEqual(isAutoreply(messageData), false);
326
- });
327
- });
@@ -1,151 +0,0 @@
1
- 'use strict';
2
-
3
- const test = require('node:test');
4
- const assert = require('node:assert').strict;
5
-
6
- const { bounceDetect } = require('../lib/bounce-detect');
7
- const fs = require('fs');
8
-
9
- const Path = require('path');
10
- const path = fname => Path.join(__dirname, 'fixtures', 'bounces', fname);
11
-
12
- test('Bounce parsing tests', async t => {
13
- await t.test('163', async () => {
14
- const content = await fs.promises.readFile(path('163.eml'));
15
- const bounce = await bounceDetect(content);
16
-
17
- assert.strictEqual(bounce.recipient, 'jgfhhoiyfjhhugjhv@ethereal.email');
18
- assert.strictEqual(bounce.action, 'failed');
19
- assert.strictEqual(bounce.response.message, 'SMTP error, RCPT TO: Host ethereal.email(54.36.85.113) RCPT TO said 550 No such user here');
20
- assert.strictEqual(bounce.messageId, '<cc799ab9-ab11-0960-f3c2-2e4b9a5e8fb6@163.com>');
21
- });
22
-
23
- await t.test('fastmail', async () => {
24
- const content = await fs.promises.readFile(path('fastmail.eml'));
25
- const bounce = await bounceDetect(content);
26
-
27
- assert.strictEqual(bounce.recipient, 'htfgvhyufthdgcvhgjyfthgc@ethereal.email');
28
- assert.strictEqual(bounce.action, 'failed');
29
- assert.strictEqual(bounce.response.message, '550 No such user here');
30
- assert.strictEqual(bounce.messageId, '<e85f1c9b-9b51-4028-8ec0-0a657155028e@app.fastmail.com>');
31
- });
32
-
33
- await t.test('gmail', async () => {
34
- const content = await fs.promises.readFile(path('gmail.eml'));
35
- const bounce = await bounceDetect(content);
36
-
37
- assert.strictEqual(bounce.recipient, 'jhfthgfuyfhvjkugjhvjuyfv@hot.ee');
38
- assert.strictEqual(bounce.action, 'failed');
39
- assert.strictEqual(
40
- bounce.response.message,
41
- '550 5.1.1 <jhfthgfuyfhvjkugjhvjuyfv@hot.ee>: Recipient address rejected: User unknown in relay recipient table'
42
- );
43
- assert.strictEqual(bounce.messageId, '<CAPacwgw3pCyVcmW4nVy8VPX5u5ksn_wZB2jZ_tLUM2es7LaiEA@mail.gmail.com>');
44
- });
45
-
46
- await t.test('hotmail', async () => {
47
- const content = await fs.promises.readFile(path('hotmail.eml'));
48
- const bounce = await bounceDetect(content);
49
-
50
- assert.strictEqual(bounce.recipient, 'sdfadsdfwedsfcasfeqwefwq@hot.ee');
51
- assert.strictEqual(bounce.action, 'failed');
52
- assert.strictEqual(
53
- bounce.response.message,
54
- '550 5.1.1 <sdfadsdfwedsfcasfeqwefwq@hot.ee>: Recipient address rejected: User unknown in relay recipient table'
55
- );
56
- assert.strictEqual(bounce.messageId, '<DB6PR0902MB194406730EDCF3E12EE16DCF90209@DB6PR0902MB1944.eurprd09.prod.outlook.com>');
57
- });
58
-
59
- await t.test('mailru', async () => {
60
- const content = await fs.promises.readFile(path('mailru.eml'));
61
- const bounce = await bounceDetect(content);
62
-
63
- assert.strictEqual(bounce.recipient, 'tfhgyuftghjyftghv@hot.ee');
64
- assert.strictEqual(bounce.action, 'failed');
65
- assert.strictEqual(bounce.response.message, '550 5.1.1 <tfhgyuftghjyftghv@hot.ee>: Recipient address rejected: User unknown in relay recipient table');
66
- assert.strictEqual(bounce.messageId, '<1665380146.431729680@f705.i.mail.ru>');
67
- });
68
-
69
- await t.test('outlook', async () => {
70
- const content = await fs.promises.readFile(path('outlook.eml'));
71
- const bounce = await bounceDetect(content);
72
-
73
- assert.strictEqual(bounce.recipient, 'wfsddaSdasffasdqwqw@hot.ee');
74
- assert.strictEqual(bounce.action, 'failed');
75
- assert.strictEqual(
76
- bounce.response.message,
77
- '550 5.1.1 <wfsddaSdasffasdqwqw@hot.ee>: Recipient address rejected: User unknown in relay recipient table'
78
- );
79
- assert.strictEqual(bounce.messageId, '<PR1PR07MB57558E5D11D6C2BA6F950391D7209@PR1PR07MB5755.eurprd07.prod.outlook.com>');
80
- });
81
-
82
- await t.test('postfix', async () => {
83
- const content = await fs.promises.readFile(path('postfix.eml'));
84
- const bounce = await bounceDetect(content);
85
-
86
- assert.strictEqual(bounce.recipient, 'sdagfsdfgdasfsdf@hot.ee');
87
- assert.strictEqual(bounce.action, 'failed');
88
- assert.strictEqual(bounce.response.message, '550 5.1.1 <sdagfsdfgdasfsdf@hot.ee>: Recipient address rejected: User unknown in relay recipient table');
89
- assert.strictEqual(bounce.queueId, 'DF59B82305');
90
- assert.strictEqual(bounce.messageId, '<0f51267b17be7a93bb0017205b6c4fca@ekiri.ee>');
91
- });
92
-
93
- await t.test('rambler', async () => {
94
- const content = await fs.promises.readFile(path('rambler.eml'));
95
- const bounce = await bounceDetect(content);
96
-
97
- assert.strictEqual(bounce.recipient, 'yhfgcvjyutfdchgyufthgc@ethereal.email');
98
- assert.strictEqual(bounce.action, 'failed');
99
- assert.strictEqual(bounce.response.message, '550 No such user here');
100
- assert.strictEqual(bounce.messageId, '<18c57ad7166403358c3893f62d7e3a7f@mail.rambler.ru>');
101
- });
102
-
103
- await t.test('workmail', async () => {
104
- const content = await fs.promises.readFile(path('workmail.eml'));
105
- const bounce = await bounceDetect(content);
106
-
107
- assert.strictEqual(bounce.recipient, 'gfdutydrfghutydrfcuftydh@hot.ee');
108
- assert.strictEqual(bounce.action, 'failed');
109
- assert.strictEqual(
110
- bounce.response.message,
111
- '550 5.1.1 <gfdutydrfghutydrfcuftydh@hot.ee>: Recipient address rejected: User unknown in relay recipient table'
112
- );
113
- assert.strictEqual(bounce.messageId, '<mail.6343b157.093e.5156c64350ef7e50@storage.wm.amazon.com>');
114
- });
115
-
116
- await t.test('Yahoo', async () => {
117
- const content = await fs.promises.readFile(path('yahoo.eml'));
118
- const bounce = await bounceDetect(content);
119
-
120
- assert.strictEqual(bounce.recipient, 'thgdcgrfchvutycfgxcvg@hot.ee');
121
- assert.strictEqual(bounce.action, 'failed');
122
- assert.strictEqual(
123
- bounce.response.message,
124
- '550: 5.1.1 <thgdcgrfchvutycfgxcvg@hot.ee>: Recipient address rejected: User unknown in relay recipient table'
125
- );
126
- assert.strictEqual(bounce.messageId, '<1956854879.3770605.1665380049620@mail.yahoo.com>');
127
- });
128
-
129
- await t.test('zonemta', async () => {
130
- const content = await fs.promises.readFile(path('zonemta.eml'));
131
- const bounce = await bounceDetect(content);
132
-
133
- assert.strictEqual(bounce.recipient, 'sdffasdfgfasfadas@hot.ee');
134
- assert.strictEqual(bounce.action, 'failed');
135
- assert.strictEqual(bounce.response.message, '550 5.1.1 <sdffasdfgfasfadas@hot.ee>: Recipient address rejected: User unknown in relay recipient table');
136
- assert.strictEqual(bounce.messageId, '<48a84e64-d471-cfa6-3ea5-f10cd8571135@zone.ee>');
137
- });
138
-
139
- await t.test('zoho', async () => {
140
- const content = await fs.promises.readFile(path('zoho.eml'));
141
- const bounce = await bounceDetect(content);
142
-
143
- assert.strictEqual(bounce.recipient, 'recipient@example.com');
144
- assert.strictEqual(bounce.action, 'failed');
145
- assert.strictEqual(
146
- bounce.response.message,
147
- '5.2.1 The email account that you tried to reach is disabled. Learn more at 5.2.1 https://support.google.com/mail/?p=DisabledUser j8-20020a170903024800b001946612570csi19333477plh.316 - gsmtp'
148
- );
149
- assert.strictEqual(bounce.messageId, '<63d982c2660381675199170@smtppro.zoho.com>');
150
- });
151
- });