email-bounce-parser 1.0.11 → 1.0.13
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.
- package/lib/parser.js +84 -37
- package/package.json +1 -1
package/lib/parser.js
CHANGED
|
@@ -9,16 +9,40 @@ var ERROR_CODES_TYPES = {
|
|
|
9
9
|
"421 4.3.0" : "temporary_system_problem",
|
|
10
10
|
"421 4.4.5" : "server_busy",
|
|
11
11
|
"432 4.7.12" : "password_needed",
|
|
12
|
-
"450" : "
|
|
13
|
-
"
|
|
14
|
-
"
|
|
12
|
+
"450" : "action_not_taken_mailbox_unavailable",
|
|
13
|
+
"450 4.2.1" : "action_not_taken_mailbox_rate_limited",
|
|
14
|
+
"451 4.4.2" : "timeout",
|
|
15
|
+
"451" : "action_aborted_local_error",
|
|
16
|
+
"451 4.5.0" : "smtp_protocol_violation_rfc_2821",
|
|
17
|
+
"452" : "action_not_taken_insufficient_system_storage",
|
|
18
|
+
"452 4.2.2" : "mailbox_over_quota",
|
|
19
|
+
"454" : "smtp_protocol_violation_rfc_3207",
|
|
20
|
+
"454 4.5.0" : "smtp_protocol_violation_rfc_3207",
|
|
21
|
+
"454 4.7.0" : "authentication_issue",
|
|
22
|
+
"455" : "server_unable_to_accommodate_parameters",
|
|
23
|
+
"500" : "syntax_error",
|
|
24
|
+
"501" : "syntax_error_parameters",
|
|
25
|
+
"501 5.5.2" : "response_decode_error",
|
|
26
|
+
"501 5.5.4" : "invalid_helo_ehlo",
|
|
27
|
+
"502" : "command_not_implemented",
|
|
15
28
|
"503" : "bad_commands_sequence",
|
|
29
|
+
"503 5.7.0" : "no_identity_changes_permitted",
|
|
30
|
+
"504" : "parameter_not_implemented",
|
|
31
|
+
"504 5.7.4" : "unrecognized_authentication_type",
|
|
32
|
+
"530 5.5.1" : "authentication_required",
|
|
16
33
|
"550" : "action_not_taken",
|
|
17
34
|
"550 5.1.1" : "no_such_recipient",
|
|
18
35
|
"550 5.2.1" : "recipient_disabled_or_recipient_rate_limited",
|
|
19
36
|
"550 5.7.1" : "spam_content",
|
|
37
|
+
"551" : "user_not_local",
|
|
38
|
+
"552" : "action_aborted_exceeded_storage_allocation",
|
|
39
|
+
"552 5.2.2" : "mailbox_over_quota",
|
|
40
|
+
"552 5.2.3" : "message_size_limit",
|
|
41
|
+
"553" : "action_not_taken_mailbox_name_not_allowed",
|
|
20
42
|
"554" : "transaction_failed",
|
|
21
43
|
"554 5.7.1" : "spam_content",
|
|
44
|
+
"555" : "parameters_not_recognized",
|
|
45
|
+
"555 5.5.2" : "syntax_error"
|
|
22
46
|
};
|
|
23
47
|
|
|
24
48
|
var REGEXES = {
|
|
@@ -45,6 +69,7 @@ var REGEXES = {
|
|
|
45
69
|
|
|
46
70
|
email_server : [
|
|
47
71
|
/host (\S+)\[([\d\.]+)\](?:\:(\d+)\:)? (?:said|refused to talk)/m,
|
|
72
|
+
/^(\S+) rejected your message/m,
|
|
48
73
|
/\: connect to (.+)\[(.+)\](?:\:(\d+)\:)?/m,
|
|
49
74
|
/Name service error for name\=(\S+)\s/m,
|
|
50
75
|
/RCPT TO\:\<(.+?)\>/m,
|
|
@@ -55,17 +80,24 @@ var REGEXES = {
|
|
|
55
80
|
error : [
|
|
56
81
|
/said\: (\d{3}(?:[\s\-]\d\.\d\.\d\d?)?) (.+) \(in reply to/m,
|
|
57
82
|
/said\: (\d{3}(?:[\s\-]\d\.\d\.\d\d?)?)-(.+)/m,
|
|
83
|
+
/(\d{3}\-\'\d\.\d\.\d\d?) (.+)/m,
|
|
58
84
|
/LMTP error after (?:.+?)\:\<.+?\>\: (\d{3}(?:[\s\-]\d\.\d\.\d\d?)?) <.+?\>(.+)$/m,
|
|
59
85
|
/Remote Server returned \'(\d{3}(?:[\s\-]\d\.\d\.\d\d?)?) (.+)\'/m,
|
|
60
86
|
/The response from the remote server was:\s(\d{3}(?:[\s\-]\d\.\d\.\d\d?)?) (.+)/m,
|
|
61
87
|
/refused to talk to me\: (\d{3}(?:[\s\-]\d\.\d\.\d\d?)?) (.+)/m,
|
|
62
|
-
/
|
|
63
|
-
/
|
|
64
|
-
/(\d{3}
|
|
88
|
+
/(?:error|reason)\:\s*?(\d{3}(?:[\s\-]\d\.\d\.\d\d?)?) (.+)/mi,
|
|
89
|
+
/(\d{3}[\s\-]\d\.\d\.\d\d?)/m,
|
|
90
|
+
/(\d{3}\-\'\d\.\d\.\d\d?)/m
|
|
91
|
+
],
|
|
92
|
+
|
|
93
|
+
error_lax : [
|
|
94
|
+
/(^\<.+?\>:.+)/m
|
|
65
95
|
],
|
|
66
96
|
|
|
67
97
|
recipient : [
|
|
68
98
|
/The following addresses had permanent fatal errors (?:.*?)\s\<(.+?)\>/,
|
|
99
|
+
/The following message to \<(.+?)\> was undeliverable/,
|
|
100
|
+
/to the following addresses:\s*(.+)/,
|
|
69
101
|
/^\<(.+?)\>:/m,
|
|
70
102
|
/^(.+?)\s?\n?\s*[\[|<]mailto\:(.+?)[\]|>]/m,
|
|
71
103
|
/^Your message wasn't delivered to (.+?)\s/m,
|
|
@@ -74,14 +106,15 @@ var REGEXES = {
|
|
|
74
106
|
],
|
|
75
107
|
|
|
76
108
|
temporary_safe : /(temporary|temporarily)/i,
|
|
77
|
-
blocked : /((?:is listed)blocked|banned|denied|dnsbl)/i,
|
|
109
|
+
blocked : /((?:is listed)|blocked|banned|denied|dnsbl)/i,
|
|
78
110
|
spam : /(spam)/i,
|
|
79
111
|
|
|
80
112
|
enhanced_types_no_such_recipient : [
|
|
81
113
|
/(recipient address rejected: access denied)/i, // Outlook DBEB for invalid addresses
|
|
82
|
-
/(invalid mailbox)/i,
|
|
114
|
+
/((?:terminated|disabled|inactive|not found|unavailable|invalid) (?:account|user|mailbox|recipient))/i,
|
|
83
115
|
/(do(e)?sn\'t exist)/i, // Some Chinese SMTP return "dosn't" instead of "doesn't"
|
|
84
|
-
/(
|
|
116
|
+
/(user (?:.+?) does not exist)/i,
|
|
117
|
+
/((?:account|user|mailbox|recipient) (?:.+@.+ )?(?:is )?(?:terminated|disabled|inactive|not found|unavailable|invalid))/i
|
|
85
118
|
],
|
|
86
119
|
|
|
87
120
|
enhanced_types_server_unknown : [
|
|
@@ -97,12 +130,9 @@ var REGEXES = {
|
|
|
97
130
|
],
|
|
98
131
|
|
|
99
132
|
error_code : [
|
|
100
|
-
/(\d{3})[\s\-](\d\.\d\.\d)/,
|
|
101
|
-
/(\d{3})
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
mailbox_address : [
|
|
105
|
-
/^(([^\s@]+)@([^\s@]+)\.([^\s@]+))$/
|
|
133
|
+
/(\d{3})[\s\-](\d\.\d\.\d)/, // "550 5.4.1" or "550-5.4.1"
|
|
134
|
+
/(\d{3})\-\'(\d\.\d\.\d)/, // "550-'5.4.1"
|
|
135
|
+
/(\d{3})/ // "550"
|
|
106
136
|
]
|
|
107
137
|
};
|
|
108
138
|
|
|
@@ -234,6 +264,7 @@ class Parser {
|
|
|
234
264
|
enhanced : null
|
|
235
265
|
},
|
|
236
266
|
_label = null,
|
|
267
|
+
_type = null,
|
|
237
268
|
_temporary = false,
|
|
238
269
|
_permanent = false;
|
|
239
270
|
|
|
@@ -259,6 +290,20 @@ class Parser {
|
|
|
259
290
|
_permanent = false;
|
|
260
291
|
}
|
|
261
292
|
}
|
|
293
|
+
|
|
294
|
+
if (_code.basic) {
|
|
295
|
+
_type = ERROR_CODES_TYPES[_code.basic] || null
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
// No label detected? Probably because there's no error code
|
|
300
|
+
if (!_label) {
|
|
301
|
+
// Attempt a lax check
|
|
302
|
+
var _match = loopRegexes(this.__regexes.error_lax, str);
|
|
303
|
+
|
|
304
|
+
if (_match && _match.length > 1) {
|
|
305
|
+
_label = trimString(_match[1]);
|
|
306
|
+
}
|
|
262
307
|
}
|
|
263
308
|
|
|
264
309
|
// Extract further data
|
|
@@ -268,7 +313,7 @@ class Parser {
|
|
|
268
313
|
code : _code,
|
|
269
314
|
label : _label,
|
|
270
315
|
|
|
271
|
-
type :
|
|
316
|
+
type : _type,
|
|
272
317
|
|
|
273
318
|
temporary : _temporary,
|
|
274
319
|
permanent : _permanent,
|
|
@@ -321,34 +366,36 @@ class Parser {
|
|
|
321
366
|
_blocked = false,
|
|
322
367
|
_spam = false;
|
|
323
368
|
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
_type = ERROR_CODES_TYPES[`${code.basic} ${code.enhanced}`] || null;
|
|
327
|
-
} else {
|
|
328
|
-
var _match = loopRegexes(this.__regexes.enhanced_types_no_such_recipient, str);
|
|
369
|
+
// Detect enhanced-type from bounce content
|
|
370
|
+
var _match = loopRegexes(this.__regexes.enhanced_types_no_such_recipient, str);
|
|
329
371
|
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
372
|
+
if (_match && _match.length > 1) {
|
|
373
|
+
_type = "no_such_recipient";
|
|
374
|
+
}
|
|
333
375
|
|
|
334
|
-
|
|
376
|
+
_match = loopRegexes(this.__regexes.enhanced_types_server_unknown, str);
|
|
335
377
|
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
378
|
+
if (!_type && _match && _match.length > 1) {
|
|
379
|
+
_type = "server_unknown";
|
|
380
|
+
}
|
|
339
381
|
|
|
340
|
-
|
|
382
|
+
_match = loopRegexes(this.__regexes.enhanced_types_server_timeout, str);
|
|
341
383
|
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
384
|
+
if (!_type && _match && _match.length > 1) {
|
|
385
|
+
_type = "server_timeout";
|
|
386
|
+
}
|
|
345
387
|
|
|
346
|
-
|
|
388
|
+
_match = loopRegexes(this.__regexes.enhanced_types_mailbox_full, str);
|
|
347
389
|
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
390
|
+
if (!_type && _match && _match.length > 1) {
|
|
391
|
+
_type = "mailbox_full";
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
// Detect enhanced-type from enhanced error code
|
|
395
|
+
// Notice: this is done as a last resort, as sometimes enhanced code \
|
|
396
|
+
// doesn't clearly convey the actual error
|
|
397
|
+
if (!_type && _match && code.enhanced) {
|
|
398
|
+
_type = ERROR_CODES_TYPES[`${code.basic} ${code.enhanced}`] || null;
|
|
352
399
|
}
|
|
353
400
|
|
|
354
401
|
// Check if blocked
|