@mavogel/awscdk-rootmail 0.1.8 → 0.1.9

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 (166) hide show
  1. package/.jsii +10 -10
  2. package/lib/rootmail.js +1 -1
  3. package/lib/ses-receive.js +1 -1
  4. package/node_modules/@aws-sdk/client-cloudwatch-logs/dist-cjs/index.js +5 -5
  5. package/node_modules/@aws-sdk/client-cloudwatch-logs/dist-es/schemas/schemas_0.js +4 -4
  6. package/node_modules/@aws-sdk/client-cloudwatch-logs/dist-types/commands/DescribeDeliveryDestinationsCommand.d.ts +1 -0
  7. package/node_modules/@aws-sdk/client-cloudwatch-logs/dist-types/commands/GetDeliveryDestinationCommand.d.ts +1 -0
  8. package/node_modules/@aws-sdk/client-cloudwatch-logs/dist-types/commands/PutAccountPolicyCommand.d.ts +4 -1
  9. package/node_modules/@aws-sdk/client-cloudwatch-logs/dist-types/commands/PutDeliveryDestinationCommand.d.ts +2 -0
  10. package/node_modules/@aws-sdk/client-cloudwatch-logs/dist-types/models/models_0.d.ts +80 -36
  11. package/node_modules/@aws-sdk/client-cloudwatch-logs/dist-types/ts3.4/models/models_0.d.ts +2 -0
  12. package/node_modules/@aws-sdk/client-cloudwatch-logs/package.json +1 -1
  13. package/node_modules/@aws-sdk/client-route-53/dist-cjs/index.js +1 -1
  14. package/node_modules/@aws-sdk/client-route-53/package.json +1 -1
  15. package/node_modules/@aws-sdk/client-s3/dist-cjs/index.js +2 -1
  16. package/node_modules/@aws-sdk/client-s3/dist-es/models/enums.js +1 -0
  17. package/node_modules/@aws-sdk/client-s3/dist-types/commands/GetBucketInventoryConfigurationCommand.d.ts +1 -1
  18. package/node_modules/@aws-sdk/client-s3/dist-types/commands/ListBucketInventoryConfigurationsCommand.d.ts +1 -1
  19. package/node_modules/@aws-sdk/client-s3/dist-types/commands/PutBucketInventoryConfigurationCommand.d.ts +1 -1
  20. package/node_modules/@aws-sdk/client-s3/dist-types/models/enums.d.ts +1 -0
  21. package/node_modules/@aws-sdk/client-s3/dist-types/ts3.4/models/enums.d.ts +1 -0
  22. package/node_modules/@aws-sdk/client-s3/package.json +2 -2
  23. package/node_modules/@aws-sdk/client-ses/dist-cjs/index.js +1 -1
  24. package/node_modules/@aws-sdk/client-ses/package.json +1 -1
  25. package/node_modules/@aws-sdk/client-ssm/dist-cjs/index.js +9 -3
  26. package/node_modules/@aws-sdk/client-ssm/dist-es/models/enums.js +4 -0
  27. package/node_modules/@aws-sdk/client-ssm/dist-es/schemas/schemas_0.js +3 -2
  28. package/node_modules/@aws-sdk/client-ssm/dist-types/commands/DeleteResourcePolicyCommand.d.ts +6 -0
  29. package/node_modules/@aws-sdk/client-ssm/dist-types/commands/PutResourcePolicyCommand.d.ts +12 -0
  30. package/node_modules/@aws-sdk/client-ssm/dist-types/models/enums.d.ts +12 -0
  31. package/node_modules/@aws-sdk/client-ssm/dist-types/models/models_0.d.ts +20 -1
  32. package/node_modules/@aws-sdk/client-ssm/dist-types/models/models_1.d.ts +2 -2
  33. package/node_modules/@aws-sdk/client-ssm/dist-types/ts3.4/models/enums.d.ts +5 -0
  34. package/node_modules/@aws-sdk/client-ssm/dist-types/ts3.4/models/models_0.d.ts +2 -0
  35. package/node_modules/@aws-sdk/client-ssm/package.json +1 -1
  36. package/node_modules/@zone-eu/mailsplit/lib/flowed-decoder.js +1 -5
  37. package/node_modules/@zone-eu/mailsplit/lib/headers.js +35 -25
  38. package/node_modules/@zone-eu/mailsplit/lib/message-splitter.js +126 -79
  39. package/node_modules/@zone-eu/mailsplit/lib/mime-node.js +27 -5
  40. package/node_modules/@zone-eu/mailsplit/lib/node-rewriter.js +3 -2
  41. package/node_modules/@zone-eu/mailsplit/lib/types.d.ts +0 -3
  42. package/node_modules/@zone-eu/mailsplit/package.json +5 -5
  43. package/node_modules/libbase64/.github/workflows/release.yaml +12 -10
  44. package/node_modules/libbase64/.ncurc.js +7 -1
  45. package/node_modules/libbase64/CHANGELOG.md +7 -0
  46. package/node_modules/libbase64/lib/libbase64.js +27 -0
  47. package/node_modules/libbase64/package.json +4 -4
  48. package/node_modules/libmime/CHANGELOG.md +14 -0
  49. package/node_modules/libmime/lib/libmime.js +41 -21
  50. package/node_modules/libmime/package.json +3 -3
  51. package/node_modules/libqp/.github/workflows/release.yaml +12 -10
  52. package/node_modules/libqp/CHANGELOG.md +7 -0
  53. package/node_modules/libqp/lib/libqp.js +6 -4
  54. package/node_modules/libqp/package.json +2 -2
  55. package/node_modules/libqp/test/libqp-test.js +71 -14
  56. package/node_modules/mailparser/.release-please-manifest.json +1 -1
  57. package/node_modules/mailparser/CHANGELOG.md +42 -0
  58. package/node_modules/mailparser/README.md +5 -0
  59. package/node_modules/mailparser/lib/mail-parser.js +107 -32
  60. package/node_modules/mailparser/lib/simple-parser.js +12 -0
  61. package/node_modules/mailparser/lib/stream-hash.js +1 -1
  62. package/node_modules/mailparser/package.json +6 -6
  63. package/node_modules/nodemailer/CHANGELOG.md +38 -0
  64. package/node_modules/nodemailer/README.md +1 -1
  65. package/node_modules/nodemailer/dist/cjs/addressparser/index.d.ts +16 -2
  66. package/node_modules/nodemailer/dist/cjs/addressparser/index.js +147 -28
  67. package/node_modules/nodemailer/dist/cjs/base64/index.js +2 -1
  68. package/node_modules/nodemailer/dist/cjs/dkim/index.d.ts +13 -1
  69. package/node_modules/nodemailer/dist/cjs/dkim/index.js +25 -8
  70. package/node_modules/nodemailer/dist/cjs/dkim/message-parser.d.ts +10 -1
  71. package/node_modules/nodemailer/dist/cjs/dkim/message-parser.js +28 -4
  72. package/node_modules/nodemailer/dist/cjs/dkim/relaxed-body.d.ts +10 -1
  73. package/node_modules/nodemailer/dist/cjs/dkim/sign.d.ts +3 -0
  74. package/node_modules/nodemailer/dist/cjs/dkim/sign.js +18 -1
  75. package/node_modules/nodemailer/dist/cjs/errors.d.ts +3 -2
  76. package/node_modules/nodemailer/dist/cjs/fetch/cookies.d.ts +12 -1
  77. package/node_modules/nodemailer/dist/cjs/fetch/index.d.ts +15 -1
  78. package/node_modules/nodemailer/dist/cjs/fetch/index.js +39 -64
  79. package/node_modules/nodemailer/dist/cjs/json-transport/index.d.ts +14 -4
  80. package/node_modules/nodemailer/dist/cjs/json-transport/index.js +2 -0
  81. package/node_modules/nodemailer/dist/cjs/mail-composer/index.d.ts +8 -3
  82. package/node_modules/nodemailer/dist/cjs/mailer/index.d.ts +43 -25
  83. package/node_modules/nodemailer/dist/cjs/mailer/mail-message.d.ts +11 -4
  84. package/node_modules/nodemailer/dist/cjs/mime-funcs/index.d.ts +7 -3
  85. package/node_modules/nodemailer/dist/cjs/mime-funcs/index.js +198 -84
  86. package/node_modules/nodemailer/dist/cjs/mime-node/index.d.ts +5 -2
  87. package/node_modules/nodemailer/dist/cjs/mime-node/index.js +2 -1
  88. package/node_modules/nodemailer/dist/cjs/nodemailer.d.ts +38 -16
  89. package/node_modules/nodemailer/dist/cjs/nodemailer.js +1 -0
  90. package/node_modules/nodemailer/dist/cjs/package-info.d.ts +1 -1
  91. package/node_modules/nodemailer/dist/cjs/package-info.js +1 -1
  92. package/node_modules/nodemailer/dist/cjs/punycode/index.js +1 -0
  93. package/node_modules/nodemailer/dist/cjs/qp/index.d.ts +2 -0
  94. package/node_modules/nodemailer/dist/cjs/qp/index.js +10 -1
  95. package/node_modules/nodemailer/dist/cjs/sendmail-transport/index.d.ts +2 -0
  96. package/node_modules/nodemailer/dist/cjs/ses-transport/index.d.ts +39 -2
  97. package/node_modules/nodemailer/dist/cjs/shared/index.d.ts +43 -7
  98. package/node_modules/nodemailer/dist/cjs/shared/index.js +5 -2
  99. package/node_modules/nodemailer/dist/cjs/smtp-connection/data-stream.d.ts +2 -1
  100. package/node_modules/nodemailer/dist/cjs/smtp-connection/data-stream.js +32 -24
  101. package/node_modules/nodemailer/dist/cjs/smtp-connection/http-proxy-client.d.ts +13 -5
  102. package/node_modules/nodemailer/dist/cjs/smtp-connection/http-proxy-client.js +23 -11
  103. package/node_modules/nodemailer/dist/cjs/smtp-connection/index.d.ts +59 -24
  104. package/node_modules/nodemailer/dist/cjs/smtp-connection/index.js +156 -75
  105. package/node_modules/nodemailer/dist/cjs/smtp-pool/index.d.ts +12 -4
  106. package/node_modules/nodemailer/dist/cjs/smtp-pool/index.js +39 -11
  107. package/node_modules/nodemailer/dist/cjs/smtp-pool/pool-resource.js +27 -31
  108. package/node_modules/nodemailer/dist/cjs/smtp-transport/index.d.ts +19 -6
  109. package/node_modules/nodemailer/dist/cjs/smtp-transport/index.js +25 -33
  110. package/node_modules/nodemailer/dist/cjs/stream-transport/index.d.ts +2 -0
  111. package/node_modules/nodemailer/dist/cjs/well-known/services.js +6 -0
  112. package/node_modules/nodemailer/dist/cjs/xoauth2/index.d.ts +13 -3
  113. package/node_modules/nodemailer/dist/cjs/xoauth2/index.js +25 -13
  114. package/node_modules/nodemailer/dist/esm/addressparser/index.d.ts +16 -2
  115. package/node_modules/nodemailer/dist/esm/addressparser/index.js +147 -27
  116. package/node_modules/nodemailer/dist/esm/base64/index.js +2 -1
  117. package/node_modules/nodemailer/dist/esm/dkim/index.d.ts +13 -1
  118. package/node_modules/nodemailer/dist/esm/dkim/index.js +25 -8
  119. package/node_modules/nodemailer/dist/esm/dkim/message-parser.d.ts +10 -1
  120. package/node_modules/nodemailer/dist/esm/dkim/message-parser.js +30 -5
  121. package/node_modules/nodemailer/dist/esm/dkim/relaxed-body.d.ts +10 -1
  122. package/node_modules/nodemailer/dist/esm/dkim/relaxed-body.js +2 -1
  123. package/node_modules/nodemailer/dist/esm/dkim/sign.d.ts +3 -0
  124. package/node_modules/nodemailer/dist/esm/dkim/sign.js +18 -1
  125. package/node_modules/nodemailer/dist/esm/errors.d.ts +3 -2
  126. package/node_modules/nodemailer/dist/esm/fetch/cookies.d.ts +12 -1
  127. package/node_modules/nodemailer/dist/esm/fetch/cookies.js +2 -1
  128. package/node_modules/nodemailer/dist/esm/fetch/index.d.ts +15 -1
  129. package/node_modules/nodemailer/dist/esm/fetch/index.js +39 -64
  130. package/node_modules/nodemailer/dist/esm/json-transport/index.d.ts +14 -4
  131. package/node_modules/nodemailer/dist/esm/json-transport/index.js +2 -0
  132. package/node_modules/nodemailer/dist/esm/mail-composer/index.d.ts +8 -3
  133. package/node_modules/nodemailer/dist/esm/mailer/index.d.ts +43 -25
  134. package/node_modules/nodemailer/dist/esm/mailer/mail-message.d.ts +11 -4
  135. package/node_modules/nodemailer/dist/esm/mime-funcs/index.d.ts +7 -3
  136. package/node_modules/nodemailer/dist/esm/mime-funcs/index.js +198 -84
  137. package/node_modules/nodemailer/dist/esm/mime-node/index.d.ts +5 -2
  138. package/node_modules/nodemailer/dist/esm/mime-node/index.js +2 -1
  139. package/node_modules/nodemailer/dist/esm/nodemailer.d.ts +38 -16
  140. package/node_modules/nodemailer/dist/esm/package-info.d.ts +1 -1
  141. package/node_modules/nodemailer/dist/esm/package-info.js +1 -1
  142. package/node_modules/nodemailer/dist/esm/punycode/index.js +1 -0
  143. package/node_modules/nodemailer/dist/esm/qp/index.d.ts +2 -0
  144. package/node_modules/nodemailer/dist/esm/qp/index.js +10 -1
  145. package/node_modules/nodemailer/dist/esm/sendmail-transport/index.d.ts +2 -0
  146. package/node_modules/nodemailer/dist/esm/ses-transport/index.d.ts +39 -2
  147. package/node_modules/nodemailer/dist/esm/shared/index.d.ts +43 -7
  148. package/node_modules/nodemailer/dist/esm/shared/index.js +5 -2
  149. package/node_modules/nodemailer/dist/esm/smtp-connection/data-stream.d.ts +2 -1
  150. package/node_modules/nodemailer/dist/esm/smtp-connection/data-stream.js +32 -24
  151. package/node_modules/nodemailer/dist/esm/smtp-connection/http-proxy-client.d.ts +13 -5
  152. package/node_modules/nodemailer/dist/esm/smtp-connection/http-proxy-client.js +23 -11
  153. package/node_modules/nodemailer/dist/esm/smtp-connection/index.d.ts +59 -24
  154. package/node_modules/nodemailer/dist/esm/smtp-connection/index.js +156 -75
  155. package/node_modules/nodemailer/dist/esm/smtp-pool/index.d.ts +12 -4
  156. package/node_modules/nodemailer/dist/esm/smtp-pool/index.js +39 -11
  157. package/node_modules/nodemailer/dist/esm/smtp-pool/pool-resource.js +27 -31
  158. package/node_modules/nodemailer/dist/esm/smtp-transport/index.d.ts +19 -6
  159. package/node_modules/nodemailer/dist/esm/smtp-transport/index.js +25 -33
  160. package/node_modules/nodemailer/dist/esm/stream-transport/index.d.ts +2 -0
  161. package/node_modules/nodemailer/dist/esm/well-known/services.js +6 -0
  162. package/node_modules/nodemailer/dist/esm/xoauth2/index.d.ts +13 -3
  163. package/node_modules/nodemailer/dist/esm/xoauth2/index.js +25 -13
  164. package/node_modules/nodemailer/dist/well-known/services.json +7 -0
  165. package/node_modules/nodemailer/package.json +16 -12
  166. package/package.json +16 -16
