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

6
node_modules/nodemailer/.gitattributes generated vendored Normal file
View File

@ -0,0 +1,6 @@
*.js text eol=lf
*.txt text eol=lf
*.html text eol=lf
*.htm text eol=lf
*.ics -text
*.bin -text

58
node_modules/nodemailer/CHANGELOG.md generated vendored
View File

@ -1,5 +1,61 @@
# CHANGELOG
## 6.8.0 2022-09-28
- Add DNS timeout (huksley)
- add dns.REFUSED (lucagianfelici)
## 6.7.8 2022-08-11
- Allow to use multiple Reply-To addresses
## 6.7.7 2022-07-06
- Resolver fixes
## 6.7.5 2022-05-04
- No changes, pushing a new README to npmjs.org
## 6.7.4 2022-04-29
- Ensure compatibility with Node 18
- Replaced Travis with Github Actions
## 6.7.3 2022-03-21
- Typo fixes
- Added stale issue automation fir Github
- Add Infomaniak config to well known service (popod)
- Update Outlook/Hotmail host in well known services (popod)
- fix: DSN recipient gets ignored (KornKalle)
## 6.7.2 2021-11-26
- Fix proxies for account verification
## 6.7.1 2021-11-15
- fix verify on ses-transport (stanofsky)
## 6.7.0 2021-10-11
- Updated DNS resolving logic. If there are multiple responses for a A/AAAA record, then loop these randomly instead of only caching the first one
## 6.6.5 2021-09-23
- Replaced Object.values() and Array.flat() with polyfills to allow using Nodemailer in Node v6+
## 6.6.4 2021-09-22
- Better compatibility with IPv6-only SMTP hosts (oxzi)
- Fix ses verify for sdk v3 (hannesvdvreken)
- Added SECURITY.txt for contact info
## 6.6.3 2021-07-14
- Do not show passwords in SMTP transaction logs. All passwords used in logging are replaced by `"/* secret */"`
## 6.6.1 2021-05-23
- Fixed address formatting issue where newlines in an email address, if provided via address object, were not properly removed. Reported by tmazeika (#1289)
@ -55,7 +111,7 @@
## 6.4.7 2020-05-28
- Always set charset=utf-8 for Content-Type headers
- Catch error whn using invalid crypto.sign input
- Catch error when using invalid crypto.sign input
## 6.4.6 2020-03-20

61
node_modules/nodemailer/README.md generated vendored
View File

@ -2,12 +2,24 @@
[![Nodemailer](https://raw.githubusercontent.com/nodemailer/nodemailer/master/assets/nm_logo_200x136.png)](https://nodemailer.com/about/)
Send e-mails from Node.js easy as cake! 🍰✉️
Send emails from Node.js easy as cake! 🍰✉️
[![NPM](https://nodei.co/npm/nodemailer.png?downloads=true&downloadRank=true&stars=true)](https://nodemailer.com/about/)
See [nodemailer.com](https://nodemailer.com/) for documentation and terms.
---
> Check out **[EmailEngine](https://emailengine.app/?utm_source=github-nodemailer&utm_campaign=nodemailer&utm_medium=readme-link)** a self-hosted email gateway that allows making **REST requests against IMAP and SMTP servers**. EmailEngine also sends webhooks whenever something changes on the registered accounts.\
> \
> Using the email accounts registered with EmailEngine, you can receive and [send emails](https://emailengine.app/sending-emails?utm_source=github-nodemailer&utm_campaign=nodemailer&utm_medium=readme-link). EmailEngine supports OAuth2, delayed sends, opens and clicks tracking, bounce detection, etc. All on top of regular email accounts without an external MTA service.
---
This project is supported by [Forward Email](https://forwardemail.net) the 100% open-source and privacy-focused email service.
---
## Having an issue?
#### First review the docs
@ -16,20 +28,57 @@ Documentation for Nodemailer can be found at [nodemailer.com](https://nodemailer
#### Nodemailer throws a SyntaxError for "..."
You are using older Node.js version than v6.0. Upgrade Node.js to get support for the spread operator.
You are using an older Node.js version than v6.0. Upgrade Node.js to get support for the spread operator. Nodemailer supports all Node.js versions starting from Node.js@v6.0.0.
#### I'm having issues with Gmail
Gmail either works well or it does not work at all. It is probably easier to switch to an alternative service instead of fixing issues with Gmail. If Gmail does not work for you then don't use it. Read more about it [here](https://nodemailer.com/usage/using-gmail/).
Gmail either works well, or it does not work at all. It is probably easier to switch to an alternative service instead of fixing issues with Gmail. If Gmail does not work for you, then don't use it. Read more about it [here](https://nodemailer.com/usage/using-gmail/).
#### I get ETIMEDOUT errors
Check your firewall settings. Timeout usually occurs when you try to open a connection to a port that is firewalled either on the server or on your machine.
Check your firewall settings. Timeout usually occurs when you try to open a connection to a firewalled port either on the server or on your machine. Some ISPs also block email ports to prevent spamming.
#### Nodemailer works on one machine but not in another
It's either a firewall issue, or your SMTP server blocks authentication attempts from some servers.
#### I get TLS errors
- If you are running the code in your own machine, then check your antivirus settings. Antiviruses often mess around with email ports usage. Node.js might not recognize the MITM cert your antivirus is using.
- Latest Node versions allow only TLS versions 1.2 and higher, some servers might still use TLS 1.1 or lower. Check Node.js docs how to get correct TLS support for your app.
- If you are running the code on your machine, check your antivirus settings. Antiviruses often mess around with email ports usage. Node.js might not recognize the MITM cert your antivirus is using.
- Latest Node versions allow only TLS versions 1.2 and higher. Some servers might still use TLS 1.1 or lower. Check Node.js docs on how to get correct TLS support for your app. You can change this with [tls.minVersion](https://nodejs.org/dist/latest-v16.x/docs/api/tls.html#tls_tls_createsecurecontext_options) option
- You might have the wrong value for the `secure` option. This should be set to `true` only for port 465. For every other port, it should be `false`. Setting it to `false` does not mean that Nodemailer would not use TLS. Nodemailer would still try to upgrade the connection to use TLS if the server supports it.
- Older Node versions do not fully support the certificate chain of the newest Let's Encrypt certificates. Either set [tls.rejectUnauthorized](https://nodejs.org/dist/latest-v16.x/docs/api/tls.html#tlsconnectoptions-callback) to `false` to skip chain verification or upgrade your Node version
```
let configOptions = {
host: "smtp.example.com",
port: 587,
tls: {
rejectUnauthorized: true,
minVersion: "TLSv1.2"
}
}
```
#### I have issues with DNS / hosts file
Node.js uses [c-ares](https://nodejs.org/en/docs/meta/topics/dependencies/#c-ares) to resolve domain names, not the DNS library provided by the system, so if you have some custom DNS routing set up, it might be ignored. Nodemailer runs [dns.resolve4()](https://nodejs.org/dist/latest-v16.x/docs/api/dns.html#dnsresolve4hostname-options-callback) and [dns.resolve6()](https://nodejs.org/dist/latest-v16.x/docs/api/dns.html#dnsresolve6hostname-options-callback) to resolve hostname into an IP address. If both calls fail, then Nodemailer will fall back to [dns.lookup()](https://nodejs.org/dist/latest-v16.x/docs/api/dns.html#dnslookuphostname-options-callback). If this does not work for you, you can hard code the IP address into the configuration like shown below. In that case, Nodemailer would not perform any DNS lookups.
```
let configOptions = {
host: "1.2.3.4",
port: 465,
secure: true,
tls: {
// must provide server name, otherwise TLS certificate check will fail
servername: "example.com"
}
}
```
#### I have an issue with TypeScript types
Nodemailer has official support for Node.js only. For anything related to TypeScript, you need to directly contact the authors of the [type definitions](https://www.npmjs.com/package/@types/nodemailer).
#### I have a different problem

22
node_modules/nodemailer/SECURITY.txt generated vendored Normal file
View File

@ -0,0 +1,22 @@
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256
Contact: mailto:andris@reinman.eu
Encryption: https://keys.openpgp.org/vks/v1/by-fingerprint/5D952A46E1D8C931F6364E01DC6C83F4D584D364
Preferred-Languages: en, et
-----BEGIN PGP SIGNATURE-----
iQIzBAEBCAAdFiEEXZUqRuHYyTH2Nk4B3GyD9NWE02QFAmFDnUgACgkQ3GyD9NWE
02RqUA/+MM3afmRYq874C7wp+uN6dTMCvUX5g5zqBZ2yKpFr46L+PYvM7o8TMm5h
hmLT2I1zZmi+xezOL3zHFizaw0tKkZIz9cWl3Jrgs0FLp0zOsSz1xucp9Q2tYM/Q
vbiP6ys0gbim4tkDGRmZOEiO23s0BuRnmHt7vZg210O+D105Yd8/Ohzbj6PSLBO5
W1tA7Xw5t0FQ14NNH5+MKyDIKoCX12n0FmrC6qLTXeojf291UgKhCUPda3LIGTmx
mTXz0y68149Mw+JikRCYP8HfGRY9eA4XZrYXF7Bl2T9OJpKD3JAH+69P3xBw19Gn
Csaw3twu8P1bxoVGjY4KRrBOp68W8TwZYjWVWbqY6oV8hb/JfrMxa+kaSxRuloFs
oL6+phrDSPTWdOj2LlEDBJbPOMeDFzIlsBBcJ/JHCEHTvlHl7LoWr3YuWce9PUwl
4r3JUovvaeuJxLgC0vu3WCB3Jeocsl3SreqNkrVc1IjvkSomn3YGm5nCNAd/2F0V
exCGRk/8wbkSjAY38GwQ8K/VuFsefWN3L9sVwIMAMu88KFCAN+GzVFiwvyIXehF5
eogP9mIXzdQ5YReQjUjApOzGz54XnDyv9RJ3sdvMHosLP+IOg+0q5t9agWv6aqSR
2HzCpiQnH/gmM5NS0AU4Koq/L7IBeLu1B8+61/+BiHgZJJmPdgU=
=BUZr
-----END PGP SIGNATURE-----

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,

24
node_modules/nodemailer/package.json generated vendored
View File

@ -1,10 +1,10 @@
{
"name": "nodemailer",
"version": "6.6.2",
"version": "6.8.0",
"description": "Easy as cake e-mail sending from your Node.js applications",
"main": "lib/nodemailer.js",
"scripts": {
"test": "grunt"
"test": "grunt --trace-warnings"
},
"repository": {
"type": "git",
@ -20,23 +20,25 @@
},
"homepage": "https://nodemailer.com/",
"devDependencies": {
"@aws-sdk/client-ses": "3.180.0",
"aws-sdk": "2.1225.0",
"bunyan": "1.8.15",
"chai": "4.3.4",
"chai": "4.3.6",
"eslint-config-nodemailer": "1.2.0",
"eslint-config-prettier": "8.3.0",
"grunt": "1.4.1",
"eslint-config-prettier": "8.5.0",
"grunt": "1.5.3",
"grunt-cli": "1.4.3",
"grunt-eslint": "23.0.0",
"grunt-eslint": "24.0.0",
"grunt-mocha-test": "0.13.3",
"libbase64": "1.2.1",
"libmime": "5.0.0",
"libmime": "5.1.0",
"libqp": "1.1.0",
"mocha": "9.0.0",
"nodemailer-ntlm-auth": "1.0.1",
"mocha": "10.0.0",
"nodemailer-ntlm-auth": "1.0.3",
"proxy": "1.0.2",
"proxy-test-server": "1.0.0",
"sinon": "11.1.1",
"smtp-server": "3.9.0"
"sinon": "14.0.0",
"smtp-server": "3.11.0"
},
"engines": {
"node": ">=6.0.0"