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.
Files changed (2) hide show
  1. package/lib/parser.js +84 -37
  2. 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" : "mailbox_unavailable",
13
- "451" : "local_error",
14
- "452" : "insufficient_system_storage",
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
- /Error\:\s*?(\d{3}(?:[\s\-]\d\.\d\.\d\d?)?) (.+)/m,
63
- /reason: (\d{3}[\s\-]\d\.\d\.\d\d?) (.+)/m,
64
- /(\d{3}[\s\-]\d\.\d\.\d\d?)/m
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
- /((?:account|user|mailbox) (?:is )?(?:terminated|disabled|not found|unavailable|invalid))/i
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 : ERROR_CODES_TYPES[(_code || {}).basic],
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
- if (code.basic) {
325
- if (code.enhanced) {
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
- if (_match && _match.length > 1) {
331
- _type = "no_such_recipient";
332
- }
372
+ if (_match && _match.length > 1) {
373
+ _type = "no_such_recipient";
374
+ }
333
375
 
334
- _match = loopRegexes(this.__regexes.enhanced_types_server_unknown, str);
376
+ _match = loopRegexes(this.__regexes.enhanced_types_server_unknown, str);
335
377
 
336
- if (!_type && _match && _match.length > 1) {
337
- _type = "server_unknown";
338
- }
378
+ if (!_type && _match && _match.length > 1) {
379
+ _type = "server_unknown";
380
+ }
339
381
 
340
- _match = loopRegexes(this.__regexes.enhanced_types_server_timeout, str);
382
+ _match = loopRegexes(this.__regexes.enhanced_types_server_timeout, str);
341
383
 
342
- if (!_type && _match && _match.length > 1) {
343
- _type = "server_timeout";
344
- }
384
+ if (!_type && _match && _match.length > 1) {
385
+ _type = "server_timeout";
386
+ }
345
387
 
346
- _match = loopRegexes(this.__regexes.enhanced_types_mailbox_full, str);
388
+ _match = loopRegexes(this.__regexes.enhanced_types_mailbox_full, str);
347
389
 
348
- if (!_type && _match && _match.length > 1) {
349
- _type = "mailbox_full";
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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "email-bounce-parser",
3
- "version": "1.0.11",
3
+ "version": "1.0.13",
4
4
  "description": "Parses bounce emails and extract errors",
5
5
  "author": "Eliott Vincent <eliott@crisp.chat>",
6
6
  "main": "lib/index.js",