emailengine-app 2.61.0 → 2.61.2

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 (137) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/data/google-crawlers.json +1 -1
  3. package/lib/account/account-state.js +248 -0
  4. package/lib/account.js +17 -178
  5. package/lib/api-routes/account-routes.js +1006 -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 +3 -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 +5 -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 +12 -12
  35. package/sbom.json +1 -1
  36. package/static/js/app.js +5 -5
  37. package/static/licenses.html +91 -21
  38. package/translations/de.mo +0 -0
  39. package/translations/de.po +85 -82
  40. package/translations/en.mo +0 -0
  41. package/translations/en.po +63 -71
  42. package/translations/et.mo +0 -0
  43. package/translations/et.po +84 -82
  44. package/translations/fr.mo +0 -0
  45. package/translations/fr.po +85 -82
  46. package/translations/ja.mo +0 -0
  47. package/translations/ja.po +84 -82
  48. package/translations/messages.pot +67 -80
  49. package/translations/nl.mo +0 -0
  50. package/translations/nl.po +86 -82
  51. package/translations/pl.mo +0 -0
  52. package/translations/pl.po +84 -82
  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/workers/webhooks.js +6 -0
  78. package/lib/imapproxy/imap-core/test/client.js +0 -46
  79. package/lib/imapproxy/imap-core/test/fixtures/append.eml +0 -1196
  80. package/lib/imapproxy/imap-core/test/fixtures/chunks.js +0 -44
  81. package/lib/imapproxy/imap-core/test/fixtures/fix1.eml +0 -6
  82. package/lib/imapproxy/imap-core/test/fixtures/fix2.eml +0 -599
  83. package/lib/imapproxy/imap-core/test/fixtures/fix3.eml +0 -32
  84. package/lib/imapproxy/imap-core/test/fixtures/fix4.eml +0 -6
  85. package/lib/imapproxy/imap-core/test/fixtures/mimetorture.eml +0 -599
  86. package/lib/imapproxy/imap-core/test/fixtures/mimetorture.js +0 -2740
  87. package/lib/imapproxy/imap-core/test/fixtures/mimetorture.json +0 -1411
  88. package/lib/imapproxy/imap-core/test/fixtures/mimetree.js +0 -85
  89. package/lib/imapproxy/imap-core/test/fixtures/nodemailer.eml +0 -582
  90. package/lib/imapproxy/imap-core/test/fixtures/ryan_finnie_mime_torture.eml +0 -599
  91. package/lib/imapproxy/imap-core/test/fixtures/simple.eml +0 -42
  92. package/lib/imapproxy/imap-core/test/fixtures/simple.json +0 -164
  93. package/lib/imapproxy/imap-core/test/imap-compile-stream-test.js +0 -671
  94. package/lib/imapproxy/imap-core/test/imap-compiler-test.js +0 -272
  95. package/lib/imapproxy/imap-core/test/imap-indexer-test.js +0 -236
  96. package/lib/imapproxy/imap-core/test/imap-parser-test.js +0 -922
  97. package/lib/imapproxy/imap-core/test/memory-notifier.js +0 -129
  98. package/lib/imapproxy/imap-core/test/prepare.sh +0 -74
  99. package/lib/imapproxy/imap-core/test/protocol-test.js +0 -1756
  100. package/lib/imapproxy/imap-core/test/search-test.js +0 -1356
  101. package/lib/imapproxy/imap-core/test/test-client.js +0 -152
  102. package/lib/imapproxy/imap-core/test/test-server.js +0 -623
  103. package/lib/imapproxy/imap-core/test/tools-test.js +0 -22
  104. package/test/api-test.js +0 -899
  105. package/test/autoreply-test.js +0 -327
  106. package/test/bounce-test.js +0 -151
  107. package/test/complaint-test.js +0 -256
  108. package/test/fixtures/autoreply/LICENSE +0 -27
  109. package/test/fixtures/autoreply/rfc3834-01.eml +0 -23
  110. package/test/fixtures/autoreply/rfc3834-02.eml +0 -24
  111. package/test/fixtures/autoreply/rfc3834-03.eml +0 -26
  112. package/test/fixtures/autoreply/rfc3834-04.eml +0 -48
  113. package/test/fixtures/autoreply/rfc3834-05.eml +0 -19
  114. package/test/fixtures/autoreply/rfc3834-06.eml +0 -59
  115. package/test/fixtures/bounces/163.eml +0 -2521
  116. package/test/fixtures/bounces/fastmail.eml +0 -242
  117. package/test/fixtures/bounces/gmail.eml +0 -252
  118. package/test/fixtures/bounces/hotmail.eml +0 -655
  119. package/test/fixtures/bounces/mailru.eml +0 -121
  120. package/test/fixtures/bounces/outlook.eml +0 -1107
  121. package/test/fixtures/bounces/postfix.eml +0 -101
  122. package/test/fixtures/bounces/rambler.eml +0 -116
  123. package/test/fixtures/bounces/workmail.eml +0 -142
  124. package/test/fixtures/bounces/yahoo.eml +0 -139
  125. package/test/fixtures/bounces/zoho.eml +0 -83
  126. package/test/fixtures/bounces/zonemta.eml +0 -100
  127. package/test/fixtures/complaints/LICENSE +0 -27
  128. package/test/fixtures/complaints/amazonses.eml +0 -72
  129. package/test/fixtures/complaints/dmarc.eml +0 -59
  130. package/test/fixtures/complaints/hotmail.eml +0 -49
  131. package/test/fixtures/complaints/optout.eml +0 -40
  132. package/test/fixtures/complaints/standard-arf.eml +0 -68
  133. package/test/fixtures/complaints/yahoo.eml +0 -68
  134. package/test/oauth2-apps-test.js +0 -301
  135. package/test/sendonly-test.js +0 -160
  136. package/test/test-config.js +0 -34
  137. 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
- });