@nocobase/plugin-workflow-mailer 2.2.16 → 2.2.18

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 (53) hide show
  1. package/dist/externalVersion.js +6 -6
  2. package/dist/node_modules/joi/dist/joi-browser.min.js +1 -1
  3. package/dist/node_modules/joi/lib/index.js +1 -1
  4. package/dist/node_modules/joi/lib/messages.js +35 -6
  5. package/dist/node_modules/joi/lib/types/keys.js +18 -1
  6. package/dist/node_modules/joi/lib/types/link.js +18 -2
  7. package/dist/node_modules/joi/lib/types/string.js +2 -2
  8. package/dist/node_modules/joi/package.json +1 -1
  9. package/dist/node_modules/nodemailer/.ncurc.js +2 -0
  10. package/dist/node_modules/nodemailer/.prettierignore +8 -0
  11. package/dist/node_modules/nodemailer/.prettierrc +12 -0
  12. package/dist/node_modules/nodemailer/.prettierrc.js +2 -0
  13. package/dist/node_modules/nodemailer/.release-please-config.json +9 -0
  14. package/dist/node_modules/nodemailer/eslint.config.js +88 -0
  15. package/dist/node_modules/nodemailer/lib/addressparser/index.js +314 -71
  16. package/dist/node_modules/nodemailer/lib/base64/index.js +9 -13
  17. package/dist/node_modules/nodemailer/lib/dkim/index.js +17 -18
  18. package/dist/node_modules/nodemailer/lib/dkim/message-parser.js +12 -13
  19. package/dist/node_modules/nodemailer/lib/dkim/relaxed-body.js +3 -3
  20. package/dist/node_modules/nodemailer/lib/dkim/sign.js +22 -18
  21. package/dist/node_modules/nodemailer/lib/errors.js +59 -0
  22. package/dist/node_modules/nodemailer/lib/fetch/cookies.js +14 -19
  23. package/dist/node_modules/nodemailer/lib/fetch/index.js +164 -27
  24. package/dist/node_modules/nodemailer/lib/json-transport/index.js +4 -4
  25. package/dist/node_modules/nodemailer/lib/mail-composer/index.js +229 -155
  26. package/dist/node_modules/nodemailer/lib/mailer/index.js +106 -54
  27. package/dist/node_modules/nodemailer/lib/mailer/mail-message.js +106 -68
  28. package/dist/node_modules/nodemailer/lib/mime-funcs/index.js +105 -59
  29. package/dist/node_modules/nodemailer/lib/mime-funcs/mime-types.js +21 -14
  30. package/dist/node_modules/nodemailer/lib/mime-node/index.js +389 -137
  31. package/dist/node_modules/nodemailer/lib/mime-node/last-newline.js +1 -1
  32. package/dist/node_modules/nodemailer/lib/mime-node/le-unix.js +4 -7
  33. package/dist/node_modules/nodemailer/lib/mime-node/le-windows.js +1 -4
  34. package/dist/node_modules/nodemailer/lib/nodemailer.js +1 -1
  35. package/dist/node_modules/nodemailer/lib/punycode/index.js +1 -1
  36. package/dist/node_modules/nodemailer/lib/qp/index.js +33 -22
  37. package/dist/node_modules/nodemailer/lib/sendmail-transport/index.js +54 -44
  38. package/dist/node_modules/nodemailer/lib/ses-transport/index.js +110 -193
  39. package/dist/node_modules/nodemailer/lib/shared/index.js +299 -240
  40. package/dist/node_modules/nodemailer/lib/shared/objects.js +42 -0
  41. package/dist/node_modules/nodemailer/lib/shared/url.js +151 -0
  42. package/dist/node_modules/nodemailer/lib/smtp-connection/data-stream.js +3 -6
  43. package/dist/node_modules/nodemailer/lib/smtp-connection/http-proxy-client.js +50 -19
  44. package/dist/node_modules/nodemailer/lib/smtp-connection/index.js +415 -223
  45. package/dist/node_modules/nodemailer/lib/smtp-pool/index.js +27 -34
  46. package/dist/node_modules/nodemailer/lib/smtp-pool/pool-resource.js +19 -16
  47. package/dist/node_modules/nodemailer/lib/smtp-transport/index.js +66 -53
  48. package/dist/node_modules/nodemailer/lib/stream-transport/index.js +16 -7
  49. package/dist/node_modules/nodemailer/lib/well-known/index.js +7 -7
  50. package/dist/node_modules/nodemailer/lib/well-known/services.json +328 -38
  51. package/dist/node_modules/nodemailer/lib/xoauth2/index.js +105 -33
  52. package/dist/node_modules/nodemailer/package.json +1 -1
  53. package/package.json +4 -4
