eml-parser-qaap 1.1.15
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/LICENSE +21 -0
- package/README.md +55 -0
- package/dist/addressparser.d.ts +46 -0
- package/dist/charset.d.ts +24 -0
- package/dist/index.d.ts +76 -0
- package/dist/interface.d.ts +103 -0
- package/dist/utils.d.ts +32 -0
- package/lib/bundle.amd.js +1427 -0
- package/lib/bundle.cjs.js +1428 -0
- package/lib/bundle.esm.js +1404 -0
- package/lib/bundle.iife.js +1431 -0
- package/lib/bundle.umd.js +1431 -0
- package/package.json +107 -0
- package/src/addressparser.ts +317 -0
- package/src/charset.ts +72 -0
- package/src/index.ts +983 -0
- package/src/interface.ts +118 -0
- package/src/utils.ts +198 -0
package/src/interface.ts
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
export interface KeyValue extends Object {
|
|
2
|
+
[k: string]: any;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
export interface EmailAddress {
|
|
6
|
+
name: string;
|
|
7
|
+
email: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* parse result
|
|
12
|
+
*/
|
|
13
|
+
export interface ParsedEmlJson {
|
|
14
|
+
headers: EmlHeaders;
|
|
15
|
+
body?: string | (BoundaryConvertedData | null)[];
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* read result
|
|
20
|
+
*/
|
|
21
|
+
export interface ReadedEmlJson {
|
|
22
|
+
date: Date | string;
|
|
23
|
+
subject: string;
|
|
24
|
+
from: EmailAddress | EmailAddress[] | null;
|
|
25
|
+
to: EmailAddress | EmailAddress[] | null;
|
|
26
|
+
cc?: EmailAddress | EmailAddress[] | null;
|
|
27
|
+
headers: EmlHeaders;
|
|
28
|
+
multipartAlternative?: {
|
|
29
|
+
'Content-Type': string;
|
|
30
|
+
};
|
|
31
|
+
text?: string;
|
|
32
|
+
textheaders?: BoundaryHeaders;
|
|
33
|
+
html?: string;
|
|
34
|
+
htmlheaders?: BoundaryHeaders;
|
|
35
|
+
attachments?: Attachment[];
|
|
36
|
+
// data not be build
|
|
37
|
+
// if have EMl can find `data`, maybe I will know how to do
|
|
38
|
+
data?: string;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Attachment file
|
|
43
|
+
*/
|
|
44
|
+
export interface Attachment {
|
|
45
|
+
name: string;
|
|
46
|
+
contentType: string;
|
|
47
|
+
inline: boolean;
|
|
48
|
+
data: string | Uint8Array;
|
|
49
|
+
data64: string;
|
|
50
|
+
filename?: string;
|
|
51
|
+
mimeType?: string;
|
|
52
|
+
id?: string;
|
|
53
|
+
qaapId?: string;
|
|
54
|
+
cid?: string;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* EML headers
|
|
59
|
+
* @description `MIME-Version`, `Accept-Language`, `Content-Language` and `Content-Type` shuld Must exist when to build a EML file
|
|
60
|
+
*/
|
|
61
|
+
export interface EmlHeaders extends KeyValue {
|
|
62
|
+
Date?: string;
|
|
63
|
+
Subject?: string;
|
|
64
|
+
From?: string;
|
|
65
|
+
To?: string;
|
|
66
|
+
Cc?: string;
|
|
67
|
+
CC?: string;
|
|
68
|
+
'Content-Disposition'?: string | null;
|
|
69
|
+
'Content-Type'?: string | null;
|
|
70
|
+
'Content-Transfer-Encoding'?: string;
|
|
71
|
+
'MIME-Version'?: string;
|
|
72
|
+
'Content-ID'?: string;
|
|
73
|
+
// zh-CN, en-US
|
|
74
|
+
'Accept-Language'?: string;
|
|
75
|
+
// zh-CN
|
|
76
|
+
'Content-Language'?: string;
|
|
77
|
+
// Why not all ?
|
|
78
|
+
// OutLook is follows
|
|
79
|
+
'Content-type'?: string | null;
|
|
80
|
+
'Content-transfer-encoding'?: string;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export interface Options {
|
|
84
|
+
headersOnly: boolean;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* encode is not realized yet
|
|
88
|
+
*/
|
|
89
|
+
export interface BuildOptions extends Options {
|
|
90
|
+
encode?: boolean; // Not realized yet
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export type CallbackFn<T> = (error: any, result?: T) => void;
|
|
94
|
+
|
|
95
|
+
export type OptionOrNull = Options | null;
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* BoundaryRawData
|
|
99
|
+
*/
|
|
100
|
+
export interface BoundaryRawData {
|
|
101
|
+
boundary: string;
|
|
102
|
+
lines: string[];
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Convert BoundaryRawData result
|
|
106
|
+
*/
|
|
107
|
+
export interface BoundaryConvertedData {
|
|
108
|
+
boundary: string;
|
|
109
|
+
part: {
|
|
110
|
+
headers: BoundaryHeaders;
|
|
111
|
+
body: string | Array<BoundaryConvertedData | string>;
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
export interface BoundaryHeaders extends KeyValue {
|
|
115
|
+
'Content-Type': string;
|
|
116
|
+
'Content-Transfer-Encoding'?: string;
|
|
117
|
+
'Content-Disposition'?: string;
|
|
118
|
+
}
|
package/src/utils.ts
ADDED
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
import { decode } from './charset';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Gets the boundary name
|
|
5
|
+
* @param contentType - string
|
|
6
|
+
*/
|
|
7
|
+
export function getBoundary(contentType: string) {
|
|
8
|
+
const match = /(?:B|b)oundary=(?:'|")?(.+?)(?:'|")?(\s*;[\s\S]*)?$/g.exec(contentType);
|
|
9
|
+
return match ? match[1] : undefined;
|
|
10
|
+
}
|
|
11
|
+
//Gets the character encoding name for iconv, e.g. 'iso-8859-2' -> 'iso88592'
|
|
12
|
+
export function getCharsetName(charset: string) {
|
|
13
|
+
return charset.toLowerCase().replace(/[^0-9a-z]/g, '');
|
|
14
|
+
}
|
|
15
|
+
//Generates a random id
|
|
16
|
+
export function guid() {
|
|
17
|
+
return 'xxxxxxxxxxxx-4xxx-yxxx-xxxxxxxxxxxx'
|
|
18
|
+
.replace(/[xy]/g, function(c) {
|
|
19
|
+
const r = (Math.random() * 16) | 0,
|
|
20
|
+
v = c == 'x' ? r : (r & 0x3) | 0x8;
|
|
21
|
+
return v.toString(16);
|
|
22
|
+
})
|
|
23
|
+
.replace('-', '');
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
//Word-wrap the string 's' to 'i' chars per row
|
|
27
|
+
export function wrap(s: string, i: number) {
|
|
28
|
+
const a = [] as any[];
|
|
29
|
+
do {
|
|
30
|
+
a.push(s.substring(0, i));
|
|
31
|
+
} while ((s = s.substring(i, s.length)) != '');
|
|
32
|
+
return a.join('\r\n');
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Decodes mime encoded string to an unicode string
|
|
37
|
+
*
|
|
38
|
+
* @param {String} str Mime encoded string
|
|
39
|
+
* @param {String} [fromCharset='UTF-8'] Source encoding
|
|
40
|
+
* @return {String} Decoded unicode string
|
|
41
|
+
*/
|
|
42
|
+
export function mimeDecode(str = '', fromCharset = 'UTF-8') {
|
|
43
|
+
const encodedBytesCount = (str.match(/=[\da-fA-F]{2}/g) || []).length;
|
|
44
|
+
let buffer = new Uint8Array(str.length - encodedBytesCount * 2);
|
|
45
|
+
|
|
46
|
+
for (let i = 0, len = str.length, bufferPos = 0; i < len; i++) {
|
|
47
|
+
let hex = str.substr(i + 1, 2);
|
|
48
|
+
const chr = str.charAt(i);
|
|
49
|
+
if (chr === '=' && hex && /[\da-fA-F]{2}/.test(hex)) {
|
|
50
|
+
buffer[bufferPos++] = parseInt(hex, 16);
|
|
51
|
+
i += 2;
|
|
52
|
+
} else {
|
|
53
|
+
buffer[bufferPos++] = chr.charCodeAt(0);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return decode(buffer, fromCharset);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* adjust string Or Error
|
|
62
|
+
* @param param
|
|
63
|
+
*/
|
|
64
|
+
export function isStringOrError(param: any) {
|
|
65
|
+
return typeof param === 'string' || param instanceof Error;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* converting strings from gbk to utf-8
|
|
70
|
+
*/
|
|
71
|
+
export const GB2312UTF8 = {
|
|
72
|
+
Dig2Dec: function(s: string) {
|
|
73
|
+
let retV = 0;
|
|
74
|
+
if (s.length == 4) {
|
|
75
|
+
for (let i = 0; i < 4; i++) {
|
|
76
|
+
retV += eval(s.charAt(i)) * Math.pow(2, 3 - i);
|
|
77
|
+
}
|
|
78
|
+
return retV;
|
|
79
|
+
}
|
|
80
|
+
return -1;
|
|
81
|
+
},
|
|
82
|
+
|
|
83
|
+
Hex2Utf8: function(s: string) {
|
|
84
|
+
let retS = '';
|
|
85
|
+
let tempS = '';
|
|
86
|
+
let ss = '';
|
|
87
|
+
if (s.length == 16) {
|
|
88
|
+
tempS = '1110' + s.substring(0, 4);
|
|
89
|
+
tempS += '10' + s.substring(4, 10);
|
|
90
|
+
tempS += '10' + s.substring(10, 16);
|
|
91
|
+
let sss = '0123456789ABCDEF';
|
|
92
|
+
for (let i = 0; i < 3; i++) {
|
|
93
|
+
retS += '%';
|
|
94
|
+
ss = tempS.substring(i * 8, (eval(i.toString()) + 1) * 8);
|
|
95
|
+
retS += sss.charAt(this.Dig2Dec(ss.substring(0, 4)));
|
|
96
|
+
retS += sss.charAt(this.Dig2Dec(ss.substring(4, 8)));
|
|
97
|
+
}
|
|
98
|
+
return retS;
|
|
99
|
+
}
|
|
100
|
+
return '';
|
|
101
|
+
},
|
|
102
|
+
|
|
103
|
+
Dec2Dig: function(n1: number) {
|
|
104
|
+
let s = '';
|
|
105
|
+
let n2 = 0;
|
|
106
|
+
for (let i = 0; i < 4; i++) {
|
|
107
|
+
n2 = Math.pow(2, 3 - i);
|
|
108
|
+
if (n1 >= n2) {
|
|
109
|
+
s += '1';
|
|
110
|
+
n1 = n1 - n2;
|
|
111
|
+
} else {
|
|
112
|
+
s += '0';
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return s;
|
|
116
|
+
},
|
|
117
|
+
|
|
118
|
+
Str2Hex: function(s: string) {
|
|
119
|
+
let c = '';
|
|
120
|
+
let n;
|
|
121
|
+
let ss = '0123456789ABCDEF';
|
|
122
|
+
let digS = '';
|
|
123
|
+
for (let i = 0; i < s.length; i++) {
|
|
124
|
+
c = s.charAt(i);
|
|
125
|
+
n = ss.indexOf(c);
|
|
126
|
+
digS += this.Dec2Dig(eval(n.toString()));
|
|
127
|
+
}
|
|
128
|
+
return digS;
|
|
129
|
+
},
|
|
130
|
+
|
|
131
|
+
GB2312ToUTF8: function(s1: string) {
|
|
132
|
+
let s = escape(s1);
|
|
133
|
+
let sa = s.split('%');
|
|
134
|
+
let retV = '';
|
|
135
|
+
if (sa[0] != '') {
|
|
136
|
+
retV = sa[0];
|
|
137
|
+
}
|
|
138
|
+
for (let i = 1; i < sa.length; i++) {
|
|
139
|
+
if (sa[i].substring(0, 1) == 'u') {
|
|
140
|
+
retV += this.Hex2Utf8(this.Str2Hex(sa[i].substring(1, 5)));
|
|
141
|
+
if (sa[i].length) {
|
|
142
|
+
retV += sa[i].substring(5);
|
|
143
|
+
}
|
|
144
|
+
} else {
|
|
145
|
+
retV += unescape('%' + sa[i]);
|
|
146
|
+
if (sa[i].length) {
|
|
147
|
+
retV += sa[i].substring(5);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
return retV;
|
|
152
|
+
},
|
|
153
|
+
|
|
154
|
+
UTF8ToGB2312: function(str1: string) {
|
|
155
|
+
let substr = '';
|
|
156
|
+
let a = '';
|
|
157
|
+
let b = '';
|
|
158
|
+
let c = '';
|
|
159
|
+
let i = -1;
|
|
160
|
+
i = str1.indexOf('%');
|
|
161
|
+
if (i == -1) {
|
|
162
|
+
return str1;
|
|
163
|
+
}
|
|
164
|
+
while (i != -1) {
|
|
165
|
+
if (i < 3) {
|
|
166
|
+
substr = substr + str1.substr(0, i - 1);
|
|
167
|
+
str1 = str1.substr(i + 1, str1.length - i);
|
|
168
|
+
a = str1.substr(0, 2);
|
|
169
|
+
str1 = str1.substr(2, str1.length - 2);
|
|
170
|
+
if ((parseInt('0x' + a) & 0x80) === 0) {
|
|
171
|
+
substr = substr + String.fromCharCode(parseInt('0x' + a));
|
|
172
|
+
} else if ((parseInt('0x' + a) & 0xe0) === 0xc0) {
|
|
173
|
+
//two byte
|
|
174
|
+
b = str1.substr(1, 2);
|
|
175
|
+
str1 = str1.substr(3, str1.length - 3);
|
|
176
|
+
let widechar = (parseInt('0x' + a) & 0x1f) << 6;
|
|
177
|
+
widechar = widechar | (parseInt('0x' + b) & 0x3f);
|
|
178
|
+
substr = substr + String.fromCharCode(widechar);
|
|
179
|
+
} else {
|
|
180
|
+
b = str1.substr(1, 2);
|
|
181
|
+
str1 = str1.substr(3, str1.length - 3);
|
|
182
|
+
c = str1.substr(1, 2);
|
|
183
|
+
str1 = str1.substr(3, str1.length - 3);
|
|
184
|
+
let widechar = (parseInt('0x' + a) & 0x0f) << 12;
|
|
185
|
+
widechar = widechar | ((parseInt('0x' + b) & 0x3f) << 6);
|
|
186
|
+
widechar = widechar | (parseInt('0x' + c) & 0x3f);
|
|
187
|
+
substr = substr + String.fromCharCode(widechar);
|
|
188
|
+
}
|
|
189
|
+
} else {
|
|
190
|
+
substr = substr + str1.substring(0, i);
|
|
191
|
+
str1 = str1.substring(i);
|
|
192
|
+
}
|
|
193
|
+
i = str1.indexOf('%');
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
return substr + str1;
|
|
197
|
+
},
|
|
198
|
+
};
|