mirror of
https://github.com/dawidd6/action-send-mail.git
synced 2026-10-23 06:55:45 +07:00
Compare commits
2
Commits
v23
...
node_modules
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b43b7a6aba | ||
|
|
67d71b1eee |
No files matched your search
+3
-3
@@ -94,9 +94,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/nodemailer": {
|
"node_modules/nodemailer": {
|
||||||
"version": "10.2.0",
|
"version": "10.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-10.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-10.2.1.tgz",
|
||||||
"integrity": "sha512-/XyGw6kX2stMdKGUJdAQmYAeY1FscWfdRydfd2NtK3A3KDfUUXCqZzExSNAt2xhh90X2qLCR+o2Gd48YPJcJwA==",
|
"integrity": "sha512-ZrDNsPFoDMwefNs7sJwrYiEJ/CG4ClJWDZv05iNJsEBWa8GRDry1QJHTJxsuTAY9eDDKjX4k+q3SxslXJOao7w==",
|
||||||
"license": "MIT-0",
|
"license": "MIT-0",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=20.0.0"
|
"node": ">=20.0.0"
|
||||||
|
|||||||
+7
@@ -1,5 +1,12 @@
|
|||||||
# CHANGELOG
|
# 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)
|
## [10.2.0](https://github.com/nodemailer/nodemailer/compare/v10.1.7...v10.2.0) (2026-10-21)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+18
-1
@@ -107,6 +107,22 @@ export declare function buildHeaderValue(structured: StructuredHeaderValue): str
|
|||||||
* @return A list of encoded keys and headers
|
* @return A list of encoded keys and headers
|
||||||
*/
|
*/
|
||||||
export declare function buildHeaderParam(key: string, data: string | Buffer, maxLength?: number): EncodedHeaderParam[];
|
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
|
* Parses a header value with key=value arguments into a structured
|
||||||
* object.
|
* object.
|
||||||
@@ -120,9 +136,10 @@ export declare function buildHeaderParam(key: string, data: string | Buffer, max
|
|||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
* @param str Header value
|
* @param str Header value
|
||||||
|
* @param options Options, see ParseHeaderValueOptions
|
||||||
* @return Header value as a parsed structure
|
* @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
|
* Returns file extension for a content type string. If no suitable extensions
|
||||||
* are found, 'bin' is used as the default extension
|
* are found, 'bin' is used as the default extension
|
||||||
|
|||||||
+43
-1
@@ -414,6 +414,26 @@ function buildHeaderParam(key, data, maxLength) {
|
|||||||
* goes in. Whitespace used to come off it only because the value was trimmed first.
|
* goes in. Whitespace used to come off it only because the value was trimmed first.
|
||||||
*/
|
*/
|
||||||
const TOKEN = /^[^\x00-\x20\x7f()<>@,;:\\"/[\]?=]+$/;
|
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.
|
* Whether a string can be a header parameter name.
|
||||||
*
|
*
|
||||||
@@ -440,13 +460,16 @@ function _isParamName(name) {
|
|||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
* @param str Header value
|
* @param str Header value
|
||||||
|
* @param options Options, see ParseHeaderValueOptions
|
||||||
* @return Header value as a parsed structure
|
* @return Header value as a parsed structure
|
||||||
*/
|
*/
|
||||||
function parseHeaderValue(str) {
|
function parseHeaderValue(str, options) {
|
||||||
const response = {
|
const response = {
|
||||||
value: '',
|
value: '',
|
||||||
params: {}
|
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
|
// 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
|
// 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
|
// 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++) {
|
for (let i = 0, len = str.length; i < len; i++) {
|
||||||
chr = str.charAt(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 (stage === 'key') {
|
||||||
if (chr === '=') {
|
if (chr === '=') {
|
||||||
key = takeValue().trim();
|
key = takeValue().trim();
|
||||||
|
|||||||
+5
-2
@@ -654,15 +654,18 @@ class MimeNode {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
switch (header.key) {
|
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':
|
case 'Content-Disposition':
|
||||||
structured = mimeFuncs.parseHeaderValue(value);
|
structured = mimeFuncs.parseHeaderValue(value, { stripComments: true });
|
||||||
if (this.filename) {
|
if (this.filename) {
|
||||||
structured.params.filename = this.filename;
|
structured.params.filename = this.filename;
|
||||||
}
|
}
|
||||||
value = mimeFuncs.buildHeaderValue(structured);
|
value = mimeFuncs.buildHeaderValue(structured);
|
||||||
break;
|
break;
|
||||||
case 'Content-Type':
|
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
|
// 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
|
// 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
|
// the checks miss and the header ends up claiming a type it is not set up for
|
||||||
|
|||||||
+1
-1
@@ -1,3 +1,3 @@
|
|||||||
export declare const name = "nodemailer";
|
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/";
|
export declare const homepage = "https://nodemailer.com/";
|
||||||
+1
-1
@@ -3,5 +3,5 @@
|
|||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
exports.homepage = exports.version = exports.name = void 0;
|
exports.homepage = exports.version = exports.name = void 0;
|
||||||
exports.name = 'nodemailer';
|
exports.name = 'nodemailer';
|
||||||
exports.version = '10.2.0';
|
exports.version = '10.2.1';
|
||||||
exports.homepage = 'https://nodemailer.com/';
|
exports.homepage = 'https://nodemailer.com/';
|
||||||
+18
-1
@@ -107,6 +107,22 @@ export declare function buildHeaderValue(structured: StructuredHeaderValue): str
|
|||||||
* @return A list of encoded keys and headers
|
* @return A list of encoded keys and headers
|
||||||
*/
|
*/
|
||||||
export declare function buildHeaderParam(key: string, data: string | Buffer, maxLength?: number): EncodedHeaderParam[];
|
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
|
* Parses a header value with key=value arguments into a structured
|
||||||
* object.
|
* object.
|
||||||
@@ -120,9 +136,10 @@ export declare function buildHeaderParam(key: string, data: string | Buffer, max
|
|||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
* @param str Header value
|
* @param str Header value
|
||||||
|
* @param options Options, see ParseHeaderValueOptions
|
||||||
* @return Header value as a parsed structure
|
* @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
|
* Returns file extension for a content type string. If no suitable extensions
|
||||||
* are found, 'bin' is used as the default extension
|
* are found, 'bin' is used as the default extension
|
||||||
|
|||||||
+43
-1
@@ -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.
|
* goes in. Whitespace used to come off it only because the value was trimmed first.
|
||||||
*/
|
*/
|
||||||
const TOKEN = /^[^\x00-\x20\x7f()<>@,;:\\"/[\]?=]+$/;
|
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.
|
* Whether a string can be a header parameter name.
|
||||||
*
|
*
|
||||||
@@ -391,13 +411,16 @@ function _isParamName(name) {
|
|||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
* @param str Header value
|
* @param str Header value
|
||||||
|
* @param options Options, see ParseHeaderValueOptions
|
||||||
* @return Header value as a parsed structure
|
* @return Header value as a parsed structure
|
||||||
*/
|
*/
|
||||||
export function parseHeaderValue(str) {
|
export function parseHeaderValue(str, options) {
|
||||||
const response = {
|
const response = {
|
||||||
value: '',
|
value: '',
|
||||||
params: {}
|
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
|
// 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
|
// 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
|
// 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++) {
|
for (let i = 0, len = str.length; i < len; i++) {
|
||||||
chr = str.charAt(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 (stage === 'key') {
|
||||||
if (chr === '=') {
|
if (chr === '=') {
|
||||||
key = takeValue().trim();
|
key = takeValue().trim();
|
||||||
|
|||||||
+5
-2
@@ -616,15 +616,18 @@ class MimeNode {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
switch (header.key) {
|
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':
|
case 'Content-Disposition':
|
||||||
structured = mimeFuncs.parseHeaderValue(value);
|
structured = mimeFuncs.parseHeaderValue(value, { stripComments: true });
|
||||||
if (this.filename) {
|
if (this.filename) {
|
||||||
structured.params.filename = this.filename;
|
structured.params.filename = this.filename;
|
||||||
}
|
}
|
||||||
value = mimeFuncs.buildHeaderValue(structured);
|
value = mimeFuncs.buildHeaderValue(structured);
|
||||||
break;
|
break;
|
||||||
case 'Content-Type':
|
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
|
// 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
|
// 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
|
// the checks miss and the header ends up claiming a type it is not set up for
|
||||||
|
|||||||
+1
-1
@@ -1,3 +1,3 @@
|
|||||||
export declare const name = "nodemailer";
|
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/";
|
export declare const homepage = "https://nodemailer.com/";
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
// Generated by scripts/build.js from package.json. Do not edit by hand.
|
// Generated by scripts/build.js from package.json. Do not edit by hand.
|
||||||
export const name = 'nodemailer';
|
export const name = 'nodemailer';
|
||||||
export const version = '10.2.0';
|
export const version = '10.2.1';
|
||||||
export const homepage = 'https://nodemailer.com/';
|
export const homepage = 'https://nodemailer.com/';
|
||||||
+8
-8
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "nodemailer",
|
"name": "nodemailer",
|
||||||
"version": "10.2.0",
|
"version": "10.2.1",
|
||||||
"description": "Easy as cake e-mail sending from your Node.js applications",
|
"description": "Easy as cake e-mail sending from your Node.js applications",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "./dist/cjs/nodemailer.js",
|
"main": "./dist/cjs/nodemailer.js",
|
||||||
@@ -153,24 +153,24 @@
|
|||||||
},
|
},
|
||||||
"homepage": "https://nodemailer.com/",
|
"homepage": "https://nodemailer.com/",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@aws-sdk/client-sesv2": "3.1151.0",
|
"@aws-sdk/client-sesv2": "3.1155.0",
|
||||||
"@types/node": "20.19.43",
|
"@types/node": "20.19.43",
|
||||||
"bunyan": "1.8.15",
|
"bunyan": "1.8.15",
|
||||||
"c8": "12.0.0",
|
"c8": "12.0.0",
|
||||||
"eslint": "10.13.0",
|
"eslint": "10.13.0",
|
||||||
"eslint-config-prettier": "10.1.8",
|
"eslint-config-prettier": "10.1.8",
|
||||||
"globals": "17.13.0",
|
"globals": "17.13.0",
|
||||||
"libbase64": "1.3.2",
|
"libbase64": "1.4.1",
|
||||||
"libmime": "5.4.7",
|
"libmime": "5.6.3",
|
||||||
"libqp": "2.1.2",
|
"libqp": "3.0.1",
|
||||||
"mailauth": "7.3.0",
|
"mailauth": "8.0.2",
|
||||||
"prettier": "3.9.10",
|
"prettier": "3.9.10",
|
||||||
"proxy": "1.0.2",
|
"proxy": "1.0.2",
|
||||||
"proxy-test-server": "1.0.0",
|
"proxy-test-server": "1.0.0",
|
||||||
"smtp-server": "3.19.21",
|
"smtp-server": "3.21.0",
|
||||||
"tsx": "4.23.15",
|
"tsx": "4.23.15",
|
||||||
"typescript": "6.0.3",
|
"typescript": "6.0.3",
|
||||||
"typescript-eslint": "8.71.2"
|
"typescript-eslint": "8.72.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=20.0.0"
|
"node": ">=20.0.0"
|
||||||
|
|||||||
Generated
+3
-3
@@ -103,9 +103,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/nodemailer": {
|
"node_modules/nodemailer": {
|
||||||
"version": "10.2.0",
|
"version": "10.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-10.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-10.2.1.tgz",
|
||||||
"integrity": "sha512-/XyGw6kX2stMdKGUJdAQmYAeY1FscWfdRydfd2NtK3A3KDfUUXCqZzExSNAt2xhh90X2qLCR+o2Gd48YPJcJwA==",
|
"integrity": "sha512-ZrDNsPFoDMwefNs7sJwrYiEJ/CG4ClJWDZv05iNJsEBWa8GRDry1QJHTJxsuTAY9eDDKjX4k+q3SxslXJOao7w==",
|
||||||
"license": "MIT-0",
|
"license": "MIT-0",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=20.0.0"
|
"node": ">=20.0.0"
|
||||||
|
|||||||
Reference in new issue
Block a user