email-bounce-parser 1.0.17 → 1.0.19

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 (3) hide show
  1. package/README.md +4 -2
  2. package/lib/parser.js +37 -25
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -53,7 +53,7 @@ console.log(result);
53
53
  // email: {
54
54
  // body: "This is the mail system at host mailer.acme.email [...] (in reply to RCPT TO command)",
55
55
  // intro: "This is the mail system at host mailer.acme.email [...] The mail system",
56
- // error: "<support@yipee.com>: host smtp.secureserver.net[92.240.81.0] said: [...] (in reply to RCPT TO command)"
56
+ // error: "<john@yipee.com>: host smtp.secureserver.net[92.240.81.0] said: [...] (in reply to RCPT TO command)"
57
57
  // },
58
58
  //
59
59
  // data: {
@@ -62,7 +62,7 @@ console.log(result);
62
62
  // basic: "550",
63
63
  // enhanced: "5.1.1"
64
64
  // },
65
- // label: "<support@yipee.com> Recipient not found.",
65
+ // label: "<john@yipee.com> Recipient not found.",
66
66
  //
67
67
  // type: "action_not_taken",
68
68
  //
@@ -76,6 +76,8 @@ console.log(result);
76
76
  // }
77
77
  // },
78
78
  //
79
+ // recipient: "john@yipee.com",
80
+ //
79
81
  // server: {
80
82
  // hostname: "smtp.secureserver.net",
81
83
  // ip: "92.240.81.0",
package/lib/parser.js CHANGED
@@ -82,16 +82,16 @@ var REGEXES = {
82
82
  ],
83
83
 
