node_modules: upgrade

This commit is contained in:
Dawid Dziurla
2022-10-21 16:52:45 +02:00
parent 6063705cef
commit f27e7f6b8d
140 changed files with 6117 additions and 261 deletions

View File

@ -51,7 +51,7 @@ function wrap(str, lineLength) {
*
* @constructor
* @param {Object} options Stream options
* @param {Number} [options.lineLength=76] Maximum lenght for lines, set to false to disable wrapping
* @param {Number} [options.lineLength=76] Maximum length for lines, set to false to disable wrapping
*/
class Encoder extends Transform {
constructor(options) {

View File

@ -54,10 +54,10 @@ class DKIMSigner {
this.output = output;
this.output.usingCache = false;
this.errored = false;
this.hasErrored = false;
this.input.on('error', err => {
this.errored = true;
this.hasErrored = true;
this.cleanup();
output.emit('error', err);
});
@ -84,7 +84,7 @@ class DKIMSigner {
}
sendNextChunk() {
if (this.errored) {
if (this.hasErrored) {
return;
}
@ -145,7 +145,7 @@ class DKIMSigner {
// do nothing
}
});
this.errored = true;
this.hasErrored = true;
// emit error
this.output.emit('error', err);
});

View File

@ -11,12 +11,12 @@ const packageData = require('../../package.json');
const MAX_REDIRECTS = 5;
module.exports = function (url, options) {
return fetch(url, options);
return nmfetch(url, options);
};
module.exports.Cookies = Cookies;
function fetch(url, options) {
function nmfetch(url, options) {
options = options || {};
options.fetchRes = options.fetchRes || new PassThrough();
@ -202,7 +202,7 @@ function fetch(url, options) {
// redirect does not include POST body
options.method = 'GET';
options.body = false;
return fetch(urllib.resolve(url, res.headers.location), options);
return nmfetch(urllib.resolve(url, res.headers.location), options);
}
fetchRes.statusCode = res.statusCode;

View File

@ -95,6 +95,10 @@ class Mail extends EventEmitter {
['close', 'isIdle', 'verify'].forEach(method => {
this[method] = (...args) => {
if (typeof this.transporter[method] === 'function') {
if (method === 'verify' && typeof this.getSocket === 'function') {
this.transporter.getSocket = this.getSocket;
this.getSocket = false;
}
return this.transporter[method](...args);
} else {
this.logger.warn(

View File

@ -96,7 +96,7 @@ class MailMessage {
}
});
let singleKeys = ['from', 'sender', 'replyTo'];
let singleKeys = ['from', 'sender'];
singleKeys.forEach(address => {
if (this.data[address]) {
this.data[address] = this.data[address].shift();

View File

@ -532,7 +532,7 @@ const mimeTypes = new Map([
['application/x-bittorrent', 'torrent'],
['application/x-bsh', ['bsh', 'sh', 'shar']],
['application/x-bytecode.elisp', 'elc'],
['applicaiton/x-bytecode.python', 'pyc'],
['application/x-bytecode.python', 'pyc'],
['application/x-bzip', 'bz'],
['application/x-bzip2', ['boz', 'bz2']],
['application/x-cdf', 'cdf'],
@ -1688,7 +1688,7 @@ const extensions = new Map([
['pwz', 'application/vnd.ms-powerpoint'],
['py', 'text/x-script.phyton'],
['pya', 'audio/vnd.ms-playready.media.pya'],
['pyc', 'applicaiton/x-bytecode.python'],
['pyc', 'application/x-bytecode.python'],
['pyv', 'video/vnd.ms-playready.media.pyv'],
['qam', 'application/vnd.epson.quickanime'],
['qbo', 'application/vnd.intu.qbo'],

View File

@ -3,7 +3,6 @@
'use strict';
const crypto = require('crypto');
const os = require('os');
const fs = require('fs');
const punycode = require('punycode');
const PassThrough = require('stream').PassThrough;
@ -13,7 +12,7 @@ const mimeFuncs = require('../mime-funcs');
const qp = require('../qp');
const base64 = require('../base64');
const addressparser = require('../addressparser');
const fetch = require('../fetch');
const nmfetch = require('../fetch');
const LastNewline = require('./last-newline');
const LeWindows = require('./le-windows');
@ -971,7 +970,7 @@ class MimeNode {
return contentStream;
}
// fetch URL
return fetch(content.href, { headers: content.httpHeaders });
return nmfetch(content.href, { headers: content.httpHeaders });
} else {
// pass string or buffer content as a stream
contentStream = new PassThrough();
@ -1282,7 +1281,7 @@ class MimeNode {
) +
'@' +
// try to use the domain of the FROM address or fallback to server hostname
(this.getEnvelope().from || this.hostname || os.hostname() || 'localhost').split('@').pop() +
(this.getEnvelope().from || this.hostname || 'localhost').split('@').pop() +
'>'
);
}

View File

@ -8,7 +8,7 @@ const SendmailTransport = require('./sendmail-transport');
const StreamTransport = require('./stream-transport');
const JSONTransport = require('./json-transport');
const SESTransport = require('./ses-transport');
const fetch = require('./fetch');
const nmfetch = require('./fetch');
const packageData = require('../package.json');
const ETHEREAL_API = (process.env.ETHEREAL_API || 'https://api.nodemailer.com').replace(/\/+$/, '');
@ -79,7 +79,7 @@ module.exports.createTestAccount = function (apiUrl, callback) {
let chunks = [];
let chunklen = 0;
let req = fetch(apiUrl + '/user', {
let req = nmfetch(apiUrl + '/user', {
contentType: 'application/json',
method: 'POST',
body: Buffer.from(

View File

@ -149,7 +149,7 @@ function checkRanges(nr, ranges) {
*
* @constructor
* @param {Object} options Stream options
* @param {Number} [options.lineLength=76] Maximum lenght for lines, set to false to disable wrapping
* @param {Number} [options.lineLength=76] Maximum length for lines, set to false to disable wrapping
*/
class Encoder extends Transform {
constructor(options) {

View File

@ -320,25 +320,26 @@ class SESTransport extends EventEmitter {
Source: 'invalid@invalid',
Destinations: ['invalid@invalid']
};
const cb = err => {
if (err && err.code !== 'InvalidParameterValue') {
return callback(err);
}
return callback(null, true);
};
if (!callback) {
promise = new Promise((resolve, reject) => {
callback = shared.callbackPromise(resolve, reject);
});
}
const cb = err => {
if (err && (err.code || err.Code) !== 'InvalidParameterValue') {
return callback(err);
}
return callback(null, true);
};
if (typeof ses.send === 'function' && aws.SendRawEmailCommand) {
// v3 API
sesMessage.RawMessage.Data = Buffer.from(sesMessage.RawMessage.Data);
ses.send(new aws.SendRawEmailCommand(sesMessage), cb);
} else {
// v2 API
ses.sendRawEmail(sesMessage, cb).promise();
ses.sendRawEmail(sesMessage, cb);
}
return promise;

View File

@ -5,14 +5,51 @@
const urllib = require('url');
const util = require('util');
const fs = require('fs');
const fetch = require('../fetch');
const nmfetch = require('../fetch');
const dns = require('dns');
const net = require('net');
const os = require('os');
const DNS_TTL = 5 * 60 * 1000;
const resolver = (family, hostname, callback) => {
dns['resolve' + family](hostname, (err, addresses) => {
let networkInterfaces;
try {
networkInterfaces = os.networkInterfaces();
} catch (err) {
// fails on some systems
}
module.exports.networkInterfaces = networkInterfaces;
const isFamilySupported = (family, allowInternal) => {
let networkInterfaces = module.exports.networkInterfaces;
if (!networkInterfaces) {
// hope for the best
return true;
}
const familySupported =
// crux that replaces Object.values(networkInterfaces) as Object.values is not supported in nodejs v6
Object.keys(networkInterfaces)
.map(key => networkInterfaces[key])
// crux that replaces .flat() as it is not supported in older Node versions (v10 and older)
.reduce((acc, val) => acc.concat(val), [])
.filter(i => !i.internal || allowInternal)
.filter(i => i.family === 'IPv' + family || i.family === family).length > 0;
return familySupported;
};
const resolver = (family, hostname, options, callback) => {
options = options || {};
const familySupported = isFamilySupported(family, options.allowInternalNetworkInterfaces);
if (!familySupported) {
return callback(null, []);
}
const resolver = dns.Resolver ? new dns.Resolver(options) : dns;
resolver['resolve' + family](hostname, (err, addresses) => {
if (err) {
switch (err.code) {
case dns.NODATA:
@ -20,6 +57,7 @@ const resolver = (family, hostname, callback) => {
case dns.NOTIMP:
case dns.SERVFAIL:
case dns.CONNREFUSED:
case dns.REFUSED:
case 'EAI_AGAIN':
return callback(null, []);
}
@ -30,100 +68,195 @@ const resolver = (family, hostname, callback) => {
};
const dnsCache = (module.exports.dnsCache = new Map());
const formatDNSValue = (value, extra) => {
if (!value) {
return Object.assign({}, extra || {});
}
return Object.assign(
{
servername: value.servername,
host:
!value.addresses || !value.addresses.length
? null
: value.addresses.length === 1
? value.addresses[0]
: value.addresses[Math.floor(Math.random() * value.addresses.length)]
},
extra || {}
);
};
module.exports.resolveHostname = (options, callback) => {
options = options || {};
if (!options.host && options.servername) {
options.host = options.servername;
}
if (!options.host || net.isIP(options.host)) {
// nothing to do here
let value = {
host: options.host,
addresses: [options.host],
servername: options.servername || false
};
return callback(null, value);
return callback(
null,
formatDNSValue(value, {
cached: false
})
);
}
let cached;
if (dnsCache.has(options.host)) {
cached = dnsCache.get(options.host);
if (!cached.expires || cached.expires >= Date.now()) {
return callback(null, {
host: cached.value.host,
servername: cached.value.servername,
_cached: true
});
return callback(
null,
formatDNSValue(cached.value, {
cached: true
})
);
}
}
resolver(4, options.host, (err, addresses) => {
resolver(4, options.host, options, (err, addresses) => {
if (err) {
if (cached) {
// ignore error, use expired value
return callback(null, cached.value);
return callback(
null,
formatDNSValue(cached.value, {
cached: true,
error: err
})
);
}
return callback(err);
}
if (addresses && addresses.length) {
let value = {
host: addresses[0] || options.host,
addresses,
servername: options.servername || options.host
};
dnsCache.set(options.host, {
value,
expires: Date.now() + DNS_TTL
expires: Date.now() + (options.dnsTtl || DNS_TTL)
});
return callback(null, value);
return callback(
null,
formatDNSValue(value, {
cached: false
})
);
}
resolver(6, options.host, (err, addresses) => {
resolver(6, options.host, options, (err, addresses) => {
if (err) {
if (cached) {
// ignore error, use expired value
return callback(null, cached.value);
return callback(
null,
formatDNSValue(cached.value, {
cached: true,
error: err
})
);
}
return callback(err);
}
if (addresses && addresses.length) {
let value = {
host: addresses[0] || options.host,
addresses,
servername: options.servername || options.host
};
dnsCache.set(options.host, {
value,
expires: Date.now() + DNS_TTL
expires: Date.now() + (options.dnsTtl || DNS_TTL)
});
return callback(null, value);
return callback(
null,
formatDNSValue(value, {
cached: false
})
);
}
try {
dns.lookup(options.host, {}, (err, address) => {
dns.lookup(options.host, { all: true }, (err, addresses) => {
if (err) {
if (cached) {
// ignore error, use expired value
return callback(null, cached.value);
return callback(
null,
formatDNSValue(cached.value, {
cached: true,
error: err
})
);
}
return callback(err);
}
let address = addresses
? addresses
.filter(addr => isFamilySupported(addr.family))
.map(addr => addr.address)
.shift()
: false;
if (addresses && addresses.length && !address) {
// there are addresses but none can be used
let err = new Error(`Can not use IPv${addresses[0].family} addresses with current network`);
return callback(err);
}
if (!address && cached) {
// nothing was found, fallback to cached value
return callback(null, cached.value);
return callback(
null,
formatDNSValue(cached.value, {
cached: true
})
);
}
let value = {
host: address || options.host,
addresses: address ? [address] : [options.host],
servername: options.servername || options.host
};
dnsCache.set(options.host, {
value,
expires: Date.now() + DNS_TTL
expires: Date.now() + (options.dnsTtl || DNS_TTL)
});
return callback(null, value);
return callback(
null,
formatDNSValue(value, {
cached: false
})
);
});
} catch (err) {
if (cached) {
// ignore error, use expired value
return callback(null, cached.value);
return callback(
null,
formatDNSValue(cached.value, {
cached: true,
error: err
})
);
}
return callback(err);
}
@ -335,7 +468,7 @@ module.exports.resolveContent = (data, key, callback) => {
callback(null, value);
});
} else if (/^https?:\/\//i.test(content.path || content.href)) {
contentStream = fetch(content.path || content.href);
contentStream = nmfetch(content.path || content.href);
return resolveStream(contentStream, callback);
} else if (/^data:/i.test(content.path || content.href)) {
let parts = (content.path || content.href).match(/^data:((?:[^;]*;)*(?:[^,]*)),(.*)$/i);

View File

@ -44,7 +44,7 @@ function httpProxyClient(proxyUrl, destinationPort, destinationHost, callback) {
// Error harness for initial connection. Once connection is established, the responsibility
// to handle errors is passed to whoever uses this socket
let finished = false;
let tempSocketErr = function (err) {
let tempSocketErr = err => {
if (finished) {
return;
}
@ -57,6 +57,12 @@ function httpProxyClient(proxyUrl, destinationPort, destinationHost, callback) {
callback(err);
};
let timeoutErr = () => {
let err = new Error('Proxy socket timed out');
err.code = 'ETIMEDOUT';
tempSocketErr(err);
};
socket = connect(options, () => {
if (finished) {
return;
@ -119,12 +125,18 @@ function httpProxyClient(proxyUrl, destinationPort, destinationHost, callback) {
}
socket.removeListener('error', tempSocketErr);
socket.removeListener('timeout', timeoutErr);
socket.setTimeout(0);
return callback(null, socket);
}
};
socket.on('data', onSocketData);
});
socket.setTimeout(httpProxyClient.timeout || 30 * 1000);
socket.on('timeout', timeoutErr);
socket.once('error', tempSocketErr);
}

View File

@ -14,6 +14,7 @@ const shared = require('../shared');
const CONNECTION_TIMEOUT = 2 * 60 * 1000; // how much to wait for the connection to be established
const SOCKET_TIMEOUT = 10 * 60 * 1000; // how much to wait for socket inactivity before disconnecting the client
const GREETING_TIMEOUT = 30 * 1000; // how much to wait after connection is established but SMTP greeting is not receieved
const DNS_TIMEOUT = 30 * 1000; // how much to wait for resolveHostname
/**
* Generates a SMTP connection object
@ -30,6 +31,7 @@ const GREETING_TIMEOUT = 30 * 1000; // how much to wait after connection is esta
* * **greetingTimeout** - Time to wait in ms until greeting message is received from the server (defaults to 10000)
* * **connectionTimeout** - how many milliseconds to wait for the connection to establish
* * **socketTimeout** - Time of inactivity until the connection is closed (defaults to 1 hour)
* * **dnsTimeout** - Time to wait in ms for the DNS requests to be resolved (defaults to 30 seconds)
* * **lmtp** - if true, uses LMTP instead of SMTP protocol
* * **logger** - bunyan compatible logger interface
* * **debug** - if true pass SMTP traffic to the logger
@ -56,6 +58,8 @@ class SMTPConnection extends EventEmitter {
this.port = Number(this.options.port) || (this.secureConnection ? 465 : 587);
this.host = this.options.host || 'localhost';
this.allowInternalNetworkInterfaces = this.options.allowInternalNetworkInterfaces || false;
if (typeof this.options.secure === 'undefined' && this.port === 465) {
// if secure option is not set but port is 465, then default to secure
this.secureConnection = true;
@ -217,7 +221,9 @@ class SMTPConnection extends EventEmitter {
let opts = {
port: this.port,
host: this.host
host: this.host,
allowInternalNetworkInterfaces: this.allowInternalNetworkInterfaces,
timeout: this.options.dnsTimeout || DNS_TIMEOUT
};
if (this.options.localAddress) {
@ -261,12 +267,12 @@ class SMTPConnection extends EventEmitter {
tnx: 'dns',
source: opts.host,
resolved: resolved.host,
cached: !!resolved._cached
cached: !!resolved.cached
},
'Resolved %s as %s [cache %s]',
opts.host,
resolved.host,
resolved._cached ? 'hit' : 'miss'
resolved.cached ? 'hit' : 'miss'
);
Object.keys(resolved).forEach(key => {
if (key.charAt(0) !== '_' && resolved[key]) {
@ -299,12 +305,12 @@ class SMTPConnection extends EventEmitter {
tnx: 'dns',
source: opts.host,
resolved: resolved.host,
cached: !!resolved._cached
cached: !!resolved.cached
},
'Resolved %s as %s [cache %s]',
opts.host,
resolved.host,
resolved._cached ? 'hit' : 'miss'
resolved.cached ? 'hit' : 'miss'
);
Object.keys(resolved).forEach(key => {
if (key.charAt(0) !== '_' && resolved[key]) {
@ -332,12 +338,12 @@ class SMTPConnection extends EventEmitter {
tnx: 'dns',
source: opts.host,
resolved: resolved.host,
cached: !!resolved._cached
cached: !!resolved.cached
},
'Resolved %s as %s [cache %s]',
opts.host,
resolved.host,
resolved._cached ? 'hit' : 'miss'
resolved.cached ? 'hit' : 'miss'
);
Object.keys(resolved).forEach(key => {
if (key.charAt(0) !== '_' && resolved[key]) {
@ -548,6 +554,16 @@ class SMTPConnection extends EventEmitter {
'\u0000' +
this._auth.credentials.pass,
'utf-8'
).toString('base64'),
// log entry without passwords
'AUTH PLAIN ' +
Buffer.from(
//this._auth.user+'\u0000'+
'\u0000' + // skip authorization identity as it causes problems with some servers
this._auth.credentials.user +
'\u0000' +
'/* secret */',
'utf-8'
).toString('base64')
);
return;
@ -945,8 +961,9 @@ class SMTPConnection extends EventEmitter {
* Send a command to the server, append \r\n
*
* @param {String} str String to be sent to the server
* @param {String} logStr Optional string to be used for logging instead of the actual string
*/
_sendCommand(str) {
_sendCommand(str, logStr) {
if (this._destroyed) {
// Connection already closed, can't send any more data
return;
@ -961,7 +978,7 @@ class SMTPConnection extends EventEmitter {
{
tnx: 'client'
},
(str || '').toString().replace(/\r?\n$/, '')
(logStr || str || '').toString().replace(/\r?\n$/, '')
);
}
@ -1097,7 +1114,7 @@ class SMTPConnection extends EventEmitter {
notify = notify.join(',');
}
let orcpt = (params.orcpt || params.recipient || '').toString() || null;
let orcpt = (params.recipient || params.orcpt || '').toString() || null;
if (orcpt && orcpt.indexOf(';') < 0) {
orcpt = 'rfc822;' + orcpt;
}
@ -1420,18 +1437,21 @@ class SMTPConnection extends EventEmitter {
// Decode from base64
let base64decoded = Buffer.from(challengeString, 'base64').toString('ascii'),
hmac_md5 = crypto.createHmac('md5', this._auth.credentials.pass);
hmacMD5 = crypto.createHmac('md5', this._auth.credentials.pass);
hmac_md5.update(base64decoded);
hmacMD5.update(base64decoded);
let hex_hmac = hmac_md5.digest('hex');
let prepended = this._auth.credentials.user + ' ' + hex_hmac;
let prepended = this._auth.credentials.user + ' ' + hmacMD5.digest('hex');
this._responseActions.push(str => {
this._actionAUTH_CRAM_MD5_PASS(str, callback);
});
this._sendCommand(Buffer.from(prepended).toString('base64'));
this._sendCommand(
Buffer.from(prepended).toString('base64'),
// hidden hash for logs
Buffer.from(this._auth.credentials.user + ' /* secret */').toString('base64')
);
}
/**
@ -1476,7 +1496,11 @@ class SMTPConnection extends EventEmitter {
this._actionAUTHComplete(str, callback);
});
this._sendCommand(Buffer.from(this._auth.credentials.pass + '', 'utf-8').toString('base64'));
this._sendCommand(
Buffer.from((this._auth.credentials.pass || '').toString(), 'utf-8').toString('base64'),
// Hidden pass for logs
Buffer.from('/* secret */', 'utf-8').toString('base64')
);
}
/**
@ -1706,7 +1730,11 @@ class SMTPConnection extends EventEmitter {
this._responseActions.push(str => {
this._actionAUTHComplete(str, isRetry, callback);
});
this._sendCommand('AUTH XOAUTH2 ' + this._auth.oauth2.buildXOAuth2Token(accessToken));
this._sendCommand(
'AUTH XOAUTH2 ' + this._auth.oauth2.buildXOAuth2Token(accessToken),
// Hidden for logs
'AUTH XOAUTH2 ' + this._auth.oauth2.buildXOAuth2Token('/* secret */')
);
});
}
@ -1733,10 +1761,16 @@ class SMTPConnection extends EventEmitter {
_getHostname() {
// defaul hostname is machine hostname or [IP]
let defaultHostname = os.hostname() || '';
let defaultHostname;
try {
defaultHostname = os.hostname() || '';
} catch (err) {
// fails on windows 7
defaultHostname = 'localhost';
}
// ignore if not FQDN
if (defaultHostname.indexOf('.') < 0) {
if (!defaultHostname || defaultHostname.indexOf('.') < 0) {
defaultHostname = '[127.0.0.1]';
}

View File

@ -627,6 +627,13 @@ class SMTPPool extends EventEmitter {
finalize();
});
} else if (!auth && connection.allowsAuth && options.forceAuth) {
let err = new Error('Authentication info was not provided');
err.code = 'NoAuth';
returned = true;
connection.close();
return callback(err);
} else {
finalize();
}

View File

@ -18,6 +18,7 @@ class SMTPTransport extends EventEmitter {
super();
options = options || {};
if (typeof options === 'string') {
options = {
url: options
@ -384,6 +385,13 @@ class SMTPTransport extends EventEmitter {
finalize();
});
} else if (!authData && connection.allowsAuth && options.forceAuth) {
let err = new Error('Authentication info was not provided');
err.code = 'NoAuth';
returned = true;
connection.close();
return callback(err);
} else {
finalize();
}

View File

@ -11,6 +11,12 @@
"host": "smtp.aol.com",
"port": 587
},
"Bluewin": {
"host": "smtpauths.bluewin.ch",
"domains": ["bluewin.ch"],
"port": 465
},
"DebugMail": {
"host": "debugmail.io",
@ -72,7 +78,7 @@
"Hotmail": {
"aliases": ["Outlook", "Outlook.com", "Hotmail.com"],
"domains": ["hotmail.com", "outlook.com"],
"host": "smtp.live.com",
"host": "smtp-mail.outlook.com",
"port": 587
},
@ -83,6 +89,12 @@
"port": 587
},
"Infomaniak": {
"host": "mail.infomaniak.com",
"domains": ["ik.me", "ikmail.com", "etik.com"],
"port": 587
},
"mail.ee": {
"host": "smtp.mail.ee"
},
@ -182,8 +194,8 @@
},
"SendCloud": {
"host": "smtpcloud.sohu.com",
"port": 25
"host": "smtp.sendcloud.net",
"port": 2525
},
"SendGrid": {

View File

@ -1,7 +1,7 @@
'use strict';
const Stream = require('stream').Stream;
const fetch = require('../fetch');
const nmfetch = require('../fetch');
const crypto = require('crypto');
const shared = require('../shared');
@ -310,7 +310,7 @@ class XOAuth2 extends Stream {
let chunks = [];
let chunklen = 0;
let req = fetch(url, {
let req = nmfetch(url, {
method: 'post',
headers: params.customHeaders,
body: payload,