postal-mime 2.4.1 → 2.4.2

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,12 @@
1
1
  # Changelog
2
2
 
3
+ ## [2.4.2](https://github.com/postalsys/postal-mime/compare/v2.4.1...v2.4.2) (2025-01-24)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * **decodeWords:** Better handling of decoded words ([e0f0047](https://github.com/postalsys/postal-mime/commit/e0f0047b6f97e1251f86f7852eb7935882ead0c1))
9
+
3
10
  ## [2.4.1](https://github.com/postalsys/postal-mime/compare/v2.4.0...v2.4.1) (2025-01-05)
4
11
 
5
12
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "postal-mime",
3
- "version": "2.4.1",
3
+ "version": "2.4.2",
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.6.0",
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",
@@ -155,20 +155,29 @@ export function decodeWord(charset, encoding, str) {
155
155
  }
156
156
 
157
157
  export function decodeWords(str) {
158
- return (
159
- (str || '')
158
+ let joinString = true;
159
+ let done = false;
160
+ while (!done) {
161
+ let result = (str || '')
160
162
  .toString()
161
163
  // find base64 words that can be joined
162
- .replace(/(=\?([^?]+)\?[Bb]\?[^?]*\?=)\s*(?==\?([^?]+)\?[Bb]\?[^?]*\?=)/g, (match, left, chLeft, chRight) => {
163
- // only mark b64 chunks to be joined if charsets match
164
- if (chLeft === chRight) {
164
+ .replace(/(=\?([^?]+)\?[Bb]\?([^?]*)\?=)\s*(?==\?([^?]+)\?[Bb]\?[^?]*\?=)/g, (match, left, chLeft, encodedLeftStr, chRight) => {
165
+ if (!joinString) {
166
+ return match;
167
+ }
168
+ // only mark b64 chunks to be joined if charsets match and left side does not end with =
169
+ if (chLeft === chRight && encodedLeftStr.length % 4 === 0 && !/=$/.test(encodedLeftStr)) {
165
170
  // set a joiner marker
166
171
  return left + '__\x00JOIN\x00__';
167
172
  }
173
+
168
174
  return match;
169
175
  })
170
176
  // find QP words that can be joined
171
177
  .replace(/(=\?([^?]+)\?[Qq]\?[^?]*\?=)\s*(?==\?([^?]+)\?[Qq]\?[^?]*\?=)/g, (match, left, chLeft, chRight) => {
178
+ if (!joinString) {
179
+ return match;
180
+ }
172
181
  // only mark QP chunks to be joined if charsets match
173
182
  if (chLeft === chRight) {
174
183
  // set a joiner marker
@@ -181,8 +190,15 @@ export function decodeWords(str) {
181
190
  // remove spaces between mime encoded words
182
191
  .replace(/(=\?[^?]+\?[QqBb]\?[^?]*\?=)\s+(?==\?[^?]+\?[QqBb]\?[^?]*\?=)/g, '$1')
183
192
  // decode words
184
- .replace(/=\?([\w_\-*]+)\?([QqBb])\?([^?]*)\?=/g, (m, charset, encoding, text) => decodeWord(charset, encoding, text))
185
- );
193
+ .replace(/=\?([\w_\-*]+)\?([QqBb])\?([^?]*)\?=/g, (m, charset, encoding, text) => decodeWord(charset, encoding, text));
194
+
195
+ if (joinString && result.indexOf('\ufffd') >= 0) {
196
+ // text contains \ufffd (EF BF BD), so unicode conversion failed, retry without joining strings
197
+ joinString = false;
198
+ } else {
199
+ return result;
200
+ }
201
+ }
186
202
  }
187
203
 
188
204
  export function decodeURIComponentWithCharset(encodedStr, charset) {