nodemailer 6.4.2 → 6.4.6

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,17 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## 6.4.6 2020-03-20
4
+
5
+ - fix: `requeueAttempts=n` should requeue `n` times (Patrick Malouin) [a27ed2f7]
6
+
7
+ ## 6.4.4 2020-03-01
8
+
9
+ - Add `options.forceAuth` for SMTP (Patrick Malouin) [a27ed2f7]
10
+
11
+ ## 6.4.3 2020-02-22
12
+
13
+ - Added an option to specify max number of requeues when connection closes unexpectedly (Igor Sechyn) [8a927f5a]
14
+
3
15
  ## 6.4.2 2019-12-11
4
16
 
5
17
  - Fixed bug where array item was used with a potentially empty array
package/README.md CHANGED
@@ -8,10 +8,6 @@ Send e-mails from Node.js – easy as cake! 🍰✉️
8
8
 
9
9
  See [nodemailer.com](https://nodemailer.com/) for documentation and terms.
10
10
 
11
- ## Why version bump to 5?
12
-
13
- Nodemailer changed from `dns.lookup()` to `dns.resolve` for resolving SMTP hostnames which might be backwards incompatible and thus the version bump. Nodemailer tries first `resolve4()` and if no match is found then `resolve6()` and finally reverts back to `lookup()`. Additionally found DNS results are cached (for 5 minutes). This should make it easier to manage high performance clients that send a lot of messages in parallel.
14
-
15
11
  ## Having an issue?
16
12
 
17
13
  #### First review the docs
@@ -24,7 +20,7 @@ You are using older Node.js version than v6.0. Upgrade Node.js to get support fo
24
20
 
25
21
  #### I'm having issues with Gmail
26
22
 
27
- Gmail either works well or it does not work at all. It is probably easier to switch to an alternative service instead of fixing issues with Gmail. If Gmail does not work for you then don't use it.
23
+ Gmail either works well or it does not work at all. It is probably easier to switch to an alternative service instead of fixing issues with Gmail. If Gmail does not work for you then don't use it. Read more about it [here](https://nodemailer.com/usage/using-gmail/).
28
24
 
29
25
  #### I get ETIMEDOUT errors
30
26
 
@@ -32,7 +28,8 @@ Check your firewall settings. Timeout usually occurs when you try to open a conn
32
28
 
33
29
  #### I get TLS errors
34
30
 
35
- 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.
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.
36
33
 
37
34
  #### I have a different problem
38
35
 
@@ -103,6 +103,7 @@ class SMTPPool extends EventEmitter {
103
103
 
104
104
  this._queue.push({
105
105
  mail,
106
+ requeueAttempts: 0,
106
107
  callback
107
108
  });
108
109
 
@@ -391,23 +392,16 @@ class SMTPPool extends EventEmitter {
391
392
 
392
393
  if (connection.queueEntry) {
393
394
  // If the connection closed when sending, add the message to the queue again
395
+ // if max number of requeues is not reached yet
394
396
  // Note that we must wait a bit.. because the callback of the 'error' handler might be called
395
397
  // in the next event loop
396
398
  setTimeout(() => {
397
399
  if (connection.queueEntry) {
398
- this.logger.debug(
399
- {
400
- tnx: 'pool',
401
- cid: connection.id,
402
- messageId: connection.queueEntry.messageId,
403
- action: 'requeue'
404
- },
405
- 'Re-queued message <%s> for #%s',
406
- connection.queueEntry.messageId,
407
- connection.id
408
- );
409
- this._queue.unshift(connection.queueEntry);
410
- connection.queueEntry = false;
400
+ if (this._shouldRequeuOnConnectionClose(connection.queueEntry)) {
401
+ this._requeueEntryOnConnectionClose(connection);
402
+ } else {
403
+ this._failDeliveryOnConnectionClose(connection);
404
+ }
411
405
  }
412
406
  this._continueProcessing();
413
407
  }, 50);
@@ -421,6 +415,53 @@ class SMTPPool extends EventEmitter {
421
415
  return connection;
422
416
  }
423
417
 
418
+ _shouldRequeuOnConnectionClose(queueEntry) {
419
+ if (this.options.maxRequeues === undefined || this.options.maxRequeues < 0) {
420
+ return true;
421
+ }
422
+
423
+ return queueEntry.requeueAttempts < this.options.maxRequeues;
424
+ }
425
+
426
+ _failDeliveryOnConnectionClose(connection) {
427
+ if (connection.queueEntry && connection.queueEntry.callback) {
428
+ try {
429
+ connection.queueEntry.callback(new Error('Reached maximum number of retries after connection was closed'));
430
+ } catch (E) {
431
+ this.logger.error(
432
+ {
433
+ err: E,
434
+ tnx: 'callback',
435
+ messageId: connection.queueEntry.messageId,
436
+ cid: connection.id
437
+ },
438
+ 'Callback error for #%s: %s',
439
+ connection.id,
440
+ E.message
441
+ );
442
+ }
443
+ connection.queueEntry = false;
444
+ }
445
+ }
446
+
447
+ _requeueEntryOnConnectionClose(connection) {
448
+ connection.queueEntry.requeueAttempts = connection.queueEntry.requeueAttempts + 1;
449
+ this.logger.debug(
450
+ {
451
+ tnx: 'pool',
452
+ cid: connection.id,
453
+ messageId: connection.queueEntry.messageId,
454
+ action: 'requeue'
455
+ },
456
+ 'Re-queued message <%s> for #%s. Attempt: #%s',
457
+ connection.queueEntry.messageId,
458
+ connection.id,
459
+ connection.queueEntry.requeueAttempts
460
+ );
461
+ this._queue.unshift(connection.queueEntry);
462
+ connection.queueEntry = false;
463
+ }
464
+
424
465
  /**
425
466
  * Continue to process message if the pool hasn't closed
426
467
  */
@@ -572,7 +613,7 @@ class SMTPPool extends EventEmitter {
572
613
  return;
573
614
  }
574
615
 
575
- if (auth && connection.allowsAuth) {
616
+ if (auth && (connection.allowsAuth || options.forceAuth)) {
576
617
  connection.login(auth, err => {
577
618
  if (returned) {
578
619
  return;
@@ -137,7 +137,7 @@ class PoolResource extends EventEmitter {
137
137
  return;
138
138
  }
139
139
 
140
- if (this.auth && this.connection.allowsAuth) {
140
+ if (this.auth && (this.connection.allowsAuth || options.forceAuth)) {
141
141
  this.connection.login(this.auth, err => {
142
142
  if (returned) {
143
143
  return;
@@ -267,7 +267,7 @@ class SMTPTransport extends EventEmitter {
267
267
 
268
268
  let auth = this.getAuth(mail.data.auth);
269
269
 
270
- if (auth && connection.allowsAuth) {
270
+ if (auth && (connection.allowsAuth || options.forceAuth)) {
271
271
  connection.login(auth, err => {
272
272
  if (auth && auth !== this.auth && auth.oauth2) {
273
273
  auth.oauth2.removeAllListeners();
@@ -370,7 +370,7 @@ class SMTPTransport extends EventEmitter {
370
370
 
371
371
  let authData = this.getAuth({});
372
372
 
373
- if (authData && connection.allowsAuth) {
373
+ if (authData && (connection.allowsAuth || options.forceAuth)) {
374
374
  connection.login(authData, err => {
375
375
  if (returned) {
376
376
  return;
package/package.json CHANGED
@@ -1,10 +1,11 @@
1
1
  {
2
2
  "name": "nodemailer",
3
- "version": "6.4.2",
3
+ "version": "6.4.6",
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.7.0",
27
- "grunt": "1.0.4",
27
+ "eslint-config-prettier": "6.10.0",
28
+ "grunt": "1.1.0",
28
29
  "grunt-cli": "1.3.2",
29
30
  "grunt-eslint": "22.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": "6.2.2",
35
+ "mocha": "7.1.1",
35
36
  "nodemailer-ntlm-auth": "1.0.1",
36
37
  "proxy": "1.0.1",
37
38
  "proxy-test-server": "1.0.0",
38
- "sinon": "7.5.0",
39
- "smtp-server": "3.5.0"
39
+ "sinon": "9.0.1",
40
+ "smtp-server": "3.6.0"
40
41
  },
41
42
  "engines": {
42
43
  "node": ">=6.0.0"
package/postinstall.js ADDED
@@ -0,0 +1,58 @@
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 text = `=== Nodemailer ${packageData.version} ===
9
+
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
+ For example:
13
+ > IMAP API ( https://imapapi.com ) is a server application to easily access IMAP accounts via REST API
14
+ > NodemailerApp ( https://nodemailer.com/app/ ) is a cross platform GUI app to debug emails
15
+ `;
16
+
17
+ const formatRow = (row, columns) => {
18
+ if (row.length <= columns) {
19
+ return [row];
20
+ }
21
+ // wrap!
22
+ let lines = [];
23
+ while (row.length) {
24
+ if (row.length <= columns) {
25
+ lines.push(row);
26
+ break;
27
+ }
28
+ let slice = row.substr(0, columns);
29
+
30
+ let match = slice.match(/(\s+)[^\s]*$/);
31
+ if (match && match.index) {
32
+ let line = row.substr(0, match.index);
33
+ row = row.substr(line.length + match[1].length);
34
+ lines.push(line);
35
+ } else {
36
+ lines.push(row);
37
+ break;
38
+ }
39
+ }
40
+ return lines;
41
+ };
42
+
43
+ const wrapText = text => {
44
+ let columns = Number(process.stdout.columns) || 80;
45
+ columns = Math.min(columns, 80) - 1;
46
+
47
+ return text
48
+ .split('\n')
49
+ .flatMap(row => formatRow(row, columns))
50
+ .join('\n');
51
+ };
52
+
53
+ const banner = wrapText(text)
54
+ .replace(/^/gm, '\u001B[96m')
55
+ .replace(/$/gm, '\u001B[0m')
56
+ .replace(/(https:[^\s)]+)/g, '\u001B[94m $1 \u001B[96m');
57
+
58
+ console.log(canUseColor ? banner : banner.replace(/\u001B\[\d+m/g, ''));