@@ -5,21 +5,37 @@
5
5
  const base64 = require('../base64');
6
6
  const qp = require('../qp');
7
7
  const mimeTypes = require('./mime-types');
8
+ const { isProtoKey } = require('../shared/objects');
8
9
 
9
10
  module.exports = {
10
11
  /**
11
12
  * Checks if a value is plaintext string (uses only printable 7bit chars)
12
13
  *
14
+ * When isParam is set the value is destined for a header parameter, so HT, CR and LF
15
+ * are not plaintext either: a header parameter has no way to carry them. HT is a valid
16
+ * fold point, so folding and unfolding a header would rewrite it as a space, and CR/LF
17
+ * cannot appear in a header value at all. DEL is neither a token character nor qtext,
18
+ * so it can not be carried bare or quoted. Such values have to go through the rfc2231
19
+ * parameter continuation encoding instead, the same way a quote already does.
20
+ *
13
21
  * @param {String} value String to be tested
22
+ * @param {Boolean} [isParam] Set to true if the value is a header parameter value
14
23
  * @returns {Boolean} true if it is a plaintext string
15
24
  */
16
25
  isPlainText(value, isParam) {
17
- const re = isParam ? /[\x00-\x08\x0b\x0c\x0e-\x1f"\u0080-\uFFFF]/ : /[\x00-\x08\x0b\x0c\x0e-\x1f\u0080-\uFFFF]/;
18
- if (typeof value !== 'string' || re.test(value)) {
19
- return false;
20
- } else {
21
- return true;
22
- }
26
+ const re = isParam ? /[\x00-\x1f\x7f"\u0080-\uFFFF]/ : /[\x00-\x08\x0b\x0c\x0e-\x1f\u0080-\uFFFF]/;
27
+ return typeof value === 'string' && !re.test(value);
28
+ },
29
+
30
+ /**
31
+ * Wraps a value into a quoted-string. Inside one a quote would end the string early
32
+ * and a backslash would escape whatever follows it, so both go out as quoted-pairs.
33
+ *
34
+ * @param {String} value String to be quoted
35
+ * @returns {String} The value as a quoted-string, quotes included
36
+ */
37
+ quoteString(value) {
38
+ return '"' + (value || '').toString().replace(/["\\]/g, '\\$&') + '"';
23
39
  },
24
40
 
25
41
  /**
@@ -54,7 +70,7 @@ module.exports = {
54
70
  maxLength = maxLength || 0;
55
71
 
56
72
  let encodedStr;
57
- let toCharset = 'UTF-8';
73
+ const toCharset = 'UTF-8';
58
74
 
59
75
  if (maxLength && maxLength > 7 + toCharset.length) {
60
76
  maxLength -= 7 + toCharset.length;
@@ -63,12 +79,11 @@ module.exports = {
63
79
  if (mimeWordEncoding === 'Q') {
64
80
  // https://tools.ietf.org/html/rfc2047#section-5 rule (3)
65
81
  encodedStr = qp.encode(data).replace(/[^a-z0-9!*+\-/=]/gi, chr => {
66
- let ord = chr.charCodeAt(0).toString(16).toUpperCase();
82
+ const ord = chr.charCodeAt(0).toString(16).toUpperCase();
67
83
  if (chr === ' ') {
68
84
  return '_';
69
- } else {
70
- return '=' + (ord.length === 1 ? '0' + ord : ord);
71
85
  }
86
+ return '=' + (ord.length === 1 ? '0' + ord : ord);
72
87
  });
73
88
  } else if (mimeWordEncoding === 'B') {
74
89
  encodedStr = typeof data === 'string' ? data : base64.encode(data);
@@ -80,13 +95,15 @@ module.exports = {
80
95
  encodedStr = this.splitMimeEncodedString(encodedStr, maxLength).join('?= =?' + toCharset + '?' + mimeWordEncoding + '?');
81
96
  } else {
82
97
  // RFC2047 6.3 (2) states that encoded-word must include an integral number of characters, so no chopping unicode sequences
83
- let parts = [];
98
+ const parts = [];
84
99
  let lpart = '';
85
100
  for (let i = 0, len = encodedStr.length; i < len; i++) {
86
101
  let chr = encodedStr.charAt(i);
87
102
 
88
- if (/[\ud83c\ud83d\ud83e]/.test(chr) && i < len - 1) {
89
- // composite emoji byte, so add the next byte as well
103
+ if (/[\ud800-\udbff]/.test(chr) && /[\udc00-\udfff]/.test(encodedStr.charAt(i + 1))) {
104
+ // leading surrogate, so add the trailing surrogate as well
105
+ // an unpaired one must not swallow the next unit, that would destroy
106
+ // a valid pair following it
90
107
  chr += encodedStr.charAt(++i);
91
108
  }
92
109
 
@@ -129,42 +146,38 @@ module.exports = {
129
146
  encodeWords(value, mimeWordEncoding, maxLength, encodeAll) {
130
147
  maxLength = maxLength || 0;
131
148
 
132
- let encodedValue;
133
-
134
149
  // find first word with a non-printable ascii or special symbol in it
135
- let firstMatch = value.match(/(?:^|\s)([^\s]*["\u0080-\uFFFF])/);
150
+ const firstMatch = value.match(/(?:^|\s)([^\s]*["\u0080-\uFFFF])/);
136
151
  if (!firstMatch) {
137
152
  return value;
138
153
  }
139
154
 
140
155
  if (encodeAll) {
141
156
  // if it is requested to encode everything or the string contains something that resebles encoded word, then encode everything
142
-
143
157
  return this.encodeWord(value, mimeWordEncoding, maxLength);
144
158
  }
145
159
 
146
160
  // find the last word with a non-printable ascii in it
147
- let lastMatch = value.match(/(["\u0080-\uFFFF][^\s]*)[^"\u0080-\uFFFF]*$/);
161
+ const lastMatch = value.match(/(["\u0080-\uFFFF][^\s]*)[^"\u0080-\uFFFF]*$/);
148
162
  if (!lastMatch) {
149
163
  // should not happen
150
164
  return value;
151
165
  }
152
166
 
153
- let startIndex =
167
+ const startIndex =
154
168
  firstMatch.index +
155
169
  (
156
170
  firstMatch[0].match(/[^\s]/) || {
157
171
  index: 0
158
172
  }
159
173
  ).index;
160
- let endIndex = lastMatch.index + (lastMatch[1] || '').length;
174
+ const endIndex = lastMatch.index + (lastMatch[1] || '').length;
161
175
 
162
- encodedValue =
176
+ return (
163
177
  (startIndex ? value.substr(0, startIndex) : '') +
164
178
  this.encodeWord(value.substring(startIndex, endIndex), mimeWordEncoding || 'Q', maxLength) +
165
- (endIndex < value.length ? value.substr(endIndex) : '');
166
-
167
- return encodedValue;
179
+ (endIndex < value.length ? value.substr(endIndex) : '')
180
+ );
168
181
  },
169
182
 
170
183
  /**
@@ -175,12 +188,14 @@ module.exports = {
175
188
  * @return {String} joined header value
176
189
  */
177
190
  buildHeaderValue(structured) {
178
- let paramsArray = [];
191
+ const paramsArray = [];
179
192
 
180
- Object.keys(structured.params || {}).forEach(param => {
193
+ Object.keys(structured.params || {}).forEach(key => {
181
194
  // filename might include unicode characters so it is a special case
182
195
  // other values probably do not
183
- let value = structured.params[param];
196
+ const value = structured.params[key];
197
+ // a parameter name is a token too and it is emitted without any quoting around it
198
+ const param = key.replace(/[\x00-\x1f\x7f]/g, '');
184
199
  if (!this.isPlainText(value, true) || value.length >= 75) {
185
200
  this.buildHeaderParam(param, value, 50).forEach(encodedParam => {
186
201
  if (!/[\s"\\;:/=(),<>@[\]?]|^[-']|'$/.test(encodedParam.value) || encodedParam.key.substr(-1) === '*') {
@@ -196,7 +211,11 @@ module.exports = {
196
211
  }
197
212
  });
198
213
 
199
- return structured.value + (paramsArray.length ? '; ' + paramsArray.join('; ') : '');
214
+ // the value ahead of the parameters is a token, it has no way to carry a control
215
+ // char or DEL and there is no quoting construct around it to escape one into
216
+ const value = typeof structured.value === 'string' ? structured.value.replace(/[\x00-\x1f\x7f]/g, '') : structured.value;
217
+
218
+ return value + (paramsArray.length ? '; ' + paramsArray.join('; ') : '');
200
219
  },
201
220
 
202
221
  /**
@@ -215,10 +234,9 @@ module.exports = {
215
234
  * @return {Array} A list of encoded keys and headers
216
235
  */
217
236
  buildHeaderParam(key, data, maxLength) {
218
- let list = [];
237
+ const list = [];
219
238
  let encodedStr = typeof data === 'string' ? data : (data || '').toString();
220
- let encodedStrArr;
221
- let chr, ord;
239
+ let chr;
222
240
  let line;
223
241
  let startPos = 0;
224
242
  let i, len;
@@ -252,11 +270,12 @@ module.exports = {
252
270
  } else {
253
271
  if (/[\uD800-\uDBFF]/.test(encodedStr)) {
254
272
  // string containts surrogate pairs, so normalize it to an array of bytes
255
- encodedStrArr = [];
273
+ const encodedStrArr = [];
256
274
  for (i = 0, len = encodedStr.length; i < len; i++) {
257
275
  chr = encodedStr.charAt(i);
258
- ord = chr.charCodeAt(0);
259
- if (ord >= 0xd800 && ord <= 0xdbff && i < len - 1) {
276
+ if (/[\ud800-\udbff]/.test(chr) && /[\udc00-\udfff]/.test(encodedStr.charAt(i + 1))) {
277
+ // an unpaired leading surrogate must not consume the next unit, that
278
+ // would tear apart a valid pair following it
260
279
  chr += encodedStr.charAt(i + 1);
261
280
  encodedStrArr.push(chr);
262
281
  i++;
@@ -269,7 +288,7 @@ module.exports = {
269
288
 
270
289
  // first line includes the charset and language info and needs to be encoded
271
290
  // even if it does not contain any unicode characters
272
- line = 'utf-8\x27\x27';
291
+ line = "utf-8''";
273
292
  let encoded = true;
274
293
  startPos = 0;
275
294
 
@@ -294,8 +313,11 @@ module.exports = {
294
313
  line,
295
314
  encoded
296
315
  });
316
+ // the line we start here holds an encoded char, so it has to be
317
+ // flagged as one. otherwise it gets an unstarred continuation key
318
+ // and a receiver reads the percent escapes as literal text
297
319
  line = '';
298
- startPos = i - 1;
320
+ encoded = true;
299
321
  } else {
300
322
  encoded = true;
301
323
  i = startPos;
@@ -356,10 +378,20 @@ module.exports = {
356
378
  * @return {Object} Header value as a parsed structure
357
379
  */
358
380
  parseHeaderValue(str) {
359
- let response = {
381
+ const response = {
360
382
  value: false,
361
383
  params: {}
362
384
  };
385
+
386
+ // Parameter names come from a caller supplied contentType/contentDisposition. A
387
+ // "__proto__" name would target the prototype chain of the params object instead of
388
+ // an own property of it, and read back as Object.prototype, so it is dropped.
389
+ const setParam = (name, value) => {
390
+ if (!isProtoKey(name)) {
391
+ response.params[name] = value;
392
+ }
393
+ };
394
+
363
395
  let key = false;
364
396
  let value = '';
365
397
  let type = 'value';
@@ -391,7 +423,7 @@ module.exports = {
391
423
  if (key === false) {
392
424
  response.value = value.trim();
393
425
  } else {
394
- response.params[key] = value.trim();
426
+ setParam(key, value.trim());
395
427
  }
396
428
  type = 'key';
397
429
  value = '';
@@ -406,10 +438,10 @@ module.exports = {
406
438
  if (key === false) {
407
439
  response.value = value.trim();
408
440
  } else {
409
- response.params[key] = value.trim();
441
+ setParam(key, value.trim());
410
442
  }
411
443
  } else if (value.trim()) {
412
- response.params[value.trim().toLowerCase()] = '';
444
+ setParam(value.trim().toLowerCase(), '');
413
445
  }
414
446
 
415
447
  // handle parameter value continuations
@@ -422,6 +454,14 @@ module.exports = {
422
454
  actualKey = key.substr(0, match.index);
423
455
  nr = Number(match[2] || match[3]) || 0;
424
456
 
457
+ if (isProtoKey(actualKey)) {
458
+ // see setParam. Reading it back would yield Object.prototype, which is
459
+ // an object, so the initializer below would be skipped and the write
460
+ // that follows would throw out of a header build the caller can not catch
461
+ delete response.params[key];
462
+ return;
463
+ }
464
+
425
465
  if (!response.params[actualKey] || typeof response.params[actualKey] !== 'object') {
426
466
  response.params[actualKey] = {
427
467
  charset: false,
@@ -458,12 +498,11 @@ module.exports = {
458
498
  value
459
499
  // fix invalidly encoded chars
460
500
  .replace(/[=?_\s]/g, s => {
461
- let c = s.charCodeAt(0).toString(16);
501
+ const c = s.charCodeAt(0).toString(16);
462
502
  if (s === ' ') {
463
503
  return '_';
464
- } else {
465
- return '%' + (c.length < 2 ? '0' : '') + c;
466
504
  }
505
+ return '%' + (c.length < 2 ? '0' : '') + c;
467
506
  })
468
507
  // change from urlencoding to percent encoding
469
508
  .replace(/%/g, '=') +
@@ -508,11 +547,10 @@ module.exports = {
508
547
  str = (str || '').toString();
509
548
  lineLength = lineLength || 76;
510
549
 
511
- let pos = 0,
512
- len = str.length,
513
- result = '',
514
- line,
515
- match;
550
+ let pos = 0;
551
+ const len = str.length;
552
+ let result = '';
553
+ let line, match;
516
554
 
517
555
  while (pos < len) {
518
556
  line = str.substr(pos, lineLength);
@@ -549,11 +587,8 @@ module.exports = {
549
587
  * @return {Array} Split string
550
588
  */
551
589
  splitMimeEncodedString: (str, maxlen) => {
552
- let curLine,
553
- match,
554
- chr,
555
- done,
556
- lines = [];
590
+ const lines = [];
591
+ let curLine, fallbackLine, match, chr, done;
557
592
 
558
593
  // require at least 12 symbols to fit possible 4 octet UTF-8 sequences
559
594
  maxlen = Math.max(maxlen || 0, 12);
@@ -566,8 +601,14 @@ module.exports = {
566
601
  curLine = curLine.substr(0, match.index);
567
602
  }
568
603
 
604
+ // Malformed input (a run of stray UTF-8 continuation bytes) has no split point
605
+ // that keeps a character sequence whole, so the loop below walks back to an
606
+ // empty line looking for one. Keep the widest chunk that at least does not cut
607
+ // a "=XX" escape in half, so the part stays a decodable encoded word.
608
+ fallbackLine = curLine.length ? curLine : str.substr(0, maxlen);
609
+
569
610
  done = false;
570
- while (!done) {
611
+ while (!done && curLine.length) {
571
612
  done = true;
572
613
  // check if not middle of a unicode char sequence
573
614
  if ((match = str.substr(curLine.length).match(/^[=]([0-9A-F]{2})/i))) {
@@ -580,9 +621,11 @@ module.exports = {
580
621
  }
581
622
  }
582
623
 
583
- if (curLine.length) {
584
- lines.push(curLine);
624
+ if (!curLine.length) {
625
+ curLine = fallbackLine;
585
626
  }
627
+
628
+ lines.push(curLine);
586
629
  str = str.substr(curLine.length);
587
630
  }
588
631
 
@@ -614,9 +657,12 @@ module.exports = {
614
657
  try {
615
658
  // might throw if we try to encode invalid sequences, eg. partial emoji
616
659
  str = encodeURIComponent(str);
617
- } catch (E) {
618
- // should never run
619
- return str.replace(/[^\x00-\x1F *'()<>@,;:\\"[\]?=\u007F-\uFFFF]+/g, '');
660
+ } catch (_E) {
661
+ // an unpaired surrogate has no utf-8 representation, so run the value through a
662
+ // utf-8 roundtrip to get the same U+FFFD every other encoder here produces and
663
+ // retry. the value must never come back unencoded, it goes into a header parameter
664
+ // where a bare quote or semicolon would break it out into a parameter of its own
665
+ str = encodeURIComponent(Buffer.from(str, 'utf-8').toString('utf-8'));
620
666
  }
621
667
 
622
668
  // ensure chars that are not handled by encodeURICompent are converted as well
@@ -44,6 +44,7 @@ const mimeTypes = new Map([
44
44
  ['application/fractals', 'fif'],
45
45
  ['application/freeloader', 'frl'],
46
46
  ['application/futuresplash', 'spl'],
47
+ ['application/geo+json', 'geojson'],
47
48
  ['application/gnutar', 'tgz'],
48
49
  ['application/groupwise', 'vew'],
49
50
  ['application/hlp', 'hlp'],
@@ -1101,7 +1102,10 @@ const extensions = new Map([
1101
1102
  ['bdm', 'application/vnd.syncml.dm+wbxml'],
1102
1103
  ['bed', 'application/vnd.realvnc.bed'],
1103
1104
  ['bh2', 'application/vnd.fujitsu.oasysprs'],
1104
- ['bin', ['application/octet-stream', 'application/mac-binary', 'application/macbinary', 'application/x-macbinary', 'application/x-binary']],
1105
+ [
1106
+ 'bin',
1107
+ ['application/octet-stream', 'application/mac-binary', 'application/macbinary', 'application/x-macbinary', 'application/x-binary']
1108
+ ],
1105
1109
  ['bm', 'image/bmp'],
1106
1110
  ['bmi', 'application/vnd.bmi'],
1107
1111
  ['bmp', ['image/bmp', 'image/x-windows-bmp']],
@@ -1146,7 +1150,10 @@ const extensions = new Map([
1146
1150
  ['cii', 'application/vnd.anser-web-certificate-issue-initiation'],
1147
1151
  ['cil', 'application/vnd.ms-artgalry'],
1148
1152
  ['cla', 'application/vnd.claymore'],
1149
- ['class', ['application/octet-stream', 'application/java', 'application/java-byte-code', 'application/java-vm', 'application/x-java-class']],
1153
+ [
1154
+ 'class',
1155
+ ['application/octet-stream', 'application/java', 'application/java-byte-code', 'application/java-vm', 'application/x-java-class']
1156
+ ],
1150
1157
  ['clkk', 'application/vnd.crick.clicker.keyboard'],
1151
1158
  ['clkp', 'application/vnd.crick.clicker.palette'],
1152
1159
  ['clkt', 'application/vnd.crick.clicker.template'],
@@ -1287,6 +1294,7 @@ const extensions = new Map([
1287
1294
  ['gac', 'application/vnd.groove-account'],
1288
1295
  ['gdl', 'model/vnd.gdl'],
1289
1296
  ['geo', 'application/vnd.dynageo'],
1297
+ ['geojson', 'application/geo+json'],
1290
1298
  ['gex', 'application/vnd.geometry-explorer'],
1291
1299
  ['ggb', 'application/vnd.geogebra.file'],
1292
1300
  ['ggt', 'application/vnd.geogebra.tool'],
@@ -1750,7 +1758,10 @@ const extensions = new Map([
1750
1758
  ['sbml', 'application/sbml+xml'],
1751
1759
  ['sc', 'application/vnd.ibm.secure-container'],
1752
1760
  ['scd', 'application/x-msschedule'],
1753
- ['scm', ['application/vnd.lotus-screencam', 'video/x-scm', 'text/x-script.guile', 'application/x-lotusscreencam', 'text/x-script.scheme']],
1761
+ [
1762
+ 'scm',
1763
+ ['application/vnd.lotus-screencam', 'video/x-scm', 'text/x-script.guile', 'application/x-lotusscreencam', 'text/x-script.scheme']
1764
+ ],
1754
1765
  ['scq', 'application/scvp-cv-request'],
1755
1766
  ['scs', 'application/scvp-cv-response'],
1756
1767
  ['sct', 'text/scriptlet'],
@@ -2062,13 +2073,9 @@ module.exports = {
2062
2073
  return defaultMimeType;
2063
2074
  }
2064
2075
 
2065
- let parsed = path.parse(filename);
2066
- let extension = (parsed.ext.substr(1) || parsed.name || '').split('?').shift().trim().toLowerCase();
2067
- let value = defaultMimeType;
2068
-
2069
- if (extensions.has(extension)) {
2070
- value = extensions.get(extension);
2071
- }
2076
+ const parsed = path.parse(filename);
2077
+ const extension = (parsed.ext.substr(1) || parsed.name || '').split('?').shift().trim().toLowerCase();
2078
+ const value = extensions.has(extension) ? extensions.get(extension) : defaultMimeType;
2072
2079
 
2073
2080
  if (Array.isArray(value)) {
2074
2081
  return value[0];
@@ -2080,12 +2087,12 @@ module.exports = {
2080
2087
  if (!mimeType) {
2081
2088
  return defaultExtension;
2082
2089
  }
2083
- let parts = (mimeType || '').toLowerCase().trim().split('/');
2084
- let rootType = parts.shift().trim();
2085
- let subType = parts.join('/').trim();
2090
+ const parts = mimeType.toLowerCase().trim().split('/');
2091
+ const rootType = parts.shift().trim();
2092
+ const subType = parts.join('/').trim();
2086
2093
 
2087
2094
  if (mimeTypes.has(rootType + '/' + subType)) {
2088
- let value = mimeTypes.get(rootType + '/' + subType);
2095
+ const value = mimeTypes.get(rootType + '/' + subType);
2089
2096
  if (Array.isArray(value)) {
2090
2097
  return value[0];
2091
2098
  }