@mavogel/awscdk-rootmail 0.1.14 → 0.1.16
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/.jsii +10 -10
- package/lib/rootmail.js +1 -1
- package/lib/ses-receive.js +1 -1
- package/node_modules/@aws-sdk/checksums/package.json +3 -3
- package/node_modules/@aws-sdk/client-cloudwatch-logs/dist-cjs/index.js +23 -1
- package/node_modules/@aws-sdk/client-cloudwatch-logs/dist-es/models/CloudWatchLogsServiceException.js +1 -0
- package/node_modules/@aws-sdk/client-cloudwatch-logs/dist-es/models/errors.js +21 -0
- package/node_modules/@aws-sdk/client-cloudwatch-logs/dist-types/models/CloudWatchLogsServiceException.d.ts +1 -0
- package/node_modules/@aws-sdk/client-cloudwatch-logs/dist-types/models/errors.d.ts +21 -0
- package/node_modules/@aws-sdk/client-cloudwatch-logs/dist-types/ts3.4/models/CloudWatchLogsServiceException.d.ts +1 -0
- package/node_modules/@aws-sdk/client-cloudwatch-logs/dist-types/ts3.4/models/errors.d.ts +21 -0
- package/node_modules/@aws-sdk/client-cloudwatch-logs/package.json +4 -4
- package/node_modules/@aws-sdk/client-route-53/dist-cjs/index.js +71 -1
- package/node_modules/@aws-sdk/client-route-53/dist-es/models/Route53ServiceException.js +1 -0
- package/node_modules/@aws-sdk/client-route-53/dist-es/models/errors.js +69 -0
- package/node_modules/@aws-sdk/client-route-53/dist-types/models/Route53ServiceException.d.ts +1 -0
- package/node_modules/@aws-sdk/client-route-53/dist-types/models/errors.d.ts +69 -0
- package/node_modules/@aws-sdk/client-route-53/dist-types/ts3.4/models/Route53ServiceException.d.ts +1 -0
- package/node_modules/@aws-sdk/client-route-53/dist-types/ts3.4/models/errors.d.ts +69 -0
- package/node_modules/@aws-sdk/client-route-53/package.json +4 -4
- package/node_modules/@aws-sdk/client-s3/dist-cjs/index.js +23 -1
- package/node_modules/@aws-sdk/client-s3/dist-es/models/S3ServiceException.js +1 -0
- package/node_modules/@aws-sdk/client-s3/dist-es/models/errors.js +21 -0
- package/node_modules/@aws-sdk/client-s3/dist-types/models/S3ServiceException.d.ts +1 -0
- package/node_modules/@aws-sdk/client-s3/dist-types/models/errors.d.ts +21 -0
- package/node_modules/@aws-sdk/client-s3/dist-types/ts3.4/models/S3ServiceException.d.ts +1 -0
- package/node_modules/@aws-sdk/client-s3/dist-types/ts3.4/models/errors.d.ts +21 -0
- package/node_modules/@aws-sdk/client-s3/package.json +8 -8
- package/node_modules/@aws-sdk/client-ses/dist-cjs/index.js +36 -1
- package/node_modules/@aws-sdk/client-ses/dist-es/models/SESServiceException.js +1 -0
- package/node_modules/@aws-sdk/client-ses/dist-es/models/errors.js +34 -0
- package/node_modules/@aws-sdk/client-ses/dist-types/models/SESServiceException.d.ts +1 -0
- package/node_modules/@aws-sdk/client-ses/dist-types/models/errors.d.ts +34 -0
- package/node_modules/@aws-sdk/client-ses/dist-types/ts3.4/models/SESServiceException.d.ts +1 -0
- package/node_modules/@aws-sdk/client-ses/dist-types/ts3.4/models/errors.d.ts +34 -0
- package/node_modules/@aws-sdk/client-ses/package.json +4 -4
- package/node_modules/@aws-sdk/client-ssm/dist-cjs/index.js +142 -1
- package/node_modules/@aws-sdk/client-ssm/dist-es/models/SSMServiceException.js +1 -0
- package/node_modules/@aws-sdk/client-ssm/dist-es/models/errors.js +140 -0
- package/node_modules/@aws-sdk/client-ssm/dist-types/models/SSMServiceException.d.ts +1 -0
- package/node_modules/@aws-sdk/client-ssm/dist-types/models/errors.d.ts +140 -0
- package/node_modules/@aws-sdk/client-ssm/dist-types/ts3.4/models/SSMServiceException.d.ts +1 -0
- package/node_modules/@aws-sdk/client-ssm/dist-types/ts3.4/models/errors.d.ts +140 -0
- package/node_modules/@aws-sdk/client-ssm/package.json +4 -4
- package/node_modules/@aws-sdk/core/package.json +3 -3
- package/node_modules/@aws-sdk/credential-provider-env/package.json +3 -3
- package/node_modules/@aws-sdk/credential-provider-http/package.json +3 -3
- package/node_modules/@aws-sdk/credential-provider-ini/package.json +10 -10
- package/node_modules/@aws-sdk/credential-provider-login/package.json +4 -4
- package/node_modules/@aws-sdk/credential-provider-node/package.json +8 -8
- package/node_modules/@aws-sdk/credential-provider-process/package.json +3 -3
- package/node_modules/@aws-sdk/credential-provider-sso/package.json +5 -5
- package/node_modules/@aws-sdk/credential-provider-web-identity/package.json +4 -4
- package/node_modules/@aws-sdk/middleware-sdk-s3/package.json +4 -4
- package/node_modules/@aws-sdk/nested-clients/dist-cjs/submodules/cognito-identity/index.js +11 -1
- package/node_modules/@aws-sdk/nested-clients/dist-cjs/submodules/signin/index.js +6 -1
- package/node_modules/@aws-sdk/nested-clients/dist-cjs/submodules/sso/index.js +6 -1
- package/node_modules/@aws-sdk/nested-clients/dist-cjs/submodules/sso-oidc/index.js +13 -1
- package/node_modules/@aws-sdk/nested-clients/dist-cjs/submodules/sts/index.js +9 -1
- package/node_modules/@aws-sdk/nested-clients/dist-es/submodules/cognito-identity/models/CognitoIdentityServiceException.js +1 -0
- package/node_modules/@aws-sdk/nested-clients/dist-es/submodules/cognito-identity/models/errors.js +9 -0
- package/node_modules/@aws-sdk/nested-clients/dist-es/submodules/signin/models/SigninServiceException.js +1 -0
- package/node_modules/@aws-sdk/nested-clients/dist-es/submodules/signin/models/errors.js +4 -0
- package/node_modules/@aws-sdk/nested-clients/dist-es/submodules/sso/models/SSOServiceException.js +1 -0
- package/node_modules/@aws-sdk/nested-clients/dist-es/submodules/sso/models/errors.js +4 -0
- package/node_modules/@aws-sdk/nested-clients/dist-es/submodules/sso-oidc/models/SSOOIDCServiceException.js +1 -0
- package/node_modules/@aws-sdk/nested-clients/dist-es/submodules/sso-oidc/models/errors.js +11 -0
- package/node_modules/@aws-sdk/nested-clients/dist-es/submodules/sts/models/STSServiceException.js +1 -0
- package/node_modules/@aws-sdk/nested-clients/dist-es/submodules/sts/models/errors.js +7 -0
- package/node_modules/@aws-sdk/nested-clients/dist-types/submodules/cognito-identity/models/CognitoIdentityServiceException.d.ts +1 -0
- package/node_modules/@aws-sdk/nested-clients/dist-types/submodules/cognito-identity/models/errors.d.ts +9 -0
- package/node_modules/@aws-sdk/nested-clients/dist-types/submodules/signin/models/SigninServiceException.d.ts +1 -0
- package/node_modules/@aws-sdk/nested-clients/dist-types/submodules/signin/models/errors.d.ts +4 -0
- package/node_modules/@aws-sdk/nested-clients/dist-types/submodules/sso/models/SSOServiceException.d.ts +1 -0
- package/node_modules/@aws-sdk/nested-clients/dist-types/submodules/sso/models/errors.d.ts +4 -0
- package/node_modules/@aws-sdk/nested-clients/dist-types/submodules/sso-oidc/models/SSOOIDCServiceException.d.ts +1 -0
- package/node_modules/@aws-sdk/nested-clients/dist-types/submodules/sso-oidc/models/errors.d.ts +11 -0
- package/node_modules/@aws-sdk/nested-clients/dist-types/submodules/sts/models/STSServiceException.d.ts +1 -0
- package/node_modules/@aws-sdk/nested-clients/dist-types/submodules/sts/models/errors.d.ts +7 -0
- package/node_modules/@aws-sdk/nested-clients/dist-types/ts3.4/submodules/cognito-identity/models/CognitoIdentityServiceException.d.ts +1 -0
- package/node_modules/@aws-sdk/nested-clients/dist-types/ts3.4/submodules/cognito-identity/models/errors.d.ts +9 -0
- package/node_modules/@aws-sdk/nested-clients/dist-types/ts3.4/submodules/signin/models/SigninServiceException.d.ts +1 -0
- package/node_modules/@aws-sdk/nested-clients/dist-types/ts3.4/submodules/signin/models/errors.d.ts +4 -0
- package/node_modules/@aws-sdk/nested-clients/dist-types/ts3.4/submodules/sso/models/SSOServiceException.d.ts +1 -0
- package/node_modules/@aws-sdk/nested-clients/dist-types/ts3.4/submodules/sso/models/errors.d.ts +4 -0
- package/node_modules/@aws-sdk/nested-clients/dist-types/ts3.4/submodules/sso-oidc/models/SSOOIDCServiceException.d.ts +1 -0
- package/node_modules/@aws-sdk/nested-clients/dist-types/ts3.4/submodules/sso-oidc/models/errors.d.ts +11 -0
- package/node_modules/@aws-sdk/nested-clients/dist-types/ts3.4/submodules/sts/models/STSServiceException.d.ts +1 -0
- package/node_modules/@aws-sdk/nested-clients/dist-types/ts3.4/submodules/sts/models/errors.d.ts +7 -0
- package/node_modules/@aws-sdk/nested-clients/package.json +4 -4
- package/node_modules/@aws-sdk/signature-v4-multi-region/package.json +2 -2
- package/node_modules/@aws-sdk/token-providers/package.json +4 -4
- package/node_modules/@smithy/core/dist-cjs/submodules/client/index.js +33 -11
- package/node_modules/@smithy/core/dist-cjs/submodules/endpoints/index.browser.js +2 -1
- package/node_modules/@smithy/core/dist-cjs/submodules/endpoints/index.js +2 -1
- package/node_modules/@smithy/core/dist-cjs/submodules/schema/index.js +3 -0
- package/node_modules/@smithy/core/dist-es/submodules/client/smithy-client/exceptions.js +33 -11
- package/node_modules/@smithy/core/dist-es/submodules/endpoints/util-endpoints/cache/EndpointCache.js +2 -1
- package/node_modules/@smithy/core/dist-es/submodules/schema/TypeRegistry.js +3 -0
- package/node_modules/@smithy/core/dist-types/submodules/client/smithy-client/exceptions.d.ts +1 -0
- package/node_modules/@smithy/core/dist-types/ts3.4/submodules/client/smithy-client/exceptions.d.ts +1 -0
- package/node_modules/@smithy/core/package.json +1 -1
- package/node_modules/@smithy/signature-v4/dist-cjs/index.js +4 -1
- package/node_modules/@smithy/signature-v4/dist-es/getCanonicalHeaders.js +4 -1
- package/node_modules/@smithy/signature-v4/package.json +3 -3
- package/node_modules/mailparser/.release-please-manifest.json +1 -1
- package/node_modules/mailparser/CHANGELOG.md +7 -0
- package/node_modules/mailparser/package.json +2 -2
- package/node_modules/nodemailer/CHANGELOG.md +27 -0
- package/node_modules/nodemailer/dist/cjs/base64/index.d.ts +3 -0
- package/node_modules/nodemailer/dist/cjs/base64/index.js +80 -41
- package/node_modules/nodemailer/dist/cjs/dkim/index.js +43 -29
- package/node_modules/nodemailer/dist/cjs/dkim/message-parser.js +2 -2
- package/node_modules/nodemailer/dist/cjs/errors.d.ts +17 -0
- package/node_modules/nodemailer/dist/cjs/errors.js +12 -1
- package/node_modules/nodemailer/dist/cjs/fetch/index.js +23 -3
- package/node_modules/nodemailer/dist/cjs/mailer/index.js +23 -7
- package/node_modules/nodemailer/dist/cjs/mailer/mail-message.d.ts +5 -0
- package/node_modules/nodemailer/dist/cjs/mailer/mail-message.js +20 -0
- package/node_modules/nodemailer/dist/cjs/mime-node/index.d.ts +1 -1
- package/node_modules/nodemailer/dist/cjs/mime-node/index.js +165 -105
- package/node_modules/nodemailer/dist/cjs/nodemailer.js +12 -9
- package/node_modules/nodemailer/dist/cjs/package-info.d.ts +1 -1
- package/node_modules/nodemailer/dist/cjs/package-info.js +1 -1
- package/node_modules/nodemailer/dist/cjs/qp/index.d.ts +2 -0
- package/node_modules/nodemailer/dist/cjs/qp/index.js +103 -33
- package/node_modules/nodemailer/dist/cjs/sendmail-transport/index.js +54 -14
- package/node_modules/nodemailer/dist/cjs/shared/index.d.ts +32 -1
- package/node_modules/nodemailer/dist/cjs/shared/index.js +212 -115
- package/node_modules/nodemailer/dist/cjs/smtp-connection/http-proxy-client.d.ts +3 -1
- package/node_modules/nodemailer/dist/cjs/smtp-connection/http-proxy-client.js +88 -68
- package/node_modules/nodemailer/dist/cjs/smtp-connection/index.d.ts +7 -1
- package/node_modules/nodemailer/dist/cjs/smtp-connection/index.js +348 -136
- package/node_modules/nodemailer/dist/cjs/smtp-pool/index.d.ts +3 -0
- package/node_modules/nodemailer/dist/cjs/smtp-pool/index.js +7 -1
- package/node_modules/nodemailer/dist/cjs/smtp-pool/pool-resource.js +106 -17
- package/node_modules/nodemailer/dist/cjs/smtp-transport/index.js +8 -2
- package/node_modules/nodemailer/dist/esm/base64/index.d.ts +3 -0
- package/node_modules/nodemailer/dist/esm/base64/index.js +80 -41
- package/node_modules/nodemailer/dist/esm/dkim/index.js +43 -29
- package/node_modules/nodemailer/dist/esm/dkim/message-parser.js +2 -2
- package/node_modules/nodemailer/dist/esm/errors.d.ts +17 -0
- package/node_modules/nodemailer/dist/esm/errors.js +10 -0
- package/node_modules/nodemailer/dist/esm/fetch/index.js +23 -3
- package/node_modules/nodemailer/dist/esm/mailer/index.js +23 -7
- package/node_modules/nodemailer/dist/esm/mailer/mail-message.d.ts +5 -0
- package/node_modules/nodemailer/dist/esm/mailer/mail-message.js +20 -0
- package/node_modules/nodemailer/dist/esm/mime-node/index.d.ts +1 -1
- package/node_modules/nodemailer/dist/esm/mime-node/index.js +166 -106
- package/node_modules/nodemailer/dist/esm/nodemailer.js +12 -9
- package/node_modules/nodemailer/dist/esm/package-info.d.ts +1 -1
- package/node_modules/nodemailer/dist/esm/package-info.js +1 -1
- package/node_modules/nodemailer/dist/esm/qp/index.d.ts +2 -0
- package/node_modules/nodemailer/dist/esm/qp/index.js +103 -33
- package/node_modules/nodemailer/dist/esm/sendmail-transport/index.js +54 -14
- package/node_modules/nodemailer/dist/esm/shared/index.d.ts +32 -1
- package/node_modules/nodemailer/dist/esm/shared/index.js +207 -115
- package/node_modules/nodemailer/dist/esm/smtp-connection/http-proxy-client.d.ts +3 -1
- package/node_modules/nodemailer/dist/esm/smtp-connection/http-proxy-client.js +88 -68
- package/node_modules/nodemailer/dist/esm/smtp-connection/index.d.ts +7 -1
- package/node_modules/nodemailer/dist/esm/smtp-connection/index.js +348 -136
- package/node_modules/nodemailer/dist/esm/smtp-pool/index.d.ts +3 -0
- package/node_modules/nodemailer/dist/esm/smtp-pool/index.js +7 -1
- package/node_modules/nodemailer/dist/esm/smtp-pool/pool-resource.js +106 -17
- package/node_modules/nodemailer/dist/esm/smtp-transport/index.js +8 -2
- package/node_modules/nodemailer/package.json +1 -1
- package/node_modules/uuid/package.json +17 -17
- package/package.json +9 -9
|
@@ -8,6 +8,7 @@ import { isProtoKey, copyOwnKeys } from './objects.js';
|
|
|
8
8
|
import dns from 'node:dns';
|
|
9
9
|
import net from 'node:net';
|
|
10
10
|
import os from 'node:os';
|
|
11
|
+
import { finished } from 'node:stream';
|
|
11
12
|
// re-exported for the callers that already depend on this module, see ./objects
|
|
12
13
|
export { isProtoKey, copyOwnKeys };
|
|
13
14
|
const DNS_TTL = 5 * 60 * 1000;
|
|
@@ -21,14 +22,24 @@ export const _resetCacheCleanup = () => {
|
|
|
21
22
|
lastCacheCleanup = 0;
|
|
22
23
|
};
|
|
23
24
|
export let networkInterfaces;
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
25
|
+
let networkInterfacesRead = false;
|
|
26
|
+
// Read on first use rather than at load, so that importing the module does not ask for
|
|
27
|
+
// the interface table (Deno prompts for --allow-sys on it)
|
|
28
|
+
/** @internal */
|
|
29
|
+
export const _readNetworkInterfaces = () => {
|
|
30
|
+
if (!networkInterfacesRead) {
|
|
31
|
+
networkInterfacesRead = true;
|
|
32
|
+
try {
|
|
33
|
+
networkInterfaces = os.networkInterfaces();
|
|
34
|
+
}
|
|
35
|
+
catch (_err) {
|
|
36
|
+
// fails on some systems
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return networkInterfaces;
|
|
40
|
+
};
|
|
30
41
|
const isFamilySupported = (family, allowInternal) => {
|
|
31
|
-
const addresses = Object.values(
|
|
42
|
+
const addresses = Object.values(_readNetworkInterfaces() || {}).flat();
|
|
32
43
|
if (!addresses.length) {
|
|
33
44
|
// hope for the best. Runtimes without an interface table (Cloudflare
|
|
34
45
|
// Workers) report an empty object rather than throwing
|
|
@@ -39,7 +50,8 @@ const isFamilySupported = (family, allowInternal) => {
|
|
|
39
50
|
const resolve = (family, hostname, options, callback) => {
|
|
40
51
|
options = options || {};
|
|
41
52
|
if (!isFamilySupported(family, options.allowInternalNetworkInterfaces)) {
|
|
42
|
-
|
|
53
|
+
callback(null, []);
|
|
54
|
+
return null;
|
|
43
55
|
}
|
|
44
56
|
const dnsResolver = dns.Resolver ? new dns.Resolver(options) : dns;
|
|
45
57
|
dnsResolver['resolve' + family](hostname, (err, addresses) => {
|
|
@@ -58,6 +70,7 @@ const resolve = (family, hostname, options, callback) => {
|
|
|
58
70
|
}
|
|
59
71
|
return callback(null, Array.isArray(addresses) ? addresses : [].concat(addresses || []));
|
|
60
72
|
});
|
|
73
|
+
return dns.Resolver ? dnsResolver : null;
|
|
61
74
|
};
|
|
62
75
|
export const dnsCache = new Map();
|
|
63
76
|
const formatDNSValue = (value, extra) => {
|
|
@@ -121,115 +134,139 @@ export const resolveHostname = (options, callback) => {
|
|
|
121
134
|
}));
|
|
122
135
|
}
|
|
123
136
|
}
|
|
124
|
-
//
|
|
137
|
+
// The timeout limits the lookup as a whole. It is also handed to the resolver, but there
|
|
138
|
+
// it applies to every query attempt on its own, and the resolver retries a few times
|
|
139
|
+
let responded = false;
|
|
140
|
+
let deadline;
|
|
141
|
+
const respond = (err, result) => {
|
|
142
|
+
if (responded) {
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
responded = true;
|
|
146
|
+
clearTimeout(deadline);
|
|
147
|
+
callback(err, result);
|
|
148
|
+
};
|
|
149
|
+
// a stale cached value is still better than no value at all
|
|
150
|
+
const respondCached = (error) => {
|
|
151
|
+
if (!cached) {
|
|
152
|
+
return false;
|
|
153
|
+
}
|
|
154
|
+
dnsCache.set(host, {
|
|
155
|
+
value: cached.value,
|
|
156
|
+
expires: Date.now() + (options.dnsTtl || DNS_TTL)
|
|
157
|
+
});
|
|
158
|
+
respond(null, formatDNSValue(cached.value, {
|
|
159
|
+
servername,
|
|
160
|
+
cached: true,
|
|
161
|
+
error
|
|
162
|
+
}));
|
|
163
|
+
return true;
|
|
164
|
+
};
|
|
165
|
+
const resolvers = [];
|
|
166
|
+
const timeout = Number(options.timeout) || 0;
|
|
167
|
+
if (timeout > 0) {
|
|
168
|
+
deadline = setTimeout(() => {
|
|
169
|
+
for (const resolver of resolvers) {
|
|
170
|
+
if (typeof resolver.cancel === 'function') {
|
|
171
|
+
resolver.cancel();
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
const err = new Error('DNS lookup for ' + host + ' timed out');
|
|
175
|
+
err.code = dns.TIMEOUT;
|
|
176
|
+
if (!respondCached(err)) {
|
|
177
|
+
respond(err);
|
|
178
|
+
}
|
|
179
|
+
}, timeout);
|
|
180
|
+
}
|
|
181
|
+
// Resolve both IPv4 and IPv6 addresses for fallback support, at the same time
|
|
125
182
|
let ipv4Addresses = [];
|
|
126
183
|
let ipv6Addresses = [];
|
|
127
184
|
let ipv4Error = null;
|
|
128
185
|
let ipv6Error = null;
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
186
|
+
let pending = 2;
|
|
187
|
+
const onResolved = () => {
|
|
188
|
+
if (--pending || responded) {
|
|
189
|
+
return;
|
|
132
190
|
}
|
|
133
|
-
|
|
134
|
-
|
|
191
|
+
// Combine addresses: IPv4 first, then IPv6
|
|
192
|
+
const allAddresses = ipv4Addresses.concat(ipv6Addresses);
|
|
193
|
+
if (allAddresses.length) {
|
|
194
|
+
const value = {
|
|
195
|
+
addresses: allAddresses
|
|
196
|
+
};
|
|
197
|
+
dnsCache.set(host, {
|
|
198
|
+
value,
|
|
199
|
+
expires: Date.now() + (options.dnsTtl || DNS_TTL)
|
|
200
|
+
});
|
|
201
|
+
return respond(null, formatDNSValue(value, {
|
|
202
|
+
servername,
|
|
203
|
+
cached: false
|
|
204
|
+
}));
|
|
135
205
|
}
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
206
|
+
// No addresses from resolve4/resolve6, try dns.lookup as fallback
|
|
207
|
+
if (ipv4Error && ipv6Error && respondCached(ipv4Error)) {
|
|
208
|
+
// Both resolvers had errors
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
try {
|
|
212
|
+
dns.lookup(host, { all: true }, (err, addresses) => {
|
|
213
|
+
if (err) {
|
|
214
|
+
if (respondCached(err)) {
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
return respond(err);
|
|
218
|
+
}
|
|
219
|
+
// Get all supported addresses from dns.lookup
|
|
220
|
+
const supportedAddresses = addresses
|
|
221
|
+
? addresses.filter(addr => isFamilySupported(addr.family)).map(addr => addr.address)
|
|
222
|
+
: [];
|
|
223
|
+
if (addresses && addresses.length && !supportedAddresses.length) {
|
|
224
|
+
// there are addresses but none can be used
|
|
225
|
+
console.warn(`Failed to resolve IPv${addresses[0].family} addresses with current network`);
|
|
226
|
+
}
|
|
227
|
+
if (!supportedAddresses.length && cached) {
|
|
228
|
+
// nothing was found, fallback to cached value
|
|
229
|
+
return respond(null, formatDNSValue(cached.value, {
|
|
230
|
+
servername,
|
|
231
|
+
cached: true
|
|
232
|
+
}));
|
|
233
|
+
}
|
|
146
234
|
const value = {
|
|
147
|
-
addresses:
|
|
235
|
+
addresses: supportedAddresses.length ? supportedAddresses : [host]
|
|
148
236
|
};
|
|
149
237
|
dnsCache.set(host, {
|
|
150
238
|
value,
|
|
151
239
|
expires: Date.now() + (options.dnsTtl || DNS_TTL)
|
|
152
240
|
});
|
|
153
|
-
return
|
|
241
|
+
return respond(null, formatDNSValue(value, {
|
|
154
242
|
servername,
|
|
155
243
|
cached: false
|
|
156
244
|
}));
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
catch (lookupErr) {
|
|
248
|
+
if (respondCached(lookupErr)) {
|
|
249
|
+
return;
|
|
157
250
|
}
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
return callback(null, formatDNSValue(cached.value, {
|
|
167
|
-
servername,
|
|
168
|
-
cached: true,
|
|
169
|
-
error: ipv4Error
|
|
170
|
-
}));
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
try {
|
|
174
|
-
dns.lookup(host, { all: true }, (err, addresses) => {
|
|
175
|
-
if (err) {
|
|
176
|
-
if (cached) {
|
|
177
|
-
dnsCache.set(host, {
|
|
178
|
-
value: cached.value,
|
|
179
|
-
expires: Date.now() + (options.dnsTtl || DNS_TTL)
|
|
180
|
-
});
|
|
181
|
-
return callback(null, formatDNSValue(cached.value, {
|
|
182
|
-
servername,
|
|
183
|
-
cached: true,
|
|
184
|
-
error: err
|
|
185
|
-
}));
|
|
186
|
-
}
|
|
187
|
-
return callback(err);
|
|
188
|
-
}
|
|
189
|
-
// Get all supported addresses from dns.lookup
|
|
190
|
-
const supportedAddresses = addresses
|
|
191
|
-
? addresses.filter(addr => isFamilySupported(addr.family)).map(addr => addr.address)
|
|
192
|
-
: [];
|
|
193
|
-
if (addresses && addresses.length && !supportedAddresses.length) {
|
|
194
|
-
// there are addresses but none can be used
|
|
195
|
-
console.warn(`Failed to resolve IPv${addresses[0].family} addresses with current network`);
|
|
196
|
-
}
|
|
197
|
-
if (!supportedAddresses.length && cached) {
|
|
198
|
-
// nothing was found, fallback to cached value
|
|
199
|
-
return callback(null, formatDNSValue(cached.value, {
|
|
200
|
-
servername,
|
|
201
|
-
cached: true
|
|
202
|
-
}));
|
|
203
|
-
}
|
|
204
|
-
const value = {
|
|
205
|
-
addresses: supportedAddresses.length ? supportedAddresses : [host]
|
|
206
|
-
};
|
|
207
|
-
dnsCache.set(host, {
|
|
208
|
-
value,
|
|
209
|
-
expires: Date.now() + (options.dnsTtl || DNS_TTL)
|
|
210
|
-
});
|
|
211
|
-
return callback(null, formatDNSValue(value, {
|
|
212
|
-
servername,
|
|
213
|
-
cached: false
|
|
214
|
-
}));
|
|
215
|
-
});
|
|
251
|
+
return respond(ipv4Error || ipv6Error || lookupErr);
|
|
252
|
+
}
|
|
253
|
+
};
|
|
254
|
+
for (const family of [4, 6]) {
|
|
255
|
+
const resolver = resolve(family, host, options, (err, addresses) => {
|
|
256
|
+
if (family === 4) {
|
|
257
|
+
ipv4Error = err;
|
|
258
|
+
ipv4Addresses = addresses || [];
|
|
216
259
|
}
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
value: cached.value,
|
|
221
|
-
expires: Date.now() + (options.dnsTtl || DNS_TTL)
|
|
222
|
-
});
|
|
223
|
-
return callback(null, formatDNSValue(cached.value, {
|
|
224
|
-
servername,
|
|
225
|
-
cached: true,
|
|
226
|
-
error: lookupErr
|
|
227
|
-
}));
|
|
228
|
-
}
|
|
229
|
-
return callback(ipv4Error || ipv6Error || lookupErr);
|
|
260
|
+
else {
|
|
261
|
+
ipv6Error = err;
|
|
262
|
+
ipv6Addresses = addresses || [];
|
|
230
263
|
}
|
|
264
|
+
onResolved();
|
|
231
265
|
});
|
|
232
|
-
|
|
266
|
+
if (resolver) {
|
|
267
|
+
resolvers.push(resolver);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
233
270
|
};
|
|
234
271
|
/**
|
|
235
272
|
* Parses connection url to a structured configuration object
|
|
@@ -548,43 +585,98 @@ export const encodeXText = (str) => {
|
|
|
548
585
|
}
|
|
549
586
|
return result;
|
|
550
587
|
};
|
|
588
|
+
// The first error a stream emitted, see recordStreamErrors
|
|
589
|
+
const streamErrors = new WeakMap();
|
|
590
|
+
/**
|
|
591
|
+
* Keeps the first error a content stream emits before it is read, so the error is reported
|
|
592
|
+
* when the stream is read instead of being thrown as unhandled. The listener stays attached
|
|
593
|
+
* for good, a stream that emits 'error' more than once never throws the later ones either
|
|
594
|
+
*
|
|
595
|
+
* @param stream Readable stream
|
|
596
|
+
*/
|
|
597
|
+
export function recordStreamErrors(stream) {
|
|
598
|
+
stream.on('error', err => {
|
|
599
|
+
if (!streamErrors.has(stream)) {
|
|
600
|
+
streamErrors.set(stream, err);
|
|
601
|
+
}
|
|
602
|
+
});
|
|
603
|
+
}
|
|
604
|
+
/**
|
|
605
|
+
* Destroys a value if it is a readable stream that was not destroyed yet
|
|
606
|
+
*
|
|
607
|
+
* @param value Any content value
|
|
608
|
+
*/
|
|
609
|
+
export function destroyStream(value) {
|
|
610
|
+
const stream = value;
|
|
611
|
+
if (stream && typeof stream.pipe === 'function' && typeof stream.destroy === 'function' && !stream.destroyed) {
|
|
612
|
+
stream.destroy();
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
/**
|
|
616
|
+
* Tells why a stream can not be read from start to end anymore. A stream that ended or was
|
|
617
|
+
* destroyed before anyone read it would never emit 'end' to a new reader, or, when piped, would
|
|
618
|
+
* end the destination right away and turn into an empty value without any error
|
|
619
|
+
*
|
|
620
|
+
* @param stream Readable stream
|
|
621
|
+
* @returns The error the stream failed with, an ESTREAM error, or null when it can be read
|
|
622
|
+
*/
|
|
623
|
+
export function unreadableStreamError(stream) {
|
|
624
|
+
const err = streamErrors.get(stream) || stream.errored;
|
|
625
|
+
if (err) {
|
|
626
|
+
return err;
|
|
627
|
+
}
|
|
628
|
+
if (stream.readableEnded || stream.destroyed) {
|
|
629
|
+
const unreadable = new Error('Content stream was already read or destroyed');
|
|
630
|
+
unreadable.code = errors.ESTREAM;
|
|
631
|
+
return unreadable;
|
|
632
|
+
}
|
|
633
|
+
return null;
|
|
634
|
+
}
|
|
551
635
|
/**
|
|
552
636
|
* Streams a stream value into a Buffer
|
|
553
637
|
*
|
|
554
638
|
* @param stream Readable stream
|
|
555
639
|
* @param callback Callback function with (err, value)
|
|
556
640
|
*/
|
|
557
|
-
function resolveStream(stream, callback) {
|
|
641
|
+
export function resolveStream(stream, callback) {
|
|
558
642
|
let responded = false;
|
|
559
|
-
const
|
|
560
|
-
let chunklen = 0;
|
|
561
|
-
stream.on('error', err => {
|
|
643
|
+
const respond = (err, value) => {
|
|
562
644
|
if (responded) {
|
|
563
645
|
return;
|
|
564
646
|
}
|
|
565
647
|
responded = true;
|
|
566
|
-
callback(err);
|
|
567
|
-
}
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
648
|
+
callback(err, value);
|
|
649
|
+
};
|
|
650
|
+
const unreadable = unreadableStreamError(stream);
|
|
651
|
+
if (unreadable) {
|
|
652
|
+
// absorbs a later 'error' from the stream, there is nobody left to report it to
|
|
653
|
+
stream.on('error', () => false);
|
|
654
|
+
setImmediate(() => respond(unreadable));
|
|
655
|
+
return;
|
|
656
|
+
}
|
|
657
|
+
const chunks = [];
|
|
658
|
+
let chunklen = 0;
|
|
659
|
+
stream.on('data', (chunk) => {
|
|
660
|
+
if (typeof chunk === 'string') {
|
|
661
|
+
chunk = Buffer.from(chunk);
|
|
573
662
|
}
|
|
663
|
+
chunks.push(chunk);
|
|
664
|
+
chunklen += chunk.length;
|
|
574
665
|
});
|
|
575
|
-
stream
|
|
576
|
-
|
|
577
|
-
|
|
666
|
+
// finished() also reports a stream that is destroyed before 'end', which would otherwise
|
|
667
|
+
// leave the callback waiting forever
|
|
668
|
+
finished(stream, { writable: false }, err => {
|
|
669
|
+
if (err) {
|
|
670
|
+
return respond(err);
|
|
578
671
|
}
|
|
579
|
-
responded = true;
|
|
580
672
|
let value;
|
|
581
673
|
try {
|
|
582
674
|
value = Buffer.concat(chunks, chunklen);
|
|
583
675
|
}
|
|
584
676
|
catch (E) {
|
|
585
|
-
return
|
|
677
|
+
return respond(E);
|
|
586
678
|
}
|
|
587
|
-
|
|
679
|
+
respond(null, value);
|
|
588
680
|
});
|
|
589
681
|
}
|
|
590
682
|
/**
|
|
@@ -9,6 +9,8 @@ import type { Callback } from '../errors.js';
|
|
|
9
9
|
export interface HttpProxyClientOptions {
|
|
10
10
|
/** Set to false to accept a proxy certificate that fails validation (e.g. self-signed) */
|
|
11
11
|
rejectUnauthorized?: boolean | undefined;
|
|
12
|
+
/** Time in milliseconds the CONNECT handshake may take, defaults to httpProxyClient.timeout or 30 seconds */
|
|
13
|
+
timeout?: number | undefined;
|
|
12
14
|
}
|
|
13
15
|
/**
|
|
14
16
|
* Receives the proxied socket once the CONNECT handshake has succeeded, or the error that prevented it
|
|
@@ -38,7 +40,7 @@ declare function httpProxyClient(proxyUrl: string, destinationPort: number | str
|
|
|
38
40
|
*/
|
|
39
41
|
declare function httpProxyClient(proxyUrl: string, destinationPort: number | string, destinationHost: string, tlsOptions: HttpProxyClientOptions | undefined, callback: HttpProxyClientCallback): void;
|
|
40
42
|
/**
|
|
41
|
-
*
|
|
43
|
+
* Time in milliseconds the CONNECT handshake may take when the call does not set one, defaults to 30 seconds.
|
|
42
44
|
* Settable on the function itself, the same way the CommonJS module exposed it.
|
|
43
45
|
*/
|
|
44
46
|
declare namespace httpProxyClient {
|
|
@@ -8,6 +8,8 @@ import * as errors from '../errors.js';
|
|
|
8
8
|
// Cap the CONNECT response we buffer before the header terminator, so a proxy that
|
|
9
9
|
// never sends \r\n\r\n cannot grow memory unboundedly before the socket times out.
|
|
10
10
|
const MAX_RESPONSE_HEADER_BYTES = 64 * 1024;
|
|
11
|
+
// URL hostnames keep the brackets around an IPv6 literal, socket options and net.isIPv6 take it without
|
|
12
|
+
const unbracket = (host) => typeof host === 'string' && host.startsWith('[') && host.endsWith(']') ? host.slice(1, -1) : host;
|
|
11
13
|
function httpProxyClient(proxyUrl, destinationPort, destinationHost, tlsOptions, callback) {
|
|
12
14
|
if (typeof tlsOptions === 'function') {
|
|
13
15
|
callback = tlsOptions;
|
|
@@ -27,6 +29,8 @@ function httpProxyClient(proxyUrl, destinationPort, destinationHost, tlsOptions,
|
|
|
27
29
|
return;
|
|
28
30
|
}
|
|
29
31
|
const proxy = urllib.parse(proxyUrl);
|
|
32
|
+
// the CONNECT request line and the Host header take an IPv6 destination in brackets
|
|
33
|
+
const authority = (net.isIPv6(unbracket(destinationHost)) ? '[' + unbracket(destinationHost) + ']' : destinationHost) + ':' + destinationPort;
|
|
30
34
|
const connectOptions = {
|
|
31
35
|
host: proxy.hostname,
|
|
32
36
|
port: Number(proxy.port) ? Number(proxy.port) : proxy.protocol === 'https:' ? 443 : 80
|
|
@@ -42,15 +46,27 @@ function httpProxyClient(proxyUrl, destinationPort, destinationHost, tlsOptions,
|
|
|
42
46
|
else {
|
|
43
47
|
connect = net.connect.bind(net);
|
|
44
48
|
}
|
|
49
|
+
// The handshake is bounded as a whole, a proxy that keeps sending a byte now and then can
|
|
50
|
+
// not hold the connection open past it
|
|
51
|
+
const timeout = Number(tlsOptions.timeout) || httpProxyClient.timeout || 30 * 1000;
|
|
45
52
|
let socket;
|
|
46
|
-
//
|
|
47
|
-
//
|
|
53
|
+
// Single settlement path for the handshake: every temporary listener and the timer are
|
|
54
|
+
// dropped exactly once. Once the tunnel is up, the responsibility to handle errors is passed
|
|
55
|
+
// to whoever uses this socket
|
|
48
56
|
let finished = false;
|
|
49
|
-
|
|
57
|
+
let timer;
|
|
58
|
+
const cleanup = () => {
|
|
59
|
+
clearTimeout(timer);
|
|
60
|
+
socket.removeListener('data', onSocketData);
|
|
61
|
+
socket.removeListener('error', fail);
|
|
62
|
+
socket.removeListener('close', onEarlyClose);
|
|
63
|
+
};
|
|
64
|
+
function fail(err) {
|
|
50
65
|
if (finished) {
|
|
51
66
|
return;
|
|
52
67
|
}
|
|
53
68
|
finished = true;
|
|
69
|
+
cleanup();
|
|
54
70
|
try {
|
|
55
71
|
socket.destroy();
|
|
56
72
|
}
|
|
@@ -58,18 +74,72 @@ function httpProxyClient(proxyUrl, destinationPort, destinationHost, tlsOptions,
|
|
|
58
74
|
// ignore
|
|
59
75
|
}
|
|
60
76
|
done(err);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
const err = new Error('Proxy
|
|
64
|
-
err.code =
|
|
65
|
-
|
|
66
|
-
}
|
|
77
|
+
}
|
|
78
|
+
function onEarlyClose() {
|
|
79
|
+
const err = new Error('Proxy closed the connection before the tunnel was established');
|
|
80
|
+
err.code = errors.EPROXY;
|
|
81
|
+
fail(err);
|
|
82
|
+
}
|
|
83
|
+
// The response is collected as chunks and only the bytes that just arrived, together
|
|
84
|
+
// with the three before them, are searched for the end of the headers. Appending to a
|
|
85
|
+
// string and searching all of it again re-read the whole response on every chunk.
|
|
86
|
+
const chunks = [];
|
|
87
|
+
let received = 0;
|
|
88
|
+
let tail = '';
|
|
89
|
+
function onSocketData(chunk) {
|
|
90
|
+
if (finished) {
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
const window = tail + chunk.toString('binary');
|
|
94
|
+
const windowEnd = window.indexOf('\r\n\r\n');
|
|
95
|
+
chunks.push(chunk);
|
|
96
|
+
received += chunk.length;
|
|
97
|
+
tail = window.slice(-3);
|
|
98
|
+
if (windowEnd < 0) {
|
|
99
|
+
if (received > MAX_RESPONSE_HEADER_BYTES) {
|
|
100
|
+
const err = new Error('Proxy response headers too large');
|
|
101
|
+
err.code = errors.EPROXY;
|
|
102
|
+
fail(err);
|
|
103
|
+
}
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
// Stop reading before anything is put back. A socket that keeps flowing would emit the
|
|
107
|
+
// bytes after the headers, a greeting the proxy sent together with its own response,
|
|
108
|
+
// before the next owner of the socket has a listener for them
|
|
109
|
+
socket.removeListener('data', onSocketData);
|
|
110
|
+
socket.pause();
|
|
111
|
+
const headerEnd = received - window.length + windowEnd;
|
|
112
|
+
const response = Buffer.concat(chunks, received);
|
|
113
|
+
if (response.length > headerEnd + 4) {
|
|
114
|
+
socket.unshift(response.subarray(headerEnd + 4));
|
|
115
|
+
}
|
|
116
|
+
// check response code
|
|
117
|
+
const match = response.toString('binary', 0, headerEnd).match(/^HTTP\/\d+\.\d+ (\d+)/i);
|
|
118
|
+
if (!match || (match[1] || '').charAt(0) !== '2') {
|
|
119
|
+
const err = new Error('Invalid response from proxy' + ((match && ': ' + match[1]) || ''));
|
|
120
|
+
err.code = errors.EPROXY;
|
|
121
|
+
return fail(err);
|
|
122
|
+
}
|
|
123
|
+
// proxy connection is now established
|
|
124
|
+
finished = true;
|
|
125
|
+
cleanup();
|
|
126
|
+
// A fresh socket starts flowing once something listens for 'data', a paused one would
|
|
127
|
+
// not. Keep that behaviour for the next owner of the socket
|
|
128
|
+
const resumeOnData = (event) => {
|
|
129
|
+
if (event === 'data') {
|
|
130
|
+
socket.removeListener('newListener', resumeOnData);
|
|
131
|
+
socket.resume();
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
socket.on('newListener', resumeOnData);
|
|
135
|
+
return done(null, socket);
|
|
136
|
+
}
|
|
67
137
|
socket = connect(connectOptions, () => {
|
|
68
138
|
if (finished) {
|
|
69
139
|
return;
|
|
70
140
|
}
|
|
71
141
|
const reqHeaders = {
|
|
72
|
-
Host:
|
|
142
|
+
Host: authority,
|
|
73
143
|
Connection: 'close'
|
|
74
144
|
};
|
|
75
145
|
if (proxy.auth) {
|
|
@@ -78,9 +148,7 @@ function httpProxyClient(proxyUrl, destinationPort, destinationHost, tlsOptions,
|
|
|
78
148
|
socket.write(
|
|
79
149
|
// HTTP method
|
|
80
150
|
'CONNECT ' +
|
|
81
|
-
|
|
82
|
-
':' +
|
|
83
|
-
destinationPort +
|
|
151
|
+
authority +
|
|
84
152
|
' HTTP/1.1\r\n' +
|
|
85
153
|
// HTTP request headers
|
|
86
154
|
Object.keys(reqHeaders)
|
|
@@ -88,62 +156,14 @@ function httpProxyClient(proxyUrl, destinationPort, destinationHost, tlsOptions,
|
|
|
88
156
|
.join('\r\n') +
|
|
89
157
|
// End request
|
|
90
158
|
'\r\n\r\n');
|
|
91
|
-
// The response is collected as chunks and only the bytes that just arrived, together
|
|
92
|
-
// with the three before them, are searched for the end of the headers. Appending to a
|
|
93
|
-
// string and searching all of it again re-read the whole response on every chunk.
|
|
94
|
-
const chunks = [];
|
|
95
|
-
let received = 0;
|
|
96
|
-
let tail = '';
|
|
97
|
-
const onSocketData = (chunk) => {
|
|
98
|
-
let match;
|
|
99
|
-
if (finished) {
|
|
100
|
-
return;
|
|
101
|
-
}
|
|
102
|
-
const window = tail + chunk.toString('binary');
|
|
103
|
-
const windowEnd = window.indexOf('\r\n\r\n');
|
|
104
|
-
chunks.push(chunk);
|
|
105
|
-
received += chunk.length;
|
|
106
|
-
tail = window.slice(-3);
|
|
107
|
-
if (windowEnd >= 0) {
|
|
108
|
-
socket.removeListener('data', onSocketData);
|
|
109
|
-
const headerEnd = received - window.length + windowEnd;
|
|
110
|
-
const response = Buffer.concat(chunks, received).toString('binary');
|
|
111
|
-
const headers = response.substr(0, headerEnd);
|
|
112
|
-
const remainder = response.substr(headerEnd + 4);
|
|
113
|
-
if (remainder) {
|
|
114
|
-
socket.unshift(Buffer.from(remainder, 'binary'));
|
|
115
|
-
}
|
|
116
|
-
// proxy connection is now established
|
|
117
|
-
finished = true;
|
|
118
|
-
// check response code
|
|
119
|
-
match = headers.match(/^HTTP\/\d+\.\d+ (\d+)/i);
|
|
120
|
-
if (!match || (match[1] || '').charAt(0) !== '2') {
|
|
121
|
-
try {
|
|
122
|
-
socket.destroy();
|
|
123
|
-
}
|
|
124
|
-
catch (_E) {
|
|
125
|
-
// ignore
|
|
126
|
-
}
|
|
127
|
-
const err = new Error('Invalid response from proxy' + ((match && ': ' + match[1]) || ''));
|
|
128
|
-
err.code = errors.EPROXY;
|
|
129
|
-
return done(err);
|
|
130
|
-
}
|
|
131
|
-
socket.removeListener('error', tempSocketErr);
|
|
132
|
-
socket.removeListener('timeout', timeoutErr);
|
|
133
|
-
socket.setTimeout(0);
|
|
134
|
-
return done(null, socket);
|
|
135
|
-
}
|
|
136
|
-
if (received > MAX_RESPONSE_HEADER_BYTES) {
|
|
137
|
-
socket.removeListener('data', onSocketData);
|
|
138
|
-
const err = new Error('Proxy response headers too large');
|
|
139
|
-
err.code = errors.EPROXY;
|
|
140
|
-
return tempSocketErr(err);
|
|
141
|
-
}
|
|
142
|
-
};
|
|
143
159
|
socket.on('data', onSocketData);
|
|
144
160
|
});
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
161
|
+
timer = setTimeout(() => {
|
|
162
|
+
const err = new Error('Proxy socket timed out');
|
|
163
|
+
err.code = errors.ETIMEDOUT;
|
|
164
|
+
fail(err);
|
|
165
|
+
}, timeout);
|
|
166
|
+
socket.once('error', fail);
|
|
167
|
+
socket.once('close', onEarlyClose);
|
|
148
168
|
}
|
|
149
169
|
export default httpProxyClient;
|
|
@@ -3,7 +3,7 @@ import net from 'node:net';
|
|
|
3
3
|
import tls from 'node:tls';
|
|
4
4
|
import { type Readable } from 'node:stream';
|
|
5
5
|
import * as shared from '../shared/index.js';
|
|
6
|
-
import type
|
|
6
|
+
import { type Callback, type NodemailerError } from '../errors.js';
|
|
7
7
|
import type XOAuth2 from '../xoauth2/index.js';
|
|
8
8
|
import type { XOAuth2Options } from '../xoauth2/index.js';
|
|
9
9
|
/**
|
|
@@ -275,6 +275,12 @@ export interface SMTPConnectionConnectOptions extends tls.ConnectionOptions {
|
|
|
275
275
|
allowInternalNetworkInterfaces?: boolean | undefined;
|
|
276
276
|
/** DNS lookup timeout in ms */
|
|
277
277
|
timeout?: number | undefined;
|
|
278
|
+
/** Try the resolved addresses in turn, see net.connect */
|
|
279
|
+
autoSelectFamily?: boolean | undefined;
|
|
280
|
+
/** Time in ms an address gets before the next one is tried, see net.connect */
|
|
281
|
+
autoSelectFamilyAttemptTimeout?: number | undefined;
|
|
282
|
+
/** Hands the resolved addresses to net.connect */
|
|
283
|
+
lookup?: net.LookupFunction | undefined;
|
|
278
284
|
}
|
|
279
285
|
/**
|
|
280
286
|
* A queued handler for the next server response
|