nodemailer 6.6.4 → 6.7.2
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 +16 -0
- package/README.md +2 -0
- package/lib/mailer/index.js +4 -0
- package/lib/ses-transport/index.js +7 -7
- package/lib/shared/index.js +110 -23
- package/lib/smtp-connection/index.js +6 -6
- package/package.json +6 -6
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# CHANGELOG
|
|
2
2
|
|
|
3
|
+
## 6.7.2 2021-11-26
|
|
4
|
+
|
|
5
|
+
- Fix proxies for account verification
|
|
6
|
+
|
|
7
|
+
## 6.7.1 2021-11-15
|
|
8
|
+
|
|
9
|
+
- fix verify on ses-transport (stanofsky)
|
|
10
|
+
|
|
11
|
+
## 6.7.0 2021-10-11
|
|
12
|
+
|
|
13
|
+
- Updated DNS resolving logic. If there are multiple responses for a A/AAAA record, then loop these randomly instead of only caching the first one
|
|
14
|
+
|
|
15
|
+
## 6.6.5 2021-09-23
|
|
16
|
+
|
|
17
|
+
- Replaced Object.values() and Array.flat() with polyfills to allow using Nodemailer in Node v6+
|
|
18
|
+
|
|
3
19
|
## 6.6.4 2021-09-22
|
|
4
20
|
|
|
5
21
|
- Better compatibility with IPv6-only SMTP hosts (oxzi)
|
package/README.md
CHANGED
|
@@ -10,6 +10,8 @@ See [nodemailer.com](https://nodemailer.com/) for documentation and terms.
|
|
|
10
10
|
|
|
11
11
|
## Having an issue?
|
|
12
12
|
|
|
13
|
+
> Nodemailer supports all Node.js versions starting from Node.js@v6.0.0. Existing test suite does not support such old Node.js versions so all features are not actually tested. From time to time some regression bugs might occur because of this.
|
|
14
|
+
|
|
13
15
|
#### First review the docs
|
|
14
16
|
|
|
15
17
|
Documentation for Nodemailer can be found at [nodemailer.com](https://nodemailer.com/about/).
|
package/lib/mailer/index.js
CHANGED
|
@@ -95,6 +95,10 @@ class Mail extends EventEmitter {
|
|
|
95
95
|
['close', 'isIdle', 'verify'].forEach(method => {
|
|
96
96
|
this[method] = (...args) => {
|
|
97
97
|
if (typeof this.transporter[method] === 'function') {
|
|
98
|
+
if (method === 'verify' && typeof this.getSocket === 'function') {
|
|
99
|
+
this.transporter.getSocket = this.getSocket;
|
|
100
|
+
this.getSocket = false;
|
|
101
|
+
}
|
|
98
102
|
return this.transporter[method](...args);
|
|
99
103
|
} else {
|
|
100
104
|
this.logger.warn(
|
|
@@ -320,18 +320,18 @@ class SESTransport extends EventEmitter {
|
|
|
320
320
|
Source: 'invalid@invalid',
|
|
321
321
|
Destinations: ['invalid@invalid']
|
|
322
322
|
};
|
|
323
|
-
const cb = err => {
|
|
324
|
-
if (err && (err.code || err.Code) !== 'InvalidParameterValue') {
|
|
325
|
-
return callback(err);
|
|
326
|
-
}
|
|
327
|
-
return callback(null, true);
|
|
328
|
-
};
|
|
329
323
|
|
|
330
324
|
if (!callback) {
|
|
331
325
|
promise = new Promise((resolve, reject) => {
|
|
332
326
|
callback = shared.callbackPromise(resolve, reject);
|
|
333
327
|
});
|
|
334
328
|
}
|
|
329
|
+
const cb = err => {
|
|
330
|
+
if (err && (err.code || err.Code) !== 'InvalidParameterValue') {
|
|
331
|
+
return callback(err);
|
|
332
|
+
}
|
|
333
|
+
return callback(null, true);
|
|
334
|
+
};
|
|
335
335
|
|
|
336
336
|
if (typeof ses.send === 'function' && aws.SendRawEmailCommand) {
|
|
337
337
|
// v3 API
|
|
@@ -339,7 +339,7 @@ class SESTransport extends EventEmitter {
|
|
|
339
339
|
ses.send(new aws.SendRawEmailCommand(sesMessage), cb);
|
|
340
340
|
} else {
|
|
341
341
|
// v2 API
|
|
342
|
-
ses.sendRawEmail(sesMessage, cb)
|
|
342
|
+
ses.sendRawEmail(sesMessage, cb);
|
|
343
343
|
}
|
|
344
344
|
|
|
345
345
|
return promise;
|
package/lib/shared/index.js
CHANGED
|
@@ -12,12 +12,17 @@ const os = require('os');
|
|
|
12
12
|
|
|
13
13
|
const DNS_TTL = 5 * 60 * 1000;
|
|
14
14
|
|
|
15
|
+
const networkInterfaces = (module.exports.networkInterfaces = os.networkInterfaces());
|
|
16
|
+
|
|
15
17
|
const resolver = (family, hostname, callback) => {
|
|
16
|
-
const familySupported =
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
const familySupported =
|
|
19
|
+
// crux that replaces Object.values(networkInterfaces) as Object.values is not supported in nodejs v6
|
|
20
|
+
Object.keys(networkInterfaces)
|
|
21
|
+
.map(key => networkInterfaces[key])
|
|
22
|
+
// crux that replaces .flat() as it is not supported in older Node versions (v10 and older)
|
|
23
|
+
.reduce((acc, val) => acc.concat(val), [])
|
|
24
|
+
.filter(i => !i.internal)
|
|
25
|
+
.filter(i => i.family === 'IPv' + family).length > 0;
|
|
21
26
|
|
|
22
27
|
if (!familySupported) {
|
|
23
28
|
return callback(null, []);
|
|
@@ -41,16 +46,45 @@ const resolver = (family, hostname, callback) => {
|
|
|
41
46
|
};
|
|
42
47
|
|
|
43
48
|
const dnsCache = (module.exports.dnsCache = new Map());
|
|
49
|
+
|
|
50
|
+
const formatDNSValue = (value, extra) => {
|
|
51
|
+
if (!value) {
|
|
52
|
+
return Object.assign({}, extra || {});
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return Object.assign(
|
|
56
|
+
{
|
|
57
|
+
servername: value.servername,
|
|
58
|
+
host:
|
|
59
|
+
!value.addresses || !value.addresses.length
|
|
60
|
+
? null
|
|
61
|
+
: value.addresses.length === 1
|
|
62
|
+
? value.addresses[0]
|
|
63
|
+
: value.addresses[Math.floor(Math.random() * value.addresses.length)]
|
|
64
|
+
},
|
|
65
|
+
extra || {}
|
|
66
|
+
);
|
|
67
|
+
};
|
|
68
|
+
|
|
44
69
|
module.exports.resolveHostname = (options, callback) => {
|
|
45
70
|
options = options || {};
|
|
46
71
|
|
|
72
|
+
if (!options.host && options.servername) {
|
|
73
|
+
options.host = options.servername;
|
|
74
|
+
}
|
|
75
|
+
|
|
47
76
|
if (!options.host || net.isIP(options.host)) {
|
|
48
77
|
// nothing to do here
|
|
49
78
|
let value = {
|
|
50
|
-
|
|
79
|
+
addresses: [options.host],
|
|
51
80
|
servername: options.servername || false
|
|
52
81
|
};
|
|
53
|
-
return callback(
|
|
82
|
+
return callback(
|
|
83
|
+
null,
|
|
84
|
+
formatDNSValue(value, {
|
|
85
|
+
cached: false
|
|
86
|
+
})
|
|
87
|
+
);
|
|
54
88
|
}
|
|
55
89
|
|
|
56
90
|
let cached;
|
|
@@ -58,11 +92,12 @@ module.exports.resolveHostname = (options, callback) => {
|
|
|
58
92
|
if (dnsCache.has(options.host)) {
|
|
59
93
|
cached = dnsCache.get(options.host);
|
|
60
94
|
if (!cached.expires || cached.expires >= Date.now()) {
|
|
61
|
-
return callback(
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
95
|
+
return callback(
|
|
96
|
+
null,
|
|
97
|
+
formatDNSValue(cached.value, {
|
|
98
|
+
cached: true
|
|
99
|
+
})
|
|
100
|
+
);
|
|
66
101
|
}
|
|
67
102
|
}
|
|
68
103
|
|
|
@@ -70,40 +105,68 @@ module.exports.resolveHostname = (options, callback) => {
|
|
|
70
105
|
if (err) {
|
|
71
106
|
if (cached) {
|
|
72
107
|
// ignore error, use expired value
|
|
73
|
-
return callback(
|
|
108
|
+
return callback(
|
|
109
|
+
null,
|
|
110
|
+
formatDNSValue(cached.value, {
|
|
111
|
+
cached: true,
|
|
112
|
+
error: err
|
|
113
|
+
})
|
|
114
|
+
);
|
|
74
115
|
}
|
|
75
116
|
return callback(err);
|
|
76
117
|
}
|
|
118
|
+
|
|
77
119
|
if (addresses && addresses.length) {
|
|
78
120
|
let value = {
|
|
79
|
-
|
|
121
|
+
addresses,
|
|
80
122
|
servername: options.servername || options.host
|
|
81
123
|
};
|
|
124
|
+
|
|
82
125
|
dnsCache.set(options.host, {
|
|
83
126
|
value,
|
|
84
127
|
expires: Date.now() + DNS_TTL
|
|
85
128
|
});
|
|
86
|
-
|
|
129
|
+
|
|
130
|
+
return callback(
|
|
131
|
+
null,
|
|
132
|
+
formatDNSValue(value, {
|
|
133
|
+
cached: false
|
|
134
|
+
})
|
|
135
|
+
);
|
|
87
136
|
}
|
|
88
137
|
|
|
89
138
|
resolver(6, options.host, (err, addresses) => {
|
|
90
139
|
if (err) {
|
|
91
140
|
if (cached) {
|
|
92
141
|
// ignore error, use expired value
|
|
93
|
-
return callback(
|
|
142
|
+
return callback(
|
|
143
|
+
null,
|
|
144
|
+
formatDNSValue(cached.value, {
|
|
145
|
+
cached: true,
|
|
146
|
+
error: err
|
|
147
|
+
})
|
|
148
|
+
);
|
|
94
149
|
}
|
|
95
150
|
return callback(err);
|
|
96
151
|
}
|
|
152
|
+
|
|
97
153
|
if (addresses && addresses.length) {
|
|
98
154
|
let value = {
|
|
99
|
-
|
|
155
|
+
addresses,
|
|
100
156
|
servername: options.servername || options.host
|
|
101
157
|
};
|
|
158
|
+
|
|
102
159
|
dnsCache.set(options.host, {
|
|
103
160
|
value,
|
|
104
161
|
expires: Date.now() + DNS_TTL
|
|
105
162
|
});
|
|
106
|
-
|
|
163
|
+
|
|
164
|
+
return callback(
|
|
165
|
+
null,
|
|
166
|
+
formatDNSValue(value, {
|
|
167
|
+
cached: false
|
|
168
|
+
})
|
|
169
|
+
);
|
|
107
170
|
}
|
|
108
171
|
|
|
109
172
|
try {
|
|
@@ -111,30 +174,54 @@ module.exports.resolveHostname = (options, callback) => {
|
|
|
111
174
|
if (err) {
|
|
112
175
|
if (cached) {
|
|
113
176
|
// ignore error, use expired value
|
|
114
|
-
return callback(
|
|
177
|
+
return callback(
|
|
178
|
+
null,
|
|
179
|
+
formatDNSValue(cached.value, {
|
|
180
|
+
cached: true,
|
|
181
|
+
error: err
|
|
182
|
+
})
|
|
183
|
+
);
|
|
115
184
|
}
|
|
116
185
|
return callback(err);
|
|
117
186
|
}
|
|
118
187
|
|
|
119
188
|
if (!address && cached) {
|
|
120
189
|
// nothing was found, fallback to cached value
|
|
121
|
-
return callback(
|
|
190
|
+
return callback(
|
|
191
|
+
null,
|
|
192
|
+
formatDNSValue(cached.value, {
|
|
193
|
+
cached: true
|
|
194
|
+
})
|
|
195
|
+
);
|
|
122
196
|
}
|
|
123
197
|
|
|
124
198
|
let value = {
|
|
125
|
-
|
|
199
|
+
addresses: address ? [address] : [options.host],
|
|
126
200
|
servername: options.servername || options.host
|
|
127
201
|
};
|
|
202
|
+
|
|
128
203
|
dnsCache.set(options.host, {
|
|
129
204
|
value,
|
|
130
205
|
expires: Date.now() + DNS_TTL
|
|
131
206
|
});
|
|
132
|
-
|
|
207
|
+
|
|
208
|
+
return callback(
|
|
209
|
+
null,
|
|
210
|
+
formatDNSValue(value, {
|
|
211
|
+
cached: false
|
|
212
|
+
})
|
|
213
|
+
);
|
|
133
214
|
});
|
|
134
215
|
} catch (err) {
|
|
135
216
|
if (cached) {
|
|
136
217
|
// ignore error, use expired value
|
|
137
|
-
return callback(
|
|
218
|
+
return callback(
|
|
219
|
+
null,
|
|
220
|
+
formatDNSValue(cached.value, {
|
|
221
|
+
cached: true,
|
|
222
|
+
error: err
|
|
223
|
+
})
|
|
224
|
+
);
|
|
138
225
|
}
|
|
139
226
|
return callback(err);
|
|
140
227
|
}
|
|
@@ -261,12 +261,12 @@ class SMTPConnection extends EventEmitter {
|
|
|
261
261
|
tnx: 'dns',
|
|
262
262
|
source: opts.host,
|
|
263
263
|
resolved: resolved.host,
|
|
264
|
-
cached: !!resolved.
|
|
264
|
+
cached: !!resolved.cached
|
|
265
265
|
},
|
|
266
266
|
'Resolved %s as %s [cache %s]',
|
|
267
267
|
opts.host,
|
|
268
268
|
resolved.host,
|
|
269
|
-
resolved.
|
|
269
|
+
resolved.cached ? 'hit' : 'miss'
|
|
270
270
|
);
|
|
271
271
|
Object.keys(resolved).forEach(key => {
|
|
272
272
|
if (key.charAt(0) !== '_' && resolved[key]) {
|
|
@@ -299,12 +299,12 @@ class SMTPConnection extends EventEmitter {
|
|
|
299
299
|
tnx: 'dns',
|
|
300
300
|
source: opts.host,
|
|
301
301
|
resolved: resolved.host,
|
|
302
|
-
cached: !!resolved.
|
|
302
|
+
cached: !!resolved.cached
|
|
303
303
|
},
|
|
304
304
|
'Resolved %s as %s [cache %s]',
|
|
305
305
|
opts.host,
|
|
306
306
|
resolved.host,
|
|
307
|
-
resolved.
|
|
307
|
+
resolved.cached ? 'hit' : 'miss'
|
|
308
308
|
);
|
|
309
309
|
Object.keys(resolved).forEach(key => {
|
|
310
310
|
if (key.charAt(0) !== '_' && resolved[key]) {
|
|
@@ -332,12 +332,12 @@ class SMTPConnection extends EventEmitter {
|
|
|
332
332
|
tnx: 'dns',
|
|
333
333
|
source: opts.host,
|
|
334
334
|
resolved: resolved.host,
|
|
335
|
-
cached: !!resolved.
|
|
335
|
+
cached: !!resolved.cached
|
|
336
336
|
},
|
|
337
337
|
'Resolved %s as %s [cache %s]',
|
|
338
338
|
opts.host,
|
|
339
339
|
resolved.host,
|
|
340
|
-
resolved.
|
|
340
|
+
resolved.cached ? 'hit' : 'miss'
|
|
341
341
|
);
|
|
342
342
|
Object.keys(resolved).forEach(key => {
|
|
343
343
|
if (key.charAt(0) !== '_' && resolved[key]) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nodemailer",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.7.2",
|
|
4
4
|
"description": "Easy as cake e-mail sending from your Node.js applications",
|
|
5
5
|
"main": "lib/nodemailer.js",
|
|
6
6
|
"scripts": {
|
|
@@ -20,24 +20,24 @@
|
|
|
20
20
|
},
|
|
21
21
|
"homepage": "https://nodemailer.com/",
|
|
22
22
|
"devDependencies": {
|
|
23
|
-
"@aws-sdk/client-ses": "3.
|
|
24
|
-
"aws-sdk": "2.
|
|
23
|
+
"@aws-sdk/client-ses": "3.41.0",
|
|
24
|
+
"aws-sdk": "2.1028.0",
|
|
25
25
|
"bunyan": "1.8.15",
|
|
26
26
|
"chai": "4.3.4",
|
|
27
27
|
"eslint-config-nodemailer": "1.2.0",
|
|
28
28
|
"eslint-config-prettier": "8.3.0",
|
|
29
29
|
"grunt": "1.4.1",
|
|
30
30
|
"grunt-cli": "1.4.3",
|
|
31
|
-
"grunt-eslint": "
|
|
31
|
+
"grunt-eslint": "24.0.0",
|
|
32
32
|
"grunt-mocha-test": "0.13.3",
|
|
33
33
|
"libbase64": "1.2.1",
|
|
34
34
|
"libmime": "5.0.0",
|
|
35
35
|
"libqp": "1.1.0",
|
|
36
|
-
"mocha": "9.1.
|
|
36
|
+
"mocha": "9.1.3",
|
|
37
37
|
"nodemailer-ntlm-auth": "1.0.1",
|
|
38
38
|
"proxy": "1.0.2",
|
|
39
39
|
"proxy-test-server": "1.0.0",
|
|
40
|
-
"sinon": "
|
|
40
|
+
"sinon": "12.0.1",
|
|
41
41
|
"smtp-server": "3.9.0"
|
|
42
42
|
},
|
|
43
43
|
"engines": {
|