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.
@@ -0,0 +1,1431 @@
1
+ (function (exports, jsBase64, textEncoding) {
2
+ 'use strict';
3
+
4
+ /**
5
+ * Encodes an unicode string into an Uint8Array object as UTF-8
6
+ *
7
+ * @param {String} str String to be encoded
8
+ * @return {Uint8Array} UTF-8 encoded typed array
9
+ */
10
+ var encode = function (str, fromCharset) {
11
+ if (fromCharset === void 0) { fromCharset = 'utf-8'; }
12
+ return new textEncoding.TextEncoder(fromCharset).encode(str);
13
+ };
14
+ var arr2str = function (arr) {
15
+ var CHUNK_SZ = 0x8000;
16
+ var strs = [];
17
+ for (var i = 0; i < arr.length; i += CHUNK_SZ) {
18
+ strs.push(String.fromCharCode.apply(null, arr.subarray(i, i + CHUNK_SZ)));
19
+ }
20
+ return strs.join('');
21
+ };
22
+ /**
23
+ * Decodes a string from Uint8Array to an unicode string using specified encoding
24
+ *
25
+ * @param {Uint8Array} buf Binary data to be decoded
26
+ * @param {String} Binary data is decoded into string using this charset
27
+ * @return {String} Decoded string
28
+ */
29
+ function decode(buf, fromCharset) {
30
+ if (fromCharset === void 0) { fromCharset = 'utf-8'; }
31
+ var charsets = [
32
+ { charset: normalizeCharset(fromCharset), fatal: false },
33
+ { charset: 'utf-8', fatal: true },
34
+ { charset: 'iso-8859-15', fatal: false },
35
+ ];
36
+ for (var _i = 0, charsets_1 = charsets; _i < charsets_1.length; _i++) {
37
+ var _a = charsets_1[_i], charset = _a.charset, fatal = _a.fatal;
38
+ try {
39
+ return new textEncoding.TextDecoder(charset, { fatal: fatal }).decode(buf);
40
+ // eslint-disable-next-line no-empty
41
+ }
42
+ catch (e) { }
43
+ }
44
+ return arr2str(buf); // all else fails, treat it as binary
45
+ }
46
+ /**
47
+ * Convert a string from specific encoding to UTF-8 Uint8Array
48
+ *
49
+ * @param {String|Uint8Array} data Data to be encoded
50
+ * @param {String} Source encoding for the string (optional for data of type String)
51
+ * @return {Uint8Array} UTF-8 encoded typed array
52
+ */
53
+ var convert = function (data, fromCharset) {
54
+ return typeof data === 'string' ? encode(data) : encode(decode(data, fromCharset));
55
+ };
56
+ function normalizeCharset(charset) {
57
+ if (charset === void 0) { charset = 'utf-8'; }
58
+ var match;
59
+ if ((match = charset.match(/^utf[-_]?(\d+)$/i))) {
60
+ return 'UTF-' + match[1];
61
+ }
62
+ if ((match = charset.match(/^win[-_]?(\d+)$/i))) {
63
+ return 'WINDOWS-' + match[1];
64
+ }
65
+ if ((match = charset.match(/^latin[-_]?(\d+)$/i))) {
66
+ return 'ISO-8859-' + match[1];
67
+ }
68
+ return charset;
69
+ }
70
+
71
+ /**
72
+ * Gets the boundary name
73
+ * @param contentType - string
74
+ */
75
+ function getBoundary(contentType) {
76
+ var match = /(?:B|b)oundary=(?:'|")?(.+?)(?:'|")?(\s*;[\s\S]*)?$/g.exec(contentType);
77
+ return match ? match[1] : undefined;
78
+ }
79
+ //Gets the character encoding name for iconv, e.g. 'iso-8859-2' -> 'iso88592'
80
+ function getCharsetName(charset) {
81
+ return charset.toLowerCase().replace(/[^0-9a-z]/g, '');
82
+ }
83
+ //Generates a random id
84
+ function guid() {
85
+ return 'xxxxxxxxxxxx-4xxx-yxxx-xxxxxxxxxxxx'
86
+ .replace(/[xy]/g, function (c) {
87
+ var r = (Math.random() * 16) | 0, v = c == 'x' ? r : (r & 0x3) | 0x8;
88
+ return v.toString(16);
89
+ })
90
+ .replace('-', '');
91
+ }
92
+ //Word-wrap the string 's' to 'i' chars per row
93
+ function wrap(s, i) {
94
+ var a = [];
95
+ do {
96
+ a.push(s.substring(0, i));
97
+ } while ((s = s.substring(i, s.length)) != '');
98
+ return a.join('\r\n');
99
+ }
100
+ /**
101
+ * Decodes mime encoded string to an unicode string
102
+ *
103
+ * @param {String} str Mime encoded string
104
+ * @param {String} [fromCharset='UTF-8'] Source encoding
105
+ * @return {String} Decoded unicode string
106
+ */
107
+ function mimeDecode(str, fromCharset) {
108
+ if (str === void 0) { str = ''; }
109
+ if (fromCharset === void 0) { fromCharset = 'UTF-8'; }
110
+ var encodedBytesCount = (str.match(/=[\da-fA-F]{2}/g) || []).length;
111
+ var buffer = new Uint8Array(str.length - encodedBytesCount * 2);
112
+ for (var i = 0, len = str.length, bufferPos = 0; i < len; i++) {
113
+ var hex = str.substr(i + 1, 2);
114
+ var chr = str.charAt(i);
115
+ if (chr === '=' && hex && /[\da-fA-F]{2}/.test(hex)) {
116
+ buffer[bufferPos++] = parseInt(hex, 16);
117
+ i += 2;
118
+ }
119
+ else {
120
+ buffer[bufferPos++] = chr.charCodeAt(0);
121
+ }
122
+ }
123
+ return decode(buffer, fromCharset);
124
+ }
125
+ /**
126
+ * converting strings from gbk to utf-8
127
+ */
128
+ var GB2312UTF8 = {
129
+ Dig2Dec: function (s) {
130
+ var retV = 0;
131
+ if (s.length == 4) {
132
+ for (var i = 0; i < 4; i++) {
133
+ retV += eval(s.charAt(i)) * Math.pow(2, 3 - i);
134
+ }
135
+ return retV;
136
+ }
137
+ return -1;
138
+ },
139
+ Hex2Utf8: function (s) {
140
+ var retS = '';
141
+ var tempS = '';
142
+ var ss = '';
143
+ if (s.length == 16) {
144
+ tempS = '1110' + s.substring(0, 4);
145
+ tempS += '10' + s.substring(4, 10);
146
+ tempS += '10' + s.substring(10, 16);
147
+ var sss = '0123456789ABCDEF';
148
+ for (var i = 0; i < 3; i++) {
149
+ retS += '%';
150
+ ss = tempS.substring(i * 8, (eval(i.toString()) + 1) * 8);
151
+ retS += sss.charAt(this.Dig2Dec(ss.substring(0, 4)));
152
+ retS += sss.charAt(this.Dig2Dec(ss.substring(4, 8)));
153
+ }
154
+ return retS;
155
+ }
156
+ return '';
157
+ },
158
+ Dec2Dig: function (n1) {
159
+ var s = '';
160
+ var n2 = 0;
161
+ for (var i = 0; i < 4; i++) {
162
+ n2 = Math.pow(2, 3 - i);
163
+ if (n1 >= n2) {
164
+ s += '1';
165
+ n1 = n1 - n2;
166
+ }
167
+ else {
168
+ s += '0';
169
+ }
170
+ }
171
+ return s;
172
+ },
173
+ Str2Hex: function (s) {
174
+ var c = '';
175
+ var n;
176
+ var ss = '0123456789ABCDEF';
177
+ var digS = '';
178
+ for (var i = 0; i < s.length; i++) {
179
+ c = s.charAt(i);
180
+ n = ss.indexOf(c);
181
+ digS += this.Dec2Dig(eval(n.toString()));
182
+ }
183
+ return digS;
184
+ },
185
+ GB2312ToUTF8: function (s1) {
186
+ var s = escape(s1);
187
+ var sa = s.split('%');
188
+ var retV = '';
189
+ if (sa[0] != '') {
190
+ retV = sa[0];
191
+ }
192
+ for (var i = 1; i < sa.length; i++) {
193
+ if (sa[i].substring(0, 1) == 'u') {
194
+ retV += this.Hex2Utf8(this.Str2Hex(sa[i].substring(1, 5)));
195
+ if (sa[i].length) {
196
+ retV += sa[i].substring(5);
197
+ }
198
+ }
199
+ else {
200
+ retV += unescape('%' + sa[i]);
201
+ if (sa[i].length) {
202
+ retV += sa[i].substring(5);
203
+ }
204
+ }
205
+ }
206
+ return retV;
207
+ },
208
+ UTF8ToGB2312: function (str1) {
209
+ var substr = '';
210
+ var a = '';
211
+ var b = '';
212
+ var c = '';
213
+ var i = -1;
214
+ i = str1.indexOf('%');
215
+ if (i == -1) {
216
+ return str1;
217
+ }
218
+ while (i != -1) {
219
+ if (i < 3) {
220
+ substr = substr + str1.substr(0, i - 1);
221
+ str1 = str1.substr(i + 1, str1.length - i);
222
+ a = str1.substr(0, 2);
223
+ str1 = str1.substr(2, str1.length - 2);
224
+ if ((parseInt('0x' + a) & 0x80) === 0) {
225
+ substr = substr + String.fromCharCode(parseInt('0x' + a));
226
+ }
227
+ else if ((parseInt('0x' + a) & 0xe0) === 0xc0) {
228
+ //two byte
229
+ b = str1.substr(1, 2);
230
+ str1 = str1.substr(3, str1.length - 3);
231
+ var widechar = (parseInt('0x' + a) & 0x1f) << 6;
232
+ widechar = widechar | (parseInt('0x' + b) & 0x3f);
233
+ substr = substr + String.fromCharCode(widechar);
234
+ }
235
+ else {
236
+ b = str1.substr(1, 2);
237
+ str1 = str1.substr(3, str1.length - 3);
238
+ c = str1.substr(1, 2);
239
+ str1 = str1.substr(3, str1.length - 3);
240
+ var widechar = (parseInt('0x' + a) & 0x0f) << 12;
241
+ widechar = widechar | ((parseInt('0x' + b) & 0x3f) << 6);
242
+ widechar = widechar | (parseInt('0x' + c) & 0x3f);
243
+ substr = substr + String.fromCharCode(widechar);
244
+ }
245
+ }
246
+ else {
247
+ substr = substr + str1.substring(0, i);
248
+ str1 = str1.substring(i);
249
+ }
250
+ i = str1.indexOf('%');
251
+ }
252
+ return substr + str1;
253
+ },
254
+ };
255
+
256
+ /**
257
+ * Converts tokens for a single address into an address object
258
+ *
259
+ * @param {Array} tokens Tokens object
260
+ * @return {Object} Address object
261
+ */
262
+ function _handleAddress(tokens) {
263
+ var token;
264
+ var isGroup = false;
265
+ var state = 'text';
266
+ var address;
267
+ var addresses = [];
268
+ var data = {
269
+ address: [],
270
+ comment: [],
271
+ group: [],
272
+ text: [],
273
+ };
274
+ var i;
275
+ var len;
276
+ // Filter out <addresses>, (comments) and regular text
277
+ for (i = 0, len = tokens.length; i < len; i++) {
278
+ token = tokens[i];
279
+ if (token.type === 'operator') {
280
+ switch (token.value) {
281
+ case '<':
282
+ state = 'address';
283
+ break;
284
+ case '(':
285
+ state = 'comment';
286
+ break;
287
+ case ':':
288
+ state = 'group';
289
+ isGroup = true;
290
+ break;
291
+ default:
292
+ state = 'text';
293
+ }
294
+ }
295
+ else if (token.value) {
296
+ if (state === 'address') {
297
+ // handle use case where unquoted name includes a "<"
298
+ // Apple Mail truncates everything between an unexpected < and an address
299
+ // and so will we
300
+ token.value = token.value.replace(/^[^<]*<\s*/, '');
301
+ }
302
+ data[state].push(token.value);
303
+ }
304
+ }
305
+ // If there is no text but a comment, replace the two
306
+ if (!data.text.length && data.comment.length) {
307
+ data.text = data.comment;
308
+ data.comment = [];
309
+ }
310
+ if (isGroup) {
311
+ // http://tools.ietf.org/html/rfc2822#appendix-A.1.3
312
+ data.text = data.text.join(' ');
313
+ addresses.push({
314
+ name: data.text || (address && address.name),
315
+ group: data.group.length ? addressparser(data.group.join(',')) : [],
316
+ });
317
+ }
318
+ else {
319
+ // If no address was found, try to detect one from regular text
320
+ if (!data.address.length && data.text.length) {
321
+ for (i = data.text.length - 1; i >= 0; i--) {
322
+ if (data.text[i].match(/^[^@\s]+@[^@\s]+$/)) {
323
+ data.address = data.text.splice(i, 1);
324
+ break;
325
+ }
326
+ }
327
+ var _regexHandler = function (address) {
328
+ if (!data.address.length) {
329
+ data.address = [address.trim()];
330
+ return ' ';
331
+ }
332
+ else {
333
+ return address;
334
+ }
335
+ };
336
+ // still no address
337
+ if (!data.address.length) {
338
+ for (i = data.text.length - 1; i >= 0; i--) {
339
+ // fixed the regex to parse email address correctly when email address has more than one @
340
+ data.text[i] = data.text[i].replace(/\s*\b[^@\s]+@[^\s]+\b\s*/, _regexHandler).trim();
341
+ if (data.address.length) {
342
+ break;
343
+ }
344
+ }
345
+ }
346
+ }
347
+ // If there's still is no text but a comment exixts, replace the two
348
+ if (!data.text.length && data.comment.length) {
349
+ data.text = data.comment;
350
+ data.comment = [];
351
+ }
352
+ // Keep only the first address occurence, push others to regular text
353
+ if (data.address.length > 1) {
354
+ data.text = data.text.concat(data.address.splice(1));
355
+ }
356
+ // Join values with spaces
357
+ data.text = data.text.join(' ');
358
+ data.address = data.address.join(' ');
359
+ if (!data.address && isGroup) {
360
+ return [];
361
+ }
362
+ else {
363
+ address = {
364
+ address: data.address || data.text || '',
365
+ name: data.text || data.address || '',
366
+ };
367
+ if (address.address === address.name) {
368
+ if ((address.address || '').match(/@/)) {
369
+ address.name = '';
370
+ }
371
+ else {
372
+ address.address = '';
373
+ }
374
+ }
375
+ addresses.push(address);
376
+ }
377
+ }
378
+ return addresses;
379
+ }
380
+ /**
381
+ * Creates a Tokenizer object for tokenizing address field strings
382
+ *
383
+ * @constructor
384
+ * @param {String} str Address field string
385
+ */
386
+ var Tokenizer = /** @class */ (function () {
387
+ function Tokenizer(str) {
388
+ this.str = (str || '').toString();
389
+ this.operatorCurrent = '';
390
+ this.operatorExpecting = '';
391
+ this.node = null;
392
+ this.escaped = false;
393
+ this.list = [];
394
+ /**
395
+ * Operator tokens and which tokens are expected to end the sequence
396
+ */
397
+ this.operators = {
398
+ '"': '"',
399
+ '(': ')',
400
+ '<': '>',
401
+ ',': '',
402
+ ':': ';',
403
+ // Semicolons are not a legal delimiter per the RFC2822 grammar other
404
+ // than for terminating a group, but they are also not valid for any
405
+ // other use in this context. Given that some mail clients have
406
+ // historically allowed the semicolon as a delimiter equivalent to the
407
+ // comma in their UI, it makes sense to treat them the same as a comma
408
+ // when used outside of a group.
409
+ ';': '',
410
+ };
411
+ }
412
+ /**
413
+ * Tokenizes the original input string
414
+ *
415
+ * @return {Array} An array of operator|text tokens
416
+ */
417
+ Tokenizer.prototype.tokenize = function () {
418
+ var chr, list = [];
419
+ for (var i = 0, len = this.str.length; i < len; i++) {
420
+ chr = this.str.charAt(i);
421
+ this.checkChar(chr);
422
+ }
423
+ this.list.forEach(function (node) {
424
+ node.value = (node.value || '').toString().trim();
425
+ if (node.value) {
426
+ list.push(node);
427
+ }
428
+ });
429
+ return list;
430
+ };
431
+ /**
432
+ * Checks if a character is an operator or text and acts accordingly
433
+ *
434
+ * @param {String} chr Character from the address field
435
+ */
436
+ Tokenizer.prototype.checkChar = function (chr) {
437
+ if (this.escaped) ;
438
+ else if (chr === this.operatorExpecting) {
439
+ this.node = {
440
+ type: 'operator',
441
+ value: chr,
442
+ };
443
+ this.list.push(this.node);
444
+ this.node = null;
445
+ this.operatorExpecting = '';
446
+ this.escaped = false;
447
+ return;
448
+ }
449
+ else if (!this.operatorExpecting && chr in this.operators) {
450
+ this.node = {
451
+ type: 'operator',
452
+ value: chr,
453
+ };
454
+ this.list.push(this.node);
455
+ this.node = null;
456
+ this.operatorExpecting = this.operators[chr];
457
+ this.escaped = false;
458
+ return;
459
+ }
460
+ else if (['"', "'"].includes(this.operatorExpecting) && chr === '\\') {
461
+ this.escaped = true;
462
+ return;
463
+ }
464
+ if (!this.node) {
465
+ this.node = {
466
+ type: 'text',
467
+ value: '',
468
+ };
469
+ this.list.push(this.node);
470
+ }
471
+ if (chr === '\n') {
472
+ // Convert newlines to spaces. Carriage return is ignored as \r and \n usually
473
+ // go together anyway and there already is a WS for \n. Lone \r means something is fishy.
474
+ chr = ' ';
475
+ }
476
+ if (chr.charCodeAt(0) >= 0x21 || [' ', '\t'].includes(chr)) {
477
+ // skip command bytes
478
+ this.node.value += chr;
479
+ }
480
+ this.escaped = false;
481
+ };
482
+ return Tokenizer;
483
+ }());
484
+ /**
485
+ * Parses structured e-mail addresses from an address field
486
+ *
487
+ * Example:
488
+ *
489
+ * 'Name <address@domain>'
490
+ *
491
+ * will be converted to
492
+ *
493
+ * [{name: 'Name', address: 'address@domain'}]
494
+ *
495
+ * @param {String} str Address field
496
+ * @return {Array} An array of address objects
497
+ */
498
+ function addressparser(str, options) {
499
+ options = options || {};
500
+ var tokenizer = new Tokenizer(str);
501
+ var tokens = tokenizer.tokenize();
502
+ var addresses = [];
503
+ var address = [];
504
+ var parsedAddresses = [];
505
+ tokens.forEach(function (token) {
506
+ if (token.type === 'operator' && (token.value === ',' || token.value === ';')) {
507
+ if (address.length) {
508
+ addresses.push(address);
509
+ }
510
+ address = [];
511
+ }
512
+ else {
513
+ address.push(token);
514
+ }
515
+ });
516
+ if (address.length) {
517
+ addresses.push(address);
518
+ }
519
+ addresses.forEach(function (address) {
520
+ address = _handleAddress(address);
521
+ if (address.length) {
522
+ parsedAddresses = parsedAddresses.concat(address);
523
+ }
524
+ });
525
+ if (options.flatten) {
526
+ var addresses_1 = [];
527
+ var walkAddressList_1 = function (list) {
528
+ list.forEach(function (address) {
529
+ if (address.group) {
530
+ return walkAddressList_1(address.group);
531
+ }
532
+ else {
533
+ addresses_1.push(address);
534
+ }
535
+ });
536
+ };
537
+ walkAddressList_1(parsedAddresses);
538
+ return addresses_1;
539
+ }
540
+ return parsedAddresses;
541
+ }
542
+
543
+ /**
544
+ * @author superchow
545
+ * @emil superchow@live.cn
546
+ */
547
+ /**
548
+ * log for test
549
+ */
550
+ var verbose = false;
551
+ var defaultCharset = 'utf-8';
552
+ /**
553
+ * create a boundary
554
+ */
555
+ function createBoundary() {
556
+ return '----=' + guid();
557
+ }
558
+ /**
559
+ * Builds e-mail address string, e.g. { name: 'PayPal', email: 'noreply@paypal.com' } => 'PayPal' <noreply@paypal.com>
560
+ * @param {String|EmailAddress|EmailAddress[]|null} data
561
+ */
562
+ function toEmailAddress(data) {
563
+ var email = '';
564
+ if (typeof data === 'undefined') ;
565
+ else if (typeof data === 'string') {
566
+ email = data;
567
+ }
568
+ else if (typeof data === 'object') {
569
+ if (Array.isArray(data)) {
570
+ email += data
571
+ .map(function (item) {
572
+ var str = '';
573
+ if (item.name) {
574
+ str += '"' + item.name.replace(/^"|"\s*$/g, '') + '" ';
575
+ }
576
+ if (item.email) {
577
+ str += '<' + item.email + '>';
578
+ }
579
+ return str;
580
+ })
581
+ .filter(function (a) { return a; })
582
+ .join(', ');
583
+ }
584
+ else {
585
+ if (data) {
586
+ if (data.name) {
587
+ email += '"' + data.name.replace(/^"|"\s*$/g, '') + '" ';
588
+ }
589
+ if (data.email) {
590
+ email += '<' + data.email + '>';
591
+ }
592
+ }
593
+ }
594
+ }
595
+ return email;
596
+ }
597
+ /**
598
+ * Gets character set name, e.g. contentType='.....charset='iso-8859-2'....'
599
+ * @param {String} contentType
600
+ * @returns {String|undefined}
601
+ */
602
+ function getCharset(contentType) {
603
+ var match = /charset\s*=\W*([\w\-]+)/g.exec(contentType);
604
+ return match ? match[1] : undefined;
605
+ }
606
+ /**
607
+ * Gets name and e-mail address from a string, e.g. 'PayPal' <noreply@paypal.com> => { name: 'PayPal', email: 'noreply@paypal.com' }
608
+ * @param {String} raw
609
+ * @returns { EmailAddress | EmailAddress[] | null}
610
+ */
611
+ function getEmailAddress(rawStr) {
612
+ var raw = unquoteString(rawStr);
613
+ var parseList = addressparser(raw);
614
+ var list = parseList.map(function (v) { return ({ name: v.name, email: v.address }); });
615
+ //Return result
616
+ if (list.length === 0) {
617
+ return null; //No e-mail address
618
+ }
619
+ if (list.length === 1) {
620
+ return list[0]; //Only one record, return as object, required to preserve backward compatibility
621
+ }
622
+ return list; //Multiple e-mail addresses as array
623
+ }
624
+ /**
625
+ * decode one joint
626
+ * @param {String} str
627
+ * @returns {String}
628
+ */
629
+ function decodeJoint(str) {
630
+ var match = /=\?([^?]+)\?(B|Q)\?(.+?)(\?=)/gi.exec(str);
631
+ if (match) {
632
+ var charset = getCharsetName(match[1] || defaultCharset); //eq. match[1] = 'iso-8859-2'; charset = 'iso88592'
633
+ var type = match[2].toUpperCase();
634
+ var value = match[3];
635
+ if (type === 'B') {
636
+ //Base64
637
+ if (charset === 'utf8') {
638
+ return decode(encode(jsBase64.Base64.fromBase64(value.replace(/\r?\n/g, ''))), 'utf8');
639
+ }
640
+ else {
641
+ return decode(jsBase64.Base64.toUint8Array(value.replace(/\r?\n/g, '')), charset);
642
+ }
643
+ }
644
+ else if (type === 'Q') {
645
+ //Quoted printable
646
+ return unquotePrintable(value, charset, true);
647
+ }
648
+ }
649
+ return str;
650
+ }
651
+ /**
652
+ * decode section
653
+ * @param {String} str
654
+ * @returns {String}
655
+ */
656
+ function unquoteString(str) {
657
+ var regex = /=\?([^?]+)\?(B|Q)\?(.+?)(\?=)/gi;
658
+ var decodedString = str || '';
659
+ var spinOffMatch = decodedString.match(regex);
660
+ if (spinOffMatch) {
661
+ spinOffMatch.forEach(function (spin) {
662
+ decodedString = decodedString.replace(spin, decodeJoint(spin));
663
+ });
664
+ }
665
+ return decodedString.replace(/\r?\n/g, '');
666
+ }
667
+ /**
668
+ * Decodes 'quoted-printable'
669
+ * @param {String} value
670
+ * @param {String} charset
671
+ * @param {String} qEncoding whether the encoding is RFC-2047’s Q-encoding, meaning special handling of underscores.
672
+ * @returns {String}
673
+ */
674
+ function unquotePrintable(value, charset, qEncoding) {
675
+ //Convert =0D to '\r', =20 to ' ', etc.
676
+ // if (!charset || charset == "utf8" || charset == "utf-8") {
677
+ // return value
678
+ // .replace(/=([\w\d]{2})=([\w\d]{2})=([\w\d]{2})/gi, function (matcher, p1, p2, p3, offset, string) {
679
+ if (qEncoding === void 0) { qEncoding = false; }
680
+ // })
681
+ // .replace(/=([\w\d]{2})=([\w\d]{2})/gi, function (matcher, p1, p2, offset, string) {
682
+ // })
683
+ // .replace(/=([\w\d]{2})/gi, function (matcher, p1, offset, string) { return String.fromCharCode(parseInt(p1, 16)); })
684
+ // .replace(/=\r?\n/gi, ""); //Join line
685
+ // } else {
686
+ // return value
687
+ // .replace(/=([\w\d]{2})=([\w\d]{2})/gi, function (matcher, p1, p2, offset, string) {
688
+ // })
689
+ // .replace(/=([\w\d]{2})/gi, function (matcher, p1, offset, string) {
690
+ // })
691
+ // .replace(/=\r?\n/gi, ''); //Join line
692
+ // }
693
+ var rawString = value
694
+ .replace(/[\t ]+$/gm, '') // remove invalid whitespace from the end of lines
695
+ .replace(/=(?:\r?\n|$)/g, ''); // remove soft line breaks
696
+ if (qEncoding) {
697
+ rawString = rawString.replace(/_/g, decode(new Uint8Array([0x20]), charset));
698
+ }
699
+ return mimeDecode(rawString, charset);
700
+ }
701
+ /**
702
+ * Parses EML file content and returns object-oriented representation of the content.
703
+ * @param {String} eml
704
+ * @param {OptionOrNull | CallbackFn<ParsedEmlJson>} options
705
+ * @param {CallbackFn<ParsedEmlJson>} callback
706
+ * @returns {string | Error | ParsedEmlJson}
707
+ */
708
+ function parse(eml, options, callback) {
709
+ //Shift arguments
710
+ if (typeof options === 'function' && typeof callback === 'undefined') {
711
+ callback = options;
712
+ options = null;
713
+ }
714
+ if (typeof options !== 'object') {
715
+ options = { headersOnly: false };
716
+ }
717
+ var error;
718
+ var result = {};
719
+ try {
720
+ if (typeof eml !== 'string') {
721
+ throw new Error('Argument "eml" expected to be string!');
722
+ }
723
+ var lines = eml.split(/\r?\n/);
724
+ result = parseRecursive(lines, 0, result, options);
725
+ }
726
+ catch (e) {
727
+ error = e;
728
+ }
729
+ callback && callback(error, result);
730
+ return error || result || new Error('read EML failed!');
731
+ }
732
+ /**
733
+ * Parses EML file content.
734
+ * @param {String[]} lines
735
+ * @param {Number} start
736
+ * @param {Options} options
737
+ * @returns {ParsedEmlJson}
738
+ */
739
+ function parseRecursive(lines, start, parent, options) {
740
+ var boundary = null;
741
+ var lastHeaderName = '';
742
+ var findBoundary = '';
743
+ var insideBody = false;
744
+ var insideBoundary = false;
745
+ var isMultiHeader = false;
746
+ var isMultipart = false;
747
+ var checkedForCt = false;
748
+ var ctInBody = false;
749
+ parent.headers = {};
750
+ //parent.body = null;
751
+ function complete(boundary) {
752
+ //boundary.part = boundary.lines.join("\r\n");
753
+ boundary.part = {};
754
+ parseRecursive(boundary.lines, 0, boundary.part, options);
755
+ delete boundary.lines;
756
+ }
757
+ //Read line by line
758
+ for (var i = start; i < lines.length; i++) {
759
+ var line = lines[i];
760
+ //Header
761
+ if (!insideBody) {
762
+ //Search for empty line
763
+ if (line == '') {
764
+ insideBody = true;
765
+ if (options && options.headersOnly) {
766
+ break;
767
+ }
768
+ //Expected boundary
769
+ var ct = parent.headers['Content-Type'] || parent.headers['Content-type'];
770
+ if (!ct) {
771
+ if (checkedForCt) {
772
+ insideBody = !ctInBody;
773
+ }
774
+ else {
775
+ checkedForCt = true;
776
+ var lineClone = Array.from(lines);
777
+ var string = lineClone.splice(i).join('\r\n');
778
+ var trimmedStrin = string.trim();
779
+ if (trimmedStrin.indexOf('Content-Type') === 0 || trimmedStrin.indexOf('Content-type') === 0) {
780
+ insideBody = false;
781
+ ctInBody = true;
782
+ }
783
+ else {
784
+ console.warn('Warning: undefined Content-Type');
785
+ }
786
+ }
787
+ }
788
+ else if (/^multipart\//g.test(ct)) {
789
+ var b = getBoundary(ct);
790
+ if (b && b.length) {
791
+ findBoundary = b;
792
+ isMultipart = true;
793
+ parent.body = [];
794
+ }
795
+ }
796
+ continue;
797
+ }
798
+ //Header value with new line
799
+ var match = /^\s+([^\r\n]+)/g.exec(line);
800
+ if (match) {
801
+ if (isMultiHeader) {
802
+ parent.headers[lastHeaderName][parent.headers[lastHeaderName].length - 1] += '\r\n' + match[1];
803
+ }
804
+ else {
805
+ parent.headers[lastHeaderName] += '\r\n' + match[1];
806
+ }
807
+ continue;
808
+ }
809
+ //Header name and value
810
+ match = /^([\w\d\-]+):\s*([^\r\n]*)/gi.exec(line);
811
+ if (match) {
812
+ lastHeaderName = match[1];
813
+ if (parent.headers[lastHeaderName]) {
814
+ //Multiple headers with the same name
815
+ isMultiHeader = true;
816
+ if (typeof parent.headers[lastHeaderName] == 'string') {
817
+ parent.headers[lastHeaderName] = [parent.headers[lastHeaderName]];
818
+ }
819
+ parent.headers[lastHeaderName].push(match[2]);
820
+ }
821
+ else {
822
+ //Header first appeared here
823
+ isMultiHeader = false;
824
+ parent.headers[lastHeaderName] = match[2];
825
+ }
826
+ continue;
827
+ }
828
+ }
829
+ //Body
830
+ else {
831
+ //Multipart body
832
+ if (isMultipart) {
833
+ //Search for boundary start
834
+ //Updated on 2019-10-12: A line before the boundary marker is not required to be an empty line
835
+ //if (lines[i - 1] == "" && line.indexOf("--" + findBoundary) == 0 && !/\-\-(\r?\n)?$/g.test(line)) {
836
+ if (line.indexOf('--' + findBoundary) == 0 && !/\-\-(\r?\n)?$/g.test(line)) {
837
+ insideBoundary = true;
838
+ //Complete the previous boundary
839
+ if (boundary && boundary.lines) {
840
+ complete(boundary);
841
+ }
842
+ //Start a new boundary
843
+ var match = /^\-\-([^\r\n]+)(\r?\n)?$/g.exec(line);
844
+ boundary = { boundary: match[1], lines: [] };
845
+ parent.body.push(boundary);
846
+ continue;
847
+ }
848
+ if (insideBoundary) {
849
+ //Search for boundary end
850
+ if ((boundary === null || boundary === void 0 ? void 0 : boundary.boundary) && lines[i - 1] == '' && line.indexOf('--' + findBoundary + '--') == 0) {
851
+ insideBoundary = false;
852
+ complete(boundary);
853
+ continue;
854
+ }
855
+ if ((boundary === null || boundary === void 0 ? void 0 : boundary.boundary) && line.indexOf('--' + findBoundary + '--') == 0) {
856
+ continue;
857
+ }
858
+ boundary === null || boundary === void 0 ? void 0 : boundary.lines.push(line);
859
+ }
860
+ }
861
+ else {
862
+ //Solid string body
863
+ parent.body = lines.splice(i).join('\r\n');
864
+ break;
865
+ }
866
+ }
867
+ }
868
+ //Complete the last boundary
869
+ if (parent.body && parent.body.length && parent.body[parent.body.length - 1].lines) {
870
+ complete(parent.body[parent.body.length - 1]);
871
+ }
872
+ return parent;
873
+ }
874
+ /**
875
+ * Convert BoundaryRawData to BoundaryConvertedData
876
+ * @param {BoundaryRawData} boundary
877
+ * @returns {BoundaryConvertedData} Obj
878
+ */
879
+ function completeBoundary(boundary) {
880
+ if (!boundary || !boundary.boundary) {
881
+ return null;
882
+ }
883
+ var lines = boundary.lines || [];
884
+ var result = {
885
+ boundary: boundary.boundary,
886
+ part: {
887
+ headers: {},
888
+ },
889
+ };
890
+ var lastHeaderName = '';
891
+ var insideBody = false;
892
+ var childBoundary;
893
+ for (var index = 0; index < lines.length; index++) {
894
+ var line = lines[index];
895
+ if (!insideBody) {
896
+ if (line === '') {
897
+ insideBody = true;
898
+ continue;
899
+ }
900
+ var match = /^([\w\d\-]+):\s*([^\r\n]*)/gi.exec(line);
901
+ if (match) {
902
+ lastHeaderName = match[1];
903
+ result.part.headers[lastHeaderName] = match[2];
904
+ continue;
905
+ }
906
+ //Header value with new line
907
+ var lineMatch = /^\s+([^\r\n]+)/g.exec(line);
908
+ if (lineMatch) {
909
+ result.part.headers[lastHeaderName] += '\r\n' + lineMatch[1];
910
+ continue;
911
+ }
912
+ }
913
+ else {
914
+ // part.body
915
+ var match = /^\-\-([^\r\n]+)(\r?\n)?$/g.exec(line);
916
+ var childBoundaryStr = getBoundary(result.part.headers['Content-Type'] || result.part.headers['Content-type']);
917
+ if (match && line.indexOf('--' + childBoundaryStr) === 0 && !childBoundary) {
918
+ childBoundary = { boundary: match ? match[1] : '', lines: [] };
919
+ continue;
920
+ }
921
+ else if (!!childBoundary && childBoundary.boundary) {
922
+ if (lines[index - 1] === '' && line.indexOf('--' + childBoundary.boundary) === 0) {
923
+ var child = completeBoundary(childBoundary);
924
+ if (child) {
925
+ if (Array.isArray(result.part.body)) {
926
+ result.part.body.push(child);
927
+ }
928
+ else {
929
+ result.part.body = [child];
930
+ }
931
+ }
932
+ else {
933
+ result.part.body = childBoundary.lines.join('\r\n');
934
+ }
935
+ // next line child
936
+ if (!!lines[index + 1]) {
937
+ childBoundary.lines = [];
938
+ continue;
939
+ }
940
+ // end line child And this boundary's end
941
+ if (line.indexOf('--' + childBoundary.boundary + '--') === 0 && lines[index + 1] === '') {
942
+ childBoundary = undefined;
943
+ break;
944
+ }
945
+ }
946
+ childBoundary.lines.push(line);
947
+ }
948
+ else {
949
+ result.part.body = lines.splice(index).join('\r\n');
950
+ break;
951
+ }
952
+ }
953
+ }
954
+ return result;
955
+ }
956
+ /**
957
+ * buid EML file by ReadedEmlJson or EML file content
958
+ * @param {ReadedEmlJson} data
959
+ * @param {BuildOptions | CallbackFn<string> | null} options
960
+ * @param {CallbackFn<string>} callback
961
+ */
962
+ function build(data, options, callback) {
963
+ //Shift arguments
964
+ if (typeof options === 'function' && typeof callback === 'undefined') {
965
+ callback = options;
966
+ options = null;
967
+ }
968
+ var error;
969
+ var eml = '';
970
+ var EOL = '\r\n'; //End-of-line
971
+ try {
972
+ if (!data) {
973
+ throw new Error('Argument "data" expected to be an object! or string');
974
+ }
975
+ if (typeof data === 'string') {
976
+ var readResult = read(data);
977
+ if (typeof readResult === 'string') {
978
+ throw new Error(readResult);
979
+ }
980
+ else if (readResult instanceof Error) {
981
+ throw readResult;
982
+ }
983
+ else {
984
+ data = readResult;
985
+ }
986
+ }
987
+ if (!data.headers) {
988
+ throw new Error('Argument "data" expected to be has headers');
989
+ }
990
+ if (typeof data.subject === 'string') {
991
+ data.headers['Subject'] = data.subject;
992
+ }
993
+ if (typeof data.from !== 'undefined') {
994
+ data.headers['From'] = toEmailAddress(data.from);
995
+ }
996
+ if (typeof data.to !== 'undefined') {
997
+ data.headers['To'] = toEmailAddress(data.to);
998
+ }
999
+ if (typeof data.cc !== 'undefined') {
1000
+ data.headers['Cc'] = toEmailAddress(data.cc);
1001
+ }
1002
+ // if (!data.headers['To']) {
1003
+ // throw new Error('Missing "To" e-mail address!');
1004
+ // }
1005
+ var emlBoundary = getBoundary(data.headers['Content-Type'] || data.headers['Content-type'] || '');
1006
+ var hasBoundary = false;
1007
+ var boundary = createBoundary();
1008
+ var multipartBoundary = '';
1009
+ if (data.multipartAlternative) {
1010
+ multipartBoundary = '' + (getBoundary(data.multipartAlternative['Content-Type']) || '');
1011
+ hasBoundary = true;
1012
+ }
1013
+ if (emlBoundary) {
1014
+ boundary = emlBoundary;
1015
+ hasBoundary = true;
1016
+ }
1017
+ else {
1018
+ data.headers['Content-Type'] = data.headers['Content-type'] || 'multipart/mixed;' + EOL + 'boundary="' + boundary + '"';
1019
+ // Restrained
1020
+ // hasBoundary = true;
1021
+ }
1022
+ //Build headers
1023
+ var keys = Object.keys(data.headers);
1024
+ for (var i = 0; i < keys.length; i++) {
1025
+ var key = keys[i];
1026
+ var value = data.headers[key];
1027
+ if (typeof value === 'undefined') {
1028
+ continue; //Skip missing headers
1029
+ }
1030
+ else if (typeof value === 'string') {
1031
+ eml += key + ': ' + value.replace(/\r?\n/g, EOL + ' ') + EOL;
1032
+ }
1033
+ else {
1034
+ //Array
1035
+ for (var j = 0; j < value.length; j++) {
1036
+ eml += key + ': ' + value[j].replace(/\r?\n/g, EOL + ' ') + EOL;
1037
+ }
1038
+ }
1039
+ }
1040
+ if (data.multipartAlternative) {
1041
+ eml += EOL;
1042
+ eml += '--' + emlBoundary + EOL;
1043
+ eml += 'Content-Type: ' + data.multipartAlternative['Content-Type'].replace(/\r?\n/g, EOL + ' ') + EOL;
1044
+ }
1045
+ //Start the body
1046
+ eml += EOL;
1047
+ //Plain text content
1048
+ if (data.text) {
1049
+ // Encode opened and self headers keeped
1050
+ if (typeof options === 'object' && !!options && options.encode && data.textheaders) {
1051
+ eml += '--' + boundary + EOL;
1052
+ for (var key in data.textheaders) {
1053
+ if (data.textheaders.hasOwnProperty(key)) {
1054
+ eml += key + ": " + data.textheaders[key].replace(/\r?\n/g, EOL + ' ');
1055
+ }
1056
+ }
1057
+ }
1058
+ else if (hasBoundary) {
1059
+ // else Assembly
1060
+ eml += '--' + (multipartBoundary ? multipartBoundary : boundary) + EOL;
1061
+ eml += 'Content-Type: text/plain; charset="utf-8"' + EOL;
1062
+ }
1063
+ eml += EOL + data.text;
1064
+ eml += EOL;
1065
+ }
1066
+ //HTML content
1067
+ if (data.html) {
1068
+ // Encode opened and self headers keeped
1069
+ if (typeof options === 'object' && !!options && options.encode && data.textheaders) {
1070
+ eml += '--' + boundary + EOL;
1071
+ for (var key in data.textheaders) {
1072
+ if (data.textheaders.hasOwnProperty(key)) {
1073
+ eml += key + ": " + data.textheaders[key].replace(/\r?\n/g, EOL + ' ');
1074
+ }
1075
+ }
1076
+ }
1077
+ else if (hasBoundary) {
1078
+ eml += '--' + (multipartBoundary ? multipartBoundary : boundary) + EOL;
1079
+ eml += 'Content-Type: text/html; charset="utf-8"' + EOL;
1080
+ }
1081
+ if (verbose) {
1082
+ console.info("line 765 " + hasBoundary + ", emlBoundary: " + emlBoundary + ", multipartBoundary: " + multipartBoundary + ", boundary: " + boundary);
1083
+ }
1084
+ eml += EOL + data.html;
1085
+ eml += EOL;
1086
+ }
1087
+ //Append attachments
1088
+ if (data.attachments) {
1089
+ for (var i = 0; i < data.attachments.length; i++) {
1090
+ var attachment = data.attachments[i];
1091
+ eml += '--' + boundary + EOL;
1092
+ eml += 'Content-Type: ' + (attachment.contentType.replace(/\r?\n/g, EOL + ' ') || 'application/octet-stream') + EOL;
1093
+ eml += 'Content-Transfer-Encoding: base64' + EOL;
1094
+ eml +=
1095
+ 'Content-Disposition: ' +
1096
+ (attachment.inline ? 'inline' : 'attachment') +
1097
+ '; filename="' +
1098
+ (attachment.filename || attachment.name || 'attachment_' + (i + 1)) +
1099
+ '"' +
1100
+ EOL;
1101
+ if (attachment.cid) {
1102
+ eml += 'Content-ID: <' + attachment.cid + '>' + EOL;
1103
+ }
1104
+ eml += EOL;
1105
+ if (typeof attachment.data === 'string') {
1106
+ var content = jsBase64.Base64.toBase64(attachment.data);
1107
+ eml += wrap(content, 72) + EOL;
1108
+ }
1109
+ else {
1110
+ //Buffer
1111
+ // Uint8Array to string by new TextEncoder
1112
+ var content = decode(attachment.data);
1113
+ eml += wrap(content, 72) + EOL;
1114
+ }
1115
+ eml += EOL;
1116
+ }
1117
+ }
1118
+ //Finish the boundary
1119
+ if (hasBoundary) {
1120
+ eml += '--' + boundary + '--' + EOL;
1121
+ }
1122
+ }
1123
+ catch (e) {
1124
+ error = e;
1125
+ }
1126
+ callback && callback(error, eml);
1127
+ return error || eml;
1128
+ }
1129
+ /**
1130
+ * Parses EML file content and return user-friendly object.
1131
+ * @param {String | ParsedEmlJson} eml EML file content or object from 'parse'
1132
+ * @param { OptionOrNull | CallbackFn<ReadedEmlJson>} options EML parse options
1133
+ * @param {CallbackFn<ReadedEmlJson>} callback Callback function(error, data)
1134
+ */
1135
+ function read(eml, options, callback) {
1136
+ //Shift arguments
1137
+ if (typeof options === 'function' && typeof callback === 'undefined') {
1138
+ callback = options;
1139
+ options = null;
1140
+ }
1141
+ var error;
1142
+ var result;
1143
+ //Appends the boundary to the result
1144
+ function _append(headers, content, result) {
1145
+ var contentType = headers['Content-Type'] || headers['Content-type'];
1146
+ var contentDisposition = headers['Content-Disposition'];
1147
+ var charset = getCharsetName(getCharset(contentType) || defaultCharset);
1148
+ var encoding = headers['Content-Transfer-Encoding'] || headers['Content-transfer-encoding'];
1149
+ if (typeof encoding === 'string') {
1150
+ encoding = encoding.toLowerCase();
1151
+ }
1152
+ if (encoding === 'base64') {
1153
+ if (contentType && contentType.indexOf('gbk') >= 0) {
1154
+ // is work? I'm not sure
1155
+ content = encode(GB2312UTF8.GB2312ToUTF8(content.replace(/\r?\n/g, '')));
1156
+ }
1157
+ else {
1158
+ // string to Uint8Array by TextEncoder
1159
+ content = encode(content.replace(/\r?\n/g, ''));
1160
+ }
1161
+ }
1162
+ else if (encoding === 'quoted-printable') {
1163
+ content = unquotePrintable(content, charset);
1164
+ }
1165
+ else if (encoding && charset !== 'utf8' && encoding.search(/binary|8bit/) === 0) {
1166
+ //'8bit', 'binary', '8bitmime', 'binarymime'
1167
+ content = decode(content, charset);
1168
+ }
1169
+ if (!contentDisposition && contentType && contentType.indexOf('text/html') >= 0) {
1170
+ if (typeof content !== 'string') {
1171
+ content = decode(content, charset);
1172
+ }
1173
+ var htmlContent = content.replace(/\r\n|(&quot;)/g, '').replace(/\"/g, "\"");
1174
+ try {
1175
+ if (encoding === 'base64') {
1176
+ htmlContent = jsBase64.Base64.decode(htmlContent);
1177
+ }
1178
+ else if (jsBase64.Base64.btoa(jsBase64.Base64.atob(htmlContent)) == htmlContent) {
1179
+ htmlContent = jsBase64.Base64.atob(htmlContent);
1180
+ }
1181
+ }
1182
+ catch (error) {
1183
+ console.error(error);
1184
+ }
1185
+ if (result.html) {
1186
+ result.html += htmlContent;
1187
+ }
1188
+ else {
1189
+ result.html = htmlContent;
1190
+ }
1191
+ result.htmlheaders = {
1192
+ 'Content-Type': contentType,
1193
+ 'Content-Transfer-Encoding': encoding || '',
1194
+ };
1195
+ // self boundary Not used at conversion
1196
+ }
1197
+ else if (!contentDisposition && contentType && contentType.indexOf('text/plain') >= 0) {
1198
+ if (typeof content !== 'string') {
1199
+ content = decode(content, charset);
1200
+ }
1201
+ if (encoding === 'base64') {
1202
+ content = jsBase64.Base64.decode(content);
1203
+ }
1204
+ //Plain text message
1205
+ if (result.text) {
1206
+ result.text += content;
1207
+ }
1208
+ else {
1209
+ result.text = content;
1210
+ }
1211
+ result.textheaders = {
1212
+ 'Content-Type': contentType,
1213
+ 'Content-Transfer-Encoding': encoding || '',
1214
+ };
1215
+ // self boundary Not used at conversion
1216
+ }
1217
+ else {
1218
+ //Get the attachment
1219
+ if (!result.attachments) {
1220
+ result.attachments = [];
1221
+ }
1222
+ var attachment = {};
1223
+ var id = headers['Content-ID'] || headers['Content-Id'];
1224
+ if (id) {
1225
+ attachment.id = id;
1226
+ }
1227
+ var qaaapId = headers['X-Qaap-Object-Id'];
1228
+ if (qaaapId) {
1229
+ attachment.qaapId = qaaapId;
1230
+ }
1231
+ var NameContainer = ['Content-Disposition', 'Content-Type', 'Content-type'];
1232
+ var result_name = void 0;
1233
+ for (var _i = 0, NameContainer_1 = NameContainer; _i < NameContainer_1.length; _i++) {
1234
+ var key = NameContainer_1[_i];
1235
+ var name = headers[key];
1236
+ if (name) {
1237
+ result_name = name
1238
+ .replace(/(\s|'|utf-8|\*[0-9]\*)/g, '')
1239
+ .split(';')
1240
+ .map(function (v) { return /name[\*]?="?(.+?)"?$/gi.exec(v); })
1241
+ .reduce(function (a, b) {
1242
+ if (b && b[1]) {
1243
+ a += b[1];
1244
+ }
1245
+ return a;
1246
+ }, '');
1247
+ if (result_name) {
1248
+ break;
1249
+ }
1250
+ }
1251
+ }
1252
+ if (result_name) {
1253
+ attachment.name = decodeURI(result_name);
1254
+ }
1255
+ var ct = headers['Content-Type'] || headers['Content-type'];
1256
+ if (ct) {
1257
+ attachment.contentType = ct;
1258
+ }
1259
+ var cd = headers['Content-Disposition'];
1260
+ if (cd) {
1261
+ attachment.inline = /^\s*inline/g.test(cd);
1262
+ }
1263
+ attachment.data = content;
1264
+ attachment.data64 = decode(content, charset);
1265
+ result.attachments.push(attachment);
1266
+ }
1267
+ }
1268
+ function _read(data) {
1269
+ if (!data) {
1270
+ return 'no data';
1271
+ }
1272
+ try {
1273
+ var result_1 = {};
1274
+ if (!data.headers) {
1275
+ throw new Error("data does't has headers");
1276
+ }
1277
+ if (data.headers['Date']) {
1278
+ result_1.date = new Date(data.headers['Date']);
1279
+ }
1280
+ if (data.headers['Subject']) {
1281
+ result_1.subject = unquoteString(data.headers['Subject']);
1282
+ }
1283
+ if (data.headers['From']) {
1284
+ result_1.from = getEmailAddress(data.headers['From']);
1285
+ }
1286
+ if (data.headers['To']) {
1287
+ result_1.to = getEmailAddress(data.headers['To']);
1288
+ }
1289
+ if (data.headers['CC']) {
1290
+ result_1.cc = getEmailAddress(data.headers['CC']);
1291
+ }
1292
+ if (data.headers['Cc']) {
1293
+ result_1.cc = getEmailAddress(data.headers['Cc']);
1294
+ }
1295
+ result_1.headers = data.headers;
1296
+ //Content mime type
1297
+ var boundary = null;
1298
+ var ct = data.headers['Content-Type'] || data.headers['Content-type'];
1299
+ if (ct && /^multipart\//g.test(ct)) {
1300
+ var b = getBoundary(ct);
1301
+ if (b && b.length) {
1302
+ boundary = b;
1303
+ }
1304
+ }
1305
+ if (boundary && Array.isArray(data.body)) {
1306
+ for (var i = 0; i < data.body.length; i++) {
1307
+ var boundaryBlock = data.body[i];
1308
+ if (!boundaryBlock) {
1309
+ continue;
1310
+ }
1311
+ //Get the message content
1312
+ if (typeof boundaryBlock.part === 'undefined') {
1313
+ verbose && console.warn('Warning: undefined b.part');
1314
+ }
1315
+ else if (typeof boundaryBlock.part === 'string') {
1316
+ result_1.data = boundaryBlock.part;
1317
+ }
1318
+ else {
1319
+ if (typeof boundaryBlock.part.body === 'undefined') {
1320
+ verbose && console.warn('Warning: undefined b.part.body');
1321
+ }
1322
+ else if (typeof boundaryBlock.part.body === 'string') {
1323
+ _append(boundaryBlock.part.headers, boundaryBlock.part.body, result_1);
1324
+ }
1325
+ else {
1326
+ // keep multipart/alternative
1327
+ var currentHeaders = boundaryBlock.part.headers;
1328
+ var currentHeadersContentType = currentHeaders['Content-Type'] || currentHeaders['Content-type'];
1329
+ if (verbose) {
1330
+ console.log("line 969 currentHeadersContentType: " + currentHeadersContentType);
1331
+ }
1332
+ // Hasmore ?
1333
+ if (currentHeadersContentType && currentHeadersContentType.indexOf('multipart') >= 0 && !result_1.multipartAlternative) {
1334
+ result_1.multipartAlternative = {
1335
+ 'Content-Type': currentHeadersContentType,
1336
+ };
1337
+ }
1338
+ for (var j = 0; j < boundaryBlock.part.body.length; j++) {
1339
+ var selfBoundary = boundaryBlock.part.body[j];
1340
+ if (typeof selfBoundary === 'string') {
1341
+ result_1.data = selfBoundary;
1342
+ continue;
1343
+ }
1344
+ var headers = selfBoundary.part.headers;
1345
+ var content = selfBoundary.part.body;
1346
+ if (Array.isArray(content)) {
1347
+ content.forEach(function (bound) {
1348
+ _append(bound.part.headers, bound.part.body, result_1);
1349
+ });
1350
+ }
1351
+ else {
1352
+ _append(headers, content, result_1);
1353
+ }
1354
+ }
1355
+ }
1356
+ }
1357
+ }
1358
+ }
1359
+ else if (typeof data.body === 'string') {
1360
+ _append(data.headers, data.body, result_1);
1361
+ }
1362
+ return result_1;
1363
+ }
1364
+ catch (e) {
1365
+ return e;
1366
+ }
1367
+ }
1368
+ if (typeof eml === 'string') {
1369
+ var parseResult = parse(eml, options);
1370
+ if (typeof parseResult === 'string' || parseResult instanceof Error) {
1371
+ error = parseResult;
1372
+ }
1373
+ else {
1374
+ var readResult = _read(parseResult);
1375
+ if (typeof readResult === 'string' || readResult instanceof Error) {
1376
+ error = readResult;
1377
+ }
1378
+ else {
1379
+ result = readResult;
1380
+ }
1381
+ }
1382
+ }
1383
+ else if (typeof eml === 'object') {
1384
+ var readResult = _read(eml);
1385
+ if (typeof readResult === 'string' || readResult instanceof Error) {
1386
+ error = readResult;
1387
+ }
1388
+ else {
1389
+ result = readResult;
1390
+ }
1391
+ }
1392
+ else {
1393
+ error = new Error('Missing EML file content!');
1394
+ }
1395
+ callback && callback(error, result);
1396
+ return error || result || new Error('read EML failed!');
1397
+ }
1398
+ // const GBKUTF8 = GB2312UTF8;
1399
+ // const parseEml = parse;
1400
+ // const readEml = read;
1401
+ // const buildEml = build;
1402
+
1403
+ Object.defineProperty(exports, 'Base64', {
1404
+ enumerable: true,
1405
+ get: function () {
1406
+ return jsBase64.Base64;
1407
+ }
1408
+ });
1409
+ exports.GBKUTF8 = GB2312UTF8;
1410
+ exports.buildEml = build;
1411
+ exports.completeBoundary = completeBoundary;
1412
+ exports.convert = convert;
1413
+ exports.createBoundary = createBoundary;
1414
+ exports.decode = decode;
1415
+ exports.encode = encode;
1416
+ exports.getBoundary = getBoundary;
1417
+ exports.getCharset = getCharset;
1418
+ exports.getEmailAddress = getEmailAddress;
1419
+ exports.mimeDecode = mimeDecode;
1420
+ exports.parseEml = parse;
1421
+ exports.readEml = read;
1422
+ exports.toEmailAddress = toEmailAddress;
1423
+ exports.unquotePrintable = unquotePrintable;
1424
+ exports.unquoteString = unquoteString;
1425
+
1426
+ return exports;
1427
+
1428
+ }({}, Base64 || (window || this).Base64, {
1429
+ TextEncoder: (window || this)['TextEncoder'],
1430
+ TextDecoder: (window || this)['TextDecoder'],
1431
+ }));