mirror of
https://github.com/dawidd6/action-send-mail.git
synced 2026-10-12 02:42:27 +07:00
node_modules: update (#344)
Co-authored-by: dawidd6 <9713907+dawidd6@users.noreply.github.com>
This commit is contained in:
1 parent
b099186883
commit
6e88c72525
63 files changed
+2863
-1227
No files matched your search
+32
-1
@@ -1,6 +1,7 @@
|
||||
import type { NodemailerError } from '../errors.js';
|
||||
import { isProtoKey, copyOwnKeys } from './objects.js';
|
||||
import os from 'node:os';
|
||||
import type { Readable } from 'node:stream';
|
||||
import { type Readable } from 'node:stream';
|
||||
import type { OutgoingHttpHeaders } from 'node:http';
|
||||
export { isProtoKey, copyOwnKeys };
|
||||
/**
|
||||
@@ -258,3 +259,33 @@ export declare const assign: (...args: ({
|
||||
[key: string]: any;
|
||||
};
|
||||
export declare const encodeXText: (str: string) => string;
|
||||
/**
|
||||
* Keeps the first error a content stream emits before it is read, so the error is reported
|
||||
* when the stream is read instead of being thrown as unhandled. The listener stays attached
|
||||
* for good, a stream that emits 'error' more than once never throws the later ones either
|
||||
*
|
||||
* @param stream Readable stream
|
||||
*/
|
||||
export declare function recordStreamErrors(stream: Readable): void;
|
||||
/**
|
||||
* Destroys a value if it is a readable stream that was not destroyed yet
|
||||
*
|
||||
* @param value Any content value
|
||||
*/
|
||||
export declare function destroyStream(value: unknown): void;
|
||||
/**
|
||||
* Tells why a stream can not be read from start to end anymore. A stream that ended or was
|
||||
* destroyed before anyone read it would never emit 'end' to a new reader, or, when piped, would
|
||||
* end the destination right away and turn into an empty value without any error
|
||||
*
|
||||
* @param stream Readable stream
|
||||
* @returns The error the stream failed with, an ESTREAM error, or null when it can be read
|
||||
*/
|
||||
export declare function unreadableStreamError(stream: Readable): NodemailerError | null;
|
||||
/**
|
||||
* Streams a stream value into a Buffer
|
||||
*
|
||||
* @param stream Readable stream
|
||||
* @param callback Callback function with (err, value)
|
||||
*/
|
||||
export declare function resolveStream(stream: Readable, callback: (err: Error | null, value?: Buffer) => void): void;
|
||||
+214
-117
@@ -37,8 +37,12 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.encodeXText = exports.assign = exports.parseDataURI = exports.callbackPromise = exports.getLogger = exports._logFunc = exports.parseConnectionUrl = exports.resolveHostname = exports.dnsCache = exports.networkInterfaces = exports._resetCacheCleanup = exports._lastCacheCleanup = exports.copyOwnKeys = exports.isProtoKey = void 0;
|
||||
exports.encodeXText = exports.assign = exports.parseDataURI = exports.callbackPromise = exports.getLogger = exports._logFunc = exports.parseConnectionUrl = exports.resolveHostname = exports.dnsCache = exports._readNetworkInterfaces = exports.networkInterfaces = exports._resetCacheCleanup = exports._lastCacheCleanup = exports.copyOwnKeys = exports.isProtoKey = void 0;
|
||||
exports.resolveContent = resolveContent;
|
||||
exports.recordStreamErrors = recordStreamErrors;
|
||||
exports.destroyStream = destroyStream;
|
||||
exports.unreadableStreamError = unreadableStreamError;
|
||||
exports.resolveStream = resolveStream;
|
||||
const urllib = __importStar(require("./url.js"));
|
||||
const node_util_1 = __importDefault(require("node:util"));
|
||||
const node_fs_1 = __importDefault(require("node:fs"));
|
||||
@@ -50,6 +54,7 @@ Object.defineProperty(exports, "copyOwnKeys", { enumerable: true, get: function
|
||||
const node_dns_1 = __importDefault(require("node:dns"));
|
||||
const node_net_1 = __importDefault(require("node:net"));
|
||||
const node_os_1 = __importDefault(require("node:os"));
|
||||
const node_stream_1 = require("node:stream");
|
||||
const DNS_TTL = 5 * 60 * 1000;
|
||||
const CACHE_CLEANUP_INTERVAL = 30 * 1000; // Minimum 30 seconds between cleanups
|
||||
const MAX_CACHE_SIZE = 1000; // Maximum number of entries in cache
|
||||
@@ -62,14 +67,25 @@ const _resetCacheCleanup = () => {
|
||||
lastCacheCleanup = 0;
|
||||
};
|
||||
exports._resetCacheCleanup = _resetCacheCleanup;
|
||||
try {
|
||||
exports.networkInterfaces = node_os_1.default.networkInterfaces();
|
||||
}
|
||||
catch (_err) {
|
||||
// fails on some systems
|
||||
}
|
||||
let networkInterfacesRead = false;
|
||||
// Read on first use rather than at load, so that importing the module does not ask for
|
||||
// the interface table (Deno prompts for --allow-sys on it)
|
||||
/** @internal */
|
||||
const _readNetworkInterfaces = () => {
|
||||
if (!networkInterfacesRead) {
|
||||
networkInterfacesRead = true;
|
||||
try {
|
||||
exports.networkInterfaces = node_os_1.default.networkInterfaces();
|
||||
}
|
||||
catch (_err) {
|
||||
// fails on some systems
|
||||
}
|
||||
}
|
||||
return exports.networkInterfaces;
|
||||
};
|
||||
exports._readNetworkInterfaces = _readNetworkInterfaces;
|
||||
const isFamilySupported = (family, allowInternal) => {
|
||||
const addresses = Object.values(exports.networkInterfaces || {}).flat();
|
||||
const addresses = Object.values((0, exports._readNetworkInterfaces)() || {}).flat();
|
||||
if (!addresses.length) {
|
||||
// hope for the best. Runtimes without an interface table (Cloudflare
|
||||
// Workers) report an empty object rather than throwing
|
||||
@@ -80,7 +96,8 @@ const isFamilySupported = (family, allowInternal) => {
|
||||
const resolve = (family, hostname, options, callback) => {
|
||||
options = options || {};
|
||||
if (!isFamilySupported(family, options.allowInternalNetworkInterfaces)) {
|
||||
return callback(null, []);
|
||||
callback(null, []);
|
||||
return null;
|
||||
}
|
||||
const dnsResolver = node_dns_1.default.Resolver ? new node_dns_1.default.Resolver(options) : node_dns_1.default;
|
||||
dnsResolver['resolve' + family](hostname, (err, addresses) => {
|
||||
@@ -99,6 +116,7 @@ const resolve = (family, hostname, options, callback) => {
|
||||
}
|
||||
return callback(null, Array.isArray(addresses) ? addresses : [].concat(addresses || []));
|
||||
});
|
||||
return node_dns_1.default.Resolver ? dnsResolver : null;
|
||||
};
|
||||
exports.dnsCache = new Map();
|
||||
const formatDNSValue = (value, extra) => {
|
||||
@@ -162,115 +180,139 @@ const resolveHostname = (options, callback) => {
|
||||
}));
|
||||
}
|
||||
}
|
||||
// Resolve both IPv4 and IPv6 addresses for fallback support
|
||||
// The timeout limits the lookup as a whole. It is also handed to the resolver, but there
|
||||
// it applies to every query attempt on its own, and the resolver retries a few times
|
||||
let responded = false;
|
||||
let deadline;
|
||||
const respond = (err, result) => {
|
||||
if (responded) {
|
||||
return;
|
||||
}
|
||||
responded = true;
|
||||
clearTimeout(deadline);
|
||||
callback(err, result);
|
||||
};
|
||||
// a stale cached value is still better than no value at all
|
||||
const respondCached = (error) => {
|
||||
if (!cached) {
|
||||
return false;
|
||||
}
|
||||
exports.dnsCache.set(host, {
|
||||
value: cached.value,
|
||||
expires: Date.now() + (options.dnsTtl || DNS_TTL)
|
||||
});
|
||||
respond(null, formatDNSValue(cached.value, {
|
||||
servername,
|
||||
cached: true,
|
||||
error
|
||||
}));
|
||||
return true;
|
||||
};
|
||||
const resolvers = [];
|
||||
const timeout = Number(options.timeout) || 0;
|
||||
if (timeout > 0) {
|
||||
deadline = setTimeout(() => {
|
||||
for (const resolver of resolvers) {
|
||||
if (typeof resolver.cancel === 'function') {
|
||||
resolver.cancel();
|
||||
}
|
||||
}
|
||||
const err = new Error('DNS lookup for ' + host + ' timed out');
|
||||
err.code = node_dns_1.default.TIMEOUT;
|
||||
if (!respondCached(err)) {
|
||||
respond(err);
|
||||
}
|
||||
}, timeout);
|
||||
}
|
||||
// Resolve both IPv4 and IPv6 addresses for fallback support, at the same time
|
||||
let ipv4Addresses = [];
|
||||
let ipv6Addresses = [];
|
||||
let ipv4Error = null;
|
||||
let ipv6Error = null;
|
||||
resolve(4, options.host, options, (err, addresses) => {
|
||||
if (err) {
|
||||
ipv4Error = err;
|
||||
let pending = 2;
|
||||
const onResolved = () => {
|
||||
if (--pending || responded) {
|
||||
return;
|
||||
}
|
||||
else {
|
||||
ipv4Addresses = addresses || [];
|
||||
// Combine addresses: IPv4 first, then IPv6
|
||||
const allAddresses = ipv4Addresses.concat(ipv6Addresses);
|
||||
if (allAddresses.length) {
|
||||
const value = {
|
||||
addresses: allAddresses
|
||||
};
|
||||
exports.dnsCache.set(host, {
|
||||
value,
|
||||
expires: Date.now() + (options.dnsTtl || DNS_TTL)
|
||||
});
|
||||
return respond(null, formatDNSValue(value, {
|
||||
servername,
|
||||
cached: false
|
||||
}));
|
||||
}
|
||||
resolve(6, host, options, (err, addresses) => {
|
||||
if (err) {
|
||||
ipv6Error = err;
|
||||
}
|
||||
else {
|
||||
ipv6Addresses = addresses || [];
|
||||
}
|
||||
// Combine addresses: IPv4 first, then IPv6
|
||||
const allAddresses = ipv4Addresses.concat(ipv6Addresses);
|
||||
if (allAddresses.length) {
|
||||
// No addresses from resolve4/resolve6, try dns.lookup as fallback
|
||||
if (ipv4Error && ipv6Error && respondCached(ipv4Error)) {
|
||||
// Both resolvers had errors
|
||||
return;
|
||||
}
|
||||
try {
|
||||
node_dns_1.default.lookup(host, { all: true }, (err, addresses) => {
|
||||
if (err) {
|
||||
if (respondCached(err)) {
|
||||
return;
|
||||
}
|
||||
return respond(err);
|
||||
}
|
||||
// Get all supported addresses from dns.lookup
|
||||
const supportedAddresses = addresses
|
||||
? addresses.filter(addr => isFamilySupported(addr.family)).map(addr => addr.address)
|
||||
: [];
|
||||
if (addresses && addresses.length && !supportedAddresses.length) {
|
||||
// there are addresses but none can be used
|
||||
console.warn(`Failed to resolve IPv${addresses[0].family} addresses with current network`);
|
||||
}
|
||||
if (!supportedAddresses.length && cached) {
|
||||
// nothing was found, fallback to cached value
|
||||
return respond(null, formatDNSValue(cached.value, {
|
||||
servername,
|
||||
cached: true
|
||||
}));
|
||||
}
|
||||
const value = {
|
||||
addresses: allAddresses
|
||||
addresses: supportedAddresses.length ? supportedAddresses : [host]
|
||||
};
|
||||
exports.dnsCache.set(host, {
|
||||
value,
|
||||
expires: Date.now() + (options.dnsTtl || DNS_TTL)
|
||||
});
|
||||
return callback(null, formatDNSValue(value, {
|
||||
return respond(null, formatDNSValue(value, {
|
||||
servername,
|
||||
cached: false
|
||||
}));
|
||||
});
|
||||
}
|
||||
catch (lookupErr) {
|
||||
if (respondCached(lookupErr)) {
|
||||
return;
|
||||
}
|
||||
// No addresses from resolve4/resolve6, try dns.lookup as fallback
|
||||
if (ipv4Error && ipv6Error) {
|
||||
// Both resolvers had errors
|
||||
if (cached) {
|
||||
exports.dnsCache.set(host, {
|
||||
value: cached.value,
|
||||
expires: Date.now() + (options.dnsTtl || DNS_TTL)
|
||||
});
|
||||
return callback(null, formatDNSValue(cached.value, {
|
||||
servername,
|
||||
cached: true,
|
||||
error: ipv4Error
|
||||
}));
|
||||
}
|
||||
return respond(ipv4Error || ipv6Error || lookupErr);
|
||||
}
|
||||
};
|
||||
for (const family of [4, 6]) {
|
||||
const resolver = resolve(family, host, options, (err, addresses) => {
|
||||
if (family === 4) {
|
||||
ipv4Error = err;
|
||||
ipv4Addresses = addresses || [];
|
||||
}
|
||||
try {
|
||||
node_dns_1.default.lookup(host, { all: true }, (err, addresses) => {
|
||||
if (err) {
|
||||
if (cached) {
|
||||
exports.dnsCache.set(host, {
|
||||
value: cached.value,
|
||||
expires: Date.now() + (options.dnsTtl || DNS_TTL)
|
||||
});
|
||||
return callback(null, formatDNSValue(cached.value, {
|
||||
servername,
|
||||
cached: true,
|
||||
error: err
|
||||
}));
|
||||
}
|
||||
return callback(err);
|
||||
}
|
||||
// Get all supported addresses from dns.lookup
|
||||
const supportedAddresses = addresses
|
||||
? addresses.filter(addr => isFamilySupported(addr.family)).map(addr => addr.address)
|
||||
: [];
|
||||
if (addresses && addresses.length && !supportedAddresses.length) {
|
||||
// there are addresses but none can be used
|
||||
console.warn(`Failed to resolve IPv${addresses[0].family} addresses with current network`);
|
||||
}
|
||||
if (!supportedAddresses.length && cached) {
|
||||
// nothing was found, fallback to cached value
|
||||
return callback(null, formatDNSValue(cached.value, {
|
||||
servername,
|
||||
cached: true
|
||||
}));
|
||||
}
|
||||
const value = {
|
||||
addresses: supportedAddresses.length ? supportedAddresses : [host]
|
||||
};
|
||||
exports.dnsCache.set(host, {
|
||||
value,
|
||||
expires: Date.now() + (options.dnsTtl || DNS_TTL)
|
||||
});
|
||||
return callback(null, formatDNSValue(value, {
|
||||
servername,
|
||||
cached: false
|
||||
}));
|
||||
});
|
||||
}
|
||||
catch (lookupErr) {
|
||||
if (cached) {
|
||||
exports.dnsCache.set(host, {
|
||||
value: cached.value,
|
||||
expires: Date.now() + (options.dnsTtl || DNS_TTL)
|
||||
});
|
||||
return callback(null, formatDNSValue(cached.value, {
|
||||
servername,
|
||||
cached: true,
|
||||
error: lookupErr
|
||||
}));
|
||||
}
|
||||
return callback(ipv4Error || ipv6Error || lookupErr);
|
||||
else {
|
||||
ipv6Error = err;
|
||||
ipv6Addresses = addresses || [];
|
||||
}
|
||||
onResolved();
|
||||
});
|
||||
});
|
||||
if (resolver) {
|
||||
resolvers.push(resolver);
|
||||
}
|
||||
}
|
||||
};
|
||||
exports.resolveHostname = resolveHostname;
|
||||
/**
|
||||
@@ -597,6 +639,53 @@ const encodeXText = (str) => {
|
||||
return result;
|
||||
};
|
||||
exports.encodeXText = encodeXText;
|
||||
// The first error a stream emitted, see recordStreamErrors
|
||||
const streamErrors = new WeakMap();
|
||||
/**
|
||||
* Keeps the first error a content stream emits before it is read, so the error is reported
|
||||
* when the stream is read instead of being thrown as unhandled. The listener stays attached
|
||||
* for good, a stream that emits 'error' more than once never throws the later ones either
|
||||
*
|
||||
* @param stream Readable stream
|
||||
*/
|
||||
function recordStreamErrors(stream) {
|
||||
stream.on('error', err => {
|
||||
if (!streamErrors.has(stream)) {
|
||||
streamErrors.set(stream, err);
|
||||
}
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Destroys a value if it is a readable stream that was not destroyed yet
|
||||
*
|
||||
* @param value Any content value
|
||||
*/
|
||||
function destroyStream(value) {
|
||||
const stream = value;
|
||||
if (stream && typeof stream.pipe === 'function' && typeof stream.destroy === 'function' && !stream.destroyed) {
|
||||
stream.destroy();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Tells why a stream can not be read from start to end anymore. A stream that ended or was
|
||||
* destroyed before anyone read it would never emit 'end' to a new reader, or, when piped, would
|
||||
* end the destination right away and turn into an empty value without any error
|
||||
*
|
||||
* @param stream Readable stream
|
||||
* @returns The error the stream failed with, an ESTREAM error, or null when it can be read
|
||||
*/
|
||||
function unreadableStreamError(stream) {
|
||||
const err = streamErrors.get(stream) || stream.errored;
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
if (stream.readableEnded || stream.destroyed) {
|
||||
const unreadable = new Error('Content stream was already read or destroyed');
|
||||
unreadable.code = errors.ESTREAM;
|
||||
return unreadable;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
/**
|
||||
* Streams a stream value into a Buffer
|
||||
*
|
||||
@@ -605,35 +694,43 @@ exports.encodeXText = encodeXText;
|
||||
*/
|
||||
function resolveStream(stream, callback) {
|
||||
let responded = false;
|
||||
const respond = (err, value) => {
|
||||
if (responded) {
|
||||
return;
|
||||
}
|
||||
responded = true;
|
||||
callback(err, value);
|
||||
};
|
||||
const unreadable = unreadableStreamError(stream);
|
||||
if (unreadable) {
|
||||
// absorbs a later 'error' from the stream, there is nobody left to report it to
|
||||
stream.on('error', () => false);
|
||||
setImmediate(() => respond(unreadable));
|
||||
return;
|
||||
}
|
||||
const chunks = [];
|
||||
let chunklen = 0;
|
||||
stream.on('error', err => {
|
||||
if (responded) {
|
||||
return;
|
||||
stream.on('data', (chunk) => {
|
||||
if (typeof chunk === 'string') {
|
||||
chunk = Buffer.from(chunk);
|
||||
}
|
||||
responded = true;
|
||||
callback(err);
|
||||
chunks.push(chunk);
|
||||
chunklen += chunk.length;
|
||||
});
|
||||
stream.on('readable', () => {
|
||||
let chunk;
|
||||
while ((chunk = stream.read()) !== null) {
|
||||
chunks.push(chunk);
|
||||
chunklen += chunk.length;
|
||||
// finished() also reports a stream that is destroyed before 'end', which would otherwise
|
||||
// leave the callback waiting forever
|
||||
(0, node_stream_1.finished)(stream, { writable: false }, err => {
|
||||
if (err) {
|
||||
return respond(err);
|
||||
}
|
||||
});
|
||||
stream.on('end', () => {
|
||||
if (responded) {
|
||||
return;
|
||||
}
|
||||
responded = true;
|
||||
let value;
|
||||
try {
|
||||
value = Buffer.concat(chunks, chunklen);
|
||||
}
|
||||
catch (E) {
|
||||
return callback(E);
|
||||
return respond(E);
|
||||
}
|
||||
callback(null, value);
|
||||
respond(null, value);
|
||||
});
|
||||
}
|
||||
/**
|
||||
|
||||
Reference in new issue
Block a user