84
84
  error : [
85
- /said\: (\d{3}(?:[\s\-]\d\.\d\.\d\d?)?) (.+) \(in reply to/,
86
- /said\: (\d{3}(?:[\s\-]\d\.\d\.\d\d?)?)-(.+)/,
87
- /(\d{3}\-\'\d\.\d\.\d\d?) (.+)/,
88
- /LMTP error after .+?\:\<.+?\>\: (\d{3}(?:[\s\-]\d\.\d\.\d\d?)?) <.+?\>(.+)$/m,
89
- /remote server returned \'(\d{3}(?:[\s\-]\d\.\d\.\d\d?)?) (.+)\'/i,
90
- /The response from the remote server was:\s(\d{3}(?:[\s\-]\d\.\d\.\d\d?)?) (.+)/,
91
- /refused to talk to me\: (\d{3}(?:[\s\-]\d\.\d\.\d\d?)?) (.+)/,
92
- /(?:error|reason)\:\s*?(\d{3}(?:[\s\-]\d\.\d\.\d\d?)?) (.+)/i,
93
- /(\d{3}[\s\-]\d\.\d\.\d\d?)/,
94
- /(\d{3}\-\'\d\.\d\.\d\d?)/
85
+ /said\: (\d{3}(?:[\s\-]\d\.\d\.\d{1,3})?) (.+) \(in reply to/,
86
+ /said\: (\d{3}(?:[\s\-]\d\.\d\.\d{1,3})?)-(.+)/,
87
+ /(\d{3}\-\'\d\.\d\.\d{1,3}) (.+)/,
88
+ /LMTP error after .+?\:\<.+?\>\: (\d{3}(?:[\s\-]\d\.\d\.\d{1,3})?) <.+?\>(.+)$/m,
89
+ /remote server returned \'(\d{3}(?:[\s\-]\d\.\d\.\d{1,3})?) (.+)\'/i,
90
+ /The response from the remote server was:\s(\d{3}(?:[\s\-]\d\.\d\.\d{1,3})?) (.+)/,
91
+ /refused to talk to me\: (\d{3}(?:[\s\-]\d\.\d\.\d{1,3})?) (.+)/,
92
+ /(?:error|reason)\:\s*?(\d{3}(?:[\s\-]\d\.\d\.\d{1,3})?) (.+)/i,
93
+ /(\d{3}[\s\-]\d\.\d\.\d{1,3})/,
94
+ /(\d{3}\-\'\d\.\d\.\d{1,3})/
95
95
  ],
96
96
 
97
97
  error_lax : [
@@ -110,12 +110,13 @@ var REGEXES = {
110
110
 
111
111
  recipient : [
112
112
  /the following addresses had permanent fatal errors (?:.*?)\s\<(.+?)\>/i,
113
+ /there was a temporary problem delivering your message to (.+?). Gmail will retry/i,
113
114
  /the following message to \<(.+?)\> was undeliverable/i,
114
115
  /to the following addresses:\s*(.+)/i,
115
- /^\<(.+?)\>:/m,
116
- /^(.+?)\s?\n?\s*[\[|<]mailto\:(.+?)[\]|>]/mi, // "john@acme.com<mailto:john@acme.com>"
117
116
  /^your message wasn't delivered to (.+?)\s/mi, // "Your message wasn't delivered to john@acme.com"
118
117
  /^your message to (.+?) couldn\'t/mi, // "Your message to john@acme.com couldn't"
118
+ /^(.+?)\s?(?:\s\(.*?\))?\n?\s*[\[|<]mailto\:(.+?)[\]|>]/mi, // "john@acme.com<mailto:john@acme.com>" or "john@acme.com[mailto:john@acme.com]" or "john@acme.com (john@acme.com)<mailto:john@acme.com>"
119
+ /^\<(.+?)\>:/m,
119
120
  /\<(.+?)\> \(expanded from \<.+?\>\)\:/, // "<john@acme.com> (expanded from <john@digiflex.com>): "
120
121
  /\<(.+?)\>:/ // "<john@acme.com>:"
121
122
  ],
@@ -135,7 +136,7 @@ var REGEXES = {
135
136
 
136
137
  enhanced_types_server_unknown : [
137
138
  /(does not accept mail)/i,
138
- /(domain name not found)/i,
139
+ /(domain (?:name\s+)?(?:\S+\s)?(?:not found|does not exist))/i, // "domain does not exist" or "domain name does not exist" or "domain acme.com does not exist" or "domain name acme.com does not exist"
139
140
  /(no route to host)/i
140
141
  ],
141
142
 
@@ -147,9 +148,13 @@ var REGEXES = {
147
148
  /(out of storage|(?:mailbox (?:is )?full)|(?:user (?:is )?over quota))/i // "user is over quota" (iCloud)
148
149
  ],
149
150
 
151
+ enhanced_types_reputation : [
152
+ /(rate limited due to IP reputation)/i
153
+ ],
154
+
150
155
  error_code : [
151
- /(\d{3})[\s\-](\d\.\d\.\d\d?)/, // "550 5.4.1" or "550-5.4.1" or "550-5.4.11"
152
- /(\d{3})\-\'(\d\.\d\.\d\d?)/, // "550-'5.4.1" or "550-'5.4.11"
156
+ /(\d{3})[\s\-](\d\.\d\.\d{1,3})/, // "550 5.4.1" or "550-5.4.1" or "550-5.4.11" or "550-5.4.110"
157
+ /(\d{3})\-\'(\d\.\d\.\d{1,3})/, // "550-'5.4.1" or "550-'5.4.11" or "550-'5.4.110"
153
158
  /(\d{3})/ // "550"
154
159
  ]
155
160
  };
@@ -299,21 +304,22 @@ class Parser {
299
304
  _permanent = true;
300
305
  }
301
306
 
302
- // Make sure the bounce is actually permanent
303
- if (_permanent === true) {
304
- var _match = this.__regexes.temporary_safe.match(str);
305
-
306
- if (_match && _match.length > 1) {
307
- _temporary = true;
308
- _permanent = false;
309
- }
310
- }
311
-
312
307
  if (_code.basic) {
313
308
  _type = ERROR_CODES_TYPES[_code.basic] || null
314
309
  }
315
310
  }
316
311
 
312
+ // In cases where the bounce is detected as permanent, or the \
313
+ // temporary / permanent status is still unclear, run additional detection
314
+ if (_permanent === true || (_temporary === false && _permanent === false)) {
315
+ var _match = this.__regexes.temporary_safe.match(str);
316
+
317
+ if (_match && _match.length > 1) {
318
+ _temporary = true;
319
+ _permanent = false;
320
+ }
321
+ }
322
+
317
323
  // No label detected? Probably because there's no error code
318
324
  if (!_label) {
319
325
  // Attempt a lax check
@@ -409,6 +415,12 @@ class Parser {
409
415
  _type = "mailbox_full";
410
416
  }
411
417
 
418
+ _match = loopRegexes(this.__regexes.enhanced_types_reputation, str);
419
+
420
+ if (!_type && _match && _match.length > 1) {
421
+ _type = "reputation";
422
+ }
423
+
412
424
  // Detect enhanced-type from enhanced error code
413
425
  // Notice: this is done as a last resort, as sometimes enhanced code \
414
426
  // doesn't clearly convey the actual error
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "email-bounce-parser",
3
- "version": "1.0.17",
3
+ "version": "1.0.19",
4
4
  "description": "Parses bounce emails and extract errors",
5
5
  "author": "Eliott Vincent <eliott@crisp.chat>",
6
6
  "main": "lib/index.js",