nodemailer 8.0.2 → 8.0.4
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 +17 -0
- package/lib/addressparser/index.js +68 -83
- package/lib/base64/index.js +6 -5
- package/lib/dkim/index.js +8 -16
- package/lib/dkim/message-parser.js +12 -13
- package/lib/dkim/relaxed-body.js +2 -2
- package/lib/dkim/sign.js +13 -14
- package/lib/errors.js +4 -7
- package/lib/fetch/cookies.js +13 -18
- package/lib/fetch/index.js +12 -15
- package/lib/json-transport/index.js +4 -4
- package/lib/mail-composer/index.js +86 -116
- package/lib/mailer/index.js +26 -26
- package/lib/mailer/mail-message.js +17 -21
- package/lib/mime-funcs/index.js +25 -40
- package/lib/mime-funcs/mime-types.js +7 -11
- package/lib/mime-node/index.js +81 -72
- package/lib/mime-node/last-newline.js +1 -1
- package/lib/mime-node/le-unix.js +4 -7
- package/lib/mime-node/le-windows.js +1 -4
- package/lib/nodemailer.js +11 -18
- package/lib/qp/index.js +24 -21
- package/lib/sendmail-transport/index.js +30 -41
- package/lib/ses-transport/index.js +23 -34
- package/lib/shared/index.js +94 -140
- package/lib/smtp-connection/data-stream.js +3 -6
- package/lib/smtp-connection/http-proxy-client.js +11 -13
- package/lib/smtp-connection/index.js +118 -182
- package/lib/smtp-pool/index.js +20 -32
- package/lib/smtp-pool/pool-resource.js +8 -12
- package/lib/smtp-transport/index.js +22 -42
- package/lib/stream-transport/index.js +7 -7
- package/lib/well-known/index.js +7 -7
- package/lib/xoauth2/index.js +22 -28
- package/package.json +4 -3
package/lib/fetch/cookies.js
CHANGED
|
@@ -25,8 +25,8 @@ class Cookies {
|
|
|
25
25
|
* @param {String} url Current URL
|
|
26
26
|
*/
|
|
27
27
|
set(cookieStr, url) {
|
|
28
|
-
|
|
29
|
-
|
|
28
|
+
const urlparts = urllib.parse(url || '');
|
|
29
|
+
const cookie = this.parse(cookieStr);
|
|
30
30
|
let domain;
|
|
31
31
|
|
|
32
32
|
if (cookie.domain) {
|
|
@@ -76,15 +76,13 @@ class Cookies {
|
|
|
76
76
|
* @returns {Array} An array of cookie objects
|
|
77
77
|
*/
|
|
78
78
|
list(url) {
|
|
79
|
-
|
|
80
|
-
let i;
|
|
81
|
-
let cookie;
|
|
79
|
+
const result = [];
|
|
82
80
|
|
|
83
|
-
for (i = this.cookies.length - 1; i >= 0; i--) {
|
|
84
|
-
cookie = this.cookies[i];
|
|
81
|
+
for (let i = this.cookies.length - 1; i >= 0; i--) {
|
|
82
|
+
const cookie = this.cookies[i];
|
|
85
83
|
|
|
86
84
|
if (this.isExpired(cookie)) {
|
|
87
|
-
this.cookies.splice(i,
|
|
85
|
+
this.cookies.splice(i, 1);
|
|
88
86
|
continue;
|
|
89
87
|
}
|
|
90
88
|
|
|
@@ -103,14 +101,14 @@ class Cookies {
|
|
|
103
101
|
* @returns {Object} Cookie object
|
|
104
102
|
*/
|
|
105
103
|
parse(cookieStr) {
|
|
106
|
-
|
|
104
|
+
const cookie = {};
|
|
107
105
|
|
|
108
106
|
(cookieStr || '')
|
|
109
107
|
.toString()
|
|
110
108
|
.split(';')
|
|
111
109
|
.forEach(cookiePart => {
|
|
112
|
-
|
|
113
|
-
|
|
110
|
+
const valueParts = cookiePart.split('=');
|
|
111
|
+
const key = valueParts.shift().trim().toLowerCase();
|
|
114
112
|
let value = valueParts.join('=').trim();
|
|
115
113
|
let domain;
|
|
116
114
|
|
|
@@ -171,7 +169,7 @@ class Cookies {
|
|
|
171
169
|
* @returns {Boolean} true if cookie is valid for specifiec URL
|
|
172
170
|
*/
|
|
173
171
|
match(cookie, url) {
|
|
174
|
-
|
|
172
|
+
const urlparts = urllib.parse(url || '');
|
|
175
173
|
|
|
176
174
|
// check if hostname matches
|
|
177
175
|
// .foo.com also matches subdomains, foo.com does not
|
|
@@ -183,7 +181,7 @@ class Cookies {
|
|
|
183
181
|
}
|
|
184
182
|
|
|
185
183
|
// check if path matches
|
|
186
|
-
|
|
184
|
+
const path = this.getPath(urlparts.pathname);
|
|
187
185
|
if (path.substr(0, cookie.path.length) !== cookie.path) {
|
|
188
186
|
return false;
|
|
189
187
|
}
|
|
@@ -202,16 +200,13 @@ class Cookies {
|
|
|
202
200
|
* @param {Object} cookie Cookie value to be stored
|
|
203
201
|
*/
|
|
204
202
|
add(cookie) {
|
|
205
|
-
let i;
|
|
206
|
-
let len;
|
|
207
|
-
|
|
208
203
|
// nothing to do here
|
|
209
204
|
if (!cookie || !cookie.name) {
|
|
210
205
|
return false;
|
|
211
206
|
}
|
|
212
207
|
|
|
213
208
|
// overwrite if has same params
|
|
214
|
-
for (i = 0, len = this.cookies.length; i < len; i++) {
|
|
209
|
+
for (let i = 0, len = this.cookies.length; i < len; i++) {
|
|
215
210
|
if (this.compare(this.cookies[i], cookie)) {
|
|
216
211
|
// check if the cookie needs to be removed instead
|
|
217
212
|
if (this.isExpired(cookie)) {
|
|
@@ -240,7 +235,7 @@ class Cookies {
|
|
|
240
235
|
* @returns {Boolean} True, if the cookies are the same
|
|
241
236
|
*/
|
|
242
237
|
compare(a, b) {
|
|
243
|
-
return a.name === b.name && a.path === b.path && a.domain === b.domain && a.secure === b.secure && a.httponly ===
|
|
238
|
+
return a.name === b.name && a.path === b.path && a.domain === b.domain && a.secure === b.secure && a.httponly === b.httponly;
|
|
244
239
|
}
|
|
245
240
|
|
|
246
241
|
/**
|
package/lib/fetch/index.js
CHANGED
|
@@ -4,7 +4,7 @@ const http = require('http');
|
|
|
4
4
|
const https = require('https');
|
|
5
5
|
const urllib = require('url');
|
|
6
6
|
const zlib = require('zlib');
|
|
7
|
-
const PassThrough = require('stream')
|
|
7
|
+
const { PassThrough } = require('stream');
|
|
8
8
|
const Cookies = require('./cookies');
|
|
9
9
|
const packageData = require('../../package.json');
|
|
10
10
|
const net = require('net');
|
|
@@ -33,16 +33,16 @@ function nmfetch(url, options) {
|
|
|
33
33
|
options.cookie = false;
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
|
|
37
|
-
|
|
36
|
+
const fetchRes = options.fetchRes;
|
|
37
|
+
const parsed = urllib.parse(url);
|
|
38
38
|
let method = (options.method || '').toString().trim().toUpperCase() || 'GET';
|
|
39
39
|
let finished = false;
|
|
40
40
|
let cookies;
|
|
41
41
|
let body;
|
|
42
42
|
|
|
43
|
-
|
|
43
|
+
const handler = parsed.protocol === 'https:' ? https : http;
|
|
44
44
|
|
|
45
|
-
|
|
45
|
+
const headers = {
|
|
46
46
|
'accept-encoding': 'gzip,deflate',
|
|
47
47
|
'user-agent': 'nodemailer/' + packageData.version
|
|
48
48
|
};
|
|
@@ -90,7 +90,7 @@ function nmfetch(url, options) {
|
|
|
90
90
|
body = Buffer.from(
|
|
91
91
|
Object.keys(options.body)
|
|
92
92
|
.map(key => {
|
|
93
|
-
|
|
93
|
+
const value = options.body[key].toString().trim();
|
|
94
94
|
return encodeURIComponent(key) + '=' + encodeURIComponent(value);
|
|
95
95
|
})
|
|
96
96
|
.join('&')
|
|
@@ -117,7 +117,7 @@ function nmfetch(url, options) {
|
|
|
117
117
|
}
|
|
118
118
|
|
|
119
119
|
let req;
|
|
120
|
-
|
|
120
|
+
const reqOptions = {
|
|
121
121
|
method,
|
|
122
122
|
host: parsed.hostname,
|
|
123
123
|
path: parsed.path,
|
|
@@ -128,9 +128,7 @@ function nmfetch(url, options) {
|
|
|
128
128
|
};
|
|
129
129
|
|
|
130
130
|
if (options.tls) {
|
|
131
|
-
Object.
|
|
132
|
-
reqOptions[key] = options.tls[key];
|
|
133
|
-
});
|
|
131
|
+
Object.assign(reqOptions, options.tls);
|
|
134
132
|
}
|
|
135
133
|
|
|
136
134
|
if (
|
|
@@ -162,7 +160,7 @@ function nmfetch(url, options) {
|
|
|
162
160
|
}
|
|
163
161
|
finished = true;
|
|
164
162
|
req.abort();
|
|
165
|
-
|
|
163
|
+
const err = new Error('Request Timeout');
|
|
166
164
|
err.code = errors.EFETCH;
|
|
167
165
|
err.sourceUrl = url;
|
|
168
166
|
fetchRes.emit('error', err);
|
|
@@ -204,7 +202,7 @@ function nmfetch(url, options) {
|
|
|
204
202
|
options.redirects++;
|
|
205
203
|
if (options.redirects > options.maxRedirects) {
|
|
206
204
|
finished = true;
|
|
207
|
-
|
|
205
|
+
const err = new Error('Maximum redirect count exceeded');
|
|
208
206
|
err.code = errors.EFETCH;
|
|
209
207
|
err.sourceUrl = url;
|
|
210
208
|
fetchRes.emit('error', err);
|
|
@@ -222,7 +220,7 @@ function nmfetch(url, options) {
|
|
|
222
220
|
|
|
223
221
|
if (res.statusCode >= 300 && !options.allowErrorResponse) {
|
|
224
222
|
finished = true;
|
|
225
|
-
|
|
223
|
+
const err = new Error('Invalid status code ' + res.statusCode);
|
|
226
224
|
err.code = errors.EFETCH;
|
|
227
225
|
err.sourceUrl = url;
|
|
228
226
|
fetchRes.emit('error', err);
|
|
@@ -263,9 +261,8 @@ function nmfetch(url, options) {
|
|
|
263
261
|
try {
|
|
264
262
|
if (typeof body.pipe === 'function') {
|
|
265
263
|
return body.pipe(req);
|
|
266
|
-
} else {
|
|
267
|
-
req.write(body);
|
|
268
264
|
}
|
|
265
|
+
req.write(body);
|
|
269
266
|
} catch (err) {
|
|
270
267
|
finished = true;
|
|
271
268
|
err.code = errors.EFETCH;
|
|
@@ -13,7 +13,7 @@ class JSONTransport {
|
|
|
13
13
|
constructor(options) {
|
|
14
14
|
options = options || {};
|
|
15
15
|
|
|
16
|
-
this.options = options
|
|
16
|
+
this.options = options;
|
|
17
17
|
|
|
18
18
|
this.name = 'JSONTransport';
|
|
19
19
|
this.version = packageData.version;
|
|
@@ -33,10 +33,10 @@ class JSONTransport {
|
|
|
33
33
|
// Sendmail strips this header line by itself
|
|
34
34
|
mail.message.keepBcc = true;
|
|
35
35
|
|
|
36
|
-
|
|
37
|
-
|
|
36
|
+
const envelope = mail.data.envelope || mail.message.getEnvelope();
|
|
37
|
+
const messageId = mail.message.messageId();
|
|
38
38
|
|
|
39
|
-
|
|
39
|
+
const recipients = [].concat(envelope.to || []);
|
|
40
40
|
if (recipients.length > 3) {
|
|
41
41
|
recipients.push('...and ' + recipients.splice(2).length + ' more');
|
|
42
42
|
}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
const MimeNode = require('../mime-node');
|
|
6
6
|
const mimeFuncs = require('../mime-funcs');
|
|
7
|
-
const parseDataURI = require('../shared')
|
|
7
|
+
const { parseDataURI } = require('../shared');
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* Creates the object for composing a MimeNode instance out from the mail options
|
|
@@ -59,7 +59,7 @@ class MailComposer {
|
|
|
59
59
|
|
|
60
60
|
// Add headers to the root node, always overrides custom headers
|
|
61
61
|
['from', 'sender', 'to', 'cc', 'bcc', 'reply-to', 'in-reply-to', 'references', 'subject', 'message-id', 'date'].forEach(header => {
|
|
62
|
-
|
|
62
|
+
const key = header.replace(/-(\w)/g, (o, c) => c.toUpperCase());
|
|
63
63
|
if (this.mail[key]) {
|
|
64
64
|
this.message.setHeader(header, this.mail[key]);
|
|
65
65
|
}
|
|
@@ -84,20 +84,18 @@ class MailComposer {
|
|
|
84
84
|
*/
|
|
85
85
|
getAttachments(findRelated) {
|
|
86
86
|
let icalEvent, eventObject;
|
|
87
|
-
|
|
88
|
-
let data;
|
|
89
|
-
|
|
87
|
+
const attachments = [].concat(this.mail.attachments || []).map((attachment, i) => {
|
|
90
88
|
if (/^data:/i.test(attachment.path || attachment.href)) {
|
|
91
89
|
attachment = this._processDataUrl(attachment);
|
|
92
90
|
}
|
|
93
91
|
|
|
94
|
-
|
|
92
|
+
const contentType =
|
|
95
93
|
attachment.contentType || mimeFuncs.detectMimeType(attachment.filename || attachment.path || attachment.href || 'bin');
|
|
96
94
|
|
|
97
|
-
|
|
98
|
-
|
|
95
|
+
const isImage = /^image\//i.test(contentType);
|
|
96
|
+
const isMessageNode = /^message\//i.test(contentType);
|
|
99
97
|
|
|
100
|
-
|
|
98
|
+
const contentDisposition =
|
|
101
99
|
attachment.contentDisposition || (isMessageNode || (isImage && attachment.cid) ? 'inline' : 'attachment');
|
|
102
100
|
|
|
103
101
|
let contentTransferEncoding;
|
|
@@ -111,7 +109,7 @@ class MailComposer {
|
|
|
111
109
|
contentTransferEncoding = 'base64'; // the default
|
|
112
110
|
}
|
|
113
111
|
|
|
114
|
-
data = {
|
|
112
|
+
const data = {
|
|
115
113
|
contentType,
|
|
116
114
|
contentDisposition,
|
|
117
115
|
contentTransferEncoding
|
|
@@ -173,10 +171,7 @@ class MailComposer {
|
|
|
173
171
|
};
|
|
174
172
|
}
|
|
175
173
|
|
|
176
|
-
eventObject = {};
|
|
177
|
-
Object.keys(icalEvent).forEach(key => {
|
|
178
|
-
eventObject[key] = icalEvent[key];
|
|
179
|
-
});
|
|
174
|
+
eventObject = Object.assign({}, icalEvent);
|
|
180
175
|
|
|
181
176
|
eventObject.contentType = 'application/ics';
|
|
182
177
|
if (!eventObject.headers) {
|
|
@@ -192,12 +187,12 @@ class MailComposer {
|
|
|
192
187
|
attached: attachments.concat(eventObject || []),
|
|
193
188
|
related: []
|
|
194
189
|
};
|
|
195
|
-
} else {
|
|
196
|
-
return {
|
|
197
|
-
attached: attachments.filter(attachment => !attachment.cid).concat(eventObject || []),
|
|
198
|
-
related: attachments.filter(attachment => !!attachment.cid)
|
|
199
|
-
};
|
|
200
190
|
}
|
|
191
|
+
|
|
192
|
+
return {
|
|
193
|
+
attached: attachments.filter(attachment => !attachment.cid).concat(eventObject || []),
|
|
194
|
+
related: attachments.filter(attachment => !!attachment.cid)
|
|
195
|
+
};
|
|
201
196
|
}
|
|
202
197
|
|
|
203
198
|
/**
|
|
@@ -206,13 +201,8 @@ class MailComposer {
|
|
|
206
201
|
* @returns {Array} An array of alternative elements. Includes the `text` and `html` values as well
|
|
207
202
|
*/
|
|
208
203
|
getAlternatives() {
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
html,
|
|
212
|
-
watchHtml,
|
|
213
|
-
amp,
|
|
214
|
-
icalEvent,
|
|
215
|
-
eventObject;
|
|
204
|
+
const alternatives = [];
|
|
205
|
+
let text, html, watchHtml, amp, icalEvent, eventObject;
|
|
216
206
|
|
|
217
207
|
if (this.mail.text) {
|
|
218
208
|
if (
|
|
@@ -269,10 +259,7 @@ class MailComposer {
|
|
|
269
259
|
};
|
|
270
260
|
}
|
|
271
261
|
|
|
272
|
-
eventObject = {};
|
|
273
|
-
Object.keys(icalEvent).forEach(key => {
|
|
274
|
-
eventObject[key] = icalEvent[key];
|
|
275
|
-
});
|
|
262
|
+
eventObject = Object.assign({}, icalEvent);
|
|
276
263
|
|
|
277
264
|
if (eventObject.content && typeof eventObject.content === 'object') {
|
|
278
265
|
// we are going to have the same attachment twice, so mark this to be
|
|
@@ -310,13 +297,11 @@ class MailComposer {
|
|
|
310
297
|
.concat(eventObject || [])
|
|
311
298
|
.concat(this.mail.alternatives || [])
|
|
312
299
|
.forEach(alternative => {
|
|
313
|
-
let data;
|
|
314
|
-
|
|
315
300
|
if (/^data:/i.test(alternative.path || alternative.href)) {
|
|
316
301
|
alternative = this._processDataUrl(alternative);
|
|
317
302
|
}
|
|
318
303
|
|
|
319
|
-
data = {
|
|
304
|
+
const data = {
|
|
320
305
|
contentType:
|
|
321
306
|
alternative.contentType ||
|
|
322
307
|
mimeFuncs.detectMimeType(alternative.filename || alternative.path || alternative.href || 'txt'),
|
|
@@ -368,26 +353,22 @@ class MailComposer {
|
|
|
368
353
|
* @returns {Object} MimeNode node element
|
|
369
354
|
*/
|
|
370
355
|
_createMixed(parentNode) {
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
normalizeHeaderKey: this.mail.normalizeHeaderKey,
|
|
388
|
-
newline: this.mail.newline
|
|
389
|
-
});
|
|
390
|
-
}
|
|
356
|
+
const node = parentNode
|
|
357
|
+
? parentNode.createChild('multipart/mixed', {
|
|
358
|
+
disableUrlAccess: this.mail.disableUrlAccess,
|
|
359
|
+
disableFileAccess: this.mail.disableFileAccess,
|
|
360
|
+
normalizeHeaderKey: this.mail.normalizeHeaderKey,
|
|
361
|
+
newline: this.mail.newline
|
|
362
|
+
})
|
|
363
|
+
: new MimeNode('multipart/mixed', {
|
|
364
|
+
baseBoundary: this.mail.baseBoundary,
|
|
365
|
+
textEncoding: this.mail.textEncoding,
|
|
366
|
+
boundaryPrefix: this.mail.boundaryPrefix,
|
|
367
|
+
disableUrlAccess: this.mail.disableUrlAccess,
|
|
368
|
+
disableFileAccess: this.mail.disableFileAccess,
|
|
369
|
+
normalizeHeaderKey: this.mail.normalizeHeaderKey,
|
|
370
|
+
newline: this.mail.newline
|
|
371
|
+
});
|
|
391
372
|
|
|
392
373
|
if (this._useAlternative) {
|
|
393
374
|
this._createAlternative(node);
|
|
@@ -416,26 +397,22 @@ class MailComposer {
|
|
|
416
397
|
* @returns {Object} MimeNode node element
|
|
417
398
|
*/
|
|
418
399
|
_createAlternative(parentNode) {
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
normalizeHeaderKey: this.mail.normalizeHeaderKey,
|
|
436
|
-
newline: this.mail.newline
|
|
437
|
-
});
|
|
438
|
-
}
|
|
400
|
+
const node = parentNode
|
|
401
|
+
? parentNode.createChild('multipart/alternative', {
|
|
402
|
+
disableUrlAccess: this.mail.disableUrlAccess,
|
|
403
|
+
disableFileAccess: this.mail.disableFileAccess,
|
|
404
|
+
normalizeHeaderKey: this.mail.normalizeHeaderKey,
|
|
405
|
+
newline: this.mail.newline
|
|
406
|
+
})
|
|
407
|
+
: new MimeNode('multipart/alternative', {
|
|
408
|
+
baseBoundary: this.mail.baseBoundary,
|
|
409
|
+
textEncoding: this.mail.textEncoding,
|
|
410
|
+
boundaryPrefix: this.mail.boundaryPrefix,
|
|
411
|
+
disableUrlAccess: this.mail.disableUrlAccess,
|
|
412
|
+
disableFileAccess: this.mail.disableFileAccess,
|
|
413
|
+
normalizeHeaderKey: this.mail.normalizeHeaderKey,
|
|
414
|
+
newline: this.mail.newline
|
|
415
|
+
});
|
|
439
416
|
|
|
440
417
|
this._alternatives.forEach(alternative => {
|
|
441
418
|
if (this._useRelated && this._htmlNode === alternative) {
|
|
@@ -455,26 +432,22 @@ class MailComposer {
|
|
|
455
432
|
* @returns {Object} MimeNode node element
|
|
456
433
|
*/
|
|
457
434
|
_createRelated(parentNode) {
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
normalizeHeaderKey: this.mail.normalizeHeaderKey,
|
|
475
|
-
newline: this.mail.newline
|
|
476
|
-
});
|
|
477
|
-
}
|
|
435
|
+
const node = parentNode
|
|
436
|
+
? parentNode.createChild('multipart/related; type="text/html"', {
|
|
437
|
+
disableUrlAccess: this.mail.disableUrlAccess,
|
|
438
|
+
disableFileAccess: this.mail.disableFileAccess,
|
|
439
|
+
normalizeHeaderKey: this.mail.normalizeHeaderKey,
|
|
440
|
+
newline: this.mail.newline
|
|
441
|
+
})
|
|
442
|
+
: new MimeNode('multipart/related; type="text/html"', {
|
|
443
|
+
baseBoundary: this.mail.baseBoundary,
|
|
444
|
+
textEncoding: this.mail.textEncoding,
|
|
445
|
+
boundaryPrefix: this.mail.boundaryPrefix,
|
|
446
|
+
disableUrlAccess: this.mail.disableUrlAccess,
|
|
447
|
+
disableFileAccess: this.mail.disableFileAccess,
|
|
448
|
+
normalizeHeaderKey: this.mail.normalizeHeaderKey,
|
|
449
|
+
newline: this.mail.newline
|
|
450
|
+
});
|
|
478
451
|
|
|
479
452
|
this._createContentNode(node, this._htmlNode);
|
|
480
453
|
|
|
@@ -494,33 +467,30 @@ class MailComposer {
|
|
|
494
467
|
element = element || {};
|
|
495
468
|
element.content = element.content || '';
|
|
496
469
|
|
|
497
|
-
|
|
498
|
-
let encoding = (element.encoding || 'utf8')
|
|
470
|
+
const encoding = (element.encoding || 'utf8')
|
|
499
471
|
.toString()
|
|
500
472
|
.toLowerCase()
|
|
501
473
|
.replace(/[-_\s]/g, '');
|
|
502
474
|
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
});
|
|
523
|
-
}
|
|
475
|
+
const node = parentNode
|
|
476
|
+
? parentNode.createChild(element.contentType, {
|
|
477
|
+
filename: element.filename,
|
|
478
|
+
textEncoding: this.mail.textEncoding,
|
|
479
|
+
disableUrlAccess: this.mail.disableUrlAccess,
|
|
480
|
+
disableFileAccess: this.mail.disableFileAccess,
|
|
481
|
+
normalizeHeaderKey: this.mail.normalizeHeaderKey,
|
|
482
|
+
newline: this.mail.newline
|
|
483
|
+
})
|
|
484
|
+
: new MimeNode(element.contentType, {
|
|
485
|
+
filename: element.filename,
|
|
486
|
+
baseBoundary: this.mail.baseBoundary,
|
|
487
|
+
textEncoding: this.mail.textEncoding,
|
|
488
|
+
boundaryPrefix: this.mail.boundaryPrefix,
|
|
489
|
+
disableUrlAccess: this.mail.disableUrlAccess,
|
|
490
|
+
disableFileAccess: this.mail.disableFileAccess,
|
|
491
|
+
normalizeHeaderKey: this.mail.normalizeHeaderKey,
|
|
492
|
+
newline: this.mail.newline
|
|
493
|
+
});
|
|
524
494
|
|
|
525
495
|
// add custom headers
|
|
526
496
|
if (element.headers) {
|
package/lib/mailer/index.js
CHANGED
|
@@ -106,17 +106,17 @@ class Mail extends EventEmitter {
|
|
|
106
106
|
this.getSocket = false;
|
|
107
107
|
}
|
|
108
108
|
return this.transporter[method](...args);
|
|
109
|
-
} else {
|
|
110
|
-
this.logger.warn(
|
|
111
|
-
{
|
|
112
|
-
tnx: 'transport',
|
|
113
|
-
methodName: method
|
|
114
|
-
},
|
|
115
|
-
'Non existing method %s called for transport',
|
|
116
|
-
method
|
|
117
|
-
);
|
|
118
|
-
return false;
|
|
119
109
|
}
|
|
110
|
+
|
|
111
|
+
this.logger.warn(
|
|
112
|
+
{
|
|
113
|
+
tnx: 'transport',
|
|
114
|
+
methodName: method
|
|
115
|
+
},
|
|
116
|
+
'Non existing method %s called for transport',
|
|
117
|
+
method
|
|
118
|
+
);
|
|
119
|
+
return false;
|
|
120
120
|
};
|
|
121
121
|
});
|
|
122
122
|
|
|
@@ -157,7 +157,7 @@ class Mail extends EventEmitter {
|
|
|
157
157
|
this.getSocket = false;
|
|
158
158
|
}
|
|
159
159
|
|
|
160
|
-
|
|
160
|
+
const mail = new MailMessage(this, data);
|
|
161
161
|
|
|
162
162
|
this.logger.debug(
|
|
163
163
|
{
|
|
@@ -207,7 +207,7 @@ class Mail extends EventEmitter {
|
|
|
207
207
|
|
|
208
208
|
if (mail.data.dkim || this.dkim) {
|
|
209
209
|
mail.message.processFunc(input => {
|
|
210
|
-
|
|
210
|
+
const dkim = mail.data.dkim ? new DKIM(mail.data.dkim) : this.dkim;
|
|
211
211
|
this.logger.debug(
|
|
212
212
|
{
|
|
213
213
|
tnx: 'DKIM',
|
|
@@ -259,8 +259,8 @@ class Mail extends EventEmitter {
|
|
|
259
259
|
return callback();
|
|
260
260
|
}
|
|
261
261
|
|
|
262
|
-
|
|
263
|
-
|
|
262
|
+
const userPlugins = this._userPlugins[step] || [];
|
|
263
|
+
const defaultPlugins = this._defaultPlugins[step] || [];
|
|
264
264
|
|
|
265
265
|
if (userPlugins.length) {
|
|
266
266
|
this.logger.debug(
|
|
@@ -281,7 +281,7 @@ class Mail extends EventEmitter {
|
|
|
281
281
|
|
|
282
282
|
let pos = 0;
|
|
283
283
|
let block = 'default';
|
|
284
|
-
|
|
284
|
+
const processPlugins = () => {
|
|
285
285
|
let curplugins = block === 'default' ? defaultPlugins : userPlugins;
|
|
286
286
|
if (pos >= curplugins.length) {
|
|
287
287
|
if (block === 'default' && userPlugins.length) {
|
|
@@ -292,7 +292,7 @@ class Mail extends EventEmitter {
|
|
|
292
292
|
return callback();
|
|
293
293
|
}
|
|
294
294
|
}
|
|
295
|
-
|
|
295
|
+
const plugin = curplugins[pos++];
|
|
296
296
|
plugin(mail, err => {
|
|
297
297
|
if (err) {
|
|
298
298
|
return callback(err);
|
|
@@ -310,11 +310,11 @@ class Mail extends EventEmitter {
|
|
|
310
310
|
* @param {String} proxyUrl Proxy configuration url
|
|
311
311
|
*/
|
|
312
312
|
setupProxy(proxyUrl) {
|
|
313
|
-
|
|
313
|
+
const proxy = urllib.parse(proxyUrl);
|
|
314
314
|
|
|
315
315
|
// setup socket handler for the mailer object
|
|
316
316
|
this.getSocket = (options, callback) => {
|
|
317
|
-
|
|
317
|
+
const protocol = proxy.protocol.replace(/:$/, '').toLowerCase();
|
|
318
318
|
|
|
319
319
|
if (this.meta.has('proxy_handler_' + protocol)) {
|
|
320
320
|
return this.meta.get('proxy_handler_' + protocol)(proxy, options, callback);
|
|
@@ -342,11 +342,11 @@ class Mail extends EventEmitter {
|
|
|
342
342
|
err.code = errors.EPROXY;
|
|
343
343
|
return callback(err);
|
|
344
344
|
}
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
345
|
+
const connect = ipaddress => {
|
|
346
|
+
const proxyV2 = !!this.meta.get('proxy_socks_module').SocksClient;
|
|
347
|
+
const socksClient = proxyV2 ? this.meta.get('proxy_socks_module').SocksClient : this.meta.get('proxy_socks_module');
|
|
348
|
+
const proxyType = Number(proxy.protocol.replace(/\D/g, '')) || 5;
|
|
349
|
+
const connectionOpts = {
|
|
350
350
|
proxy: {
|
|
351
351
|
ipaddress,
|
|
352
352
|
port: Number(proxy.port),
|
|
@@ -360,8 +360,8 @@ class Mail extends EventEmitter {
|
|
|
360
360
|
};
|
|
361
361
|
|
|
362
362
|
if (proxy.auth) {
|
|
363
|
-
|
|
364
|
-
|
|
363
|
+
const username = decodeURIComponent(proxy.auth.split(':').shift());
|
|
364
|
+
const password = decodeURIComponent(proxy.auth.split(':').pop());
|
|
365
365
|
if (proxyV2) {
|
|
366
366
|
connectionOpts.proxy.userId = username;
|
|
367
367
|
connectionOpts.proxy.password = password;
|
|
@@ -415,7 +415,7 @@ class Mail extends EventEmitter {
|
|
|
415
415
|
html = (html || '')
|
|
416
416
|
.toString()
|
|
417
417
|
.replace(/(<img\b[^<>]{0,1024} src\s{0,20}=[\s"']{0,20})(data:([^;]+);[^"'>\s]+)/gi, (match, prefix, dataUri, mimeType) => {
|
|
418
|
-
|
|
418
|
+
const cid = crypto.randomBytes(10).toString('hex') + '@localhost';
|
|
419
419
|
if (!mail.data.attachments) {
|
|
420
420
|
mail.data.attachments = [];
|
|
421
421
|
}
|