-
-
Notifications
You must be signed in to change notification settings - Fork 660
/
rfc1869.js
98 lines (86 loc) · 3.01 KB
/
rfc1869.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
'use strict';
// RFC 1869 command parser
// 6. MAIL FROM and RCPT TO Parameters
// [...]
//
// esmtp-cmd ::= inner-esmtp-cmd [SP esmtp-parameters] CR LF
// esmtp-parameters ::= esmtp-parameter *(SP esmtp-parameter)
// esmtp-parameter ::= esmtp-keyword ["=" esmtp-value]
// esmtp-keyword ::= (ALPHA / DIGIT) *(ALPHA / DIGIT / "-")
//
// ; syntax and values depend on esmtp-keyword
// esmtp-value ::= 1*<any CHAR excluding "=", SP, and all
// control characters (US ASCII 0-31
// inclusive)>
//
// ; The following commands are extended to
// ; accept extended parameters.
// inner-esmtp-cmd ::= ("MAIL FROM:" reverse-path) /
// ("RCPT TO:" forward-path)
/* eslint no-control-regex: 0 */
const chew_regexp = /\s+([A-Za-z0-9][A-Za-z0-9-]*(?:=[^= \x00-\x1f]+)?)$/;
exports.parse = (type, line, strict) => {
let params = [];
line = (new String(line)).replace(/\s*$/, '');
if (type === 'mail') {
line = line.replace(strict ? /from:/i : /from:\s*/i, '');
}
else {
line = line.replace(strict ? /to:/i : /to:\s*/i, '');
}
while (1) {
const old_length = line.length;
line = line.replace(chew_regexp, function repl (str, p1) {
params.push(p1);
return '';
});
if (old_length === line.length) break;
}
params = params.reverse();
// the above will "fail" (i.e. all of the line in params) on
// some addresses without <> like
// MAIL FROM: [email protected]
// or RCPT TO: postmaster
// let's see if $line contains nothing and use the first value as address:
if (line.length) {
// parameter syntax error, i.e. not all of the arguments were
// stripped by the while() loop:
if (line.match(/@.*\s/)) {
throw new Error(`Syntax error in parameters ("${line}")`);
}
params.unshift(line);
}
line = params.shift() || '';
if (strict) {
if (!line.match(/^<.*>$/)) {
throw new Error(`Invalid format of ${type} command: ${line}`);
}
}
if (type === 'mail') {
if (!line.length) {
return ["<>"]; // 'MAIL FROM:' --> 'MAIL FROM:<>'
}
if (line.match(/@.*\s/)) {
throw new Error('Syntax error in parameters');
}
}
else {
// console.log(`Looking at ${line}``);
if (line.match(/@.*\s/)) {
throw new Error('Syntax error in parameters');
}
else {
if (line.match(/\s/)) {
throw new Error('Syntax error in parameters');
}
else if (line.match(/@/)) {
if (!line.match(/^<.*>$/)) line = `<${line}>`;
}
else if (!line.match(/^<(postmaster|abuse)>$/i)) {
throw new Error(`Syntax error in address: ${line}`);
}
}
}
params.unshift(line);
return params;
}