nodemailer 6.4.4 → 6.4.8

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/.prettierrc.js CHANGED
@@ -1,5 +1,8 @@
1
1
  module.exports = {
2
2
  printWidth: 160,
3
3
  tabWidth: 4,
4
- singleQuote: true
4
+ singleQuote: true,
5
+ endOfLine: 'lf',
6
+ trailingComma: 'none',
7
+ arrowParens: 'avoid'
5
8
  };
package/CHANGELOG.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## 6.4.7 2020-05-28
4
+
5
+ - Always set charset=utf-8 for Content-Type headers
6
+ - Catch error whn using invalid crypto.sign input
7
+
8
+ ## 6.4.6 2020-03-20
9
+
10
+ - fix: `requeueAttempts=n` should requeue `n` times (Patrick Malouin) [a27ed2f7]
11
+
3
12
  ## 6.4.4 2020-03-01
4
13
 
5
14
  - Add `options.forceAuth` for SMTP (Patrick Malouin) [a27ed2f7]
@@ -100,12 +100,7 @@ class MailComposer {
100
100
  if (attachment.filename) {
101
101
  data.filename = attachment.filename;
102
102
  } else if (!isMessageNode && attachment.filename !== false) {
103
- data.filename =
104
- (attachment.path || attachment.href || '')
105
- .split('/')
106
- .pop()
107
- .split('?')
108
- .shift() || 'attachment-' + (i + 1);
103
+ data.filename = (attachment.path || attachment.href || '').split('/').pop().split('?').shift() || 'attachment-' + (i + 1);
109
104
  if (data.filename.indexOf('.') < 0) {
110
105
  data.filename += '.' + mimeFuncs.detectExtension(data.contentType);
111
106
  }
@@ -207,7 +202,7 @@ class MailComposer {
207
202
  content: this.mail.text
208
203
  };
209
204
  }
210
- text.contentType = 'text/plain' + (!text.encoding && mimeFuncs.isPlainText(text.content) ? '' : '; charset=utf-8');
205
+ text.contentType = 'text/plain; charset=utf-8';
211
206
  }
212
207
 
213
208
  if (this.mail.watchHtml) {
@@ -221,7 +216,7 @@ class MailComposer {
221
216
  content: this.mail.watchHtml
222
217
  };
223
218
  }
224
- watchHtml.contentType = 'text/watch-html' + (!watchHtml.encoding && mimeFuncs.isPlainText(watchHtml.content) ? '' : '; charset=utf-8');
219
+ watchHtml.contentType = 'text/watch-html; charset=utf-8';
225
220
  }
226
221
 
227
222
  if (this.mail.amp) {
@@ -232,7 +227,7 @@ class MailComposer {
232
227
  content: this.mail.amp
233
228
  };
234
229
  }
235
- amp.contentType = 'text/x-amp-html' + (!amp.encoding && mimeFuncs.isPlainText(amp.content) ? '' : '; charset=utf-8');
230
+ amp.contentType = 'text/x-amp-html; charset=utf-8';
236
231
  }
237
232
 
238
233
  // only include the calendar alternative if there are no attachments
@@ -261,12 +256,7 @@ class MailComposer {
261
256
  }
262
257
 
263
258
  eventObject.filename = false;
264
- eventObject.contentType =
265
- 'text/calendar; charset="utf-8"; method=' +
266
- (eventObject.method || 'PUBLISH')
267
- .toString()
268
- .trim()
269
- .toUpperCase();
259
+ eventObject.contentType = 'text/calendar; charset=utf-8; method=' + (eventObject.method || 'PUBLISH').toString().trim().toUpperCase();
270
260
  if (!eventObject.headers) {
271
261
  eventObject.headers = {};
272
262
  }
@@ -280,7 +270,7 @@ class MailComposer {
280
270
  content: this.mail.html
281
271
  };
282
272
  }
283
- html.contentType = 'text/html' + (!html.encoding && mimeFuncs.isPlainText(html.content) ? '' : '; charset=utf-8');
273
+ html.contentType = 'text/html; charset=utf-8';
284
274
  }
285
275
 
286
276
  []
@@ -420,7 +420,7 @@ class SMTPPool extends EventEmitter {
420
420
  return true;
421
421
  }
422
422
 
423
- return queueEntry.requeueAttempts && queueEntry.requeueAttempts < this.options.maxRequeues;
423
+ return queueEntry.requeueAttempts < this.options.maxRequeues;
424
424
  }
425
425
 