@@ -3,8 +3,9 @@ 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 { NodemailerError } from '../errors.js';
6
+ import type { Callback, NodemailerError } from '../errors.js';
7
7
  import type XOAuth2 from '../xoauth2/index.js';
8
+ import type { XOAuth2Options } from '../xoauth2/index.js';
8
9
  /**
9
10
  * Custom authentication handlers keyed by (case insensitive) SASL method name
10
11
  */
@@ -25,11 +26,11 @@ export interface SMTPConnectionOptions {
25
26
  secured?: boolean | undefined;
26
27
  /** Server name for SNI, defaults to host when that is not an IP address */
27
28
  servername?: string | undefined;
28
- /** Ignore STARTTLS even when the server advertises it */
29
+ /** Ignore STARTTLS even when the server advertises it, has no effect when requireTLS is set */
29
30
  ignoreTLS?: boolean | undefined;
30
- /** Force STARTTLS, fail when the server does not support it */
31
+ /** Force STARTTLS, fail when the server does not support it. Takes precedence over ignoreTLS and opportunisticTLS */
31
32
  requireTLS?: boolean | undefined;
32
- /** Continue unencrypted when the STARTTLS upgrade fails */
33
+ /** Continue unencrypted when the STARTTLS upgrade fails, has no effect when requireTLS is set */
33
34
  opportunisticTLS?: boolean | undefined;
34
35
  /** Name of the client server, sent with EHLO/HELO, CRLF is stripped */
35
36
  name?: string | undefined;
@@ -117,12 +118,23 @@ export interface SMTPConnectionCustomAuthResponse {
117
118
  * Callback for a command sent by a custom authentication handler
118
119
  */
119
120
  export type SMTPConnectionCustomAuthCommandCallback = (err: Error | null, data: SMTPConnectionCustomAuthResponse) => void;
121
+ /**
122
+ * The auth object as a custom authentication handler sees it: the object handed to login()
123
+ * with the credentials filled in from its user and pass values
124
+ */
125
+ export interface SMTPConnectionCustomAuthData extends SMTPConnectionAuth {
126
+ /** The user and pass values of the auth object, the way @types/nodemailer declared them */
127
+ credentials: SMTPConnectionCredentials & {
128
+ user: string;
129
+ pass: string;
130
+ };
131
+ }
120
132
  /**
121
133
  * The object a custom authentication handler is run with
122
134
  */
123
135
  export interface SMTPConnectionCustomAuthContext {
124
- /** The auth object handed to login() */
125
- auth: SMTPConnectionAuth;
136
+ /** The auth object handed to login(), with the credentials filled in */
137
+ auth: SMTPConnectionCustomAuthData;
126
138
  /** Selected authentication method name */
127
139
  method: string;
128
140
  /** SMTP extensions the server advertised */
@@ -131,17 +143,20 @@ export interface SMTPConnectionCustomAuthContext {
131
143
  authMethods: string[];
132
144
  /** Maximum message size the server accepts, false when not advertised */
133
145
  maxAllowedSize: number | false;
134
- /** Sends a command to the server. Returns a promise when no callback is given */
135
- sendCommand(cmd: string, done?: SMTPConnectionCustomAuthCommandCallback): Promise<SMTPConnectionCustomAuthResponse> | undefined;
146
+ /** Sends a command to the server and resolves with the parsed reply */
147
+ sendCommand(cmd: string): Promise<SMTPConnectionCustomAuthResponse>;
148
+ /** Sends a command to the server and hands the parsed reply to the callback */
149
+ sendCommand(cmd: string, done: SMTPConnectionCustomAuthCommandCallback): void;
136
150
  /** Marks the user as authenticated */
137
151
  resolve(): void;
138
152
  /** Fails the authentication with an error */
139
153
  reject(err: Error | string): void;
140
154
  }
141
155
  /**
142
- * A custom authentication handler. Calls resolve() or reject() on the context, or returns a promise
156
+ * A custom authentication handler. Calls resolve() or reject() on the context, or returns a
157
+ * promise that settles the authentication. Any other return value is ignored
143
158
  */
144
- export type SMTPConnectionCustomAuthHandler = (ctx: SMTPConnectionCustomAuthContext) => void | Promise<unknown>;
159
+ export type SMTPConnectionCustomAuthHandler = (ctx: SMTPConnectionCustomAuthContext) => unknown;
145
160
  /**
146
161
  * An envelope address, either a plain string or an object with an address property
147
162
  */
@@ -168,12 +183,16 @@ export interface SMTPEnvelopeDsn {
168
183
  /** Alias of recipient, in the 'rfc822;address' form */
169
184
  orcpt?: string | null | undefined;
170
185
  }
186
+ /**
187
+ * A single DSN notify value
188
+ */
189
+ export type SMTPEnvelopeDsnNotify = 'NEVER' | 'SUCCESS' | 'FAILURE' | 'DELAY';
171
190
  /**
172
191
  * Envelope object accepted by send()
173
192
  */
174
193
  export interface SMTPEnvelope {
175
- /** Sender address */
176
- from?: string | SMTPEnvelopeAddress | undefined;
194
+ /** Sender address, false for the null sender of a bounce message (MAIL FROM:<>) */
195
+ from?: string | SMTPEnvelopeAddress | false | undefined;
177
196
  /** Recipient address or addresses */
178
197
  to?: string | SMTPEnvelopeAddress | Array<string | SMTPEnvelopeAddress> | undefined;
179
198
  /** Message size in bytes, sent as the SIZE parameter when the server supports it */
@@ -202,9 +221,9 @@ export interface SMTPConnectionEnvelope extends SMTPEnvelope {
202
221
  accepted: string[];
203
222
  }
204
223
  /**
205
- * Result of a sent message
224
+ * The recipient bookkeeping of a sent message, known once the envelope is accepted
206
225
  */
207
- export interface SMTPConnectionSendInfo {
226
+ export interface SMTPConnectionEnvelopeInfo {
208
227
  /** Recipients the server accepted */
209
228
  accepted: string[];
210
229
  /** Recipients the server rejected */
@@ -213,19 +232,25 @@ export interface SMTPConnectionSendInfo {
213
232
  ehlo?: string[] | undefined;
214
233
  /** Errors for the rejected recipients */
215
234
  rejectedErrors?: NodemailerError[] | undefined;
235
+ }
236
+ /**
237
+ * Result of a sent message
238
+ */
239
+ export interface SMTPConnectionSendInfo extends SMTPConnectionEnvelopeInfo {
216
240
  /** Time in ms spent on the envelope commands */
217
- envelopeTime?: number | undefined;
241
+ envelopeTime: number;
218
242
  /** Time in ms spent on streaming the message */
219
- messageTime?: number | undefined;
243
+ messageTime: number;
220
244
  /** Size of the encoded message in bytes */
221
- messageSize?: number | undefined;
245
+ messageSize: number;
222
246
  /** Final server response for the message */
223
- response?: string | undefined;
247
+ response: string;
224
248
  }
225
249
  /**
226
- * Callback for send()
250
+ * Callback for send(), receives the result once the server accepted the message. The error
251
+ * path hands over the error alone
227
252
  */
228
- export type SMTPConnectionSendCallback = (err: NodemailerError | null, info?: SMTPConnectionSendInfo) => void;
253
+ export type SMTPConnectionSendCallback = Callback<SMTPConnectionSendInfo>;
229
254
  /**
230
255
  * Callback for login() and reset(), the result is true on success
231
256
  */
@@ -263,8 +288,8 @@ export type SMTPConnectionResponseAction = (str: string) => void;
263
288
  * * **port** - is the port to connect to (defaults to 587 or 465)
264
289
  * * **host** - is the hostname or IP address to connect to (defaults to 'localhost')
265
290
  * * **secure** - use SSL
266
- * * **ignoreTLS** - ignore server support for STARTTLS
267
- * * **requireTLS** - forces the client to use STARTTLS
291
+ * * **ignoreTLS** - ignore server support for STARTTLS (has no effect when requireTLS is set)
292
+ * * **requireTLS** - forces the client to use STARTTLS, takes precedence over ignoreTLS and opportunisticTLS
268
293
  * * **name** - the name of the client server
269
294
  * * **localAddress** - outbound address to bind to (see: http://nodejs.org/api/net.html#net_net_connect_options_connectionlistener)
270
295
  * * **greetingTimeout** - Time to wait in ms until greeting message is received from the server (defaults to 30 seconds)
@@ -285,7 +310,7 @@ export type SMTPConnectionResponseAction = (str: string) => void;
285
310
  */
286
311
  declare class SMTPConnection extends EventEmitter {
287
312
  id: string;
288
- stage: string;
313
+ stage: 'init' | 'connected';
289
314
  options: SMTPConnectionOptions;
290
315
  secureConnection: boolean;
291
316
  alreadySecured: boolean;
@@ -354,7 +379,7 @@ declare class SMTPConnection extends EventEmitter {
354
379
  *
355
380
  * @param envelope Envelope object, {from: addr, to: [addr]}
356
381
  * @param message String, Buffer or a Stream
357
- * @param callback Callback to return once sending is completed
382
+ * @param done Callback to return once sending is completed
358
383
  */
359
384
  send(envelope: SMTPEnvelope, message: string | Buffer | Readable, done: SMTPConnectionSendCallback): void;
360
385
  /**
@@ -370,12 +395,22 @@ declare class SMTPConnection extends EventEmitter {
370
395
  declare namespace SMTPConnection {
371
396
  type Options = SMTPConnectionOptions;
372
397
  type AuthenticationType = SMTPConnectionAuth;
398
+ type AuthenticationTypeLogin = SMTPConnectionAuth;
399
+ type AuthenticationTypeOAuth2 = SMTPConnectionAuth;
400
+ type AuthenticationTypeCustom = SMTPConnectionAuth;
401
+ type AuthenticationCredentials = SMTPConnectionAuth;
402
+ type AuthenticationOAuth2 = SMTPConnectionAuth;
373
403
  type Credentials = SMTPConnectionCredentials;
404
+ type OAuth2 = XOAuth2Options;
374
405
  type Envelope = SMTPEnvelope;
375
406
  type DSNOptions = SMTPEnvelopeDsn;
407
+ type DSNOption = SMTPEnvelopeDsnNotify;
376
408
  type SentMessageInfo = SMTPConnectionSendInfo;
409
+ type SMTPError = NodemailerError;
377
410
  type CustomAuthenticationContext = SMTPConnectionCustomAuthContext;
378
411
  type CustomAuthenticationResponse = SMTPConnectionCustomAuthResponse;
379
412
  type CustomAuthenticationHandlers = SMTPConnectionCustomAuthHandlers;
380
413
  }
414
+ /** The same aliases as module level exports, for `import * as SMTPConnection` and `import SMTPConnection = require()` */
415
+ export type { SMTPConnectionOptions as Options, SMTPConnectionAuth as AuthenticationType, SMTPConnectionAuth as AuthenticationTypeLogin, SMTPConnectionAuth as AuthenticationTypeOAuth2, SMTPConnectionAuth as AuthenticationTypeCustom, SMTPConnectionAuth as AuthenticationCredentials, SMTPConnectionAuth as AuthenticationOAuth2, SMTPConnectionCredentials as Credentials, XOAuth2Options as OAuth2, SMTPEnvelope as Envelope, SMTPEnvelopeDsn as DSNOptions, SMTPEnvelopeDsnNotify as DSNOption, SMTPConnectionSendInfo as SentMessageInfo, NodemailerError as SMTPError, SMTPConnectionCustomAuthContext as CustomAuthenticationContext, SMTPConnectionCustomAuthResponse as CustomAuthenticationResponse, SMTPConnectionCustomAuthHandlers as CustomAuthenticationHandlers };
381
416
  export default SMTPConnection;
@@ -104,8 +104,8 @@ function isPartialLine(line) {
104
104
  * * **port** - is the port to connect to (defaults to 587 or 465)
105
105
  * * **host** - is the hostname or IP address to connect to (defaults to 'localhost')
106
106
  * * **secure** - use SSL
107
- * * **ignoreTLS** - ignore server support for STARTTLS
108
- * * **requireTLS** - forces the client to use STARTTLS
107
+ * * **ignoreTLS** - ignore server support for STARTTLS (has no effect when requireTLS is set)
108
+ * * **requireTLS** - forces the client to use STARTTLS, takes precedence over ignoreTLS and opportunisticTLS
109
109
  * * **name** - the name of the client server
110
110
  * * **localAddress** - outbound address to bind to (see: http://nodejs.org/api/net.html#net_net_connect_options_connectionlistener)
111
111
  * * **greetingTimeout** - Time to wait in ms until greeting message is received from the server (defaults to 30 seconds)
@@ -130,6 +130,11 @@ class SMTPConnection extends node_events_1.EventEmitter {
130
130
  this.id = node_crypto_1.default.randomBytes(8).toString('base64').replace(/\W/g, '');
131
131
  this.stage = 'init';
132
132
  this.options = options || {};
133
+ if (this.options.requireTLS && (this.options.ignoreTLS || this.options.opportunisticTLS)) {
134
+ // requireTLS wins, a contradictory configuration must not quietly fall back to plaintext.
135
+ // Copied so the caller's (possibly shared) options object is left as it was
136
+ this.options = Object.assign({}, this.options, { ignoreTLS: false, opportunisticTLS: false });
137
+ }
133
138
  this.secureConnection = !!this.options.secure;
134
139
  this.alreadySecured = !!this.options.secured;
135
140
  this.port = Number(this.options.port) || (this.secureConnection ? 465 : 587);
@@ -173,6 +178,8 @@ class SMTPConnection extends node_events_1.EventEmitter {
173
178
  this._destroyed = false;
174
179
  this._closing = false;
175
180
  this._currentDataStream = false;
181
+ this._pendingSend = false;
182
+ this._connectCallback = false;
176
183
  this._onSocketData = chunk => this._onData(chunk);
177
184
  this._onSocketError = error => this._onError(error, 'ESOCKET', false, 'CONN');
178
185
  this._onSocketClose = () => this._onClose();
@@ -187,7 +194,9 @@ class SMTPConnection extends node_events_1.EventEmitter {
187
194
  */
188
195
  connect(connectCallback) {
189
196
  if (typeof connectCallback === 'function') {
197
+ this._connectCallback = connectCallback;
190
198
  this.once('connect', () => {
199
+ this._connectCallback = false;
191
200
  this.logger.debug({
192
201
  tnx: 'smtp'
193
202
  }, 'SMTP handshake finished');
@@ -419,6 +428,16 @@ class SMTPConnection extends node_events_1.EventEmitter {
419
428
  }
420
429
  this._currentDataStream = false;
421
430
  }
431
+ // Detach from the message stream as well. The listener is swapped for a no-op rather than
432
+ // removed, a stream destroyed with an error later on would otherwise throw it as unhandled
433
+ if (this._pendingSend) {
434
+ const { stream, onStreamError } = this._pendingSend;
435
+ if (stream) {
436
+ stream.removeListener('error', onStreamError);
437
+ stream.on('error', TEARDOWN_NOOP);
438
+ }
439
+ this._pendingSend = false;
440
+ }
422
441
  if (socket && !socket.destroyed) {
423
442
  try {
424
443
  // Clear socket timeout to prevent timer leaks
@@ -452,14 +471,21 @@ class SMTPConnection extends node_events_1.EventEmitter {
452
471
  this._auth = authData || {};
453
472
  // Select SASL authentication method
454
473
  this._authMethod = (this._auth.method || '').toString().trim().toUpperCase() || false;
474
+ // XOAUTH2 needs a token generator or a custom handler, without either the method
475
+ // can not be run even when it is the only one the server advertised
476
+ const canUseXOAuth2 = !!this._auth.oauth2 || this.customAuth.has('XOAUTH2');
455
477
  if (!this._authMethod && this._auth.oauth2 && !this._auth.credentials) {
456
478
  this._authMethod = 'XOAUTH2';
457
479
  }
458
480
  else if (!this._authMethod || (this._authMethod === 'XOAUTH2' && !this._auth.oauth2)) {
459
- // use first supported
460
- this._authMethod = (this._supportedAuth[0] || 'PLAIN').toUpperCase().trim();
461
- }
462
- if (this._authMethod !== 'XOAUTH2' && (!this._auth.credentials || !this._auth.credentials.user || !this._auth.credentials.pass)) {
481
+ // use the first supported method that can be run
482
+ const supported = this._supportedAuth.find(method => method !== 'XOAUTH2' || canUseXOAuth2);
483
+ this._authMethod = (supported || 'PLAIN').toUpperCase().trim();
484
+ }
485
+ // a token login needs no credentials, every other method and every custom handler
486
+ // gets them filled in from the user and pass values
487
+ if ((this._authMethod !== 'XOAUTH2' || this.customAuth.has('XOAUTH2')) &&
488
+ (!this._auth.credentials || !this._auth.credentials.user || !this._auth.credentials.pass)) {
463
489
  if ((this._auth.user && this._auth.pass) || this.customAuth.has(this._authMethod)) {
464
490
  this._auth.credentials = {
465
491
  user: this._auth.user,
@@ -496,42 +522,45 @@ class SMTPConnection extends node_events_1.EventEmitter {
496
522
  returned = true;
497
523
  callback(this._formatError(err, 'EAUTH', lastResponse, 'AUTH ' + this._authMethod));
498
524
  };
525
+ // one implementation serves both sendCommand overloads, the promise is returned
526
+ // exactly when no callback was given
527
+ const sendCommand = (cmd, done) => {
528
+ let promise;
529
+ if (!done) {
530
+ promise = new Promise((resolve, reject) => {
531
+ done = shared.callbackPromise(resolve, reject);
532
+ });
533
+ }
534
+ this._responseActions.push(str => {
535
+ lastResponse = str;
536
+ let codes = str.match(/^(\d+)(?:\s(\d+\.\d+\.\d+))?\s/);
537
+ let data = {
538
+ command: cmd,
539
+ response: str
540
+ };
541
+ if (codes) {
542
+ data.status = Number(codes[1]) || 0;
543
+ if (codes[2]) {
544
+ data.code = codes[2];
545
+ }
546
+ data.text = str.substr(codes[0].length);
547
+ }
548
+ else {
549
+ data.text = str;
550
+ data.status = 0; // just in case we need to perform numeric comparisons
551
+ }
552
+ done(null, data);
553
+ });
554
+ setImmediate(() => this._sendCommand(cmd));
555
+ return promise;
556
+ };
499
557
  const handlerResponse = handler({
500
558
  auth: this._auth,
501
559
  method: this._authMethod,
502
560
  extensions: [].concat(this._supportedExtensions),
503
561
  authMethods: [].concat(this._supportedAuth),
504
562
  maxAllowedSize: this._maxAllowedSize || false,
505
- sendCommand: (cmd, done) => {
506
- let promise;
507
- if (!done) {
508
- promise = new Promise((resolve, reject) => {
509
- done = shared.callbackPromise(resolve, reject);
510
- });
511
- }
512
- this._responseActions.push(str => {
513
- lastResponse = str;
514
- let codes = str.match(/^(\d+)(?:\s(\d+\.\d+\.\d+))?\s/);
515
- let data = {
516
- command: cmd,
517
- response: str
518
- };
519
- if (codes) {
520
- data.status = Number(codes[1]) || 0;
521
- if (codes[2]) {
522
- data.code = codes[2];
523
- }
524
- data.text = str.substr(codes[0].length);
525
- }
526
- else {
527
- data.text = str;
528
- data.status = 0; // just in case we need to perform numeric comparisons
529
- }
530
- done(null, data);
531
- });
532
- setImmediate(() => this._sendCommand(cmd));
533
- return promise;
534
- },
563
+ sendCommand: sendCommand,
535
564
  resolve,
536
565
  reject
537
566
  });
@@ -585,35 +614,46 @@ class SMTPConnection extends node_events_1.EventEmitter {
585
614
  *
586
615
  * @param envelope Envelope object, {from: addr, to: [addr]}
587
616
  * @param message String, Buffer or a Stream
588
- * @param callback Callback to return once sending is completed
617
+ * @param done Callback to return once sending is completed
589
618
  */
590
619
  send(envelope, message, done) {
620
+ // ensure that the callback is only called once. The public callback type has a
621
+ // required result, the error paths hand over the error alone
622
+ let returned = false;
623
+ const callback = (err, info) => {
624
+ if (returned) {
625
+ return;
626
+ }
627
+ returned = true;
628
+ if (this._pendingSend && this._pendingSend.callback === callback) {
629
+ this._pendingSend = false;
630
+ }
631
+ done(err, info);
632
+ };
591
633
  if (!message) {
592
- return done(this._formatError('Empty message', 'EMESSAGE', false, 'API'));
634
+ return callback(this._formatError('Empty message', 'EMESSAGE', false, 'API'));
593
635
  }
594
636
  const isDestroyedMessage = this._isDestroyedMessage('send message');
595
637
  if (isDestroyedMessage) {
596
- return done(this._formatError(isDestroyedMessage, 'ECONNECTION', false, 'API'));
638
+ return callback(this._formatError(isDestroyedMessage, 'ECONNECTION', false, 'API'));
597
639
  }
598
640
  // reject larger messages than allowed
599
641
  if (this._maxAllowedSize && envelope.size > this._maxAllowedSize) {
600
642
  setImmediate(() => {
601
- done(this._formatError('Message size larger than allowed ' + this._maxAllowedSize, 'EMESSAGE', false, 'MAIL FROM'));
643
+ callback(this._formatError('Message size larger than allowed ' + this._maxAllowedSize, 'EMESSAGE', false, 'MAIL FROM'));
602
644
  });
603
645
  return;
604
646
  }
605
- // ensure that callback is only called once
606
- let returned = false;
607
- const callback = function (...args) {
608
- if (returned) {
609
- return;
610
- }
611
- returned = true;
612
- done(...args);
647
+ const pendingSend = {
648
+ callback,
649
+ stream: false,
650
+ onStreamError: err => callback(this._formatError(err, 'ESTREAM', false, 'API'))
613
651
  };
614
652
  if (typeof message.on === 'function') {
615
- message.on('error', err => callback(this._formatError(err, 'ESTREAM', false, 'API')));
653
+ pendingSend.stream = message;
654
+ pendingSend.stream.on('error', pendingSend.onStreamError);
616
655
  }
656
+ this._pendingSend = pendingSend;
617
657
  const startTime = Date.now();
618
658
  this._setEnvelope(envelope, (err, info) => {
619
659
  if (err) {
@@ -633,11 +673,13 @@ class SMTPConnection extends node_events_1.EventEmitter {
633
673
  if (err) {
634
674
  return callback(err);
635
675
  }
636
- info.envelopeTime = envelopeTime - startTime;
637
- info.messageTime = Date.now() - envelopeTime;
638
- info.messageSize = stream.outByteCount;
639
- info.response = str;
640
- return callback(null, info);
676
+ // the envelope info becomes the send result once the timings are on it
677
+ const result = info;
678
+ result.envelopeTime = envelopeTime - startTime;
679
+ result.messageTime = Date.now() - envelopeTime;
680
+ result.messageSize = stream.outByteCount;
681
+ result.response = str;
682
+ return callback(null, result);
641
683
  });
642
684
  if (typeof message.pipe === 'function') {
643
685
  message.pipe(stream);
@@ -785,6 +827,8 @@ class SMTPConnection extends node_events_1.EventEmitter {
785
827
  * @event
786
828
  * @param err Error object
787
829
  * @param type Error name
830
+ * @param data Server response that triggered the error, false if there is none
831
+ * @param command SMTP command that was in flight
788
832
  * @internal
789
833
  */
790
834
  _onError(err, type, data, command) {
@@ -804,8 +848,14 @@ class SMTPConnection extends node_events_1.EventEmitter {
804
848
  else {
805
849
  this.logger.error(data, err.message);
806
850
  }
851
+ // close() forgets the send in flight, it is completed with this same error afterwards so
852
+ // a late message stream error has nothing left to report
853
+ const pendingSend = this._pendingSend;
807
854
  this.emit('error', err);
808
855
  this.close();
856
+ if (pendingSend) {
857
+ pendingSend.callback(err);
858
+ }
809
859
  }
810
860
  /** @internal */
811
861
  _formatError(message, type, response, command) {
@@ -851,14 +901,25 @@ class SMTPConnection extends node_events_1.EventEmitter {
851
901
  this.logger.info({
852
902
  tnx: 'network'
853
903
  }, 'Connection closed');
904
+ // the unterminated remainder is only reported as a reply (and so gives the error a responseCode)
905
+ // when it starts like a complete failure reply, not for a fragment such as "55" or a 250
906
+ const failureResponse = typeof serverResponse === 'string' && /^[45]\d{2}[ -]/.test(serverResponse) ? serverResponse : false;
854
907
  if (this.upgrading && !this._destroyed) {
855
- return this._onError(new Error('Connection closed unexpectedly'), 'ETLS', serverResponse, 'CONN');
856
- }
857
- else if (![this._actionGreeting, this.close].includes(this._responseActions[0]) && !this._destroyed) {
858
- return this._onError(new Error('Connection closed unexpectedly'), 'ECONNECTION', serverResponse, 'CONN');
908
+ return this._onError(new Error('Connection closed unexpectedly'), 'ETLS', failureResponse, 'CONN');
909
+ }
910
+ if (!failureResponse && this._responseActions[0] === this._actionGreeting && this._connectCallback && !this._destroyed) {
911
+ // A silent close before the greeting is handed to the connect() callback rather than
912
+ // emitted as 'error', callers that never saw an error for it must not start throwing one
913
+ const connectCallback = this._connectCallback;
914
+ this._connectCallback = false;
915
+ const err = this._formatError(new Error('Connection closed unexpectedly'), 'ECONNECTION', false, 'CONN');
916
+ this.logger.warn({ tnx: 'network' }, err.message);
917
+ connectCallback(err);
918
+ this.close();
919
+ return;
859
920
  }
860
- else if (/^[45]\d{2}\b/.test(serverResponse)) {
861
- return this._onError(new Error('Connection closed unexpectedly'), 'ECONNECTION', serverResponse, 'CONN');
921
+ if (failureResponse || (this._responseActions[0] !== this.close && !this._destroyed)) {
922
+ return this._onError(new Error('Connection closed unexpectedly'), 'ECONNECTION', failureResponse, 'CONN');
862
923
  }
863
924
  this._destroy();
864
925
  }
@@ -1036,6 +1097,7 @@ class SMTPConnection extends node_events_1.EventEmitter {
1036
1097
  * {from:'...', to:['...']}
1037
1098
  * or
1038
1099
  * {from:{address:'...',name:'...'}, to:[address:'...',name:'...']}
1100
+ * @param callback Callback to run once the envelope is processed
1039
1101
  * @internal
1040
1102
  */
1041
1103
  _setEnvelope(envelope, callback) {
@@ -1335,21 +1397,25 @@ class SMTPConnection extends node_events_1.EventEmitter {
1335
1397
  if (/[ -]AUTH\b/i.test(str)) {
1336
1398
  this.allowsAuth = true;
1337
1399
  }
1338
- // Detect if the server supports PLAIN auth
1339
- if (/[ -]AUTH(?:(\s+|=)[^\n]*\s+|\s+|=)PLAIN/i.test(str)) {
1340
- this._supportedAuth.push('PLAIN');
1341
- }
1342
- // Detect if the server supports LOGIN auth
1343
- if (/[ -]AUTH(?:(\s+|=)[^\n]*\s+|\s+|=)LOGIN/i.test(str)) {
1344
- this._supportedAuth.push('LOGIN');
1345
- }
1346
- // Detect if the server supports CRAM-MD5 auth
1347
- if (/[ -]AUTH(?:(\s+|=)[^\n]*\s+|\s+|=)CRAM-MD5/i.test(str)) {
1348
- this._supportedAuth.push('CRAM-MD5');
1400
+ // Detect the advertised SASL mechanisms. The list is split into whole tokens rather
1401
+ // than searched for each name with a pattern: the patterns this replaced let two
1402
+ // whitespace runs overlap and backtracked quadratically over an AUTH line padded with
1403
+ // spaces, so a hostile server could stall the event loop from its EHLO reply
1404
+ // (GHSA-4ffr-jq9g-5ffx).
1405
+ const authMechanisms = new Set();
1406
+ for (const line of this._ehloLines) {
1407
+ const authMatch = /^AUTH[\s=](.*)/i.exec(line);
1408
+ if (authMatch) {
1409
+ for (const mechanism of authMatch[1].split(/[\s=]+/)) {
1410
+ authMechanisms.add(mechanism.toUpperCase());
1411
+ }
1412
+ }
1349
1413
  }
1350
- // Detect if the server supports XOAUTH2 auth
1351
- if (/[ -]AUTH(?:(\s+|=)[^\n]*\s+|\s+|=)XOAUTH2/i.test(str)) {
1352
- this._supportedAuth.push('XOAUTH2');
1414
+ // listed in order of preference, the first one the credentials allow is used
1415
+ for (const mechanism of ['PLAIN', 'LOGIN', 'CRAM-MD5', 'XOAUTH2']) {
1416
+ if (authMechanisms.has(mechanism)) {
1417
+ this._supportedAuth.push(mechanism);
1418
+ }
1353
1419
  }
1354
1420
  // Detect if the server supports SIZE extensions (and the max allowed size)
1355
1421
  if ((match = str.match(/[ -]SIZE(?:[ \t]+(\d+))?/im))) {
@@ -1426,6 +1492,7 @@ class SMTPConnection extends node_events_1.EventEmitter {
1426
1492
  * hosts invalidly use a longer message than VXNlcm5hbWU6
1427
1493
  *
1428
1494
  * @param str Message from the server
1495
+ * @param callback Callback to run once the authentication sequence completes
1429
1496
  * @internal
1430
1497
  */
1431
1498
  _actionAUTH_LOGIN_USER(str, callback) {
@@ -1447,6 +1514,7 @@ class SMTPConnection extends node_events_1.EventEmitter {
1447
1514
  * base64 encoded again.
1448
1515
  *
1449
1516
  * @param str Message from the server
1517
+ * @param callback Callback to run once the authentication sequence completes
1450
1518
  * @internal
1451
1519
  */
1452
1520
  _actionAUTH_CRAM_MD5(str, callback) {
@@ -1471,6 +1539,7 @@ class SMTPConnection extends node_events_1.EventEmitter {
1471
1539
  * the user can be considered logged in. Start waiting for a message to send
1472
1540
  *
1473
1541
  * @param str Message from the server
1542
+ * @param callback Callback to run once the authentication sequence completes
1474
1543
  * @internal
1475
1544
  */
1476
1545
  _actionAUTH_CRAM_MD5_PASS(str, callback) {
@@ -1492,6 +1561,7 @@ class SMTPConnection extends node_events_1.EventEmitter {
1492
1561
  * response needs to be base64 encoded password.
1493
1562
  *
1494
1563
  * @param str Message from the server
1564
+ * @param callback Callback to run once the authentication sequence completes
1495
1565
  * @internal
1496
1566
  */
1497
1567
  _actionAUTH_LOGIN_PASS(str, callback) {
@@ -1511,6 +1581,8 @@ class SMTPConnection extends node_events_1.EventEmitter {
1511
1581
  * the user can be considered logged in. Start waiting for a message to send
1512
1582
  *
1513
1583
  * @param str Message from the server
1584
+ * @param isRetry True if this is a retry after a failed login, or the callback itself
1585
+ * @param [callback] Callback to run once the authentication sequence completes
1514
1586
  * @internal
1515
1587
  */
1516
1588
  _actionAUTHComplete(str, isRetry, callback) {
@@ -1553,6 +1625,7 @@ class SMTPConnection extends node_events_1.EventEmitter {
1553
1625
  * Handle response for a MAIL FROM: command
1554
1626
  *
1555
1627
  * @param str Message from the server
1628
+ * @param callback Callback to run once the envelope is processed
1556
1629
  * @internal
1557
1630
  */
1558
1631
  _actionMAIL(str, callback) {
@@ -1581,6 +1654,7 @@ class SMTPConnection extends node_events_1.EventEmitter {
1581
1654
  * Handle response for a RCPT TO: command
1582
1655
  *
1583
1656
  * @param str Message from the server
1657
+ * @param callback Callback to run once the envelope is processed
1584
1658
  * @internal
1585
1659
  */
1586
1660
  _actionRCPT(str, callback) {
@@ -1609,7 +1683,11 @@ class SMTPConnection extends node_events_1.EventEmitter {
1609
1683
  this._sendCommand('DATA');
1610
1684
  }
1611
1685
  else {
1612
- err = this._formatError("Can't send mail - all recipients were rejected", 'EENVELOPE', str, 'RCPT TO');
1686
+ // report a temporary rejection when there is one, taking the last reply would mark the
1687
+ // whole message as permanently failed although some recipients were only deferred
1688
+ const deferred = envelope.rejectedErrors.find(rejectedErr => rejectedErr.responseCode && rejectedErr.responseCode < 500);
1689
+ const reply = deferred?.response ?? str;
1690
+ err = this._formatError("Can't send mail - all recipients were rejected", 'EENVELOPE', reply, 'RCPT TO');
1613
1691
  err.rejected = envelope.rejected;
1614
1692
  err.rejectedErrors = envelope.rejectedErrors;
1615
1693
  return callback(err);
@@ -1628,6 +1706,7 @@ class SMTPConnection extends node_events_1.EventEmitter {
1628
1706
  * Handle response for a DATA command
1629
1707
  *
1630
1708
  * @param str Message from the server
1709
+ * @param callback Callback to run once the envelope is processed
1631
1710
  * @internal
1632
1711
  */
1633
1712
  _actionDATA(str, callback) {
@@ -1654,6 +1733,7 @@ class SMTPConnection extends node_events_1.EventEmitter {
1654
1733
  * We expect a single response that defines if the sending succeeded or failed
1655
1734
  *
1656
1735
  * @param str Message from the server
1736
+ * @param callback Callback to run with the final send result
1657
1737
  * @internal
1658
1738
  */
1659
1739
  _actionSMTPStream(str, callback) {
@@ -1670,6 +1750,7 @@ class SMTPConnection extends node_events_1.EventEmitter {
1670
1750
  * @param recipient The recipient this response applies to
1671
1751
  * @param final Is this the final recipient?
1672
1752
  * @param str Message from the server
1753
+ * @param callback Callback to run with the final send result
1673
1754
  * @internal
1674
1755
  */
1675
1756
  _actionLMTPStream(recipient, final, str, callback) {