@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.
Files changed (65) hide show
  1. package/.jsii +4 -4
  2. package/lib/rootmail.js +1 -1
  3. package/lib/ses-receive.js +1 -1
  4. package/node_modules/mailparser/.release-please-manifest.json +1 -1
  5. package/node_modules/mailparser/CHANGELOG.md +7 -0
  6. package/node_modules/mailparser/package.json +2 -2
  7. package/node_modules/nodemailer/CHANGELOG.md +27 -0
  8. package/node_modules/nodemailer/dist/cjs/base64/index.d.ts +3 -0
  9. package/node_modules/nodemailer/dist/cjs/base64/index.js +80 -41
  10. package/node_modules/nodemailer/dist/cjs/dkim/index.js +43 -29
  11. package/node_modules/nodemailer/dist/cjs/dkim/message-parser.js +2 -2
  12. package/node_modules/nodemailer/dist/cjs/errors.d.ts +17 -0
  13. package/node_modules/nodemailer/dist/cjs/errors.js +12 -1
  14. package/node_modules/nodemailer/dist/cjs/fetch/index.js +23 -3
  15. package/node_modules/nodemailer/dist/cjs/mailer/index.js +23 -7
  16. package/node_modules/nodemailer/dist/cjs/mailer/mail-message.d.ts +5 -0
  17. package/node_modules/nodemailer/dist/cjs/mailer/mail-message.js +20 -0
  18. package/node_modules/nodemailer/dist/cjs/mime-node/index.d.ts +1 -1
  19. package/node_modules/nodemailer/dist/cjs/mime-node/index.js +165 -105
  20. package/node_modules/nodemailer/dist/cjs/nodemailer.js +12 -9
  21. package/node_modules/nodemailer/dist/cjs/package-info.d.ts +1 -1
  22. package/node_modules/nodemailer/dist/cjs/package-info.js +1 -1
  23. package/node_modules/nodemailer/dist/cjs/qp/index.d.ts +2 -0
  24. package/node_modules/nodemailer/dist/cjs/qp/index.js +103 -33
  25. package/node_modules/nodemailer/dist/cjs/sendmail-transport/index.js +54 -14
  26. package/node_modules/nodemailer/dist/cjs/shared/index.d.ts +32 -1
  27. package/node_modules/nodemailer/dist/cjs/shared/index.js +212 -115
  28. package/node_modules/nodemailer/dist/cjs/smtp-connection/http-proxy-client.d.ts +3 -1
  29. package/node_modules/nodemailer/dist/cjs/smtp-connection/http-proxy-client.js +88 -68
  30. package/node_modules/nodemailer/dist/cjs/smtp-connection/index.d.ts +7 -1
  31. package/node_modules/nodemailer/dist/cjs/smtp-connection/index.js +348 -136
  32. package/node_modules/nodemailer/dist/cjs/smtp-pool/index.d.ts +3 -0
  33. package/node_modules/nodemailer/dist/cjs/smtp-pool/index.js +7 -1
  34. package/node_modules/nodemailer/dist/cjs/smtp-pool/pool-resource.js +106 -17
  35. package/node_modules/nodemailer/dist/cjs/smtp-transport/index.js +8 -2
  36. package/node_modules/nodemailer/dist/esm/base64/index.d.ts +3 -0
  37. package/node_modules/nodemailer/dist/esm/base64/index.js +80 -41
  38. package/node_modules/nodemailer/dist/esm/dkim/index.js +43 -29
  39. package/node_modules/nodemailer/dist/esm/dkim/message-parser.js +2 -2
  40. package/node_modules/nodemailer/dist/esm/errors.d.ts +17 -0
  41. package/node_modules/nodemailer/dist/esm/errors.js +10 -0
  42. package/node_modules/nodemailer/dist/esm/fetch/index.js +23 -3
  43. package/node_modules/nodemailer/dist/esm/mailer/index.js +23 -7
  44. package/node_modules/nodemailer/dist/esm/mailer/mail-message.d.ts +5 -0
  45. package/node_modules/nodemailer/dist/esm/mailer/mail-message.js +20 -0
  46. package/node_modules/nodemailer/dist/esm/mime-node/index.d.ts +1 -1
  47. package/node_modules/nodemailer/dist/esm/mime-node/index.js +166 -106
  48. package/node_modules/nodemailer/dist/esm/nodemailer.js +12 -9
  49. package/node_modules/nodemailer/dist/esm/package-info.d.ts +1 -1
  50. package/node_modules/nodemailer/dist/esm/package-info.js +1 -1
  51. package/node_modules/nodemailer/dist/esm/qp/index.d.ts +2 -0
  52. package/node_modules/nodemailer/dist/esm/qp/index.js +103 -33
  53. package/node_modules/nodemailer/dist/esm/sendmail-transport/index.js +54 -14
  54. package/node_modules/nodemailer/dist/esm/shared/index.d.ts +32 -1
  55. package/node_modules/nodemailer/dist/esm/shared/index.js +207 -115
  56. package/node_modules/nodemailer/dist/esm/smtp-connection/http-proxy-client.d.ts +3 -1
  57. package/node_modules/nodemailer/dist/esm/smtp-connection/http-proxy-client.js +88 -68
  58. package/node_modules/nodemailer/dist/esm/smtp-connection/index.d.ts +7 -1
  59. package/node_modules/nodemailer/dist/esm/smtp-connection/index.js +348 -136
  60. package/node_modules/nodemailer/dist/esm/smtp-pool/index.d.ts +3 -0
  61. package/node_modules/nodemailer/dist/esm/smtp-pool/index.js +7 -1
  62. package/node_modules/nodemailer/dist/esm/smtp-pool/pool-resource.js +106 -17
  63. package/node_modules/nodemailer/dist/esm/smtp-transport/index.js +8 -2
  64. package/node_modules/nodemailer/package.json +1 -1
  65. 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
- // Error harness for initial connection. Once connection is established, the responsibility
85
- // to handle errors is passed to whoever uses this socket
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
- const tempSocketErr = (err) => {
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
- const timeoutErr = () => {
101
- const err = new Error('Proxy socket timed out');
102
- err.code = 'ETIMEDOUT';
103
- tempSocketErr(err);
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: destinationHost + ':' + destinationPort,
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
- destinationHost +
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
- socket.setTimeout(httpProxyClient.timeout || 30 * 1000);
184
- socket.on('timeout', timeoutErr);
185
- socket.once('error', tempSocketErr);
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 { Callback, NodemailerError } from '../errors.js';
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