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 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
  [![Nodemailer](https://raw.githubusercontent.com/nodemailer/nodemailer/master/assets/nm_logo_200x136.png)](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
  [![NPM](https://nodei.co/npm/nodemailer.png?downloads=true&downloadRank=true&stars=true)](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
- * 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.
34
- * 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.
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-----
@@ -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) + ' <' + address.address + '>');
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
- values.push(
1162
- this._encodeAddressName(address.name) + ':' + (address.group.length ? this._convertAddresses(address.group, uniqueList) : '').trim() + ';'
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 || '').toString().trim();
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
- return user + '@' + punycode.toASCII(domain.toLowerCase());
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
@@ -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
- this._socket = tls.connect(opts, () => {
877
- this.secure = true;
878
- this.upgrading = false;
879
- this._socket.on('data', this._onSocketData);
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
- socketPlain.removeListener('close', this._onSocketClose);
882
- socketPlain.removeListener('end', this._onSocketEnd);
893
+ socketPlain.removeListener('close', this._onSocketClose);
894
+ socketPlain.removeListener('end', this._onSocketEnd);
883
895
 
884
- return callback(null, true);
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
- hmac_md5 = crypto.createHmac('md5', this._auth.credentials.pass);
1434
+ hmacMD5 = crypto.createHmac('md5', this._auth.credentials.pass);
1419
1435
 
1420
- hmac_md5.update(base64decoded);
1436
+ hmacMD5.update(base64decoded);
1421
1437
 
1422
- let hex_hmac = hmac_md5.digest('hex');
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(Buffer.from(prepended).toString('base64'));
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(Buffer.from(this._auth.credentials.pass + '', 'utf-8').toString('base64'));
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('AUTH XOAUTH2 ' + this._auth.oauth2.buildXOAuth2Token(accessToken));
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.0",
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.0",
28
- "grunt-cli": "1.4.2",
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": "8.3.2",
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": "10.0.0",
39
- "smtp-server": "3.8.0"
40
+ "sinon": "11.1.2",
41
+ "smtp-server": "3.9.0"
40
42
  },
41
43
  "engines": {
42
44
  "node": ">=6.0.0"