From b43b7a6aba81a71132dd481223e5d3b8fb75a122 Mon Sep 17 00:00:00 2001 From: dawidd6 <9713907+dawidd6@users.noreply.github.com> Date: Thu, 22 Oct 2026 19:47:05 +0000 Subject: [PATCH] node_modules: update --- node_modules/.package-lock.json | 6 +-- node_modules/nodemailer/CHANGELOG.md | 7 +++ .../nodemailer/dist/cjs/mime-funcs/index.d.ts | 19 +++++++- .../nodemailer/dist/cjs/mime-funcs/index.js | 44 ++++++++++++++++++- .../nodemailer/dist/cjs/mime-node/index.js | 7 ++- .../nodemailer/dist/cjs/package-info.d.ts | 2 +- .../nodemailer/dist/cjs/package-info.js | 2 +- .../nodemailer/dist/esm/mime-funcs/index.d.ts | 19 +++++++- .../nodemailer/dist/esm/mime-funcs/index.js | 44 ++++++++++++++++++- .../nodemailer/dist/esm/mime-node/index.js | 7 ++- .../nodemailer/dist/esm/package-info.d.ts | 2 +- .../nodemailer/dist/esm/package-info.js | 2 +- node_modules/nodemailer/package.json | 16 +++---- 13 files changed, 154 insertions(+), 23 deletions(-) diff --git a/node_modules/.package-lock.json b/node_modules/.package-lock.json index 0d3dc170..b9c10afd 100644 --- a/node_modules/.package-lock.json +++ b/node_modules/.package-lock.json @@ -94,9 +94,9 @@ } }, "node_modules/nodemailer": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-10.2.0.tgz", - "integrity": "sha512-/XyGw6kX2stMdKGUJdAQmYAeY1FscWfdRydfd2NtK3A3KDfUUXCqZzExSNAt2xhh90X2qLCR+o2Gd48YPJcJwA==", + "version": "10.2.1", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-10.2.1.tgz", + "integrity": "sha512-ZrDNsPFoDMwefNs7sJwrYiEJ/CG4ClJWDZv05iNJsEBWa8GRDry1QJHTJxsuTAY9eDDKjX4k+q3SxslXJOao7w==", "license": "MIT-0", "engines": { "node": ">=20.0.0" diff --git a/node_modules/nodemailer/CHANGELOG.md b/node_modules/nodemailer/CHANGELOG.md index dfda201d..00d684e5 100644 --- a/node_modules/nodemailer/CHANGELOG.md +++ b/node_modules/nodemailer/CHANGELOG.md @@ -1,5 +1,12 @@ # CHANGELOG +## [10.2.1](https://github.com/nodemailer/nodemailer/compare/v10.2.0...v10.2.1) (2026-10-22) + + +### Bug Fixes + +* drop the comments of a Content-Type or Content-Disposition value with the stripComments option ([b3052b7](https://github.com/nodemailer/nodemailer/commit/b3052b7fe2e49b51dd66d6c7814a072e885f1ac8)) + ## [10.2.0](https://github.com/nodemailer/nodemailer/compare/v10.1.7...v10.2.0) (2026-10-21) diff --git a/node_modules/nodemailer/dist/cjs/mime-funcs/index.d.ts b/node_modules/nodemailer/dist/cjs/mime-funcs/index.d.ts index c4278fa6..2165602c 100644 --- a/node_modules/nodemailer/dist/cjs/mime-funcs/index.d.ts +++ b/node_modules/nodemailer/dist/cjs/mime-funcs/index.d.ts @@ -107,6 +107,22 @@ export declare function buildHeaderValue(structured: StructuredHeaderValue): str * @return A list of encoded keys and headers */ export declare function buildHeaderParam(key: string, data: string | Buffer, maxLength?: number): EncodedHeaderParam[]; +/** + * Options of parseHeaderValue() + */ +export interface ParseHeaderValueOptions { + /** + * Drop the RFC 822 comments outside quoted strings, which the MIME headers allow and + * which are not part of the value: 'boundary=b (comment)' names the boundary 'b'. A + * parenthesis right behind the '=' of a parameter or behind a token character of its + * value continues the token, as it does for Python and postal-mime, so 'Invoice(1).pdf' + * keeps its name and 'boundary=(c)b' names the boundary '(c)b'. A comment that never + * closes runs to the end of the value, unless a parameter follows it, in which case it is + * content and the parameter survives. Comments are kept by default for the sake of the + * callers of this exported function, not because keeping them is ever the better reading + */ + stripComments?: boolean | undefined; +} /** * Parses a header value with key=value arguments into a structured * object. @@ -120,9 +136,10 @@ export declare function buildHeaderParam(key: string, data: string | Buffer, max * } * * @param str Header value + * @param options Options, see ParseHeaderValueOptions * @return Header value as a parsed structure */ -export declare function parseHeaderValue(str: string): ParsedHeaderValue; +export declare function parseHeaderValue(str: string, options?: ParseHeaderValueOptions): ParsedHeaderValue; /** * Returns file extension for a content type string. If no suitable extensions * are found, 'bin' is used as the default extension diff --git a/node_modules/nodemailer/dist/cjs/mime-funcs/index.js b/node_modules/nodemailer/dist/cjs/mime-funcs/index.js index 895b0efe..7ea33a62 100644 --- a/node_modules/nodemailer/dist/cjs/mime-funcs/index.js +++ b/node_modules/nodemailer/dist/cjs/mime-funcs/index.js @@ -414,6 +414,26 @@ function buildHeaderParam(key, data, maxLength) { * goes in. Whitespace used to come off it only because the value was trimmed first. */ const TOKEN = /^[^\x00-\x20\x7f()<>@,;:\\"/[\]?=]+$/; +/** + * Offset of the ')' that closes the RFC 822 comment opening at `start`, or -1 when the + * comment never closes. Comments nest, and a backslash escapes the character after it + */ +function _findCommentEnd(str, start) { + let depth = 0; + for (let i = start, len = str.length; i < len; i++) { + const c = str.charAt(i); + if (c === '\\') { + i++; + } + else if (c === '(') { + depth++; + } + else if (c === ')' && --depth === 0) { + return i; + } + } + return -1; +} /** * Whether a string can be a header parameter name. * @@ -440,13 +460,16 @@ function _isParamName(name) { * } * * @param str Header value + * @param options Options, see ParseHeaderValueOptions * @return Header value as a parsed structure */ -function parseHeaderValue(str) { +function parseHeaderValue(str, options) { const response = { value: '', params: {} }; + // Cleared again by an unclosed '(', see the loop + let stripComments = !!options?.stripComments; // A duplicated parameter resolves to its first occurrence, the way a duplicated header // does. Letting the last one win disagrees with the receivers that take the first, and // the two readings of 'boundary="b"; boundary="c"' name different delimiters. The @@ -508,6 +531,25 @@ function parseHeaderValue(str) { }; for (let i = 0, len = str.length; i < len; i++) { chr = str.charAt(i); + // With stripComments, an RFC 822 comment stands anywhere outside a quoted string but + // right behind a token it would continue, see ParseHeaderValueOptions. In the value + // of a parameter, no pending whitespace means the last significant character was the + // '=' or a character of the token + if (stripComments && chr === '(' && !quote && !quoteClosed && !(stage === 'value' && key !== false && !pendingSpace)) { + let end = _findCommentEnd(str, i); + if (end < 0 && str.indexOf(';', i) < 0) { + // a comment that never closes runs to the end of the value, unless a + // parameter follows it, which is content then and survives + end = len - 1; + } + if (end >= 0) { + i = end; + continue; + } + // looking for a closing ')' again would scan a run of unclosed '(' to its end + // once for each of them + stripComments = false; + } if (stage === 'key') { if (chr === '=') { key = takeValue().trim(); diff --git a/node_modules/nodemailer/dist/cjs/mime-node/index.js b/node_modules/nodemailer/dist/cjs/mime-node/index.js index ae18d9d1..ddf07651 100644 --- a/node_modules/nodemailer/dist/cjs/mime-node/index.js +++ b/node_modules/nodemailer/dist/cjs/mime-node/index.js @@ -654,15 +654,18 @@ class MimeNode { return; } switch (header.key) { + // The comments of a MIME header are not part of its value and are dropped, so a + // caller supplied 'boundary=b (comment)' is the boundary b it names, and the + // header goes out without the comment case 'Content-Disposition': - structured = mimeFuncs.parseHeaderValue(value); + structured = mimeFuncs.parseHeaderValue(value, { stripComments: true }); if (this.filename) { structured.params.filename = this.filename; } value = mimeFuncs.buildHeaderValue(structured); break; case 'Content-Type': - structured = mimeFuncs.parseHeaderValue(value); + structured = mimeFuncs.parseHeaderValue(value, { stripComments: true }); // the type token decides multipart and charset below, so clean it before // those run and not just on the way out, otherwise a control char makes // the checks miss and the header ends up claiming a type it is not set up for diff --git a/node_modules/nodemailer/dist/cjs/package-info.d.ts b/node_modules/nodemailer/dist/cjs/package-info.d.ts index c3dde549..9b02520d 100644 --- a/node_modules/nodemailer/dist/cjs/package-info.d.ts +++ b/node_modules/nodemailer/dist/cjs/package-info.d.ts @@ -1,3 +1,3 @@ export declare const name = "nodemailer"; -export declare const version = "10.2.0"; +export declare const version = "10.2.1"; export declare const homepage = "https://nodemailer.com/"; diff --git a/node_modules/nodemailer/dist/cjs/package-info.js b/node_modules/nodemailer/dist/cjs/package-info.js index 0ed8d1c7..5b637775 100644 --- a/node_modules/nodemailer/dist/cjs/package-info.js +++ b/node_modules/nodemailer/dist/cjs/package-info.js @@ -3,5 +3,5 @@ Object.defineProperty(exports, "__esModule", { value: true }); exports.homepage = exports.version = exports.name = void 0; exports.name = 'nodemailer'; -exports.version = '10.2.0'; +exports.version = '10.2.1'; exports.homepage = 'https://nodemailer.com/'; diff --git a/node_modules/nodemailer/dist/esm/mime-funcs/index.d.ts b/node_modules/nodemailer/dist/esm/mime-funcs/index.d.ts index c4278fa6..2165602c 100644 --- a/node_modules/nodemailer/dist/esm/mime-funcs/index.d.ts +++ b/node_modules/nodemailer/dist/esm/mime-funcs/index.d.ts @@ -107,6 +107,22 @@ export declare function buildHeaderValue(structured: StructuredHeaderValue): str * @return A list of encoded keys and headers */ export declare function buildHeaderParam(key: string, data: string | Buffer, maxLength?: number): EncodedHeaderParam[]; +/** + * Options of parseHeaderValue() + */ +export interface ParseHeaderValueOptions { + /** + * Drop the RFC 822 comments outside quoted strings, which the MIME headers allow and + * which are not part of the value: 'boundary=b (comment)' names the boundary 'b'. A + * parenthesis right behind the '=' of a parameter or behind a token character of its + * value continues the token, as it does for Python and postal-mime, so 'Invoice(1).pdf' + * keeps its name and 'boundary=(c)b' names the boundary '(c)b'. A comment that never + * closes runs to the end of the value, unless a parameter follows it, in which case it is + * content and the parameter survives. Comments are kept by default for the sake of the + * callers of this exported function, not because keeping them is ever the better reading + */ + stripComments?: boolean | undefined; +} /** * Parses a header value with key=value arguments into a structured * object. @@ -120,9 +136,10 @@ export declare function buildHeaderParam(key: string, data: string | Buffer, max * } * * @param str Header value + * @param options Options, see ParseHeaderValueOptions * @return Header value as a parsed structure */ -export declare function parseHeaderValue(str: string): ParsedHeaderValue; +export declare function parseHeaderValue(str: string, options?: ParseHeaderValueOptions): ParsedHeaderValue; /** * Returns file extension for a content type string. If no suitable extensions * are found, 'bin' is used as the default extension diff --git a/node_modules/nodemailer/dist/esm/mime-funcs/index.js b/node_modules/nodemailer/dist/esm/mime-funcs/index.js index 8d4b7565..5b75b39b 100644 --- a/node_modules/nodemailer/dist/esm/mime-funcs/index.js +++ b/node_modules/nodemailer/dist/esm/mime-funcs/index.js @@ -365,6 +365,26 @@ export function buildHeaderParam(key, data, maxLength) { * goes in. Whitespace used to come off it only because the value was trimmed first. */ const TOKEN = /^[^\x00-\x20\x7f()<>@,;:\\"/[\]?=]+$/; +/** + * Offset of the ')' that closes the RFC 822 comment opening at `start`, or -1 when the + * comment never closes. Comments nest, and a backslash escapes the character after it + */ +function _findCommentEnd(str, start) { + let depth = 0; + for (let i = start, len = str.length; i < len; i++) { + const c = str.charAt(i); + if (c === '\\') { + i++; + } + else if (c === '(') { + depth++; + } + else if (c === ')' && --depth === 0) { + return i; + } + } + return -1; +} /** * Whether a string can be a header parameter name. * @@ -391,13 +411,16 @@ function _isParamName(name) { * } * * @param str Header value + * @param options Options, see ParseHeaderValueOptions * @return Header value as a parsed structure */ -export function parseHeaderValue(str) { +export function parseHeaderValue(str, options) { const response = { value: '', params: {} }; + // Cleared again by an unclosed '(', see the loop + let stripComments = !!options?.stripComments; // A duplicated parameter resolves to its first occurrence, the way a duplicated header // does. Letting the last one win disagrees with the receivers that take the first, and // the two readings of 'boundary="b"; boundary="c"' name different delimiters. The @@ -459,6 +482,25 @@ export function parseHeaderValue(str) { }; for (let i = 0, len = str.length; i < len; i++) { chr = str.charAt(i); + // With stripComments, an RFC 822 comment stands anywhere outside a quoted string but + // right behind a token it would continue, see ParseHeaderValueOptions. In the value + // of a parameter, no pending whitespace means the last significant character was the + // '=' or a character of the token + if (stripComments && chr === '(' && !quote && !quoteClosed && !(stage === 'value' && key !== false && !pendingSpace)) { + let end = _findCommentEnd(str, i); + if (end < 0 && str.indexOf(';', i) < 0) { + // a comment that never closes runs to the end of the value, unless a + // parameter follows it, which is content then and survives + end = len - 1; + } + if (end >= 0) { + i = end; + continue; + } + // looking for a closing ')' again would scan a run of unclosed '(' to its end + // once for each of them + stripComments = false; + } if (stage === 'key') { if (chr === '=') { key = takeValue().trim(); diff --git a/node_modules/nodemailer/dist/esm/mime-node/index.js b/node_modules/nodemailer/dist/esm/mime-node/index.js index 7af23e80..c03d40ba 100644 --- a/node_modules/nodemailer/dist/esm/mime-node/index.js +++ b/node_modules/nodemailer/dist/esm/mime-node/index.js @@ -616,15 +616,18 @@ class MimeNode { return; } switch (header.key) { + // The comments of a MIME header are not part of its value and are dropped, so a + // caller supplied 'boundary=b (comment)' is the boundary b it names, and the + // header goes out without the comment case 'Content-Disposition': - structured = mimeFuncs.parseHeaderValue(value); + structured = mimeFuncs.parseHeaderValue(value, { stripComments: true }); if (this.filename) { structured.params.filename = this.filename; } value = mimeFuncs.buildHeaderValue(structured); break; case 'Content-Type': - structured = mimeFuncs.parseHeaderValue(value); + structured = mimeFuncs.parseHeaderValue(value, { stripComments: true }); // the type token decides multipart and charset below, so clean it before // those run and not just on the way out, otherwise a control char makes // the checks miss and the header ends up claiming a type it is not set up for diff --git a/node_modules/nodemailer/dist/esm/package-info.d.ts b/node_modules/nodemailer/dist/esm/package-info.d.ts index c3dde549..9b02520d 100644 --- a/node_modules/nodemailer/dist/esm/package-info.d.ts +++ b/node_modules/nodemailer/dist/esm/package-info.d.ts @@ -1,3 +1,3 @@ export declare const name = "nodemailer"; -export declare const version = "10.2.0"; +export declare const version = "10.2.1"; export declare const homepage = "https://nodemailer.com/"; diff --git a/node_modules/nodemailer/dist/esm/package-info.js b/node_modules/nodemailer/dist/esm/package-info.js index 1c9f1333..7a6fdade 100644 --- a/node_modules/nodemailer/dist/esm/package-info.js +++ b/node_modules/nodemailer/dist/esm/package-info.js @@ -1,4 +1,4 @@ // Generated by scripts/build.js from package.json. Do not edit by hand. export const name = 'nodemailer'; -export const version = '10.2.0'; +export const version = '10.2.1'; export const homepage = 'https://nodemailer.com/'; diff --git a/node_modules/nodemailer/package.json b/node_modules/nodemailer/package.json index 0f75f887..d9728eee 100644 --- a/node_modules/nodemailer/package.json +++ b/node_modules/nodemailer/package.json @@ -1,6 +1,6 @@ { "name": "nodemailer", - "version": "10.2.0", + "version": "10.2.1", "description": "Easy as cake e-mail sending from your Node.js applications", "type": "module", "main": "./dist/cjs/nodemailer.js", @@ -153,24 +153,24 @@ }, "homepage": "https://nodemailer.com/", "devDependencies": { - "@aws-sdk/client-sesv2": "3.1151.0", + "@aws-sdk/client-sesv2": "3.1155.0", "@types/node": "20.19.43", "bunyan": "1.8.15", "c8": "12.0.0", "eslint": "10.13.0", "eslint-config-prettier": "10.1.8", "globals": "17.13.0", - "libbase64": "1.3.2", - "libmime": "5.4.7", - "libqp": "2.1.2", - "mailauth": "7.3.0", + "libbase64": "1.4.1", + "libmime": "5.6.3", + "libqp": "3.0.1", + "mailauth": "8.0.2", "prettier": "3.9.10", "proxy": "1.0.2", "proxy-test-server": "1.0.0", - "smtp-server": "3.19.21", + "smtp-server": "3.21.0", "tsx": "4.23.15", "typescript": "6.0.3", - "typescript-eslint": "8.71.2" + "typescript-eslint": "8.72.0" }, "engines": { "node": ">=20.0.0"