email-bounce-parser 1.0.14 → 1.0.16
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 +75 -31
- package/package.json +4 -2
package/lib/parser.js
CHANGED
|
@@ -8,6 +8,7 @@ var ERROR_CODES_TYPES = {
|
|
|
8
8
|
"421" : "service_not_available",
|
|
9
9
|
"421 4.3.0" : "temporary_system_problem",
|
|
10
10
|
"421 4.4.5" : "server_busy",
|
|
11
|
+
"421 4.7.28" : "ip_blocked_spam",
|
|
11
12
|
"432 4.7.12" : "password_needed",
|
|
12
13
|
"450" : "action_not_taken_mailbox_unavailable",
|
|
13
14
|
"450 4.2.1" : "action_not_taken_mailbox_rate_limited",
|
|
@@ -61,48 +62,53 @@ var REGEXES = {
|
|
|
61
62
|
],
|
|
62
63
|
|
|
63
64
|
command : [
|
|
64
|
-
/\(in reply to end of ([A-Z\s]+) command\)$/m, //
|
|
65
|
-
/\(in reply to ([A-Z\s]+) command\)$/m, //
|
|
66
|
-
/timed out while sending ([A-Z\s]+)$/m, //
|
|
67
|
-
/error after ([A-Z\s]+)/m //
|
|
65
|
+
/\(in reply to end of ([A-Z\s]+) command\)$/m, // "in reply to end of DATA command"
|
|
66
|
+
/\(in reply to ([A-Z\s]+) command\)$/m, // "in reply to RCPT TO command"
|
|
67
|
+
/timed out while sending ([A-Z\s]+)$/m, // "timed out while sending (RCPT TO)", "timed out while sending RCPT TO"
|
|
68
|
+
/error after ([A-Z\s]+)/m, // "LMTP error after RCPT TO"
|
|
69
|
+
/while sending end of ([a-z\s]+)/m // "while sending end of data"
|
|
68
70
|
],
|
|
69
71
|
|
|
70
72
|
email_server : [
|
|
71
73
|
/host (\S+)\[([\d\.]+)\](?:\:(\d+)\:)? (?:said|refused to talk)/m,
|
|
72
74
|
/^(\S+) rejected your message/m,
|
|
73
|
-
/\: connect to (.+)\[(.+)\](?:\:(\d+)\:)?/m,
|
|
75
|
+
/\: connect to (.+)\[(.+)\](?:\:(\d+)\:)?/m, // "connect to acme.com[132.145.223.95]:25:"
|
|
74
76
|
/Name service error for name\=(\S+)\s/m,
|
|
75
77
|
/RCPT TO\:\<(.+?)\>/m,
|
|
76
78
|
/Message rejected by\:\s+([\S\.]+?)$/m, // Outlook error
|
|
77
|
-
/from (\S+) \[([\d\.]+)\](?:\:(\d+)\:)?/m
|
|
79
|
+
/from (\S+) \[([\d\.]+)\](?:\:(\d+)\:)?/m,
|
|
80
|
+
/conversation with (\S+)\[([\d\.]+)\](?:\:(\d+)\:)? timed out/m,
|
|
81
|
+
/Generating server: (\S+)(?:\[([\d\.]+)\])?(?:\:(\d+)\:)?/m // "Generating server: PH7PR02MB9549495.namprd02.prod.outlook.com"
|
|
78
82
|
],
|
|
79
83
|
|
|
80
84
|
error : [
|
|
81
|
-
/said\: (\d{3}(?:[\s\-]\d\.\d\.\d\d?)?) (.+) \(in reply to
|
|
82
|
-
/said\: (\d{3}(?:[\s\-]\d\.\d\.\d\d?)?)-(.+)
|
|
83
|
-
/(\d{3}\-\'\d\.\d\.\d\d?) (.+)
|
|
84
|
-
/LMTP error after
|
|
85
|
-
/
|
|
86
|
-
/The response from the remote server was:\s(\d{3}(?:[\s\-]\d\.\d\.\d\d?)?) (.+)
|
|
87
|
-
/refused to talk to me\: (\d{3}(?:[\s\-]\d\.\d\.\d\d?)?) (.+)
|
|
88
|
-
/(?:error|reason)\:\s*?(\d{3}(?:[\s\-]\d\.\d\.\d\d?)?) (.+)/
|
|
89
|
-
/(\d{3}[\s\-]\d\.\d\.\d\d?)
|
|
90
|
-
/(\d{3}\-\'\d\.\d\.\d\d?)/
|
|
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?)/
|
|
91
95
|
],
|
|
92
96
|
|
|
93
97
|
error_lax : [
|
|
94
|
-
|
|
98
|
+
/^(?:\<.+?\> \(expanded from \<.+?\>\)\:)(.+)/m, // "<john@acme.com> (expanded from <john@digiflex.com>): Domain name not found"
|
|
99
|
+
/^(?:\<.+?\>\:)(.+)/m // "<john@acme.com>: Domain name not found"
|
|
95
100
|
],
|
|
96
101
|
|
|
97
102
|
recipient : [
|
|
98
|
-
/
|
|
99
|
-
/
|
|
100
|
-
/to the following addresses:\s*(.+)
|
|
103
|
+
/the following addresses had permanent fatal errors (?:.*?)\s\<(.+?)\>/i,
|
|
104
|
+
/the following message to \<(.+?)\> was undeliverable/i,
|
|
105
|
+
/to the following addresses:\s*(.+)/i,
|
|
101
106
|
/^\<(.+?)\>:/m,
|
|
102
|
-
/^(.+?)\s?\n?\s*[\[|<]mailto\:(.+?)[\]|>]/
|
|
103
|
-
/^
|
|
104
|
-
/^
|
|
105
|
-
/\<(.+?)
|
|
107
|
+
/^(.+?)\s?\n?\s*[\[|<]mailto\:(.+?)[\]|>]/mi, // "john@acme.com<mailto:john@acme.com>"
|
|
108
|
+
/^your message wasn't delivered to (.+?)\s/mi, // "Your message wasn't delivered to john@acme.com"
|
|
109
|
+
/^your message to (.+?) couldn\'t/mi, // "Your message to john@acme.com couldn't"
|
|
110
|
+
/\<(.+?)\> \(expanded from \<.+?\>\)\:/, // "<john@acme.com> (expanded from <john@digiflex.com>): "
|
|
111
|
+
/\<(.+?)\>:/ // "<john@acme.com>:"
|
|
106
112
|
],
|
|
107
113
|
|
|
108
114
|
temporary_safe : /(temporary|temporarily)/i,
|
|
@@ -119,7 +125,8 @@ var REGEXES = {
|
|
|
119
125
|
],
|
|
120
126
|
|
|
121
127
|
enhanced_types_server_unknown : [
|
|
122
|
-
/(does not accept mail)/i
|
|
128
|
+
/(does not accept mail)/i,
|
|
129
|
+
/(domain name not found)/i
|
|
123
130
|
],
|
|
124
131
|
|
|
125
132
|
enhanced_types_server_timeout : [
|
|
@@ -127,12 +134,12 @@ var REGEXES = {
|
|
|
127
134
|
],
|
|
128
135
|
|
|
129
136
|
enhanced_types_mailbox_full : [
|
|
130
|
-
/(out of storage|(?:mailbox (?:is )?full)|(?:user (?:is )?over quota))/i
|
|
137
|
+
/(out of storage|(?:mailbox (?:is )?full)|(?:user (?:is )?over quota))/i // "user is over quota" (iCloud)
|
|
131
138
|
],
|
|
132
139
|
|
|
133
140
|
error_code : [
|
|
134
|
-
/(\d{3})[\s\-](\d\.\d\.\d)/, // "550 5.4.1" or "550-5.4.1"
|
|
135
|
-
/(\d{3})\-\'(\d\.\d\.\d)/, // "550-'5.4.1"
|
|
141
|
+
/(\d{3})[\s\-](\d\.\d\.\d\d?)/, // "550 5.4.1" or "550-5.4.1" or "550-5.4.11"
|
|
142
|
+
/(\d{3})\-\'(\d\.\d\.\d\d?)/, // "550-'5.4.1" or "550-'5.4.11"
|
|
136
143
|
/(\d{3})/ // "550"
|
|
137
144
|
]
|
|
138
145
|
};
|
|
@@ -273,7 +280,7 @@ class Parser {
|
|
|
273
280
|
|
|
274
281
|
if (_match && _match.length > 1) {
|
|
275
282
|
_code = this.__parseErrorCode(_match[1]);
|
|
276
|
-
_label =
|
|
283
|
+
_label = this.__cleanErrorLabel(_match[2]);
|
|
277
284
|
|
|
278
285
|
// Check temporary / permanent
|
|
279
286
|
if (_code.basic[0] === "4") {
|
|
@@ -303,7 +310,7 @@ class Parser {
|
|
|
303
310
|
var _match = loopRegexes(this.__regexes.error_lax, str);
|
|
304
311
|
|
|
305
312
|
if (_match && _match.length > 1) {
|
|
306
|
-
_label =
|
|
313
|
+
_label = this.__cleanErrorLabel(_match[1]);
|
|
307
314
|
}
|
|
308
315
|
}
|
|
309
316
|
|
|
@@ -494,7 +501,7 @@ class Parser {
|
|
|
494
501
|
var _match = loopRegexes(this.__regexes.command, str);
|
|
495
502
|
|
|
496
503
|
if (_match && _match.length > 1) {
|
|
497
|
-
_command = _match[1];
|
|
504
|
+
_command = trimString(_match[1]).toUpperCase();
|
|
498
505
|
}
|
|
499
506
|
|
|
500
507
|
return _command;
|
|
@@ -547,6 +554,43 @@ class Parser {
|
|
|
547
554
|
|
|
548
555
|
return _str;
|
|
549
556
|
}
|
|
557
|
+
|
|
558
|
+
|
|
559
|
+
/**
|
|
560
|
+
* Cleans error label
|
|
561
|
+
* @private
|
|
562
|
+
* @param {string} [label]
|
|
563
|
+
* @return {string} Unquoted text
|
|
564
|
+
*/
|
|
565
|
+
__cleanErrorLabel(label="") {
|
|
566
|
+
var _label = this.__unquoteText(label);
|
|
567
|
+
|
|
568
|
+
_label = trimString(_label);
|
|
569
|
+
|
|
570
|
+
return _label;
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
|
|
574
|
+
/**
|
|
575
|
+
* Unquotes text
|
|
576
|
+
* @private
|
|
577
|
+
* @param {string} [str]
|
|
578
|
+
* @return {string} Unquoted text
|
|
579
|
+
*/
|
|
580
|
+
__unquoteText(str="") {
|
|
581
|
+
var _str = str;
|
|
582
|
+
|
|
583
|
+
_str = trimString(_str);
|
|
584
|
+
|
|
585
|
+
if (
|
|
586
|
+
(_str.startsWith("'") && _str.endsWith("'")) ||
|
|
587
|
+
(_str.startsWith("\"") && _str.endsWith("\""))
|
|
588
|
+
) {
|
|
589
|
+
return _str.slice(1, -1);
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
return _str;
|
|
593
|
+
}
|
|
550
594
|
}
|
|
551
595
|
|
|
552
596
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "email-bounce-parser",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.16",
|
|
4
4
|
"description": "Parses bounce emails and extract errors",
|
|
5
5
|
"author": "Eliott Vincent <eliott@crisp.chat>",
|
|
6
6
|
"main": "lib/index.js",
|
|
@@ -30,7 +30,9 @@
|
|
|
30
30
|
"mail",
|
|
31
31
|
"email",
|
|
32
32
|
"bounce",
|
|
33
|
-
"bounces"
|
|
33
|
+
"bounces",
|
|
34
|
+
"smtp",
|
|
35
|
+
"rfc"
|
|
34
36
|
],
|
|
35
37
|
"license": "MIT"
|
|
36
38
|
}
|