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 +4 -1
- package/CHANGELOG.md +9 -0
- package/lib/mail-composer/index.js +6 -16
- package/lib/smtp-pool/index.js +1 -1
- package/lib/xoauth2/index.js +7 -5
- package/package.json +9 -8
- package/postinstall.js +86 -0
package/.prettierrc.js
CHANGED
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
|
|
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
|
|
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
|
|
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
|
|
273
|
+
html.contentType = 'text/html; charset=utf-8';
|
|
284
274
|
}
|
|
285
275
|
|
|
286
276
|
[]
|
package/lib/smtp-pool/index.js
CHANGED
|
@@ -420,7 +420,7 @@ class SMTPPool extends EventEmitter {
|
|
|
420
420
|
return true;
|
|
421
421
|
}
|
|
422
422
|
|
|
423
|
-
return queueEntry.requeueAttempts
|
|
423
|
+
return queueEntry.requeueAttempts < this.options.maxRequeues;
|
|
424
424
|
}
|
|
425
425
|
|
|
426
426
|
_failDeliveryOnConnectionClose(connection) {
|
package/lib/xoauth2/index.js
CHANGED
|
@@ -163,7 +163,12 @@ class XOAuth2 extends Stream {
|
|
|
163
163
|
iat,
|
|
164
164
|
exp: iat + this.options.serviceRequestTimeout
|
|
165
165
|
};
|
|
166
|
-
let token
|
|
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.
|
|
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.
|
|
27
|
-
"grunt": "1.0
|
|
27
|
+
"eslint-config-prettier": "6.11.0",
|
|
28
|
+
"grunt": "1.1.0",
|
|
28
29
|
"grunt-cli": "1.3.2",
|
|
29
|
-
"grunt-eslint": "
|
|
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.
|
|
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.
|
|
39
|
-
"smtp-server": "3.
|
|
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);
|