nodemailer 6.4.13 → 6.4.17

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,12 +1,28 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## 6.4.17 2020-12-11
4
+
5
+ - Allow mixing attachments with caendar alternatives
6
+
7
+ ## 6.4.16 2020-11-12
8
+
9
+ - Applied updated prettier formating rules
10
+
11
+ ## 6.4.15 2020-11-06
12
+
13
+ - Minor changes in header key casing
14
+
15
+ ## 6.4.14 2020-10-14
16
+
17
+ - Disabled postinstall script
18
+
3
19
  ## 6.4.13 2020-10-02
4
20
 
5
21
  - Fix normalizeHeaderKey method for single node messages
6
22
 
7
23
  ## 6.4.12 2020-09-30
8
24
 
9
- - Better handling of attadhment filenames that include quote symbols
25
+ - Better handling of attachment filenames that include quote symbols
10
26
  - Includes all information from the oath2 error response in the error message (Normal Gaussian) [1787f227]
11
27
 
12
28
  ## 6.4.11 2020-07-29
@@ -146,10 +146,7 @@ class MessageParser extends Transform {
146
146
  return lines
147
147
  .filter(line => line.trim())
148
148
  .map(line => ({
149
- key: line
150
- .substr(0, line.indexOf(':'))
151
- .trim()
152
- .toLowerCase(),
149
+ key: line.substr(0, line.indexOf(':')).trim().toLowerCase(),
153
150
  line
154
151
  }));
155
152
  }
