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