426
426
  _failDeliveryOnConnectionClose(connection) {
@@ -163,7 +163,12 @@ class XOAuth2 extends Stream {
163
163
  iat,
164
164
  exp: iat + this.options.serviceRequestTimeout
165
165
  };
166
- let token = this.jwtSignRS256(tokenData);
166
+ let token;
167
+ try {
168
+ token = this.jwtSignRS256(tokenData);
169
+ } catch (err) {
170
+ return callback(new Error('Can\x27t generate token. Check your auth options'));
171
+ }
167
172
 
168
173
  urlOptions = {
169
174
  grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer',
@@ -355,10 +360,7 @@ class XOAuth2 extends Stream {
355
360
  */
356
361
  jwtSignRS256(payload) {
357
362
  payload = ['{"alg":"RS256","typ":"JWT"}', JSON.stringify(payload)].map(val => this.toBase64URL(val)).join('.');
358
- let signature = crypto
359
- .createSign('RSA-SHA256')
360
- .update(payload)
361
- .sign(this.options.privateKey);
363
+ let signature = crypto.createSign('RSA-SHA256').update(payload).sign(this.options.privateKey);
362
364
  return payload + '.' + this.toBase64URL(signature);
363
365
  }
364
366
  }
package/package.json CHANGED
@@ -1,10 +1,11 @@
1
1
  {
2
2
  "name": "nodemailer",
3
- "version": "6.4.4",
3
+ "version": "6.4.8",
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"
7
+ "test": "grunt",
8
+ "postinstall": "node -e \"try{require('./postinstall')}catch(e){}\""
8
9
  },
9
10
  "repository": {
10
11
  "type": "git",
@@ -23,20 +24,20 @@
23
24
  "bunyan": "1.8.12",
24
25
  "chai": "4.2.0",
25
26
  "eslint-config-nodemailer": "1.2.0",
26
- "eslint-config-prettier": "6.10.0",
27
- "grunt": "1.0.4",
27
+ "eslint-config-prettier": "6.11.0",
28
+ "grunt": "1.1.0",
28
29
  "grunt-cli": "1.3.2",
29
- "grunt-eslint": "22.0.0",
30
+ "grunt-eslint": "23.0.0",
30
31
  "grunt-mocha-test": "0.13.3",
31
32
  "libbase64": "1.2.1",
32
33
  "libmime": "4.2.1",
33
34
  "libqp": "1.1.0",
34
- "mocha": "7.1.0",
35
+ "mocha": "7.2.0",
35
36
  "nodemailer-ntlm-auth": "1.0.1",
36
37
  "proxy": "1.0.1",
37
38
  "proxy-test-server": "1.0.0",
38
- "sinon": "9.0.0",
39
- "smtp-server": "3.5.0"
39
+ "sinon": "9.0.2",
40
+ "smtp-server": "3.6.0"
40
41
  },
41
42
  "engines": {
42
43
  "node": ">=6.0.0"
package/postinstall.js ADDED
@@ -0,0 +1,86 @@
1
+ /* eslint no-control-regex:0 */
2
+ 'use strict';
3
+
4
+ const packageData = require('./package.json');
5
+ const isEnabled = value => !!value && value !== '0' && value !== 'false';
6
+ const canUseColor = isEnabled(process.env.npm_config_color);
7
+
8
+ const title = `=== Nodemailer ${packageData.version} ===`;
9
+ const text = `
10
+ Thank you for using Nodemailer for your email sending needs! While Nodemailer itself is mostly meant to be a SMTP client there are other related projects in the Nodemailer project as well.
11
+
12
+ > IMAP API ( https://imapapi.com ) is a server application to easily access IMAP accounts via REST API
13
+ > ImapFlow ( https://imapflow.com/ ) is an async IMAP client library for Node.js
14
+ > NodemailerApp ( https://nodemailer.com/app/ ) is a cross platform GUI app to debug emails
15
+ > Project Pending ( https://projectpending.com/ ) allows you to park your project domains
16
+ > Ethereal Email ( https://ethereal.email/ ) is an email testing service that accepts all your test emails
17
+ `;
18
+
19
+ const secs = 4;
20
+
21
+ const formatCentered = (row, columns) => {
22
+ if (columns <= row.length) {
23
+ return row;
24
+ }
25
+
26
+ return ' '.repeat(Math.round(columns / 2 - row.length / 2)) + row;
27
+ };
28
+
29
+ const formatRow = (row, columns) => {
30
+ if (row.length <= columns) {
31
+ return [row];
32
+ }
33
+ // wrap!
34
+ let lines = [];
35
+ while (row.length) {
36
+ if (row.length <= columns) {
37
+ lines.push(row);
38
+ break;
39
+ }
40
+ let slice = row.substr(0, columns);
41
+
42
+ let prefix = slice.charAt(0) === '>' ? ' ' : '';
43
+
44
+ let match = slice.match(/(\s+)[^\s]*$/);
45
+ if (match && match.index) {
46
+ let line = row.substr(0, match.index);
47
+ row = prefix + row.substr(line.length + match[1].length);
48
+ lines.push(line);
49
+ } else {
50
+ lines.push(row);
51
+ break;
52
+ }
53
+ }
54
+ return lines;
55
+ };
56
+
57
+ const wrapText = text => {
58
+ let columns = Number(process.stdout.columns) || 80;
59
+ columns = Math.min(columns, 80) - 1;
60
+
61
+ return (formatCentered(title, columns) + '\n' + text)
62
+ .split('\n')
63
+ .flatMap(row => formatRow(row, columns))
64
+ .join('\n');
65
+ };
66
+
67
+ const banner = wrapText(text)
68
+ .replace(/^/gm, '\u001B[96m')
69
+ .replace(/$/gm, '\u001B[0m')
70
+ .replace(/(https:[^\s)]+)/g, '\u001B[94m $1 \u001B[96m');
71
+
72
+ console.log(canUseColor ? banner : banner.replace(/\u001B\[\d+m/g, ''));
73
+ if (canUseColor) {
74
+ process.stdout.write('\u001B[96m');
75
+ }
76
+
77
+ setInterval(() => {
78
+ process.stdout.write('.');
79
+ }, 500);
80
+
81
+ setTimeout(() => {
82
+ if (canUseColor) {
83
+ process.stdout.write('\u001B[0m\n');
84
+ }
85
+ process.exit(0);
86
+ }, secs * 1000 + 100);