@@ -110,10 +110,7 @@ class Cookies {
110
110
  .split(';')
111
111
  .forEach(cookiePart => {
112
112
  let valueParts = cookiePart.split('=');
113
- let key = valueParts
114
- .shift()
115
- .trim()
116
- .toLowerCase();
113
+ let key = valueParts.shift().trim().toLowerCase();
117
114
  let value = valueParts.join('=').trim();
118
115
  let domain;
119
116
 
@@ -10,7 +10,7 @@ const packageData = require('../../package.json');
10
10
 
11
11
  const MAX_REDIRECTS = 5;
12
12
 
13
- module.exports = function(url, options) {
13
+ module.exports = function (url, options) {
14
14
  return fetch(url, options);
15
15
  };
16
16
 
@@ -33,11 +33,7 @@ function fetch(url, options) {
33
33
 
34
34
  let fetchRes = options.fetchRes;
35
35
  let parsed = urllib.parse(url);
36
- let method =
37
- (options.method || '')
38
- .toString()
39
- .trim()
40
- .toUpperCase() || 'GET';
36
+ let method = (options.method || '').toString().trim().toUpperCase() || 'GET';
41
37
  let finished = false;
42
38
  let cookies;
43
39
  let body;
@@ -115,11 +111,7 @@ function fetch(url, options) {
115
111
  headers['Content-Length'] = body.length;
116
112
  }
117
113
  // if method is not provided, use POST instead of GET
118
- method =
119
- (options.method || '')
120
- .toString()
121
- .trim()
122
- .toUpperCase() || 'POST';
114
+ method = (options.method || '').toString().trim().toUpperCase() || 'POST';
123
115
  }
124
116
 
125
117
  let req;
@@ -230,9 +230,8 @@ class MailComposer {
230
230
  amp.contentType = 'text/x-amp-html; charset=utf-8';
231
231
  }
232
232
 
233
- // only include the calendar alternative if there are no attachments
234
- // otherwise you might end up in a blank screen on some clients
235
- if (this.mail.icalEvent && !(this.mail.attachments && this.mail.attachments.length)) {
233
+ // NB! when including attachments with a calendar alternative you might end up in a blank screen on some clients
234
+ if (this.mail.icalEvent) {
236
235
  if (
237
236
  typeof this.mail.icalEvent === 'object' &&
238
237
  (this.mail.icalEvent.content || this.mail.icalEvent.path || this.mail.icalEvent.href || this.mail.icalEvent.raw)
@@ -64,12 +64,7 @@ class MailMessage {
64
64
  if (this.data.attachments && this.data.attachments.length) {
65
65
  this.data.attachments.forEach((attachment, i) => {
66
66
  if (!attachment.filename) {
67
- attachment.filename =
68
- (attachment.path || attachment.href || '')
69
- .split('/')
70
- .pop()
71
- .split('?')
72
- .shift() || 'attachment-' + (i + 1);
67
+ attachment.filename = (attachment.path || attachment.href || '').split('/').pop().split('?').shift() || 'attachment-' + (i + 1);
73
68
  if (attachment.filename.indexOf('.') < 0) {
74
69
  attachment.filename += '.' + mimeFuncs.detectExtension(attachment.contentType);
75
70
  }
@@ -2063,11 +2063,7 @@ module.exports = {
2063
2063
  }
2064
2064
 
2065
2065
  let parsed = path.parse(filename);
2066
- let extension = (parsed.ext.substr(1) || parsed.name || '')
2067
- .split('?')
2068
- .shift()
2069
- .trim()
2070
- .toLowerCase();
2066
+ let extension = (parsed.ext.substr(1) || parsed.name || '').split('?').shift().trim().toLowerCase();
2071
2067
  let value = defaultMimeType;
2072
2068
 
2073
2069
  if (extensions.has(extension)) {
@@ -2084,10 +2080,7 @@ module.exports = {
2084
2080
  if (!mimeType) {
2085
2081
  return defaultExtension;
2086
2082
  }
2087
- let parts = (mimeType || '')
2088
- .toLowerCase()
2089
- .trim()
2090
- .split('/');
2083
+ let parts = (mimeType || '').toLowerCase().trim().split('/');
2091
2084
  let rootType = parts.shift().trim();
2092
2085
  let subType = parts.join('/').trim();
2093
2086
 
@@ -999,7 +999,7 @@ class MimeNode {
999
999
  .trim()
1000
1000
  .toLowerCase()
1001
1001
  // use uppercase words, except MIME
1002
- .replace(/^X-SMTPAPI$|^(MIME|DKIM)\b|^[a-z]|-(SPF|FBL|ID|MD5)$|-[a-z]/gi, c => c.toUpperCase())
1002
+ .replace(/^X-SMTPAPI$|^(MIME|DKIM|ARC|BIMI)\b|^[a-z]|-(SPF|FBL|ID|MD5)$|-[a-z]/gi, c => c.toUpperCase())
1003
1003
  // special case
1004
1004
  .replace(/^Content-Features$/i, 'Content-features');
1005
1005
 
package/lib/nodemailer.js CHANGED
@@ -13,16 +13,11 @@ const packageData = require('../package.json');
13
13
 
14
14
  const ETHEREAL_API = (process.env.ETHEREAL_API || 'https://api.nodemailer.com').replace(/\/+$/, '');
15
15
  const ETHEREAL_WEB = (process.env.ETHEREAL_WEB || 'https://ethereal.email').replace(/\/+$/, '');
16
- const ETHEREAL_CACHE = ['true', 'yes', 'y', '1'].includes(
17
- (process.env.ETHEREAL_CACHE || 'yes')
18
- .toString()
19
- .trim()
20
- .toLowerCase()
21
- );
16
+ const ETHEREAL_CACHE = ['true', 'yes', 'y', '1'].includes((process.env.ETHEREAL_CACHE || 'yes').toString().trim().toLowerCase());
22
17
 
23
18
  let testAccount = false;
24
19
 
25
- module.exports.createTransport = function(transporter, defaults) {
20
+ module.exports.createTransport = function (transporter, defaults) {
26
21
  let urlConfig;
27
22
  let options;
28
23
  let mailer;
@@ -60,7 +55,7 @@ module.exports.createTransport = function(transporter, defaults) {
60
55
  return mailer;
61
56
  };
62
57
 
63
- module.exports.createTestAccount = function(apiUrl, callback) {
58
+ module.exports.createTestAccount = function (apiUrl, callback) {
64
59
  let promise;
65
60
 
66
61
  if (!callback && typeof apiUrl === 'function') {
@@ -128,7 +123,7 @@ module.exports.createTestAccount = function(apiUrl, callback) {
128
123
  return promise;
129
124
  };
130
125
 
131
- module.exports.getTestMessageUrl = function(info) {
126
+ module.exports.getTestMessageUrl = function (info) {
132
127
  if (!info || !info.response) {
133
128
  return false;
134
129
  }
@@ -70,6 +70,14 @@ class SendmailTransport {
70
70
  let returned;
71
71
  let transform;
72
72
 
73
+ const hasInvalidAddresses = []
74
+ .concat(envelope.from || [])
75
+ .concat(envelope.to || [])
76
+ .some(addr => /^-/.test(addr));
77
+ if (hasInvalidAddresses) {
78
+ return done(new Error('Can not send mail. Invalid envelope addresses.'));
79
+ }
80
+
73
81
  if (this.args) {
74
82
  // force -i to keep single dots
75
83
  args = ['-i'].concat(this.args).concat(envelope.to);
@@ -38,7 +38,7 @@ class SESTransport extends EventEmitter {
38
38
  // max messages per second
39
39
  this.sendingRate = Number(this.options.sendingRate) || Infinity;
40
40
  this.sendingRateTTL = null;
41
- this.rateInterval = 1000;
41
+ this.rateInterval = 1000; // milliseconds
42
42
  this.rateMessages = [];
43
43
 
44
44
  this.pending = [];
@@ -276,7 +276,7 @@ module.exports.getLogger = (options, defaults) => {
276
276
  * @param {Function} reject Function to run if callback ends with an error
277
277
  */
278
278
  module.exports.callbackPromise = (resolve, reject) =>
279
- function() {
279
+ function () {
280
280
  let args = Array.from(arguments);
281
281
  let err = args.shift();
282
282
  if (err) {
@@ -357,7 +357,7 @@ module.exports.resolveContent = (data, key, callback) => {
357
357
  /**
358
358
  * Copies properties from source objects to target objects
359
359
  */
360
- module.exports.assign = function(/* target, ... sources */) {
360
+ module.exports.assign = function (/* target, ... sources */) {
361
361
  let args = Array.from(arguments);
362
362
  let target = args.shift() || {};
363
363
 
@@ -489,15 +489,7 @@ function createDefaultLogger(levels) {
489
489
 
490
490
  message = util.format(message, ...args);
491
491
  message.split(/\r?\n/).forEach(line => {
492
- console.log(
493
- '[%s] %s %s',
494
- new Date()
495
- .toISOString()
496
- .substr(0, 19)
497
- .replace(/T/, ' '),
498
- levelNames.get(level),
499
- prefix + line
500
- );
492
+ console.log('[%s] %s %s', new Date().toISOString().substr(0, 19).replace(/T/, ' '), levelNames.get(level), prefix + line);
501
493
  });
502
494
  };
503
495
 
@@ -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 = function(err) {
47
+ let tempSocketErr = function (err) {
48
48
  if (finished) {
49
49
  return;
50
50
  }
@@ -45,10 +45,7 @@ class SMTPConnection extends EventEmitter {
45
45
  constructor(options) {
46
46
  super(options);
47
47
 
48
- this.id = crypto
49
- .randomBytes(8)
50
- .toString('base64')
51
- .replace(/\W/g, '');
48
+ this.id = crypto.randomBytes(8).toString('base64').replace(/\W/g, '');
52
49
  this.stage = 'init';
53
50
 
54
51
  this.options = options || {};
@@ -73,10 +70,7 @@ class SMTPConnection extends EventEmitter {
73
70
 
74
71
  this.customAuth = new Map();
75
72
  Object.keys(this.options.customAuth || {}).forEach(key => {
76
- let mapKey = (key || '')
77
- .toString()
78
- .trim()
79
- .toUpperCase();
73
+ let mapKey = (key || '').toString().trim().toUpperCase();
80
74
  if (!mapKey) {
81
75
  return;
82
76
  }
@@ -424,11 +418,7 @@ class SMTPConnection extends EventEmitter {
424
418
 
425
419
  this._auth = authData || {};
426
420
  // Select SASL authentication method
427
- this._authMethod =
428
- (this._auth.method || '')
429
- .toString()
430
- .trim()
431
- .toUpperCase() || false;
421
+ this._authMethod = (this._auth.method || '').toString().trim().toUpperCase() || false;
432
422
 
433
423
  if (!this._authMethod && this._auth.oauth2 && !this._auth.credentials) {
434
424
  this._authMethod = 'XOAUTH2';
@@ -598,7 +588,7 @@ class SMTPConnection extends EventEmitter {
598
588
 
599
589
  // ensure that callback is only called once
600
590
  let returned = false;
601
- let callback = function() {
591
+ let callback = function () {
602
592
  if (returned) {
603
593
  return;
604
594
  }
@@ -41,7 +41,7 @@ function normalizeService(service) {
41
41
  * @param {String} key [description]
42
42
  * @returns {Object} SMTP config or false if not found
43
43
  */
44
- module.exports = function(key) {
44
+ module.exports = function (key) {
45
45
  key = normalizeKey(key.split('@').pop());
46
46
  return normalized[key] || false;
47
47
  };
@@ -23,6 +23,12 @@
23
23
  "port": 25
24
24
  },
25
25
 
26
+ "Ethereal": {
27
+ "aliases": ["ethereal.email"],
28
+ "host": "smtp.ethereal.email",
29
+ "port": 587
30
+ },
31
+
26
32
  "FastMail": {
27
33
  "domains": ["fastmail.fm"],
28
34
  "host": "smtp.fastmail.com",
@@ -263,11 +263,11 @@ class XOAuth2 extends Stream {
263
263
  if (data.error) {
264
264
  // Error Response : https://tools.ietf.org/html/rfc6749#section-5.2
265
265
  let errorMessage = data.error;
266
- if(data.error_description) {
267
- errorMessage += ': ' + data.error_description;
266
+ if (data.error_description) {
267
+ errorMessage += ': ' + data.error_description;
268
268
  }
269
- if(data.error_uri) {
270
- errorMessage += ' (' + data.error_uri + ')';
269
+ if (data.error_uri) {
270
+ errorMessage += ' (' + data.error_uri + ')';
271
271
  }
272
272
  return callback(new Error(errorMessage));
273
273
  }
package/package.json CHANGED
@@ -1,11 +1,10 @@
1
1
  {
2
2
  "name": "nodemailer",
3
- "version": "6.4.13",
3
+ "version": "6.4.17",
4
4
  "description": "Easy as cake e-mail sending from your Node.js applications",
5
5
  "main": "lib/nodemailer.js",
6
6
  "scripts": {
7
- "test": "grunt",
8
- "postinstall": "node -e \"try{require('./postinstall')}catch(e){}\""
7
+ "test": "grunt"
9
8
  },
10
9
  "repository": {
11
10
  "type": "git",
@@ -24,7 +23,7 @@
24
23
  "bunyan": "1.8.14",
25
24
  "chai": "4.2.0",
26
25
  "eslint-config-nodemailer": "1.2.0",
27
- "eslint-config-prettier": "6.12.0",
26
+ "eslint-config-prettier": "7.0.0",
28
27
  "grunt": "1.3.0",
29
28
  "grunt-cli": "1.3.2",
30
29
  "grunt-eslint": "23.0.0",
@@ -32,12 +31,12 @@
32
31
  "libbase64": "1.2.1",
33
32
  "libmime": "5.0.0",
34
33
  "libqp": "1.1.0",
35
- "mocha": "8.1.3",
34
+ "mocha": "8.2.1",
36
35
  "nodemailer-ntlm-auth": "1.0.1",
37
36
  "proxy": "1.0.2",
38
37
  "proxy-test-server": "1.0.0",
39
- "sinon": "9.1.0",
40
- "smtp-server": "3.7.0"
38
+ "sinon": "9.2.1",
39
+ "smtp-server": "3.8.0"
41
40
  },
42
41
  "engines": {
43
42
  "node": ">=6.0.0"