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 +16 -0
- package/README.md +1 -1
- package/lib/charset.js +5 -5
- package/lib/libmime.js +50 -31
- package/package.json +8 -4
- package/.eslintrc +0 -7
- package/.gitattributes +0 -1
- package/.github/FUNDING.yml +0 -4
- package/.github/workflows/release.yaml +0 -37
- package/.github/workflows/test.yml +0 -21
- package/.ncurc.js +0 -9
- package/.prettierrc.js +0 -8
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.
|
|
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}
|
|
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
|
-
|
|
51
|
+
return output;
|
|
52
52
|
}
|
|
53
|
-
|
|
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}
|
|
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}
|
|
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
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
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
|
-
*
|
|
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}
|
|
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
|
|
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
|
|
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}
|
|
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
|
|
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}
|
|
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
|
|
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.
|
|
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.
|
|
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": "
|
|
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": "
|
|
40
|
+
"mocha": "11.7.5"
|
|
37
41
|
}
|
|
38
42
|
}
|
package/.eslintrc
DELETED
package/.gitattributes
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
*.js text eol=lf
|
package/.github/FUNDING.yml
DELETED
|
@@ -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