nodemailer 6.6.0 → 6.6.4
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 +14 -0
- package/README.md +2 -4
- package/SECURITY.txt +22 -0
- package/lib/mime-node/index.js +27 -7
- package/lib/ses-transport/index.js +2 -1
- package/lib/shared/index.js +11 -0
- package/lib/smtp-connection/index.js +44 -17
- package/package.json +8 -6
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# CHANGELOG
|
|
2
2
|
|
|
3
|
+
## 6.6.4 2021-09-22
|
|
4
|
+
|
|
5
|
+
- Better compatibility with IPv6-only SMTP hosts (oxzi)
|
|
6
|
+
- Fix ses verify for sdk v3 (hannesvdvreken)
|
|
7
|
+
- Added SECURITY.txt for contact info
|
|
8
|
+
|
|
9
|
+
## 6.6.3 2021-07-14
|
|
10
|
+
|
|
11
|
+
- Do not show passwords in SMTP transaction logs. All passwords used in logging are replaced by `"/* secret */"`
|
|
12
|
+
|
|
13
|
+
## 6.6.1 2021-05-23
|
|
14
|
+
|
|
15
|
+
- Fixed address formatting issue where newlines in an email address, if provided via address object, were not properly removed. Reported by tmazeika (#1289)
|
|
16
|
+
|
|
3
17
|
## 6.6.0 2021-04-28
|
|
4
18
|
|
|
5
19
|
- Added new option `newline` for MailComposer
|
package/README.md
CHANGED
|
@@ -2,8 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://nodemailer.com/about/)
|
|
4
4
|
|
|
5
|
-
> Sponsored by [Forward Email](https://forwardemail.net/?ref=nodemailer) – free email forwarding + custom domains + 100% open-source!
|
|
6
|
-
|
|
7
5
|
Send e-mails from Node.js – easy as cake! 🍰✉️
|
|
8
6
|
|
|
9
7
|
[](https://nodemailer.com/about/)
|
|
@@ -30,8 +28,8 @@ Check your firewall settings. Timeout usually occurs when you try to open a conn
|
|
|
30
28
|
|
|
31
29
|
#### I get TLS errors
|
|
32
30
|
|
|
33
|
-
|
|
34
|
-
|
|
31
|
+
- 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.
|
|
32
|
+
- 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.
|
|
35
33
|
|
|
36
34
|
#### I have a different problem
|
|
37
35
|
|
package/SECURITY.txt
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
-----BEGIN PGP SIGNED MESSAGE-----
|
|
2
|
+
Hash: SHA256
|
|
3
|
+
|
|
4
|
+
Contact: mailto:andris@reinman.eu
|
|
5
|
+
Encryption: https://keys.openpgp.org/vks/v1/by-fingerprint/5D952A46E1D8C931F6364E01DC6C83F4D584D364
|
|
6
|
+
Preferred-Languages: en, et
|
|
7
|
+
-----BEGIN PGP SIGNATURE-----
|
|
8
|
+
|
|
9
|
+
iQIzBAEBCAAdFiEEXZUqRuHYyTH2Nk4B3GyD9NWE02QFAmFDnUgACgkQ3GyD9NWE
|
|
10
|
+
02RqUA/+MM3afmRYq874C7wp+uN6dTMCvUX5g5zqBZ2yKpFr46L+PYvM7o8TMm5h
|
|
11
|
+
hmLT2I1zZmi+xezOL3zHFizaw0tKkZIz9cWl3Jrgs0FLp0zOsSz1xucp9Q2tYM/Q
|
|
12
|
+
vbiP6ys0gbim4tkDGRmZOEiO23s0BuRnmHt7vZg210O+D105Yd8/Ohzbj6PSLBO5
|
|
13
|
+
W1tA7Xw5t0FQ14NNH5+MKyDIKoCX12n0FmrC6qLTXeojf291UgKhCUPda3LIGTmx
|
|
14
|
+
mTXz0y68149Mw+JikRCYP8HfGRY9eA4XZrYXF7Bl2T9OJpKD3JAH+69P3xBw19Gn
|
|
15
|
+
Csaw3twu8P1bxoVGjY4KRrBOp68W8TwZYjWVWbqY6oV8hb/JfrMxa+kaSxRuloFs
|
|
16
|
+
oL6+phrDSPTWdOj2LlEDBJbPOMeDFzIlsBBcJ/JHCEHTvlHl7LoWr3YuWce9PUwl
|
|
17
|
+
4r3JUovvaeuJxLgC0vu3WCB3Jeocsl3SreqNkrVc1IjvkSomn3YGm5nCNAd/2F0V
|
|
18
|
+
exCGRk/8wbkSjAY38GwQ8K/VuFsefWN3L9sVwIMAMu88KFCAN+GzVFiwvyIXehF5
|
|
19
|
+
eogP9mIXzdQ5YReQjUjApOzGz54XnDyv9RJ3sdvMHosLP+IOg+0q5t9agWv6aqSR
|
|
20
|
+
2HzCpiQnH/gmM5NS0AU4Koq/L7IBeLu1B8+61/+BiHgZJJmPdgU=
|
|
21
|
+
=BUZr
|
|
22
|
+
-----END PGP SIGNATURE-----
|
package/lib/mime-node/index.js
CHANGED
|
@@ -1147,9 +1147,9 @@ class MimeNode {
|
|
|
1147
1147
|
address.address = this._normalizeAddress(address.address);
|
|
1148
1148
|
|
|
1149
1149
|
if (!address.name) {
|
|
1150
|
-
values.push(address.address);
|
|
1150
|
+
values.push(address.address.indexOf(' ') >= 0 ? `<${address.address}>` : `${address.address}`);
|
|
1151
1151
|
} else if (address.name) {
|
|
1152
|
-
values.push(this._encodeAddressName(address.name)
|
|
1152
|
+
values.push(`${this._encodeAddressName(address.name)} <${address.address}>`);
|
|
1153
1153
|
}
|
|
1154
1154
|
|
|
1155
1155
|
if (address.address) {
|
|
@@ -1158,9 +1158,8 @@ class MimeNode {
|
|
|
1158
1158
|
}
|
|
1159
1159
|
}
|
|
1160
1160
|
} else if (address.group) {
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
);
|
|
1161
|
+
let groupListAddresses = (address.group.length ? this._convertAddresses(address.group, uniqueList) : '').trim();
|
|
1162
|
+
values.push(`${this._encodeAddressName(address.name)}:${groupListAddresses};`);
|
|
1164
1163
|
}
|
|
1165
1164
|
});
|
|
1166
1165
|
|
|
@@ -1174,13 +1173,17 @@ class MimeNode {
|
|
|
1174
1173
|
* @return {String} address string
|
|
1175
1174
|
*/
|
|
1176
1175
|
_normalizeAddress(address) {
|
|
1177
|
-
address = (address || '')
|
|
1176
|
+
address = (address || '')
|
|
1177
|
+
.toString()
|
|
1178
|
+
.replace(/[\x00-\x1F<>]+/g, ' ') // remove unallowed characters
|
|
1179
|
+
.trim();
|
|
1178
1180
|
|
|
1179
1181
|
let lastAt = address.lastIndexOf('@');
|
|
1180
1182
|
if (lastAt < 0) {
|
|
1181
1183
|
// Bare username
|
|
1182
1184
|
return address;
|
|
1183
1185
|
}
|
|
1186
|
+
|
|
1184
1187
|
let user = address.substr(0, lastAt);
|
|
1185
1188
|
let domain = address.substr(lastAt + 1);
|
|
1186
1189
|
|
|
@@ -1189,7 +1192,24 @@ class MimeNode {
|
|
|
1189
1192
|
// 'jõgeva.ee' will be converted to 'xn--jgeva-dua.ee'
|
|
1190
1193
|
// non-unicode domains are left as is
|
|
1191
1194
|
|
|
1192
|
-
|
|
1195
|
+
let encodedDomain;
|
|
1196
|
+
|
|
1197
|
+
try {
|
|
1198
|
+
encodedDomain = punycode.toASCII(domain.toLowerCase());
|
|
1199
|
+
} catch (err) {
|
|
1200
|
+
// keep as is?
|
|
1201
|
+
}
|
|
1202
|
+
|
|
1203
|
+
if (user.indexOf(' ') >= 0) {
|
|
1204
|
+
if (user.charAt(0) !== '"') {
|
|
1205
|
+
user = '"' + user;
|
|
1206
|
+
}
|
|
1207
|
+
if (user.substr(-1) !== '"') {
|
|
1208
|
+
user = user + '"';
|
|
1209
|
+
}
|
|
1210
|
+
}
|
|
1211
|
+
|
|
1212
|
+
return `${user}@${encodedDomain}`;
|
|
1193
1213
|
}
|
|
1194
1214
|
|
|
1195
1215
|
/**
|
|
@@ -321,7 +321,7 @@ class SESTransport extends EventEmitter {
|
|
|
321
321
|
Destinations: ['invalid@invalid']
|
|
322
322
|
};
|
|
323
323
|
const cb = err => {
|
|
324
|
-
if (err && err.code !== 'InvalidParameterValue') {
|
|
324
|
+
if (err && (err.code || err.Code) !== 'InvalidParameterValue') {
|
|
325
325
|
return callback(err);
|
|
326
326
|
}
|
|
327
327
|
return callback(null, true);
|
|
@@ -335,6 +335,7 @@ class SESTransport extends EventEmitter {
|
|
|
335
335
|
|
|
336
336
|
if (typeof ses.send === 'function' && aws.SendRawEmailCommand) {
|
|
337
337
|
// v3 API
|
|
338
|
+
sesMessage.RawMessage.Data = Buffer.from(sesMessage.RawMessage.Data);
|
|
338
339
|
ses.send(new aws.SendRawEmailCommand(sesMessage), cb);
|
|
339
340
|
} else {
|
|
340
341
|
// v2 API
|
package/lib/shared/index.js
CHANGED
|
@@ -8,10 +8,21 @@ const fs = require('fs');
|
|
|
8
8
|
const fetch = require('../fetch');
|
|
9
9
|
const dns = require('dns');
|
|
10
10
|
const net = require('net');
|
|
11
|
+
const os = require('os');
|
|
11
12
|
|
|
12
13
|
const DNS_TTL = 5 * 60 * 1000;
|
|
13
14
|
|
|
14
15
|
const resolver = (family, hostname, callback) => {
|
|
16
|
+
const familySupported = Object.values(os.networkInterfaces()).
|
|
17
|
+
flat().
|
|
18
|
+
filter(i => !i.internal).
|
|
19
|
+
filter(i => i.family === 'IPv' + family).
|
|
20
|
+
length > 0;
|
|
21
|
+
|
|
22
|
+
if (!familySupported) {
|
|
23
|
+
return callback(null, []);
|
|
24
|
+
}
|
|
25
|
+
|
|
15
26
|
dns['resolve' + family](hostname, (err, addresses) => {
|
|
16
27
|
if (err) {
|
|
17
28
|
switch (err.code) {
|
|
@@ -548,6 +548,16 @@ class SMTPConnection extends EventEmitter {
|
|
|
548
548
|
'\u0000' +
|
|
549
549
|
this._auth.credentials.pass,
|
|
550
550
|
'utf-8'
|
|
551
|
+
).toString('base64'),
|
|
552
|
+
// log entry without passwords
|
|
553
|
+
'AUTH PLAIN ' +
|
|
554
|
+
Buffer.from(
|
|
555
|
+
//this._auth.user+'\u0000'+
|
|
556
|
+
'\u0000' + // skip authorization identity as it causes problems with some servers
|
|
557
|
+
this._auth.credentials.user +
|
|
558
|
+
'\u0000' +
|
|
559
|
+
'/* secret */',
|
|
560
|
+
'utf-8'
|
|
551
561
|
).toString('base64')
|
|
552
562
|
);
|
|
553
563
|
return;
|
|
@@ -873,16 +883,21 @@ class SMTPConnection extends EventEmitter {
|
|
|
873
883
|
});
|
|
874
884
|
|
|
875
885
|
this.upgrading = true;
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
this.
|
|
879
|
-
|
|
886
|
+
// tls.connect is not an asynchronous function however it may still throw errors and requires to be wrapped with try/catch
|
|
887
|
+
try {
|
|
888
|
+
this._socket = tls.connect(opts, () => {
|
|
889
|
+
this.secure = true;
|
|
890
|
+
this.upgrading = false;
|
|
891
|
+
this._socket.on('data', this._onSocketData);
|
|
880
892
|
|
|
881
|
-
|
|
882
|
-
|
|
893
|
+
socketPlain.removeListener('close', this._onSocketClose);
|
|
894
|
+
socketPlain.removeListener('end', this._onSocketEnd);
|
|
883
895
|
|
|
884
|
-
|
|
885
|
-
|
|
896
|
+
return callback(null, true);
|
|
897
|
+
});
|
|
898
|
+
} catch (err) {
|
|
899
|
+
return callback(err);
|
|
900
|
+
}
|
|
886
901
|
|
|
887
902
|
this._socket.on('error', this._onSocketError);
|
|
888
903
|
this._socket.once('close', this._onSocketClose);
|
|
@@ -940,8 +955,9 @@ class SMTPConnection extends EventEmitter {
|
|
|
940
955
|
* Send a command to the server, append \r\n
|
|
941
956
|
*
|
|
942
957
|
* @param {String} str String to be sent to the server
|
|
958
|
+
* @param {String} logStr Optional string to be used for logging instead of the actual string
|
|
943
959
|
*/
|
|
944
|
-
_sendCommand(str) {
|
|
960
|
+
_sendCommand(str, logStr) {
|
|
945
961
|
if (this._destroyed) {
|
|
946
962
|
// Connection already closed, can't send any more data
|
|
947
963
|
return;
|
|
@@ -956,7 +972,7 @@ class SMTPConnection extends EventEmitter {
|
|
|
956
972
|
{
|
|
957
973
|
tnx: 'client'
|
|
958
974
|
},
|
|
959
|
-
(str || '').toString().replace(/\r?\n$/, '')
|
|
975
|
+
(logStr || str || '').toString().replace(/\r?\n$/, '')
|
|
960
976
|
);
|
|
961
977
|
}
|
|
962
978
|
|
|
@@ -1415,18 +1431,21 @@ class SMTPConnection extends EventEmitter {
|
|
|
1415
1431
|
|
|
1416
1432
|
// Decode from base64
|
|
1417
1433
|
let base64decoded = Buffer.from(challengeString, 'base64').toString('ascii'),
|
|
1418
|
-
|
|
1434
|
+
hmacMD5 = crypto.createHmac('md5', this._auth.credentials.pass);
|
|
1419
1435
|
|
|
1420
|
-
|
|
1436
|
+
hmacMD5.update(base64decoded);
|
|
1421
1437
|
|
|
1422
|
-
let
|
|
1423
|
-
let prepended = this._auth.credentials.user + ' ' + hex_hmac;
|
|
1438
|
+
let prepended = this._auth.credentials.user + ' ' + hmacMD5.digest('hex');
|
|
1424
1439
|
|
|
1425
1440
|
this._responseActions.push(str => {
|
|
1426
1441
|
this._actionAUTH_CRAM_MD5_PASS(str, callback);
|
|
1427
1442
|
});
|
|
1428
1443
|
|
|
1429
|
-
this._sendCommand(
|
|
1444
|
+
this._sendCommand(
|
|
1445
|
+
Buffer.from(prepended).toString('base64'),
|
|
1446
|
+
// hidden hash for logs
|
|
1447
|
+
Buffer.from(this._auth.credentials.user + ' /* secret */').toString('base64')
|
|
1448
|
+
);
|
|
1430
1449
|
}
|
|
1431
1450
|
|
|
1432
1451
|
/**
|
|
@@ -1471,7 +1490,11 @@ class SMTPConnection extends EventEmitter {
|
|
|
1471
1490
|
this._actionAUTHComplete(str, callback);
|
|
1472
1491
|
});
|
|
1473
1492
|
|
|
1474
|
-
this._sendCommand(
|
|
1493
|
+
this._sendCommand(
|
|
1494
|
+
Buffer.from((this._auth.credentials.pass || '').toString(), 'utf-8').toString('base64'),
|
|
1495
|
+
// Hidden pass for logs
|
|
1496
|
+
Buffer.from('/* secret */', 'utf-8').toString('base64')
|
|
1497
|
+
);
|
|
1475
1498
|
}
|
|
1476
1499
|
|
|
1477
1500
|
/**
|
|
@@ -1701,7 +1724,11 @@ class SMTPConnection extends EventEmitter {
|
|
|
1701
1724
|
this._responseActions.push(str => {
|
|
1702
1725
|
this._actionAUTHComplete(str, isRetry, callback);
|
|
1703
1726
|
});
|
|
1704
|
-
this._sendCommand(
|
|
1727
|
+
this._sendCommand(
|
|
1728
|
+
'AUTH XOAUTH2 ' + this._auth.oauth2.buildXOAuth2Token(accessToken),
|
|
1729
|
+
// Hidden for logs
|
|
1730
|
+
'AUTH XOAUTH2 ' + this._auth.oauth2.buildXOAuth2Token('/* secret */')
|
|
1731
|
+
);
|
|
1705
1732
|
});
|
|
1706
1733
|
}
|
|
1707
1734
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nodemailer",
|
|
3
|
-
"version": "6.6.
|
|
3
|
+
"version": "6.6.4",
|
|
4
4
|
"description": "Easy as cake e-mail sending from your Node.js applications",
|
|
5
5
|
"main": "lib/nodemailer.js",
|
|
6
6
|
"scripts": {
|
|
@@ -20,23 +20,25 @@
|
|
|
20
20
|
},
|
|
21
21
|
"homepage": "https://nodemailer.com/",
|
|
22
22
|
"devDependencies": {
|
|
23
|
+
"@aws-sdk/client-ses": "3.33.0",
|
|
24
|
+
"aws-sdk": "2.993.0",
|
|
23
25
|
"bunyan": "1.8.15",
|
|
24
26
|
"chai": "4.3.4",
|
|
25
27
|
"eslint-config-nodemailer": "1.2.0",
|
|
26
28
|
"eslint-config-prettier": "8.3.0",
|
|
27
|
-
"grunt": "1.4.
|
|
28
|
-
"grunt-cli": "1.4.
|
|
29
|
+
"grunt": "1.4.1",
|
|
30
|
+
"grunt-cli": "1.4.3",
|
|
29
31
|
"grunt-eslint": "23.0.0",
|
|
30
32
|
"grunt-mocha-test": "0.13.3",
|
|
31
33
|
"libbase64": "1.2.1",
|
|
32
34
|
"libmime": "5.0.0",
|
|
33
35
|
"libqp": "1.1.0",
|
|
34
|
-
"mocha": "
|
|
36
|
+
"mocha": "9.1.1",
|
|
35
37
|
"nodemailer-ntlm-auth": "1.0.1",
|
|
36
38
|
"proxy": "1.0.2",
|
|
37
39
|
"proxy-test-server": "1.0.0",
|
|
38
|
-
"sinon": "
|
|
39
|
-
"smtp-server": "3.
|
|
40
|
+
"sinon": "11.1.2",
|
|
41
|
+
"smtp-server": "3.9.0"
|
|
40
42
|
},
|
|
41
43
|
"engines": {
|
|
42
44
|
"node": ">=6.0.0"
|