nodemailer 6.7.4 → 6.7.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -0
- package/README.md +9 -3
- package/lib/base64/index.js +1 -1
- package/lib/mime-funcs/mime-types.js +2 -2
- package/lib/mime-node/index.js +1 -2
- package/lib/shared/index.js +21 -7
- package/lib/smtp-connection/http-proxy-client.js +13 -1
- package/lib/smtp-connection/index.js +12 -3
- package/lib/smtp-pool/index.js +7 -0
- package/lib/smtp-transport/index.js +8 -0
- package/lib/well-known/services.json +8 -2
- package/package.json +6 -6
package/CHANGELOG.md
CHANGED
package/README.md
CHANGED
|
@@ -8,9 +8,15 @@ Send emails from Node.js – easy as cake! 🍰✉️
|
|
|
8
8
|
|
|
9
9
|
See [nodemailer.com](https://nodemailer.com/) for documentation and terms.
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
> 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.\
|
|
14
|
+
> \
|
|
15
|
+
> 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.
|
|
12
16
|
|
|
13
|
-
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Having an issue?
|
|
14
20
|
|
|
15
21
|
#### First review the docs
|
|
16
22
|
|
|
@@ -18,7 +24,7 @@ Documentation for Nodemailer can be found at [nodemailer.com](https://nodemailer
|
|
|
18
24
|
|
|
19
25
|
#### Nodemailer throws a SyntaxError for "..."
|
|
20
26
|
|
|
21
|
-
You are using an older Node.js version than v6.0. Upgrade Node.js to get support for the spread operator.
|
|
27
|
+
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.
|
|
22
28
|
|
|
23
29
|
#### I'm having issues with Gmail
|
|
24
30
|
|
package/lib/base64/index.js
CHANGED
|
@@ -51,7 +51,7 @@ function wrap(str, lineLength) {
|
|
|
51
51
|
*
|
|
52
52
|
* @constructor
|
|
53
53
|
* @param {Object} options Stream options
|
|
54
|
-
* @param {Number} [options.lineLength=76] Maximum
|
|
54
|
+
* @param {Number} [options.lineLength=76] Maximum length for lines, set to false to disable wrapping
|
|
55
55
|
*/
|
|
56
56
|
class Encoder extends Transform {
|
|
57
57
|
constructor(options) {
|
|
@@ -532,7 +532,7 @@ const mimeTypes = new Map([
|
|
|
532
532
|
['application/x-bittorrent', 'torrent'],
|
|
533
533
|
['application/x-bsh', ['bsh', 'sh', 'shar']],
|
|
534
534
|
['application/x-bytecode.elisp', 'elc'],
|
|
535
|
-
['
|
|
535
|
+
['application/x-bytecode.python', 'pyc'],
|
|
536
536
|
['application/x-bzip', 'bz'],
|
|
537
537
|
['application/x-bzip2', ['boz', 'bz2']],
|
|
538
538
|
['application/x-cdf', 'cdf'],
|
|
@@ -1688,7 +1688,7 @@ const extensions = new Map([
|
|
|
1688
1688
|
['pwz', 'application/vnd.ms-powerpoint'],
|
|
1689
1689
|
['py', 'text/x-script.phyton'],
|
|
1690
1690
|
['pya', 'audio/vnd.ms-playready.media.pya'],
|
|
1691
|
-
['pyc', '
|
|
1691
|
+
['pyc', 'application/x-bytecode.python'],
|
|
1692
1692
|
['pyv', 'video/vnd.ms-playready.media.pyv'],
|
|
1693
1693
|
['qam', 'application/vnd.epson.quickanime'],
|
|
1694
1694
|
['qbo', 'application/vnd.intu.qbo'],
|
package/lib/mime-node/index.js
CHANGED
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
'use strict';
|
|
4
4
|
|
|
5
5
|
const crypto = require('crypto');
|
|
6
|
-
const os = require('os');
|
|
7
6
|
const fs = require('fs');
|
|
8
7
|
const punycode = require('punycode');
|
|
9
8
|
const PassThrough = require('stream').PassThrough;
|
|
@@ -1282,7 +1281,7 @@ class MimeNode {
|
|
|
1282
1281
|
) +
|
|
1283
1282
|
'@' +
|
|
1284
1283
|
// try to use the domain of the FROM address or fallback to server hostname
|
|
1285
|
-
(this.getEnvelope().from || this.hostname ||
|
|
1284
|
+
(this.getEnvelope().from || this.hostname || 'localhost').split('@').pop() +
|
|
1286
1285
|
'>'
|
|
1287
1286
|
);
|
|
1288
1287
|
}
|
package/lib/shared/index.js
CHANGED
|
@@ -12,23 +12,37 @@ const os = require('os');
|
|
|
12
12
|
|
|
13
13
|
const DNS_TTL = 5 * 60 * 1000;
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
let networkInterfaces;
|
|
16
|
+
try {
|
|
17
|
+
networkInterfaces = os.networkInterfaces();
|
|
18
|
+
} catch (err) {
|
|
19
|
+
// fails on some systems
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
module.exports.networkInterfaces = networkInterfaces;
|
|
23
|
+
|
|
24
|
+
const isFamilySupported = (family, allowInternal) => {
|
|
25
|
+
let networkInterfaces = module.exports.networkInterfaces;
|
|
26
|
+
if (!networkInterfaces) {
|
|
27
|
+
// hope for the best
|
|
28
|
+
return true;
|
|
29
|
+
}
|
|
16
30
|
|
|
17
|
-
const isFamilySupported = family => {
|
|
18
31
|
const familySupported =
|
|
19
32
|
// crux that replaces Object.values(networkInterfaces) as Object.values is not supported in nodejs v6
|
|
20
33
|
Object.keys(networkInterfaces)
|
|
21
34
|
.map(key => networkInterfaces[key])
|
|
22
35
|
// crux that replaces .flat() as it is not supported in older Node versions (v10 and older)
|
|
23
36
|
.reduce((acc, val) => acc.concat(val), [])
|
|
24
|
-
.filter(i => !i.internal)
|
|
37
|
+
.filter(i => !i.internal || allowInternal)
|
|
25
38
|
.filter(i => i.family === 'IPv' + family || i.family === family).length > 0;
|
|
26
39
|
|
|
27
40
|
return familySupported;
|
|
28
41
|
};
|
|
29
42
|
|
|
30
|
-
const resolver = (family, hostname, callback) => {
|
|
31
|
-
|
|
43
|
+
const resolver = (family, hostname, options, callback) => {
|
|
44
|
+
options = options || {};
|
|
45
|
+
const familySupported = isFamilySupported(family, options.allowInternalNetworkInterfaces);
|
|
32
46
|
|
|
33
47
|
if (!familySupported) {
|
|
34
48
|
return callback(null, []);
|
|
@@ -107,7 +121,7 @@ module.exports.resolveHostname = (options, callback) => {
|
|
|
107
121
|
}
|
|
108
122
|
}
|
|
109
123
|
|
|
110
|
-
resolver(4, options.host, (err, addresses) => {
|
|
124
|
+
resolver(4, options.host, options, (err, addresses) => {
|
|
111
125
|
if (err) {
|
|
112
126
|
if (cached) {
|
|
113
127
|
// ignore error, use expired value
|
|
@@ -141,7 +155,7 @@ module.exports.resolveHostname = (options, callback) => {
|
|
|
141
155
|
);
|
|
142
156
|
}
|
|
143
157
|
|
|
144
|
-
resolver(6, options.host, (err, addresses) => {
|
|
158
|
+
resolver(6, options.host, options, (err, addresses) => {
|
|
145
159
|
if (err) {
|
|
146
160
|
if (cached) {
|
|
147
161
|
// ignore error, use expired value
|
|
@@ -44,7 +44,7 @@ function httpProxyClient(proxyUrl, destinationPort, destinationHost, callback) {
|
|
|
44
44
|
// Error harness for initial connection. Once connection is established, the responsibility
|
|
45
45
|
// to handle errors is passed to whoever uses this socket
|
|
46
46
|
let finished = false;
|
|
47
|
-
let tempSocketErr =
|
|
47
|
+
let tempSocketErr = err => {
|
|
48
48
|
if (finished) {
|
|
49
49
|
return;
|
|
50
50
|
}
|
|
@@ -57,6 +57,12 @@ function httpProxyClient(proxyUrl, destinationPort, destinationHost, callback) {
|
|
|
57
57
|
callback(err);
|
|
58
58
|
};
|
|
59
59
|
|
|
60
|
+
let timeoutErr = () => {
|
|
61
|
+
let err = new Error('Proxy socket timed out');
|
|
62
|
+
err.code = 'ETIMEDOUT';
|
|
63
|
+
tempSocketErr(err);
|
|
64
|
+
};
|
|
65
|
+
|
|
60
66
|
socket = connect(options, () => {
|
|
61
67
|
if (finished) {
|
|
62
68
|
return;
|
|
@@ -119,12 +125,18 @@ function httpProxyClient(proxyUrl, destinationPort, destinationHost, callback) {
|
|
|
119
125
|
}
|
|
120
126
|
|
|
121
127
|
socket.removeListener('error', tempSocketErr);
|
|
128
|
+
socket.removeListener('timeout', timeoutErr);
|
|
129
|
+
socket.setTimeout(0);
|
|
130
|
+
|
|
122
131
|
return callback(null, socket);
|
|
123
132
|
}
|
|
124
133
|
};
|
|
125
134
|
socket.on('data', onSocketData);
|
|
126
135
|
});
|
|
127
136
|
|
|
137
|
+
socket.setTimeout(httpProxyClient.timeout || 30 * 1000);
|
|
138
|
+
socket.on('timeout', timeoutErr);
|
|
139
|
+
|
|
128
140
|
socket.once('error', tempSocketErr);
|
|
129
141
|
}
|
|
130
142
|
|
|
@@ -56,6 +56,8 @@ class SMTPConnection extends EventEmitter {
|
|
|
56
56
|
this.port = Number(this.options.port) || (this.secureConnection ? 465 : 587);
|
|
57
57
|
this.host = this.options.host || 'localhost';
|
|
58
58
|
|
|
59
|
+
this.allowInternalNetworkInterfaces = this.options.allowInternalNetworkInterfaces || false;
|
|
60
|
+
|
|
59
61
|
if (typeof this.options.secure === 'undefined' && this.port === 465) {
|
|
60
62
|
// if secure option is not set but port is 465, then default to secure
|
|
61
63
|
this.secureConnection = true;
|
|
@@ -217,7 +219,8 @@ class SMTPConnection extends EventEmitter {
|
|
|
217
219
|
|
|
218
220
|
let opts = {
|
|
219
221
|
port: this.port,
|
|
220
|
-
host: this.host
|
|
222
|
+
host: this.host,
|
|
223
|
+
allowInternalNetworkInterfaces: this.allowInternalNetworkInterfaces
|
|
221
224
|
};
|
|
222
225
|
|
|
223
226
|
if (this.options.localAddress) {
|
|
@@ -1755,10 +1758,16 @@ class SMTPConnection extends EventEmitter {
|
|
|
1755
1758
|
|
|
1756
1759
|
_getHostname() {
|
|
1757
1760
|
// defaul hostname is machine hostname or [IP]
|
|
1758
|
-
let defaultHostname
|
|
1761
|
+
let defaultHostname;
|
|
1762
|
+
try {
|
|
1763
|
+
defaultHostname = os.hostname() || '';
|
|
1764
|
+
} catch (err) {
|
|
1765
|
+
// fails on windows 7
|
|
1766
|
+
defaultHostname = 'localhost';
|
|
1767
|
+
}
|
|
1759
1768
|
|
|
1760
1769
|
// ignore if not FQDN
|
|
1761
|
-
if (defaultHostname.indexOf('.') < 0) {
|
|
1770
|
+
if (!defaultHostname || defaultHostname.indexOf('.') < 0) {
|
|
1762
1771
|
defaultHostname = '[127.0.0.1]';
|
|
1763
1772
|
}
|
|
1764
1773
|
|
package/lib/smtp-pool/index.js
CHANGED
|
@@ -627,6 +627,13 @@ class SMTPPool extends EventEmitter {
|
|
|
627
627
|
|
|
628
628
|
finalize();
|
|
629
629
|
});
|
|
630
|
+
} else if (!auth && connection.allowsAuth && options.forceAuth) {
|
|
631
|
+
let err = new Error('Authentication info was not provided');
|
|
632
|
+
err.code = 'NoAuth';
|
|
633
|
+
|
|
634
|
+
returned = true;
|
|
635
|
+
connection.close();
|
|
636
|
+
return callback(err);
|
|
630
637
|
} else {
|
|
631
638
|
finalize();
|
|
632
639
|
}
|
|
@@ -18,6 +18,7 @@ class SMTPTransport extends EventEmitter {
|
|
|
18
18
|
super();
|
|
19
19
|
|
|
20
20
|
options = options || {};
|
|
21
|
+
|
|
21
22
|
if (typeof options === 'string') {
|
|
22
23
|
options = {
|
|
23
24
|
url: options
|
|
@@ -384,6 +385,13 @@ class SMTPTransport extends EventEmitter {
|
|
|
384
385
|
|
|
385
386
|
finalize();
|
|
386
387
|
});
|
|
388
|
+
} else if (!authData && connection.allowsAuth && options.forceAuth) {
|
|
389
|
+
let err = new Error('Authentication info was not provided');
|
|
390
|
+
err.code = 'NoAuth';
|
|
391
|
+
|
|
392
|
+
returned = true;
|
|
393
|
+
connection.close();
|
|
394
|
+
return callback(err);
|
|
387
395
|
} else {
|
|
388
396
|
finalize();
|
|
389
397
|
}
|
|
@@ -11,6 +11,12 @@
|
|
|
11
11
|
"host": "smtp.aol.com",
|
|
12
12
|
"port": 587
|
|
13
13
|
},
|
|
14
|
+
|
|
15
|
+
"Bluewin": {
|
|
16
|
+
"host": "smtpauths.bluewin.ch",
|
|
17
|
+
"domains": ["bluewin.ch"],
|
|
18
|
+
"port": 465
|
|
19
|
+
},
|
|
14
20
|
|
|
15
21
|
"DebugMail": {
|
|
16
22
|
"host": "debugmail.io",
|
|
@@ -188,8 +194,8 @@
|
|
|
188
194
|
},
|
|
189
195
|
|
|
190
196
|
"SendCloud": {
|
|
191
|
-
"host": "
|
|
192
|
-
"port":
|
|
197
|
+
"host": "smtp.sendcloud.net",
|
|
198
|
+
"port": 2525
|
|
193
199
|
},
|
|
194
200
|
|
|
195
201
|
"SendGrid": {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nodemailer",
|
|
3
|
-
"version": "6.7.
|
|
3
|
+
"version": "6.7.7",
|
|
4
4
|
"description": "Easy as cake e-mail sending from your Node.js applications",
|
|
5
5
|
"main": "lib/nodemailer.js",
|
|
6
6
|
"scripts": {
|
|
@@ -20,24 +20,24 @@
|
|
|
20
20
|
},
|
|
21
21
|
"homepage": "https://nodemailer.com/",
|
|
22
22
|
"devDependencies": {
|
|
23
|
-
"@aws-sdk/client-ses": "3.
|
|
24
|
-
"aws-sdk": "2.
|
|
23
|
+
"@aws-sdk/client-ses": "3.121.0",
|
|
24
|
+
"aws-sdk": "2.1168.0",
|
|
25
25
|
"bunyan": "1.8.15",
|
|
26
26
|
"chai": "4.3.6",
|
|
27
27
|
"eslint-config-nodemailer": "1.2.0",
|
|
28
28
|
"eslint-config-prettier": "8.5.0",
|
|
29
|
-
"grunt": "1.5.
|
|
29
|
+
"grunt": "1.5.3",
|
|
30
30
|
"grunt-cli": "1.4.3",
|
|
31
31
|
"grunt-eslint": "24.0.0",
|
|
32
32
|
"grunt-mocha-test": "0.13.3",
|
|
33
33
|
"libbase64": "1.2.1",
|
|
34
34
|
"libmime": "5.1.0",
|
|
35
35
|
"libqp": "1.1.0",
|
|
36
|
-
"mocha": "
|
|
36
|
+
"mocha": "10.0.0",
|
|
37
37
|
"nodemailer-ntlm-auth": "1.0.1",
|
|
38
38
|
"proxy": "1.0.2",
|
|
39
39
|
"proxy-test-server": "1.0.0",
|
|
40
|
-
"sinon": "
|
|
40
|
+
"sinon": "14.0.0",
|
|
41
41
|
"smtp-server": "3.11.0"
|
|
42
42
|
},
|
|
43
43
|
"engines": {
|