@mavogel/awscdk-rootmail 0.1.15 → 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 +4 -4
- package/lib/rootmail.js +1 -1
- package/lib/ses-receive.js +1 -1
- 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/package.json +3 -3
|
@@ -46,6 +46,8 @@ const errors = __importStar(require("../errors.js"));
|
|
|
46
46
|
// Cap the CONNECT response we buffer before the header terminator, so a proxy that
|
|
47
47
|
// never sends \r\n\r\n cannot grow memory unboundedly before the socket times out.
|
|
48
48
|
const MAX_RESPONSE_HEADER_BYTES = 64 * 1024;
|
|
49
|
+
// URL hostnames keep the brackets around an IPv6 literal, socket options and net.isIPv6 take it without
|
|
50
|
+
const unbracket = (host) => typeof host === 'string' && host.startsWith('[') && host.endsWith(']') ? host.slice(1, -1) : host;
|
|
49
51
|
function httpProxyClient(proxyUrl, destinationPort, destinationHost, tlsOptions, callback) {
|
|
50
52
|
if (typeof tlsOptions === 'function') {
|
|
51
53
|
callback = tlsOptions;
|
|
@@ -65,6 +67,8 @@ function httpProxyClient(proxyUrl, destinationPort, destinationHost, tlsOptions,
|
|
|
65
67
|
return;
|
|
66
68
|
}
|
|
67
69
|
const proxy = urllib.parse(proxyUrl);
|
|
70
|
+
// the CONNECT request line and the Host header take an IPv6 destination in brackets
|
|
71
|
+
const authority = (node_net_1.default.isIPv6(unbracket(destinationHost)) ? '[' + unbracket(destinationHost) + ']' : destinationHost) + ':' + destinationPort;
|
|
68
72
|
const connectOptions = {
|
|
69
73
|
host: proxy.hostname,
|
|
70
74
|
port: Number(proxy.port) ? Number(proxy.port) : proxy.protocol === 'https:' ? 443 : 80
|
|
@@ -80,15 +84,27 @@ function httpProxyClient(proxyUrl, destinationPort, destinationHost, tlsOptions,
|
|
|
80
84
|
else {
|
|
81
85
|
connect = node_net_1.default.connect.bind(node_net_1.default);
|
|
82
86
|
}
|
|
87
|
+
// The handshake is bounded as a whole, a proxy that keeps sending a byte now and then can
|
|
88
|
+
// not hold the connection open past it
|
|
89
|
+
const timeout = Number(tlsOptions.timeout) || httpProxyClient.timeout || 30 * 1000;
|
|
83
90
|
let socket;
|
|
84
|
-
//
|
|
85
|
-
//
|
|
91
|
+
// Single settlement path for the handshake: every temporary listener and the timer are
|
|
92
|
+
// dropped exactly once. Once the tunnel is up, the responsibility to handle errors is passed
|
|
93
|
+
// to whoever uses this socket
|
|
86
94
|
let finished = false;
|
|
87
|
-
|
|
95
|
+
let timer;
|
|
96
|
+
const cleanup = () => {
|
|
97
|
+
clearTimeout(timer);
|
|
98
|
+
socket.removeListener('data', onSocketData);
|
|
99
|
+
socket.removeListener('error', fail);
|
|
100
|
+
socket.removeListener('close', onEarlyClose);
|
|
101
|
+
};
|
|
102
|
+
function fail(err) {
|
|
88
103
|
if (finished) {
|
|
89
104
|
return;
|
|
90
105
|
}
|
|
91
106
|
finished = true;
|
|
107
|
+
cleanup();
|
|
92
108
|
try {
|
|
93
109
|
socket.destroy();
|
|
94
110
|
}
|
|
@@ -96,18 +112,72 @@ function httpProxyClient(proxyUrl, destinationPort, destinationHost, tlsOptions,
|
|
|
96
112
|
// ignore
|
|
97
113
|
}
|
|
98
114
|
done(err);
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
const err = new Error('Proxy
|
|
102
|
-
err.code =
|
|
103
|
-
|
|
104
|
-
}
|
|
115
|
+
}
|
|
116
|
+
function onEarlyClose() {
|
|
117
|
+
const err = new Error('Proxy closed the connection before the tunnel was established');
|
|
118
|
+
err.code = errors.EPROXY;
|
|
119
|
+
fail(err);
|
|
120
|
+
}
|
|
121
|
+
// The response is collected as chunks and only the bytes that just arrived, together
|
|
122
|
+
// with the three before them, are searched for the end of the headers. Appending to a
|
|
123
|
+
// string and searching all of it again re-read the whole response on every chunk.
|
|
124
|
+
const chunks = [];
|
|
125
|
+
let received = 0;
|
|
126
|
+
let tail = '';
|
|
127
|
+
function onSocketData(chunk) {
|
|
128
|
+
if (finished) {
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
const window = tail + chunk.toString('binary');
|
|
132
|
+
const windowEnd = window.indexOf('\r\n\r\n');
|
|
133
|
+
chunks.push(chunk);
|
|
134
|
+
received += chunk.length;
|
|
135
|
+
tail = window.slice(-3);
|
|
136
|
+
if (windowEnd < 0) {
|
|
137
|
+
if (received > MAX_RESPONSE_HEADER_BYTES) {
|
|
138
|
+
const err = new Error('Proxy response headers too large');
|
|
139
|
+
err.code = errors.EPROXY;
|
|
140
|
+
fail(err);
|
|
141
|
+
}
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
// Stop reading before anything is put back. A socket that keeps flowing would emit the
|
|
145
|
+
// bytes after the headers, a greeting the proxy sent together with its own response,
|
|
146
|
+
// before the next owner of the socket has a listener for them
|
|
147
|
+
socket.removeListener('data', onSocketData);
|
|
148
|
+
socket.pause();
|
|
149
|
+
const headerEnd = received - window.length + windowEnd;
|
|
150
|
+
const response = Buffer.concat(chunks, received);
|
|
151
|
+
if (response.length > headerEnd + 4) {
|
|
152
|
+
socket.unshift(response.subarray(headerEnd + 4));
|
|
153
|
+
}
|
|
154
|
+
// check response code
|
|
155
|
+
const match = response.toString('binary', 0, headerEnd).match(/^HTTP\/\d+\.\d+ (\d+)/i);
|
|
156
|
+
if (!match || (match[1] || '').charAt(0) !== '2') {
|
|
157
|
+
const err = new Error('Invalid response from proxy' + ((match && ': ' + match[1]) || ''));
|
|
158
|
+
err.code = errors.EPROXY;
|
|
159
|
+
return fail(err);
|
|
160
|
+
}
|
|
161
|
+
// proxy connection is now established
|
|
162
|
+
finished = true;
|
|
163
|
+
cleanup();
|
|
164
|
+
// A fresh socket starts flowing once something listens for 'data', a paused one would
|
|
165
|
+
// not. Keep that behaviour for the next owner of the socket
|
|
166
|
+
const resumeOnData = (event) => {
|
|
167
|
+
if (event === 'data') {
|
|
168
|
+
socket.removeListener('newListener', resumeOnData);
|
|
169
|
+
socket.resume();
|
|
170
|
+
}
|
|
171
|
+
};
|
|
172
|
+
socket.on('newListener', resumeOnData);
|
|
173
|
+
return done(null, socket);
|
|
174
|
+
}
|
|
105
175
|
socket = connect(connectOptions, () => {
|
|
106
176
|
if (finished) {
|
|
107
177
|
return;
|
|
108
178
|
}
|
|
109
179
|
const reqHeaders = {
|
|
110
|
-
Host:
|
|
180
|
+
Host: authority,
|
|
111
181
|
Connection: 'close'
|
|
112
182
|
};
|
|
113
183
|
if (proxy.auth) {
|
|
@@ -116,9 +186,7 @@ function httpProxyClient(proxyUrl, destinationPort, destinationHost, tlsOptions,
|
|
|
116
186
|
socket.write(
|
|
117
187
|
// HTTP method
|
|
118
188
|
'CONNECT ' +
|
|
119
|
-
|
|
120
|
-
':' +
|
|
121
|
-
destinationPort +
|
|
189
|
+
authority +
|
|
122
190
|
' HTTP/1.1\r\n' +
|
|
123
191
|
// HTTP request headers
|
|
124
192
|
Object.keys(reqHeaders)
|
|
@@ -126,63 +194,15 @@ function httpProxyClient(proxyUrl, destinationPort, destinationHost, tlsOptions,
|
|
|
126
194
|
.join('\r\n') +
|
|
127
195
|
// End request
|
|
128
196
|
'\r\n\r\n');
|
|
129
|
-
// The response is collected as chunks and only the bytes that just arrived, together
|
|
130
|
-
// with the three before them, are searched for the end of the headers. Appending to a
|
|
131
|
-
// string and searching all of it again re-read the whole response on every chunk.
|
|
132
|
-
const chunks = [];
|
|
133
|
-
let received = 0;
|
|
134
|
-
let tail = '';
|
|
135
|
-
const onSocketData = (chunk) => {
|
|
136
|
-
let match;
|
|
137
|
-
if (finished) {
|
|
138
|
-
return;
|
|
139
|
-
}
|
|
140
|
-
const window = tail + chunk.toString('binary');
|
|
141
|
-
const windowEnd = window.indexOf('\r\n\r\n');
|
|
142
|
-
chunks.push(chunk);
|
|
143
|
-
received += chunk.length;
|
|
144
|
-
tail = window.slice(-3);
|
|
145
|
-
if (windowEnd >= 0) {
|
|
146
|
-
socket.removeListener('data', onSocketData);
|
|
147
|
-
const headerEnd = received - window.length + windowEnd;
|
|
148
|
-
const response = Buffer.concat(chunks, received).toString('binary');
|
|
149
|
-
const headers = response.substr(0, headerEnd);
|
|
150
|
-
const remainder = response.substr(headerEnd + 4);
|
|
151
|
-
if (remainder) {
|
|
152
|
-
socket.unshift(Buffer.from(remainder, 'binary'));
|
|
153
|
-
}
|
|
154
|
-
// proxy connection is now established
|
|
155
|
-
finished = true;
|
|
156
|
-
// check response code
|
|
157
|
-
match = headers.match(/^HTTP\/\d+\.\d+ (\d+)/i);
|
|
158
|
-
if (!match || (match[1] || '').charAt(0) !== '2') {
|
|
159
|
-
try {
|
|
160
|
-
socket.destroy();
|
|
161
|
-
}
|
|
162
|
-
catch (_E) {
|
|
163
|
-
// ignore
|
|
164
|
-
}
|
|
165
|
-
const err = new Error('Invalid response from proxy' + ((match && ': ' + match[1]) || ''));
|
|
166
|
-
err.code = errors.EPROXY;
|
|
167
|
-
return done(err);
|
|
168
|
-
}
|
|
169
|
-
socket.removeListener('error', tempSocketErr);
|
|
170
|
-
socket.removeListener('timeout', timeoutErr);
|
|
171
|
-
socket.setTimeout(0);
|
|
172
|
-
return done(null, socket);
|
|
173
|
-
}
|
|
174
|
-
if (received > MAX_RESPONSE_HEADER_BYTES) {
|
|
175
|
-
socket.removeListener('data', onSocketData);
|
|
176
|
-
const err = new Error('Proxy response headers too large');
|
|
177
|
-
err.code = errors.EPROXY;
|
|
178
|
-
return tempSocketErr(err);
|
|
179
|
-
}
|
|
180
|
-
};
|
|
181
197
|
socket.on('data', onSocketData);
|
|
182
198
|
});
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
199
|
+
timer = setTimeout(() => {
|
|
200
|
+
const err = new Error('Proxy socket timed out');
|
|
201
|
+
err.code = errors.ETIMEDOUT;
|
|
202
|
+
fail(err);
|
|
203
|
+
}, timeout);
|
|
204
|
+
socket.once('error', fail);
|
|
205
|
+
socket.once('close', onEarlyClose);
|
|
186
206
|
}
|
|
187
207
|
exports.default = httpProxyClient;
|
|
188
208
|
module.exports = exports.default;
|
|
@@ -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
|