forked from godsflaw/Haraka
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmailheader.js
127 lines (103 loc) · 3.34 KB
/
mailheader.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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
// An RFC 2822 email header parser
var logger = require('./logger');
function Header (options) {
this.headers = {};
this.headers_decoded = {};
this.header_list = [];
this.options = options;
};
exports.Header = Header;
Header.prototype.parse = function (lines) {
for (var i=0,l=lines.length; i < l; i++) {
var line = lines[i];
if (line.match(/^[ \t]/)) {
// continuation
this.header_list[this.header_list.length - 1] += line;
}
else {
this.header_list.push(line);
}
}
for (var i=0,l=this.header_list.length; i < l; i++) {
var match = this.header_list[i].match(/^([^:]*):\s*([\s\S]*)$/);
if (match) {
var key = match[1].toLowerCase();
var val = match[2];
this._add_header(key, val);
}
else {
logger.logerror("Header did not look right: " + this.header_list[i]);
}
}
};
function _decode_header (matched, encoding, cte, data) {
cte = cte.toUpperCase();
switch(cte) {
case 'Q':
data = data.replace('_', ' ');
data = data.replace(/=([A-F0-9][A-F0-9])/gi, function (ignore, code) {
return String.fromCharCode(parseInt(code, 16));
});
break;
case 'B':
data = new Buffer(data, "base64").toString();
break;
default:
logger.logerror("Invalid header encoding type: " + cte);
}
// todo: convert with iconv if encoding != UTF-8
return data;
}
function decode_header (val) {
// Fold continuations
val = val.replace(/\n[ \t]+/g, "\n ");
// remove end carriage return
val = val.replace(/\r?\n$/, '');
if (! (/=\?/.test(val)) ) {
// no encoded stuff
return val;
}
val = val.replace(/=\?([\w_-]+)\?([bqBQ])\?(.*?)\?=/g, _decode_header);
return val;
}
Header.prototype.get = function (key) {
return (this.headers[key.toLowerCase()] || []).join("\n");
};
Header.prototype.get_all = function (key) {
return this.headers[key.toLowerCase()] || [];
};
Header.prototype.get_decoded = function (key) {
return (this.headers_decoded[key.toLowerCase()] || []).join("\n");
};
Header.prototype.remove = function (key) {
key = key.toLowerCase();
delete this.headers[key];
delete this.headers_decoded[key];
this._remove_more(key);
}
Header.prototype._remove_more = function (key) {
var key_len = key.length;
var to_remove;
for (var i=0,l=this.header_list.length; i < l; i++) {
if (this.header_list[i].substring(0, key_len).toLowerCase() === key) {
this.header_list.splice(i, 1);
return this._remove_more(key);
}
}
};
Header.prototype._add_header = function (key, value) {
this.headers[key] = this.headers[key] || [];
this.headers[key].push(value);
this.headers_decoded[key] = this.headers_decoded[key] || [];
this.headers_decoded[key].push(decode_header(value));
};
Header.prototype.add = function (key, value) {
this._add_header(key.toLowerCase(), value);
this.header_list.push(key + ': ' + value + '\n');
};
Header.prototype.lines = function () {
return this.header_list;
};
Header.prototype.toString = function () {
return this.header_list.join("\n");
};