postal-mime 2.4.1 → 2.4.3
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 +14 -0
- package/package.json +2 -2
- package/src/decode-strings.js +25 -26
- package/src/mime-node.js +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [2.4.3](https://github.com/postalsys/postal-mime/compare/v2.4.2...v2.4.3) (2025-01-24)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
* **TextDecoder:** Do not reuse text decoders to avoid spilling data from one instance to another ([8b1013e](https://github.com/postalsys/postal-mime/commit/8b1013e52c878020b3705a2e702a560114f4c081))
|
|
9
|
+
|
|
10
|
+
## [2.4.2](https://github.com/postalsys/postal-mime/compare/v2.4.1...v2.4.2) (2025-01-24)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### Bug Fixes
|
|
14
|
+
|
|
15
|
+
* **decodeWords:** Better handling of decoded words ([e0f0047](https://github.com/postalsys/postal-mime/commit/e0f0047b6f97e1251f86f7852eb7935882ead0c1))
|
|
16
|
+
|
|
3
17
|
## [2.4.1](https://github.com/postalsys/postal-mime/compare/v2.4.0...v2.4.1) (2025-01-05)
|
|
4
18
|
|
|
5
19
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "postal-mime",
|
|
3
|
-
"version": "2.4.
|
|
3
|
+
"version": "2.4.3",
|
|
4
4
|
"description": "Email parser for browser environments",
|
|
5
5
|
"main": "./src/postal-mime.js",
|
|
6
6
|
"exports": {
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"author": "Andris Reinman",
|
|
29
29
|
"license": "MIT-0",
|
|
30
30
|
"devDependencies": {
|
|
31
|
-
"@types/node": "22.
|
|
31
|
+
"@types/node": "22.10.10",
|
|
32
32
|
"cross-blob": "3.0.2",
|
|
33
33
|
"cross-env": "7.0.3",
|
|
34
34
|
"eslint": "8.57.0",
|
package/src/decode-strings.js
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
export const textEncoder = new TextEncoder();
|
|
2
2
|
|
|
3
|
-
const decoders = new Map();
|
|
4
|
-
|
|
5
3
|
const base64Chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
|
|
6
4
|
|
|
7
5
|
// Use a lookup table to find the index.
|
|
@@ -46,23 +44,7 @@ export function decodeBase64(base64) {
|
|
|
46
44
|
|
|
47
45
|
export function getDecoder(charset) {
|
|
48
46
|
charset = charset || 'utf8';
|
|
49
|
-
|
|
50
|
-
return decoders.get(charset);
|
|
51
|
-
}
|
|
52
|
-
let decoder;
|
|
53
|
-
try {
|
|
54
|
-
decoder = new TextDecoder(charset);
|
|
55
|
-
} catch (err) {
|
|
56
|
-
if (charset === 'utf8') {
|
|
57
|
-
// is this even possible?
|
|
58
|
-
throw err;
|
|
59
|
-
}
|
|
60
|
-
// use default
|
|
61
|
-
return getDecoder();
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
decoders.set(charset, decoder);
|
|
65
|
-
return decoder;
|
|
47
|
+
return new TextDecoder(charset);
|
|
66
48
|
}
|
|
67
49
|
|
|
68
50
|
/**
|
|
@@ -155,20 +137,30 @@ export function decodeWord(charset, encoding, str) {
|
|
|
155
137
|
}
|
|
156
138
|
|
|
157
139
|
export function decodeWords(str) {
|
|
158
|
-
|
|
159
|
-
|
|
140
|
+
let joinString = true;
|
|
141
|
+
let done = false;
|
|
142
|
+
|
|
143
|
+
while (!done) {
|
|
144
|
+
let result = (str || '')
|
|
160
145
|
.toString()
|
|
161
146
|
// find base64 words that can be joined
|
|
162
|
-
.replace(/(=\?([^?]+)\?[Bb]\?[^?]
|
|
163
|
-
|
|
164
|
-
|
|
147
|
+
.replace(/(=\?([^?]+)\?[Bb]\?([^?]*)\?=)\s*(?==\?([^?]+)\?[Bb]\?[^?]*\?=)/g, (match, left, chLeft, encodedLeftStr, chRight) => {
|
|
148
|
+
if (!joinString) {
|
|
149
|
+
return match;
|
|
150
|
+
}
|
|
151
|
+
// only mark b64 chunks to be joined if charsets match and left side does not end with =
|
|
152
|
+
if (chLeft === chRight && encodedLeftStr.length % 4 === 0 && !/=$/.test(encodedLeftStr)) {
|
|
165
153
|
// set a joiner marker
|
|
166
154
|
return left + '__\x00JOIN\x00__';
|
|
167
155
|
}
|
|
156
|
+
|
|
168
157
|
return match;
|
|
169
158
|
})
|
|
170
159
|
// find QP words that can be joined
|
|
171
160
|
.replace(/(=\?([^?]+)\?[Qq]\?[^?]*\?=)\s*(?==\?([^?]+)\?[Qq]\?[^?]*\?=)/g, (match, left, chLeft, chRight) => {
|
|
161
|
+
if (!joinString) {
|
|
162
|
+
return match;
|
|
163
|
+
}
|
|
172
164
|
// only mark QP chunks to be joined if charsets match
|
|
173
165
|
if (chLeft === chRight) {
|
|
174
166
|
// set a joiner marker
|
|
@@ -181,8 +173,15 @@ export function decodeWords(str) {
|
|
|
181
173
|
// remove spaces between mime encoded words
|
|
182
174
|
.replace(/(=\?[^?]+\?[QqBb]\?[^?]*\?=)\s+(?==\?[^?]+\?[QqBb]\?[^?]*\?=)/g, '$1')
|
|
183
175
|
// decode words
|
|
184
|
-
.replace(/=\?([\w_\-*]+)\?([QqBb])\?([^?]*)\?=/g, (m, charset, encoding, text) => decodeWord(charset, encoding, text))
|
|
185
|
-
|
|
176
|
+
.replace(/=\?([\w_\-*]+)\?([QqBb])\?([^?]*)\?=/g, (m, charset, encoding, text) => decodeWord(charset, encoding, text));
|
|
177
|
+
|
|
178
|
+
if (joinString && result.indexOf('\ufffd') >= 0) {
|
|
179
|
+
// text contains \ufffd (EF BF BD), so unicode conversion failed, retry without joining strings
|
|
180
|
+
joinString = false;
|
|
181
|
+
} else {
|
|
182
|
+
return result;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
186
185
|
}
|
|
187
186
|
|
|
188
187
|
export function decodeURIComponentWithCharset(encodedStr, charset) {
|