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 +12 -0
- package/README.md +3 -6
- package/lib/smtp-pool/index.js +55 -14
- package/lib/smtp-pool/pool-resource.js +1 -1
- package/lib/smtp-transport/index.js +2 -2
- package/package.json +8 -7
- package/postinstall.js +58 -0
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
|
|
package/lib/smtp-pool/index.js
CHANGED
|
@@ -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.
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
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.
|
|
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.
|
|
27
|
-
"grunt": "1.0
|
|
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": "
|
|
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": "
|
|
39
|
-
"smtp-server": "3.
|
|
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, ''));
|