imapflow 1.0.129 → 1.0.130

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.
Files changed (2) hide show
  1. package/lib/tools.js +90 -25
  2. package/package.json +2 -2
package/lib/tools.js CHANGED
@@ -424,13 +424,99 @@ module.exports = {
424
424
  return envelope;
425
425
  },
426
426
 
427
+ getStructuredParams(arr) {
428
+ let key;
429
+
430
+ let params = {};
431
+
432
+ [].concat(arr || []).forEach((val, j) => {
433
+ if (j % 2) {
434
+ params[key] = libmime.decodeWords(((val && val.value) || '').toString());
435
+ } else {
436
+ key = ((val && val.value) || '').toString().toLowerCase();
437
+ }
438
+ });
439
+
440
+ // preprocess values
441
+ Object.keys(params).forEach(key => {
442
+ let actualKey;
443
+ let nr;
444
+ let value;
445
+
446
+ let match = key.match(/\*((\d+)\*?)?$/);
447
+
448
+ if (!match) {
449
+ // nothing to do here, does not seem like a continuation param
450
+ return;
451
+ }
452
+
453
+ actualKey = key.substr(0, match.index).toLowerCase();
454
+ nr = Number(match[2]) || 0;
455
+
456
+ if (!params[actualKey] || typeof params[actualKey] !== 'object') {
457
+ params[actualKey] = {
458
+ charset: false,
459
+ values: []
460
+ };
461
+ }
462
+
463
+ value = params[key];
464
+
465
+ if (nr === 0 && match[0].charAt(match[0].length - 1) === '*' && (match = value.match(/^([^']*)'[^']*'(.*)$/))) {
466
+ params[actualKey].charset = match[1] || 'utf-8';
467
+ value = match[2];
468
+ }
469
+
470
+ params[actualKey].values.push({ nr, value });
471
+
472
+ // remove the old reference
473
+ delete params[key];
474
+ });
475
+
476
+ // concatenate split rfc2231 strings and convert encoded strings to mime encoded words
477
+ Object.keys(params).forEach(key => {
478
+ let value;
479
+ if (params[key] && Array.isArray(params[key].values)) {
480
+ value = params[key].values
481
+ .sort((a, b) => a.nr - b.nr)
482
+ .map(val => (val && val.value) || '')
483
+ .join('');
484
+
485
+ if (params[key].charset) {
486
+ // convert "%AB" to "=?charset?Q?=AB?=" and then to unicode
487
+ params[key] = libmime.decodeWords(
488
+ '=?' +
489
+ params[key].charset +
490
+ '?Q?' +
491
+ value
492
+ // fix invalidly encoded chars
493
+ .replace(/[=?_\s]/g, s => {
494
+ let c = s.charCodeAt(0).toString(16);
495
+ if (s === ' ') {
496
+ return '_';
497
+ } else {
498
+ return '%' + (c.length < 2 ? '0' : '') + c;
499
+ }
500
+ })
501
+ // change from urlencoding to percent encoding
502
+ .replace(/%/g, '=') +
503
+ '?='
504
+ );
505
+ } else {
506
+ params[key] = libmime.decodeWords(value);
507
+ }
508
+ }
509
+ });
510
+
511
+ return params;
512
+ },
513
+
427
514
  parseBodystructure(entry) {
428
515
  let walk = (node, path) => {
429
516
  path = path || [];
430
517
 
431
518
  let curNode = {},
432
519
  i = 0,
433
- key,
434
520
  part = 0;
435
521
 
436
522
  if (path.length) {
@@ -453,14 +539,7 @@ module.exports = {
453
539
  // body parameter parenthesized list
454
540
  if (i < node.length - 1) {
455
541
  if (node[i]) {
456
- curNode.parameters = {};
457
- [].concat(node[i] || []).forEach((val, j) => {
458
- if (j % 2) {
459
- curNode.parameters[key] = libmime.decodeWords(((val && val.value) || '').toString());
460
- } else {
461
- key = ((val && val.value) || '').toString().toLowerCase();
462
- }
463
- });
542
+ curNode.parameters = this.getStructuredParams(node[i]);
464
543
  }
465
544
  i++;
466
545
  }
@@ -470,14 +549,7 @@ module.exports = {
470
549
 
471
550
  // body parameter parenthesized list
472
551
  if (node[i]) {
473
- curNode.parameters = {};
474
- [].concat(node[i] || []).forEach((val, j) => {
475
- if (j % 2) {
476
- curNode.parameters[key] = libmime.decodeWords(((val && val.value) || '').toString());
477
- } else {
478
- key = ((val && val.value) || '').toString().toLowerCase();
479
- }
480
- });
552
+ curNode.parameters = this.getStructuredParams(node[i]);
481
553
  }
482
554
  i++;
483
555
 
@@ -558,14 +630,7 @@ module.exports = {
558
630
  if (Array.isArray(node[i]) && node[i].length) {
559
631
  curNode.disposition = ((node[i][0] || {}).value || '').toString().toLowerCase();
560
632
  if (Array.isArray(node[i][1])) {
561
- curNode.dispositionParameters = {};
562
- [].concat(node[i][1] || []).forEach((val, j) => {
563
- if (j % 2) {
564
- curNode.dispositionParameters[key] = libmime.decodeWords(((val && val.value) || '').toString());
565
- } else {
566
- key = ((val && val.value) || '').toString().toLowerCase();
567
- }
568
- });
633
+ curNode.dispositionParameters = this.getStructuredParams(node[i][1]);
569
634
  }
570
635
  }
571
636
  i++;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "imapflow",
3
- "version": "1.0.129",
3
+ "version": "1.0.130",
4
4
  "description": "IMAP Client for Node",
5
5
  "main": "./lib/imap-flow.js",
6
6
  "scripts": {
@@ -31,7 +31,7 @@
31
31
  "@babel/eslint-plugin": "7.22.5",
32
32
  "@babel/plugin-syntax-class-properties": "7.12.13",
33
33
  "@babel/preset-env": "7.22.5",
34
- "@types/node": "20.3.0",
34
+ "@types/node": "20.3.1",
35
35
  "braintree-jsdoc-template": "3.3.0",
36
36
  "eslint": "8.42.0",
37
37
  "eslint-config-nodemailer": "1.2.0",