@mavogel/awscdk-rootmail 0.1.9 → 0.1.11
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/.jsii +3 -3
- package/lib/rootmail.js +1 -1
- package/lib/ses-receive.js +1 -1
- package/node_modules/@zone-eu/mailsplit/package.json +4 -4
- package/node_modules/he/README.md +38 -80
- package/node_modules/he/bin/he.mjs +165 -0
- package/node_modules/he/package.json +56 -56
- package/node_modules/he/src/data.mjs +3809 -0
- package/node_modules/he/src/he.mjs +254 -0
- package/node_modules/libbase64/CHANGELOG.md +7 -0
- package/node_modules/libbase64/lib/libbase64.js +110 -58
- package/node_modules/libbase64/package.json +1 -1
- package/node_modules/libmime/CHANGELOG.md +7 -0
- package/node_modules/libmime/package.json +2 -2
- package/node_modules/mailparser/.release-please-manifest.json +1 -1
- package/node_modules/mailparser/CHANGELOG.md +7 -0
- package/node_modules/mailparser/package.json +4 -4
- package/package.json +24 -11
- package/renovate.json5 +1 -0
- package/node_modules/he/bin/he +0 -148
- package/node_modules/he/he.js +0 -345
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
/*! https://mths.be/he by @mathias | MIT license */
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
decodeMap,
|
|
5
|
+
decodeMapLegacy,
|
|
6
|
+
decodeMapNumeric,
|
|
7
|
+
encodeMap,
|
|
8
|
+
invalidReferenceCodePoints,
|
|
9
|
+
regexAsciiWhitelist,
|
|
10
|
+
regexAstralSymbols,
|
|
11
|
+
regexBmpWhitelist,
|
|
12
|
+
regexDecode,
|
|
13
|
+
regexEncodeNonAscii,
|
|
14
|
+
regexInvalidRawCodePoint,
|
|
15
|
+
} from './data.mjs';
|
|
16
|
+
|
|
17
|
+
const regexEscape = /["&'<>`]/g;
|
|
18
|
+
const escapeMap = new Map([
|
|
19
|
+
['"', '"'],
|
|
20
|
+
['&', '&'],
|
|
21
|
+
["'", '''],
|
|
22
|
+
['<', '<'],
|
|
23
|
+
// See https://mathiasbynens.be/notes/ambiguous-ampersands: in HTML, the
|
|
24
|
+
// following is not strictly necessary unless it’s part of a tag or an
|
|
25
|
+
// unquoted attribute value. We’re only escaping it to support those
|
|
26
|
+
// situations, and for XML support.
|
|
27
|
+
['>', '>'],
|
|
28
|
+
// In Internet Explorer ≤ 8, the backtick character can be used
|
|
29
|
+
// to break out of (un)quoted attribute values or HTML comments.
|
|
30
|
+
// See http://html5sec.org/#102, http://html5sec.org/#108, and
|
|
31
|
+
// http://html5sec.org/#133.
|
|
32
|
+
['`', '`'],
|
|
33
|
+
]);
|
|
34
|
+
|
|
35
|
+
const regexInvalidEntity = /&#(?:[xX][^a-fA-F0-9]|[^0-9xX])/;
|
|
36
|
+
|
|
37
|
+
/*--------------------------------------------------------------------------*/
|
|
38
|
+
|
|
39
|
+
const has = (object, propertyName) => Object.hasOwn(object, propertyName);
|
|
40
|
+
|
|
41
|
+
const merge = (options, defaults) => {
|
|
42
|
+
if (!options) {
|
|
43
|
+
return defaults;
|
|
44
|
+
}
|
|
45
|
+
const result = {};
|
|
46
|
+
for (const key in defaults) {
|
|
47
|
+
// A `hasOwnProperty` check is not needed here, since only recognized
|
|
48
|
+
// option names are used anyway. Any others are ignored.
|
|
49
|
+
result[key] = has(options, key) ? options[key] : defaults[key];
|
|
50
|
+
}
|
|
51
|
+
return result;
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
const parseError = (message) => {
|
|
55
|
+
throw new Error(`Parse error: ${message}`);
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
// Converts a code point to a symbol, applying the HTML spec’s rules for
|
|
59
|
+
// numeric character references.
|
|
60
|
+
const codePointToSymbol = (codePoint, strict) => {
|
|
61
|
+
if ((codePoint >= 0xd800 && codePoint <= 0xdfff) || codePoint > 0x10ffff) {
|
|
62
|
+
// See issue #4:
|
|
63
|
+
// “Otherwise, if the number is in the range 0xD800 to 0xDFFF or is
|
|
64
|
+
// greater than 0x10FFFF, then this is a parse error. Return a U+FFFD
|
|
65
|
+
// REPLACEMENT CHARACTER.”
|
|
66
|
+
if (strict) {
|
|
67
|
+
parseError('character reference outside the permissible Unicode range');
|
|
68
|
+
}
|
|
69
|
+
return '\uFFFD';
|
|
70
|
+
}
|
|
71
|
+
if (decodeMapNumeric.has(codePoint)) {
|
|
72
|
+
if (strict) {
|
|
73
|
+
parseError('disallowed character reference');
|
|
74
|
+
}
|
|
75
|
+
return decodeMapNumeric.get(codePoint);
|
|
76
|
+
}
|
|
77
|
+
if (strict && invalidReferenceCodePoints.has(codePoint)) {
|
|
78
|
+
parseError('disallowed character reference');
|
|
79
|
+
}
|
|
80
|
+
return String.fromCodePoint(codePoint);
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
const hexEscape = (codePoint) => {
|
|
84
|
+
return `&#x${codePoint.toString(16).toUpperCase()};`;
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
const decEscape = (codePoint) => {
|
|
88
|
+
return `&#${codePoint};`;
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
/*--------------------------------------------------------------------------*/
|
|
92
|
+
|
|
93
|
+
const encode = (string, options) => {
|
|
94
|
+
options = merge(options, encode.options);
|
|
95
|
+
const strict = options.strict;
|
|
96
|
+
if (strict && regexInvalidRawCodePoint.test(string)) {
|
|
97
|
+
parseError('forbidden code point');
|
|
98
|
+
}
|
|
99
|
+
const encodeEverything = options.encodeEverything;
|
|
100
|
+
const useNamedReferences = options.useNamedReferences;
|
|
101
|
+
const allowUnsafeSymbols = options.allowUnsafeSymbols;
|
|
102
|
+
const escapeCodePoint = options.decimal ? decEscape : hexEscape;
|
|
103
|
+
|
|
104
|
+
const escapeBmpSymbol = (symbol) => {
|
|
105
|
+
return escapeCodePoint(symbol.charCodeAt(0));
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
if (encodeEverything) {
|
|
109
|
+
// Encode ASCII symbols.
|
|
110
|
+
string = string.replace(regexAsciiWhitelist, (symbol) => {
|
|
111
|
+
// Use named references if requested & possible.
|
|
112
|
+
if (useNamedReferences && encodeMap.has(symbol)) {
|
|
113
|
+
return `&${encodeMap.get(symbol)};`;
|
|
114
|
+
}
|
|
115
|
+
return escapeBmpSymbol(symbol);
|
|
116
|
+
});
|
|
117
|
+
// Shorten a few escapes that represent two symbols, of which at least one
|
|
118
|
+
// is within the ASCII range.
|
|
119
|
+
if (useNamedReferences) {
|
|
120
|
+
string = string
|
|
121
|
+
.replace(/>\u20D2/g, '>⃒')
|
|
122
|
+
.replace(/<\u20D2/g, '<⃒')
|
|
123
|
+
.replace(/fj/g, 'fj');
|
|
124
|
+
}
|
|
125
|
+
// Encode non-ASCII symbols.
|
|
126
|
+
if (useNamedReferences) {
|
|
127
|
+
// Encode non-ASCII symbols that can be replaced with a named reference.
|
|
128
|
+
string = string.replace(regexEncodeNonAscii, (string) => {
|
|
129
|
+
// Note: there is no need to check `encodeMap.has(string)` here.
|
|
130
|
+
return `&${encodeMap.get(string)};`;
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
// Note: any remaining non-ASCII symbols are handled outside of the `if`.
|
|
134
|
+
} else if (useNamedReferences) {
|
|
135
|
+
// Apply named character references.
|
|
136
|
+
// Encode `<>"'&` using named character references.
|
|
137
|
+
if (!allowUnsafeSymbols) {
|
|
138
|
+
string = string.replace(regexEscape, (string) => {
|
|
139
|
+
// Note: there is no need to check `encodeMap.has(string)` here.
|
|
140
|
+
return `&${encodeMap.get(string)};`;
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
// Shorten escapes that represent two symbols, of which at least one is
|
|
144
|
+
// `<>"'&`.
|
|
145
|
+
string = string
|
|
146
|
+
.replace(/>\u20D2/g, '>⃒')
|
|
147
|
+
.replace(/<\u20D2/g, '<⃒');
|
|
148
|
+
// Encode non-ASCII symbols that can be replaced with a named reference.
|
|
149
|
+
string = string.replace(regexEncodeNonAscii, (string) => {
|
|
150
|
+
// Note: there is no need to check `encodeMap.has(string)` here.
|
|
151
|
+
return `&${encodeMap.get(string)};`;
|
|
152
|
+
});
|
|
153
|
+
} else if (!allowUnsafeSymbols) {
|
|
154
|
+
// Encode `<>"'&` using hexadecimal escapes, now that they’re not handled
|
|
155
|
+
// using named character references.
|
|
156
|
+
string = string.replace(regexEscape, escapeBmpSymbol);
|
|
157
|
+
}
|
|
158
|
+
return (
|
|
159
|
+
string
|
|
160
|
+
// Encode astral symbols.
|
|
161
|
+
.replace(regexAstralSymbols, ($0) => {
|
|
162
|
+
// https://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae
|
|
163
|
+
const high = $0.charCodeAt(0);
|
|
164
|
+
const low = $0.charCodeAt(1);
|
|
165
|
+
const codePoint = (high - 0xd800) * 0x400 + low - 0xdc00 + 0x10000;
|
|
166
|
+
return escapeCodePoint(codePoint);
|
|
167
|
+
})
|
|
168
|
+
// Encode any remaining BMP symbols that are not printable ASCII symbols
|
|
169
|
+
// using a hexadecimal escape.
|
|
170
|
+
.replace(regexBmpWhitelist, escapeBmpSymbol)
|
|
171
|
+
);
|
|
172
|
+
};
|
|
173
|
+
// Expose default options (so they can be overridden globally).
|
|
174
|
+
encode.options = {
|
|
175
|
+
allowUnsafeSymbols: false,
|
|
176
|
+
encodeEverything: false,
|
|
177
|
+
strict: false,
|
|
178
|
+
useNamedReferences: false,
|
|
179
|
+
decimal: false,
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
const decode = (html, options) => {
|
|
183
|
+
options = merge(options, decode.options);
|
|
184
|
+
const strict = options.strict;
|
|
185
|
+
if (strict && regexInvalidEntity.test(html)) {
|
|
186
|
+
parseError('malformed character reference');
|
|
187
|
+
}
|
|
188
|
+
return html.replace(regexDecode, ($0, $1, $2, $3, $4, $5, $6, $7) => {
|
|
189
|
+
if ($1) {
|
|
190
|
+
// Note: there is no need to check `decodeMap.has($1)`.
|
|
191
|
+
return decodeMap.get($1);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
if ($2) {
|
|
195
|
+
// Decode named character references without trailing `;`, e.g. `&`.
|
|
196
|
+
// This is only a parse error if it gets converted to `&`, or if it is
|
|
197
|
+
// followed by `=` in an attribute context.
|
|
198
|
+
const reference = $2;
|
|
199
|
+
const next = $3;
|
|
200
|
+
if (next && options.isAttributeValue) {
|
|
201
|
+
if (strict && next == '=') {
|
|
202
|
+
parseError('`&` did not start a character reference');
|
|
203
|
+
}
|
|
204
|
+
return $0;
|
|
205
|
+
}
|
|
206
|
+
if (strict) {
|
|
207
|
+
parseError(
|
|
208
|
+
'named character reference was not terminated by a semicolon',
|
|
209
|
+
);
|
|
210
|
+
}
|
|
211
|
+
// Note: there is no need to check `decodeMapLegacy.has(reference)`.
|
|
212
|
+
return decodeMapLegacy.get(reference) + (next || '');
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
if ($4) {
|
|
216
|
+
// Decode decimal escapes, e.g. `𝌆`.
|
|
217
|
+
const semicolon = $5;
|
|
218
|
+
if (strict && !semicolon) {
|
|
219
|
+
parseError('character reference was not terminated by a semicolon');
|
|
220
|
+
}
|
|
221
|
+
return codePointToSymbol(parseInt($4, 10), strict);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
if ($6) {
|
|
225
|
+
// Decode hexadecimal escapes, e.g. `𝌆`.
|
|
226
|
+
const semicolon = $7;
|
|
227
|
+
if (strict && !semicolon) {
|
|
228
|
+
parseError('character reference was not terminated by a semicolon');
|
|
229
|
+
}
|
|
230
|
+
return codePointToSymbol(parseInt($6, 16), strict);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// If we’re still here, the ambiguous ampersand group matched; it’s an
|
|
234
|
+
// ambiguous ampersand for sure. https://mths.be/notes/ambiguous-ampersands
|
|
235
|
+
if (strict) {
|
|
236
|
+
parseError('named character reference was not recognized');
|
|
237
|
+
}
|
|
238
|
+
return $0;
|
|
239
|
+
});
|
|
240
|
+
};
|
|
241
|
+
// Expose default options (so they can be overridden globally).
|
|
242
|
+
decode.options = {
|
|
243
|
+
isAttributeValue: false,
|
|
244
|
+
strict: false,
|
|
245
|
+
};
|
|
246
|
+
|
|
247
|
+
const escape = (string) => {
|
|
248
|
+
return string.replace(regexEscape, ($0) => {
|
|
249
|
+
// Note: there is no need to check `escapeMap.has($0)` here.
|
|
250
|
+
return escapeMap.get($0);
|
|
251
|
+
});
|
|
252
|
+
};
|
|
253
|
+
|
|
254
|
+
export { decode, encode, escape, decode as unescape };
|
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.3.2](https://github.com/nodemailer/libbase64/compare/v1.3.1...v1.3.2) (2026-10-04)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
* **encoder:** wrap base64 lines without regular expressions, independent of chunk boundaries ([2c76a48](https://github.com/nodemailer/libbase64/commit/2c76a489f1444600b5645a44c933e159ac8e920f))
|
|
9
|
+
|
|
3
10
|
## [1.3.1](https://github.com/nodemailer/libbase64/compare/v1.3.0...v1.3.1) (2026-09-28)
|
|
4
11
|
|
|
5
12
|
|
|
@@ -45,6 +45,52 @@ function decode(str) {
|
|
|
45
45
|
return Buffer.from(str, 'base64');
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
+
/**
|
|
49
|
+
* Turns a line length option into a whole number of characters, the default for anything unusable
|
|
50
|
+
*/
|
|
51
|
+
function normalizeLineLength(lineLength) {
|
|
52
|
+
lineLength = Math.floor(Number(lineLength));
|
|
53
|
+
return Number.isFinite(lineLength) && lineLength >= 1 ? lineLength : 76;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Splits the bytes of `src` into lines of `lineLength` bytes, each followed by a line break. With
|
|
58
|
+
* `final` set the last line, which may be shorter, gets no line break; otherwise only complete lines
|
|
59
|
+
* are taken and the rest is left for the caller
|
|
60
|
+
*
|
|
61
|
+
* @param {Buffer} src Bytes to wrap
|
|
62
|
+
* @param {Number} lineLength Line length
|
|
63
|
+
* @param {Boolean} final Whether `src` ends the output
|
|
64
|
+
* @returns {Object} `{ output, rest }`: the wrapped bytes and the number of trailing bytes not taken
|
|
65
|
+
*/
|
|
66
|
+
function wrapBuffer(src, lineLength, final) {
|
|
67
|
+
let lines = Math.ceil(src.length / lineLength);
|
|
68
|
+
// the last line waits for more data unless this is the end: whether it gets a line break depends on
|
|
69
|
+
// whether anything follows it
|
|
70
|
+
let complete = Math.max(lines - 1, 0);
|
|
71
|
+
let rest = src.length - complete * lineLength;
|
|
72
|
+
|
|
73
|
+
let output = Buffer.allocUnsafe(complete * (lineLength + 2) + (final ? rest : 0));
|
|
74
|
+
let to = 0;
|
|
75
|
+
for (let from = 0; from < complete * lineLength; from += lineLength) {
|
|
76
|
+
src.copy(output, to, from, from + lineLength);
|
|
77
|
+
to += lineLength;
|
|
78
|
+
output[to++] = 0x0d;
|
|
79
|
+
output[to++] = 0x0a;
|
|
80
|
+
}
|
|
81
|
+
if (final) {
|
|
82
|
+
to += src.copy(output, to, complete * lineLength);
|
|
83
|
+
rest = 0;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (to !== output.length) {
|
|
87
|
+
// never hand out bytes of the unfilled allocation
|
|
88
|
+
throw new Error('Unexpected wrapped length');
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return { output, rest };
|
|
92
|
+
}
|
|
93
|
+
|
|
48
94
|
/**
|
|
49
95
|
* Adds soft line breaks to a base64 string
|
|
50
96
|
*
|
|
@@ -54,12 +100,26 @@ function decode(str) {
|
|
|
54
100
|
*/
|
|
55
101
|
function wrap(str, lineLength) {
|
|
56
102
|
str = (str || '').toString();
|
|
57
|
-
lineLength = lineLength
|
|
103
|
+
lineLength = normalizeLineLength(lineLength);
|
|
58
104
|
|
|
59
105
|
if (str.length <= lineLength) {
|
|
60
106
|
return str;
|
|
61
107
|
}
|
|
62
108
|
|
|
109
|
+
// eslint-disable-next-line no-control-regex
|
|
110
|
+
if (/[^\u0000-\u00ff]|[\r\n]/.test(str) || str.trim() !== str) {
|
|
111
|
+
// not a plain base64 string, keep the line based behaviour for whatever this is
|
|
112
|
+
return legacyWrap(str, lineLength);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
return wrapBuffer(Buffer.from(str, 'latin1'), lineLength, true).output.toString('latin1');
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Line wrapping for input that is not a plain base64 string: line breaks already in the input end a
|
|
120
|
+
* line, and surrounding whitespace is trimmed
|
|
121
|
+
*/
|
|
122
|
+
function legacyWrap(str, lineLength) {
|
|
63
123
|
let result = [];
|
|
64
124
|
let pos = 0;
|
|
65
125
|
let chunkLength = lineLength * 1024;
|
|
@@ -78,9 +138,15 @@ function wrap(str, lineLength) {
|
|
|
78
138
|
/**
|
|
79
139
|
* Creates a transform stream for encoding data to base64 encoding
|
|
80
140
|
*
|
|
141
|
+
* The output is the same as `wrap(encode(input), lineLength)` no matter how the input is split into
|
|
142
|
+
* chunks: every line but the last one ends with a line break, the last one does not
|
|
143
|
+
*
|
|
81
144
|
* @constructor
|
|
82
145
|
* @param {Object} options Stream options
|
|
83
146
|
* @param {Number} [options.lineLength=76] Maximum lenght for lines, set to false to disable wrapping
|
|
147
|
+
* @param {Number} [options.skipStartBytes] Number of output bytes to drop from the start
|
|
148
|
+
* @param {Number} [options.limitOutputBytes] Maximum number of output bytes to emit
|
|
149
|
+
* @param {String} [options.startPadding] Characters to prepend to the first line before wrapping
|
|
84
150
|
*/
|
|
85
151
|
class Encoder extends Transform {
|
|
86
152
|
constructor(options) {
|
|
@@ -89,40 +155,42 @@ class Encoder extends Transform {
|
|
|
89
155
|
this.options = options || {};
|
|
90
156
|
|
|
91
157
|
if (this.options.lineLength !== false) {
|
|
92
|
-
this.options.lineLength =
|
|
158
|
+
this.options.lineLength = normalizeLineLength(this.options.lineLength);
|
|
93
159
|
}
|
|
94
160
|
|
|
95
161
|
this.skipStartBytes = Number(this.options.skipStartBytes) || 0;
|
|
96
|
-
|
|
162
|
+
// `limitOutbutBytes` is the name earlier versions read
|
|
163
|
+
this.limitOutputBytes = Number(this.options.limitOutputBytes || this.options.limitOutbutBytes) || 0;
|
|
97
164
|
|
|
98
|
-
// startPadding can be used together
|
|
165
|
+
// encoded characters of the line that is not complete yet. startPadding can be used together
|
|
166
|
+
// with skipStartBytes
|
|
99
167
|
this._curLine = this.options.startPadding || '';
|
|
100
|
-
|
|
168
|
+
// input bytes that do not make up a complete base64 group yet
|
|
169
|
+
this._remainingBytes = null;
|
|
101
170
|
|
|
102
171
|
this.inputBytes = 0;
|
|
103
172
|
this.outputBytes = 0;
|
|
104
173
|
}
|
|
105
174
|
|
|
106
|
-
_writeChunk(chunk
|
|
175
|
+
_writeChunk(chunk) {
|
|
107
176
|
if (this.skipStartBytes) {
|
|
108
177
|
if (chunk.length <= this.skipStartBytes) {
|
|
109
178
|
this.skipStartBytes -= chunk.length;
|
|
110
179
|
return;
|
|
111
180
|
}
|
|
112
181
|
|
|
113
|
-
chunk = chunk.
|
|
182
|
+
chunk = chunk.subarray(this.skipStartBytes);
|
|
114
183
|
this.skipStartBytes = 0;
|
|
115
184
|
}
|
|
116
185
|
|
|
117
|
-
if (this.
|
|
118
|
-
if (this.outputBytes
|
|
119
|
-
// ignore, can use entire chunk
|
|
120
|
-
} else if (this.outputBytes >= this.limitOutbutBytes) {
|
|
186
|
+
if (this.limitOutputBytes) {
|
|
187
|
+
if (this.outputBytes >= this.limitOutputBytes) {
|
|
121
188
|
// chunks already processed
|
|
122
189
|
return;
|
|
123
|
-
}
|
|
190
|
+
}
|
|
191
|
+
if (this.outputBytes + chunk.length > this.limitOutputBytes) {
|
|
124
192
|
// use partial chunk
|
|
125
|
-
chunk = chunk.
|
|
193
|
+
chunk = chunk.subarray(0, this.limitOutputBytes - this.outputBytes);
|
|
126
194
|
}
|
|
127
195
|
}
|
|
128
196
|
|
|
@@ -130,12 +198,26 @@ class Encoder extends Transform {
|
|
|
130
198
|
this.push(chunk);
|
|
131
199
|
}
|
|
132
200
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
201
|
+
/**
|
|
202
|
+
* Emits the encoded characters `b64` that follow the current line, keeping what can not be emitted
|
|
203
|
+
* yet as the new current line
|
|
204
|
+
*/
|
|
205
|
+
_emit(b64, final) {
|
|
206
|
+
let src = Buffer.from(this._curLine + b64, 'latin1');
|
|
207
|
+
if (!src.length) {
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
if (!this.options.lineLength) {
|
|
212
|
+
this._curLine = '';
|
|
213
|
+
return this._writeChunk(src);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
let { output, rest } = wrapBuffer(src, this.options.lineLength, final);
|
|
217
|
+
this._curLine = rest ? src.toString('latin1', src.length - rest) : '';
|
|
218
|
+
if (output.length) {
|
|
219
|
+
this._writeChunk(output);
|
|
137
220
|
}
|
|
138
|
-
return str;
|
|
139
221
|
}
|
|
140
222
|
|
|
141
223
|
_transform(chunk, encoding, done) {
|
|
@@ -144,58 +226,28 @@ class Encoder extends Transform {
|
|
|
144
226
|
}
|
|
145
227
|
|
|
146
228
|
if (!chunk || !chunk.length) {
|
|
147
|
-
return
|
|
229
|
+
return done();
|
|
148
230
|
}
|
|
149
231
|
|
|
150
232
|
this.inputBytes += chunk.length;
|
|
151
233
|
|
|
152
|
-
if (this._remainingBytes
|
|
234
|
+
if (this._remainingBytes) {
|
|
153
235
|
chunk = Buffer.concat([this._remainingBytes, chunk], this._remainingBytes.length + chunk.length);
|
|
154
|
-
this._remainingBytes =
|
|
236
|
+
this._remainingBytes = null;
|
|
155
237
|
}
|
|
156
238
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
this._remainingBytes = false;
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
let b64 = this._curLine + encode(chunk);
|
|
165
|
-
|
|
166
|
-
if (this.options.lineLength) {
|
|
167
|
-
b64 = this._getWrapped(b64);
|
|
168
|
-
|
|
169
|
-
// remove last line as it is still most probably incomplete
|
|
170
|
-
let lastLF = b64.lastIndexOf('\n');
|
|
171
|
-
if (lastLF < 0) {
|
|
172
|
-
this._curLine = b64;
|
|
173
|
-
b64 = '';
|
|
174
|
-
} else if (lastLF === b64.length - 1) {
|
|
175
|
-
this._curLine = '';
|
|
176
|
-
} else {
|
|
177
|
-
this._curLine = b64.substr(lastLF + 1);
|
|
178
|
-
b64 = b64.substr(0, lastLF + 1);
|
|
179
|
-
}
|
|
239
|
+
let extra = chunk.length % 3;
|
|
240
|
+
if (extra) {
|
|
241
|
+
this._remainingBytes = chunk.subarray(chunk.length - extra);
|
|
242
|
+
chunk = chunk.subarray(0, chunk.length - extra);
|
|
180
243
|
}
|
|
181
244
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
setImmediate(done);
|
|
245
|
+
this._emit(encode(chunk), false);
|
|
246
|
+
done();
|
|
187
247
|
}
|
|
188
248
|
|
|
189
249
|
_flush(done) {
|
|
190
|
-
|
|
191
|
-
this._curLine += encode(this._remainingBytes);
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
if (this._curLine) {
|
|
195
|
-
this._curLine = this._getWrapped(this._curLine, true);
|
|
196
|
-
this._writeChunk(Buffer.from(this._curLine, 'ascii'), true);
|
|
197
|
-
this._curLine = '';
|
|
198
|
-
}
|
|
250
|
+
this._emit(this._remainingBytes ? encode(this._remainingBytes) : '', true);
|
|
199
251
|
done();
|
|
200
252
|
}
|
|
201
253
|
}
|
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [5.4.7](https://github.com/nodemailer/libmime/compare/v5.4.6...v5.4.7) (2026-10-04)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
* **deps:** update libbase64 to 1.3.2 ([889e761](https://github.com/nodemailer/libmime/commit/889e761b34d3d6ce46b80b9a0ab5f92097b8d41f))
|
|
9
|
+
|
|
3
10
|
## [5.4.6](https://github.com/nodemailer/libmime/compare/v5.4.5...v5.4.6) (2026-09-28)
|
|
4
11
|
|
|
5
12
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "libmime",
|
|
3
3
|
"description": "Encode and decode quoted printable and base64 strings",
|
|
4
|
-
"version": "5.4.
|
|
4
|
+
"version": "5.4.7",
|
|
5
5
|
"main": "lib/libmime.js",
|
|
6
6
|
"files": [
|
|
7
7
|
"lib",
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"dependencies": {
|
|
27
27
|
"encoding-japanese": "2.4.0",
|
|
28
28
|
"iconv-lite": "0.7.3",
|
|
29
|
-
"libbase64": "1.3.
|
|
29
|
+
"libbase64": "1.3.2",
|
|
30
30
|
"libqp": "2.1.2"
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [3.9.35](https://github.com/nodemailer/mailparser/compare/v3.9.34...v3.9.35) (2026-10-04)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
* **deps:** update libmime to 5.4.7, mailsplit to 5.4.20 and he to 2.0.0 ([c1d68c2](https://github.com/nodemailer/mailparser/commit/c1d68c2582a01a284afd6b86a8782bdfa492afda))
|
|
9
|
+
|
|
3
10
|
## [3.9.34](https://github.com/nodemailer/mailparser/compare/v3.9.33...v3.9.34) (2026-10-03)
|
|
4
11
|
|
|
5
12
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mailparser",
|
|
3
|
-
"version": "3.9.
|
|
3
|
+
"version": "3.9.35",
|
|
4
4
|
"description": "Parse e-mails",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -19,12 +19,12 @@
|
|
|
19
19
|
"license": "MIT",
|
|
20
20
|
"dependencies": {
|
|
21
21
|
"encoding-japanese": "2.4.0",
|
|
22
|
-
"he": "
|
|
22
|
+
"he": "2.0.0",
|
|
23
23
|
"html-to-text": "10.0.1",
|
|
24
24
|
"iconv-lite": "0.7.3",
|
|
25
|
-
"libmime": "5.4.
|
|
25
|
+
"libmime": "5.4.7",
|
|
26
26
|
"linkify-it": "5.0.2",
|
|
27
|
-
"@zone-eu/mailsplit": "5.4.
|
|
27
|
+
"@zone-eu/mailsplit": "5.4.20",
|
|
28
28
|
"nodemailer": "10.0.14",
|
|
29
29
|
"punycode.js": "2.3.1",
|
|
30
30
|
"tlds": "1.261.0"
|
package/package.json
CHANGED
|
@@ -86,7 +86,7 @@
|
|
|
86
86
|
"@mavogel/mvc-projen": "^0.0.50",
|
|
87
87
|
"cdk-nag": "^3.0.1",
|
|
88
88
|
"constructs": "^10.5.1",
|
|
89
|
-
"mailparser": "^3.9.
|
|
89
|
+
"mailparser": "^3.9.35",
|
|
90
90
|
"uuid": "^14.0.2"
|
|
91
91
|
},
|
|
92
92
|
"bundledDependencies": [
|
|
@@ -121,9 +121,30 @@
|
|
|
121
121
|
"publishConfig": {
|
|
122
122
|
"access": "public"
|
|
123
123
|
},
|
|
124
|
-
"version": "0.1.
|
|
124
|
+
"version": "0.1.11",
|
|
125
125
|
"jest": {
|
|
126
126
|
"coverageProvider": "v8",
|
|
127
|
+
"transformIgnorePatterns": [
|
|
128
|
+
"/node_modules/(?!he/)"
|
|
129
|
+
],
|
|
130
|
+
"transform": {
|
|
131
|
+
"^.+\\.[t]sx?$": [
|
|
132
|
+
"ts-jest",
|
|
133
|
+
{
|
|
134
|
+
"tsconfig": "test/tsconfig.json"
|
|
135
|
+
}
|
|
136
|
+
],
|
|
137
|
+
"^.+\\.mjs$": [
|
|
138
|
+
"ts-jest",
|
|
139
|
+
{
|
|
140
|
+
"tsconfig": {
|
|
141
|
+
"allowJs": true,
|
|
142
|
+
"module": "commonjs",
|
|
143
|
+
"esModuleInterop": true
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
]
|
|
147
|
+
},
|
|
127
148
|
"testMatch": [
|
|
128
149
|
"<rootDir>/@(src|test)/**/*(*.)@(spec|test).ts?(x)",
|
|
129
150
|
"<rootDir>/@(src|test)/**/__tests__/**/*.ts?(x)",
|
|
@@ -157,15 +178,7 @@
|
|
|
157
178
|
"outputDirectory": "test-reports"
|
|
158
179
|
}
|
|
159
180
|
]
|
|
160
|
-
]
|
|
161
|
-
"transform": {
|
|
162
|
-
"^.+\\.[t]sx?$": [
|
|
163
|
-
"ts-jest",
|
|
164
|
-
{
|
|
165
|
-
"tsconfig": "test/tsconfig.json"
|
|
166
|
-
}
|
|
167
|
-
]
|
|
168
|
-
}
|
|
181
|
+
]
|
|
169
182
|
},
|
|
170
183
|
"types": "lib/index.d.ts",
|
|
171
184
|
"jsii": {
|