libmime 5.3.6 → 5.3.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # Changelog
2
2
 
3
+ ## [5.3.8](https://github.com/nodemailer/libmime/compare/v5.3.7...v5.3.8) (2026-04-08)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * bump iconv-lite to 0.7.2 and refresh dev tooling ([176bde0](https://github.com/nodemailer/libmime/commit/176bde025f4d1ec1dc61266330ed1d2e11457c2c))
9
+ * charset.decode returns string for Japanese encodings ([c2cff8b](https://github.com/nodemailer/libmime/commit/c2cff8b6833d7c0d50d19bb1a63e8db1685cc866))
10
+
11
+ ## [5.3.7](https://github.com/nodemailer/libmime/compare/v5.3.6...v5.3.7) (2025-06-26)
12
+
13
+
14
+ ### Bug Fixes
15
+
16
+ * performance issue on large inputs to decodeFlowed() ([#25](https://github.com/nodemailer/libmime/issues/25)) ([c893811](https://github.com/nodemailer/libmime/commit/c8938111e212996f0809253eb195ef56778fc4dd))
17
+ * replace .npmignore with files=[] in package.json ([#22](https://github.com/nodemailer/libmime/issues/22)) ([0ae2a1f](https://github.com/nodemailer/libmime/commit/0ae2a1fd830a73a1cdcee295bca94ebfe4a3c051))
18
+
3
19
  ## [5.3.6](https://github.com/nodemailer/libmime/compare/v5.3.5...v5.3.6) (2024-11-29)
4
20
 
5
21
 
package/README.md CHANGED
@@ -200,7 +200,7 @@ Returns content type for a file extension. If no suitable content types are foun
200
200
 
201
201
  **Example**
202
202
 
203
- libmime.detectExtension('logo.jpg') // returns 'image/jpeg'
203
+ libmime.detectMimeType('logo.jpg') // returns 'image/jpeg'
204
204
 
205
205
  ## License
206
206
 
package/lib/charset.js CHANGED
@@ -27,7 +27,7 @@ const charset = (module.exports = {
27
27
  *
28
28
  * @param {Buffer} buf Binary data to be decoded
29
29
  * @param {String} [fromCharset='UTF-8'] Binary data is decoded into string using this charset
30
- * @return {String} Decded string
30
+ * @return {String} Decoded string
31
31
  */
32
32
  decode(buf, fromCharset) {
33
33
  fromCharset = charset.normalizeCharset(fromCharset || 'UTF-8');
@@ -48,9 +48,9 @@ const charset = (module.exports = {
48
48
  type: 'string'
49
49
  });
50
50
  if (typeof output === 'string') {
51
- output = Buffer.from(output);
51
+ return output;
52
52
  }
53
- return output;
53
+ // fall through to iconv-lite if convert returned something unexpected
54
54
  } catch (err) {
55
55
  // ignore, defaults to iconv-lite on error
56
56
  }
@@ -66,7 +66,7 @@ const charset = (module.exports = {
66
66
  /**
67
67
  * Convert a string from specific encoding to UTF-8 Buffer
68
68
  *
69
- * @param {String|Buffer} str String to be encoded
69
+ * @param {String|Buffer} data String or Buffer to be encoded
70
70
  * @param {String} [fromCharset='UTF-8'] Source encoding for the string
71
71
  * @return {Buffer} UTF-8 encoded typed array
72
72
  */
@@ -91,7 +91,7 @@ const charset = (module.exports = {
91
91
  * eg. win-1257 will be converted to WINDOWS-1257
92
92
  *
93
93
  * @param {String} charset Charset name to convert
94
- * @return {String} Canoninicalized charset name
94
+ * @return {String} Canonicalized charset name
95
95
  */
96
96
  normalizeCharset(charset) {
97
97
  charset = charset.toLowerCase().trim();
package/lib/libmime.js CHANGED
@@ -37,6 +37,7 @@ class Libmime {
37
37
  * no need to encode the values in any way. If the value is plaintext but has
38
38
  * longer lines then allowed, then use format=flowed
39
39
  *
40
+ * @param {String} str String to be tested
40
41
  * @param {Number} lineLength Max line length to check for
41
42
  * @returns {Boolean} Returns true if there is at least one line longer than lineLength chars
42
43
  */
@@ -54,28 +55,42 @@ class Libmime {
54
55
  decodeFlowed(str, delSp) {
55
56
  str = (str || '').toString();
56
57
 
57
- return (
58
- str
59
- .split(/\r?\n/)
60
- // remove soft linebreaks
61
- // soft linebreaks are added after space symbols
62
- .reduce((previousValue, currentValue) => {
63
- if (/ $/.test(previousValue) && !/(^|\n)-- $/.test(previousValue)) {
64
- if (delSp) {
65
- // delsp adds space to text to be able to fold it
66
- // these spaces can be removed once the text is unfolded
67
- return previousValue.slice(0, -1) + currentValue;
68
- } else {
69
- return previousValue + currentValue;
70
- }
71
- } else {
72
- return previousValue + '\n' + currentValue;
73
- }
74
- })
75
- // remove whitespace stuffing
76
- // http://tools.ietf.org/html/rfc3676#section-4.4
77
- .replace(/^ /gm, '')
78
- );
58
+ let lines = str.split(/\r?\n/);
59
+
60
+ let result = [],
61
+ buffer = null;
62
+
63
+ // remove soft linebreaks
64
+ // soft linebreaks are added after space symbols
65
+ for (let i = 0; i < lines.length; i++) {
66
+ let line = lines[i];
67
+
68
+ let isSoftBreak = buffer !== null && / $/.test(buffer) && !/(^|\n)-- $/.test(buffer);
69
+
70
+ if (isSoftBreak) {
71
+ if (delSp) {
72
+ // delsp adds space to text to be able to fold it
73
+ // these spaces can be removed once the text is unfolded
74
+ buffer = buffer.slice(0, -1) + line;
75
+ } else {
76
+ buffer += line;
77
+ }
78
+ } else {
79
+ if (buffer !== null) {
80
+ result.push(buffer);
81
+ }
82
+
83
+ buffer = line;
84
+ }
85
+ }
86
+
87
+ if (buffer) {
88
+ result.push(buffer);
89
+ }
90
+
91
+ // remove whitespace stuffing
92
+ // http://tools.ietf.org/html/rfc3676#section-4.4
93
+ return result.join('\n').replace(/^ /gm, '');
79
94
  }
80
95
 
81
96
  /**
@@ -181,9 +196,12 @@ class Libmime {
181
196
  }
182
197
 
183
198
  /**
184
- * Decode a complete mime word encoded string
199
+ * Decodes the inner payload of a single mime encoded-word into a unicode string.
200
+ * Expects the three components of `=?charset?encoding?text?=` already separated.
185
201
  *
186
- * @param {String} str Mime word encoded string
202
+ * @param {String} charset Charset name from the encoded-word (may include an RFC 2231 language tag, which is ignored)
203
+ * @param {String} encoding Encoding indicator, either 'Q' or 'B' (case insensitive)
204
+ * @param {String} str Encoded payload between the second `?` and the trailing `?=`
187
205
  * @return {String} Decoded unicode string
188
206
  */
189
207
  decodeWord(charset, encoding, str) {
@@ -243,7 +261,7 @@ class Libmime {
243
261
  * @param {String|Buffer} data String to be encoded
244
262
  * @param {String} mimeWordEncoding='Q' Encoding for the mime word, either Q or B
245
263
  * @param {Number} [maxLength=0] If set, split mime words into several chunks if needed
246
- * @param {String} [fromCharset='UTF-8'] Source sharacter set
264
+ * @param {String} [fromCharset='UTF-8'] Source character set
247
265
  * @return {String} String with possible mime words
248
266
  */
249
267
  encodeWords(data, mimeWordEncoding, maxLength, fromCharset) {
@@ -286,7 +304,7 @@ class Libmime {
286
304
  /**
287
305
  * Decode a string that might include one or several mime words
288
306
  *
289
- * @param {String} str String including some mime words that will be encoded
307
+ * @param {String} str String including some mime words that will be decoded
290
308
  * @return {String} Decoded unicode string
291
309
  */
292
310
  decodeWords(str) {
@@ -333,7 +351,7 @@ class Libmime {
333
351
  * on the rules for the specific header key
334
352
  *
335
353
  * @param {String} headerLine Single header line, might include linebreaks as well if folded
336
- * @return {Object} And object of {key, value}
354
+ * @return {Object} An object of {key, value}
337
355
  */
338
356
  decodeHeader(headerLine) {
339
357
  let line = (headerLine || '')
@@ -583,9 +601,10 @@ class Libmime {
583
601
  * title*0*=utf-8''unicode
584
602
  * title*1*=%20string
585
603
  *
604
+ * @param {String} key Parameter name (eg. 'filename')
586
605
  * @param {String|Buffer} data String to be encoded
587
606
  * @param {Number} [maxLength=50] Max length for generated chunks
588
- * @param {String} [fromCharset='UTF-8'] Source sharacter set
607
+ * @param {String} [fromCharset='UTF-8'] Source character set
589
608
  * @return {Array} A list of encoded keys and headers
590
609
  */
591
610
  buildHeaderParam(key, data, maxLength, fromCharset) {
@@ -749,8 +768,8 @@ class Libmime {
749
768
  * Returns content type for a file extension. If no suitable content types
750
769
  * are found, 'application/octet-stream' is used as the default content type
751
770
  *
752
- * @param {String} extension Extension to be checked for
753
- * @return {String} File extension
771
+ * @param {String} extension Extension (or filename) to be checked for
772
+ * @return {String} Content type
754
773
  */
755
774
  detectMimeType(extension) {
756
775
  extension = (extension || '').toString().toLowerCase().replace(/\s/g, '').replace(/^\./g, '').split('.').pop();
@@ -783,7 +802,7 @@ class Libmime {
783
802
  *
784
803
  * @param {String} str String to be folded
785
804
  * @param {Number} [lineLength=76] Maximum length of a line
786
- * @param {Boolean} afterSpace If true, leave a space in th end of a line
805
+ * @param {Boolean} afterSpace If true, leave a space in the end of a line
787
806
  * @return {String} String with folded lines
788
807
  */
789
808
  foldLines(str, lineLength, afterSpace) {
package/package.json CHANGED
@@ -1,8 +1,12 @@
1
1
  {
2
2
  "name": "libmime",
3
3
  "description": "Encode and decode quoted printable and base64 strings",
4
- "version": "5.3.6",
4
+ "version": "5.3.8",
5
5
  "main": "lib/libmime.js",
6
+ "files": [
7
+ "lib",
8
+ "CHANGELOG.md"
9
+ ],
6
10
  "homepage": "https://github.com/nodemailer/libmime",
7
11
  "repository": {
8
12
  "type": "git",
@@ -21,18 +25,18 @@
21
25
  },
22
26
  "dependencies": {
23
27
  "encoding-japanese": "2.2.0",
24
- "iconv-lite": "0.6.3",
28
+ "iconv-lite": "0.7.2",
25
29
  "libbase64": "1.3.0",
26
30
  "libqp": "2.1.1"
27
31
  },
28
32
  "devDependencies": {
29
33
  "chai": "4.4.1",
30
34
  "eslint-config-nodemailer": "1.2.0",
31
- "eslint-config-prettier": "9.1.0",
35
+ "eslint-config-prettier": "10.1.8",
32
36
  "grunt": "1.6.1",
33
37
  "grunt-cli": "1.5.0",
34
38
  "grunt-eslint": "24.3.0",
35
39
  "grunt-mocha-test": "0.13.3",
36
- "mocha": "10.8.2"
40
+ "mocha": "11.7.5"
37
41
  }
38
42
  }
package/.eslintrc DELETED
@@ -1,7 +0,0 @@
1
- {
2
- "rules": {
3
- "indent": 0,
4
- "no-prototype-builtins": 0
5
- },
6
- "extends": "nodemailer"
7
- }
package/.gitattributes DELETED
@@ -1 +0,0 @@
1
- *.js text eol=lf
@@ -1,4 +0,0 @@
1
- # These are supported funding model platforms
2
-
3
- github: [andris9] # enable once enrolled
4
- custom: ['https://www.paypal.me/nodemailer']
@@ -1,37 +0,0 @@
1
- on:
2
- push:
3
- branches:
4
- - master
5
-
6
- permissions:
7
- contents: write
8
- pull-requests: write
9
- id-token: write
10
-
11
- name: release
12
- jobs:
13
- release-please:
14
- runs-on: ubuntu-latest
15
- steps:
16
- - uses: google-github-actions/release-please-action@v3
17
- id: release
18
- with:
19
- release-type: node
20
- package-name: ${{vars.NPM_MODULE_NAME}}
21
- pull-request-title-pattern: 'chore${scope}: release ${version} [skip-ci]'
22
- # The logic below handles the npm publication:
23
- - uses: actions/checkout@v4
24
- # these if statements ensure that a publication only occurs when
25
- # a new release is created:
26
- if: ${{ steps.release.outputs.release_created }}
27
- - uses: actions/setup-node@v4
28
- with:
29
- node-version: 20
30
- registry-url: 'https://registry.npmjs.org'
31
- if: ${{ steps.release.outputs.release_created }}
32
- - run: npm ci
33
- if: ${{ steps.release.outputs.release_created }}
34
- - run: npm publish --provenance --access public
35
- env:
36
- NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}}
37
- if: ${{ steps.release.outputs.release_created }}
@@ -1,21 +0,0 @@
1
- name: Run tests
2
-
3
- on:
4
- push:
5
- pull_request:
6
-
7
- jobs:
8
- test:
9
- strategy:
10
- matrix:
11
- node: [16.x, 18.x, 20.x, 21.x]
12
- os: [ubuntu-latest]
13
- runs-on: ${{ matrix.os }}
14
- steps:
15
- - uses: actions/checkout@v2
16
- - name: Use Node.js ${{ matrix.node }}
17
- uses: actions/setup-node@v4
18
- with:
19
- node-version: ${{ matrix.node }}
20
- - run: npm install
21
- - run: npm test
package/.ncurc.js DELETED
@@ -1,9 +0,0 @@
1
- module.exports = {
2
- upgrade: true,
3
- reject: [
4
- // 5x is esm only
5
- 'chai',
6
- // api changes in newer eslint
7
- 'grunt-eslint'
8
- ]
9
- };
package/.prettierrc.js DELETED
@@ -1,8 +0,0 @@
1
- module.exports = {
2
- printWidth: 160,
3
- tabWidth: 4,
4
- singleQuote: true,
5
- endOfLine: 'lf',
6
- trailingComma: 'none',
7
- arrowParens: 'avoid'
8
- };