@mavogel/awscdk-rootmail 0.1.7 → 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 (167) 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 +18 -16
  167. package/renovate.json5 +59 -0
@@ -28,7 +28,7 @@ export default class PoolResource extends EventEmitter {
28
28
  method: 'XOAUTH2'
29
29
  };
30
30
  oauth2.on('token', (token) => this.pool.mailer.emit('token', token));
31
- oauth2.on('error', err => this.emit('error', err));
31
+ oauth2.on('error', err => this._fail(err));
32
32
  break;
33
33
  }
34
34
  default:
@@ -51,6 +51,19 @@ export default class PoolResource extends EventEmitter {
51
51
  this._connected = false;
52
52
  this.messages = 0;
53
53
  this.available = true;
54
+ this._failed = false;
55
+ }
56
+ /**
57
+ * Emits 'error' for the first failure only. A dead resource can report the same failure more
58
+ * than once (the connection error, then the send callback), the pool handles it once
59
+ * @internal
60
+ */
61
+ _fail(err) {
62
+ if (this._failed) {
63
+ return;
64
+ }
65
+ this._failed = true;
66
+ this.emit('error', err);
54
67
  }
55
68
  /**
56
69
  * Initiates a connection to the SMTP server
@@ -63,7 +76,7 @@ export default class PoolResource extends EventEmitter {
63
76
  // nothing was connected, so no 'close' event is coming that would free the
64
77
  // slot this resource holds in the pool, report the failure the way a failed
65
78
  // login does
66
- this.emit('error', err);
79
+ this._fail(err);
67
80
  return callback(err);
68
81
  }
69
82
  let returned = false;
@@ -80,8 +93,8 @@ export default class PoolResource extends EventEmitter {
80
93
  options = Object.assign(assign(false, options), socketOptions);
81
94
  }
82
95
  this.connection = new SMTPConnection(options);
83
- this.connection.once('error', err => {
84
- this.emit('error', err);
96
+ this.connection.on('error', err => {
97
+ this._fail(err);
85
98
  if (returned) {
86
99
  return;
87
100
  }
@@ -90,35 +103,18 @@ export default class PoolResource extends EventEmitter {
90
103
  });
91
104
  this.connection.once('end', () => {
92
105
  this.close();
93
- if (returned) {
94
- return;
95
- }
96
106
  returned = true;
97
- const timer = setTimeout(() => {
98
- if (returned) {
99
- return;
100
- }
101
- // still have not returned, this means we have an unexpected connection close
102
- const err = new Error('Unexpected socket close');
103
- if (this.connection &&
104
- this.connection._socket &&
105
- this.connection._socket.upgrading) {
106
- // starttls connection errors
107
- err.code = errors.ETLS;
108
- }
109
- callback(err);
110
- }, 1000);
111
- try {
112
- timer.unref();
113
- }
114
- catch (_E) {
115
- // Ignore. Happens on envs with non-node timer implementation
116
- }
117
107
  });
118
- this.connection.connect(() => {
108
+ this.connection.connect(err => {
119
109
  if (returned) {
120
110
  return;
121
111
  }
112
+ if (err) {
113
+ // a close before the greeting, the 'end' that follows closes this resource
114
+ // and the pool requeues or fails the entry, bounded by maxRequeues
115
+ returned = true;
116
+ return;
117
+ }
122
118
  if (this.auth && (this.connection.allowsAuth || options.forceAuth)) {
123
119
  this.connection.login(this.auth, err => {
124
120
  if (returned) {
@@ -127,7 +123,7 @@ export default class PoolResource extends EventEmitter {
127
123
  returned = true;
128
124
  if (err) {
129
125
  this.connection.close();
130
- this.emit('error', err);
126
+ this._fail(err);
131
127
  return callback(err);
132
128
  }
133
129
  this._connected = true;
@@ -179,7 +175,7 @@ export default class PoolResource extends EventEmitter {
179
175
  this.messages++;
180
176
  if (err) {
181
177
  this.connection.close();
182
- this.emit('error', err);
178
+ this._fail(err);
183
179
  return callback(err);
184
180
  }
185
181
  info.envelope = {
@@ -192,7 +188,7 @@ export default class PoolResource extends EventEmitter {
192
188
  const err = new Error('Resource exhausted');
193
189
  err.code = errors.EMAXLIMIT;
194
190
  this.connection.close();
195
- this.emit('error', err);
191
+ this._fail(err);
196
192
  }
197
193
  else {
198
194
  this.pool._checkRateLimit(() => {
@@ -4,7 +4,7 @@ import * as shared from '../shared/index.js';
4
4
  import { type XOAuth2Options } from '../xoauth2/index.js';
5
5
  import type { ResultCallback } from '../errors.js';
6
6
  import type MailMessage from '../mailer/mail-message.js';
7
- import type { default as Mail, SentMessageInfo, SendMailOptions, TransportOptions, VerifyCallback } from '../mailer/index.js';
7
+ import type { default as Mail, GetSocketCallback, SentMessageInfo, SendMailOptions, TransportOptions, VerifyCallback } from '../mailer/index.js';
8
8
  import type { MimeNodeEnvelope } from '../mime-node/index.js';
9
9
  /**
10
10
  * Authentication settings, either from the transport options or from the message data.
@@ -38,9 +38,10 @@ export interface SMTPTransportAuth extends SMTPConnectionAuth {
38
38
  /**
39
39
  * Receives the socket details from getSocket, false when a new socket should be opened. The
40
40
  * object is merged into the connection options, a proxy handler provides the connected socket
41
- * as `connection`
41
+ * as `connection`. The same callback type Mail hands to a transport, so that the SMTP
42
+ * transports stay assignable to the Transport interface
42
43
  */
43
- export type SMTPTransportGetSocketCallback = (err: Error | null, socketOptions?: SMTPConnectionOptions | false) => void;
44
+ export type SMTPTransportGetSocketCallback = GetSocketCallback;
44
45
  /**
45
46
  * Custom socket provider, replaces the getSocket method of the transport
46
47
  */
@@ -78,6 +79,8 @@ export interface SMTPSentMessageInfo extends SMTPConnectionSendInfo, SentMessage
78
79
  accepted: string[];
79
80
  /** Recipients the server rejected */
80
81
  rejected: string[];
82
+ /** Final server response for the message */
83
+ response: string;
81
84
  }
82
85
  /**
83
86
  * Callback for send()
@@ -101,7 +104,7 @@ declare class SMTPTransport extends EventEmitter {
101
104
  /**
102
105
  * The Mail instance using this transport, assigned by Mail
103
106
  */
104
- mailer?: Mail<SMTPSentMessageInfo> | undefined;
107
+ mailer?: Mail<SMTPSentMessageInfo, SMTPTransportOptions> | undefined;
105
108
  constructor(options?: SMTPTransportOptions | string);
106
109
  /**
107
110
  * Placeholder function for creating proxy sockets. This method immediatelly returns
@@ -118,13 +121,18 @@ declare class SMTPTransport extends EventEmitter {
118
121
  * @param mail Mail object
119
122
  * @param callback Callback function
120
123
  */
121
- send(mail: MailMessage, callback: SMTPTransportSendCallback): void;
124
+ send(mail: MailMessage<SMTPSentMessageInfo>, callback: SMTPTransportSendCallback): void;
122
125
  /**
123
126
  * Verifies SMTP configuration
124
127
  *
125
- * @param callback Callback function
128
+ * @returns Promise that resolves to true if the configuration is usable
126
129
  */
127
130
  verify(): Promise<true>;
131
+ /**
132
+ * Verifies SMTP configuration
133
+ *
134
+ * @param callback Callback function
135
+ */
128
136
  verify(callback: VerifyCallback): void;
129
137
  /**
130
138
  * Releases resources
@@ -139,5 +147,10 @@ declare namespace SMTPTransport {
139
147
  type MailOptions = SendMailOptions;
140
148
  type SentMessageInfo = SMTPSentMessageInfo;
141
149
  type AuthenticationType = SMTPTransportAuth;
150
+ type AuthenticationTypeLogin = SMTPTransportAuth;
151
+ type AuthenticationTypeOAuth2 = SMTPTransportAuth;
152
+ type AuthenticationTypeCustom = SMTPTransportAuth;
142
153
  }
154
+ /** The same aliases as module level exports, for `import * as SMTPTransport` and `import SMTPTransport = require()` */
155
+ export type { SMTPTransportOptions as Options, SendMailOptions as MailOptions, SMTPSentMessageInfo as SentMessageInfo, SMTPTransportAuth as AuthenticationType, SMTPTransportAuth as AuthenticationTypeLogin, SMTPTransportAuth as AuthenticationTypeOAuth2, SMTPTransportAuth as AuthenticationTypeCustom };
143
156
  export default SMTPTransport;
@@ -139,31 +139,6 @@ class SMTPTransport extends EventEmitter {
139
139
  connection.close();
140
140
  return callback(err);
141
141
  });
142
- connection.once('end', () => {
143
- if (returned) {
144
- return;
145
- }
146
- const timer = setTimeout(() => {
147
- if (returned) {
148
- return;
149
- }
150
- returned = true;
151
- cleanupPerCallAuth();
152
- // still have not returned, this means we have an unexpected connection close
153
- const err = new Error('Unexpected socket close');
154
- if (connection && connection._socket && connection._socket.upgrading) {
155
- // starttls connection errors
156
- err.code = errors.ETLS;
157
- }
158
- callback(err);
159
- }, 1000);
160
- try {
161
- timer.unref();
162
- }
163
- catch (_E) {
164
- // Ignore. Happens on envs with non-node timer implementation
165
- }
166
- });
167
142
  const sendMessage = () => {
168
143
  const envelope = mail.message.getEnvelope();
169
144
  const messageId = mail.message.messageId();
@@ -183,6 +158,10 @@ class SMTPTransport extends EventEmitter {
183
158
  messageId
184
159
  }, 'Sending message %s to <%s>', messageId, recipients.join(', '));
185
160
  connection.send(envelope, mail.message.createReadStream(), (err, info) => {
161
+ if (returned) {
162
+ // the connection error handler has already reported this send
163
+ return;
164
+ }
186
165
  returned = true;
187
166
  cleanupPerCallAuth();
188
167
  connection.close();
@@ -209,10 +188,16 @@ class SMTPTransport extends EventEmitter {
209
188
  }
210
189
  });
211
190
  };
212
- connection.connect(() => {
191
+ connection.connect(err => {
213
192
  if (returned) {
214
193
  return;
215
194
  }
195
+ if (err) {
196
+ // the server closed the connection before the greeting
197
+ returned = true;
198
+ connection.close();
199
+ return callback(err);
200
+ }
216
201
  perCallAuth = this.getAuth(mail.data.auth);
217
202
  if (perCallAuth && (connection.allowsAuth || options.forceAuth)) {
218
203
  connection.login(perCallAuth, err => {
@@ -241,9 +226,11 @@ class SMTPTransport extends EventEmitter {
241
226
  callback = shared.callbackPromise(resolve, reject);
242
227
  });
243
228
  }
229
+ // the error paths hand over the error alone
230
+ const done = callback;
244
231
  this.getSocket(this.options, (err, socketOptions) => {
245
232
  if (err) {
246
- return callback(err);
233
+ return done(err);
247
234
  }
248
235
  let options = this.options;
249
236
  if (socketOptions && socketOptions.connection) {
@@ -273,7 +260,7 @@ class SMTPTransport extends EventEmitter {
273
260
  returned = true;
274
261
  cleanupPerCallAuth();
275
262
  connection.close();
276
- return callback(err);
263
+ return done(err);
277
264
  });
278
265
  connection.once('end', () => {
279
266
  if (returned) {
@@ -281,7 +268,7 @@ class SMTPTransport extends EventEmitter {
281
268
  }
282
269
  returned = true;
283
270
  cleanupPerCallAuth();
284
- return callback(new Error('Connection closed'));
271
+ return done(new Error('Connection closed'));
285
272
  });
286
273
  const finalize = () => {
287
274
  if (returned) {
@@ -290,12 +277,17 @@ class SMTPTransport extends EventEmitter {
290
277
  returned = true;
291
278
  cleanupPerCallAuth();
292
279
  connection.quit();
293
- return callback(null, true);
280
+ return done(null, true);
294
281
  };
295
- connection.connect(() => {
282
+ connection.connect(err => {
296
283
  if (returned) {
297
284
  return;
298
285
  }
286
+ if (err) {
287
+ returned = true;
288
+ connection.close();
289
+ return done(err);
290
+ }
299
291
  perCallAuth = this.getAuth({});
300
292
  if (perCallAuth && (connection.allowsAuth || options.forceAuth)) {
301
293
  connection.login(perCallAuth, err => {
@@ -306,7 +298,7 @@ class SMTPTransport extends EventEmitter {
306
298
  if (err) {
307
299
  returned = true;
308
300
  connection.close();
309
- return callback(err);
301
+ return done(err);
310
302
  }
311
303
  finalize();
312
304
  });
@@ -317,7 +309,7 @@ class SMTPTransport extends EventEmitter {
317
309
  returned = true;
318
310
  cleanupPerCallAuth();
319
311
  connection.close();
320
- return callback(err);
312
+ return done(err);
321
313
  }
322
314
  else {
323
315
  finalize();
@@ -60,4 +60,6 @@ declare namespace StreamTransport {
60
60
  type MailOptions = SendMailOptions;
61
61
  type SentMessageInfo = StreamSentMessageInfo;
62
62
  }
63
+ /** The same aliases as module level exports, for `import * as StreamTransport` and `import StreamTransport = require()` */
64
+ export type { StreamTransportOptions as Options, SendMailOptions as MailOptions, StreamSentMessageInfo as SentMessageInfo };
63
65
  export default StreamTransport;
@@ -311,6 +311,12 @@ export const services = {
311
311
  "host": "mailosaur.io",
312
312
  "port": 25
313
313
  },
314
+ "MailSenpai": {
315
+ "description": "MailSenpai (SMTP Senpai, EU)",
316
+ "host": "relay.mailsenpai.com",
317
+ "port": 2525,
318
+ "secure": false
319
+ },
314
320
  "Mailtrap": {
315
321
  "description": "Mailtrap",
316
322
  "host": "live.smtp.mailtrap.io",
@@ -1,6 +1,7 @@
1
1
  import { Stream } from 'node:stream';
2
2
  import crypto from 'node:crypto';
3
3
  import * as shared from '../shared/index.js';
4
+ import type { ResultCallback } from '../errors.js';
4
5
  import type { OutgoingHttpHeaders } from 'node:http';
5
6
  /**
6
7
  * Receives the result of a provisionCallback run: an error, or the new access token and
@@ -13,9 +14,11 @@ export type XOAuth2ProvisionResultCallback = (err: Error | null, accessToken?: s
13
14
  */
14
15
  export type XOAuth2ProvisionCallback = (user: string, renew: boolean, callback: XOAuth2ProvisionResultCallback) => void;
15
16
  /**
16
- * Receives an access token, or the error that prevented generating one
17
+ * Receives an access token, or the error that prevented generating one. Declared with a
18
+ * required token, the way @types/nodemailer declared it, the error path hands over the
19
+ * error alone
17
20
  */
18
- export type XOAuth2TokenCallback = (err: Error | null, accessToken?: string) => void;
21
+ export type XOAuth2TokenCallback = (err: Error | null, accessToken: string) => void;
19
22
  /**
20
23
  * A private key accepted by crypto.createSign().sign()
21
24
  */
@@ -58,6 +61,8 @@ export interface XOAuth2Options {
58
61
  component?: string | undefined;
59
62
  /** Extra headers for the token request */
60
63
  customHeaders?: OutgoingHttpHeaders | undefined;
64
+ /** Timeout for the token request in milliseconds, defaults to 60000, 0 disables it */
65
+ requestTimeout?: number | undefined;
61
66
  /** Extra form fields for the token request */
62
67
  customParams?: {
63
68
  [key: string]: any;
@@ -79,7 +84,7 @@ export interface XOAuth2Token {
79
84
  */
80
85
  export interface XOAuth2QueuedRequest {
81
86
  renew: boolean;
82
- callback: XOAuth2TokenCallback;
87
+ callback: ResultCallback<string>;
83
88
  }
84
89
  /**
85
90
  * XOAUTH2 access_token generator for Gmail.
@@ -181,11 +186,16 @@ declare class XOAuth2 extends Stream {
181
186
  [key: string]: any;
182
187
  }): string;
183
188
  }
189
+ /** The extra request settings of the token request, the customHeaders and customParams options */
190
+ export type XOAuth2RequestParams = Pick<XOAuth2Options, 'customHeaders' | 'customParams'>;
184
191
  /**
185
192
  * Type aliases in the layout of @types/nodemailer, so `XOAuth2.Options` style references keep working
186
193
  */
187
194
  declare namespace XOAuth2 {
188
195
  type Options = XOAuth2Options;
189
196
  type Token = XOAuth2Token;
197
+ type RequestParams = XOAuth2RequestParams;
190
198
  }
199
+ /** The same aliases as module level exports, for `import * as XOAuth2` and `import XOAuth2 = require()` */
200
+ export type { XOAuth2Options as Options, XOAuth2Token as Token, XOAuth2RequestParams as RequestParams };
191
201
  export default XOAuth2;
@@ -36,12 +36,14 @@ class XOAuth2 extends Stream {
36
36
  constructor(options, logger) {
37
37
  super();
38
38
  this.options = options || {};
39
+ this.configError = false;
39
40
  if (options && options.serviceClient) {
40
41
  if (!options.privateKey || !options.user) {
42
+ // reported through getToken() rather than an 'error' event: the transports forward
43
+ // that event up to the Mail object, where nothing may be listening
41
44
  const err = new Error('Options "privateKey" and "user" are required for service account!');
42
45
  err.code = errors.EOAUTH2;
43
- setImmediate(() => this.emit('error', err));
44
- return;
46
+ this.configError = err;
45
47
  }
46
48
  const serviceRequestTimeout = Math.min(Math.max(Number(this.options.serviceRequestTimeout) || 0, 0), 3600);
47
49
  this.options.serviceRequestTimeout = serviceRequestTimeout || 5 * 60;
@@ -73,6 +75,11 @@ class XOAuth2 extends Stream {
73
75
  * @param callback Callback function with error object and token string
74
76
  */
75
77
  getToken(renew, callback) {
78
+ // the error paths hand over the error alone
79
+ const done = callback;
80
+ if (this.configError) {
81
+ return done(this.configError);
82
+ }
76
83
  if (!renew && this.accessToken && (!this.expires || this.expires > Date.now())) {
77
84
  this.logger.debug({
78
85
  tnx: 'OAUTH2',
@@ -98,11 +105,11 @@ class XOAuth2 extends Stream {
98
105
  }, 'Cannot renew access token for %s: No refresh mechanism available', this.options.user);
99
106
  const err = new Error("Can't create new access token for user");
100
107
  err.code = errors.EOAUTH2;
101
- return callback(err);
108
+ return done(err);
102
109
  }
103
110
  // If renewal already in progress, queue this request instead of starting another
104
111
  if (this.renewing) {
105
- this.renewalQueue.push({ renew, callback });
112
+ this.renewalQueue.push({ renew, callback: done });
106
113
  return;
107
114
  }
108
115
  this.renewing = true;
@@ -127,7 +134,7 @@ class XOAuth2 extends Stream {
127
134
  }, 'Generated new Access Token for %s', this.options.user);
128
135
  }
129
136
  // Complete original request
130
- callback(err, accessToken);
137
+ done(err, accessToken);
131
138
  };
132
139
  if (this.provisionCallback) {
133
140
  this.provisionCallback(this.options.user, !!renew, (err, accessToken, expires) => {
@@ -166,6 +173,8 @@ class XOAuth2 extends Stream {
166
173
  * @param callback Callback function with error object and token string
167
174
  */
168
175
  generateToken(callback) {
176
+ // the error paths hand over the error alone
177
+ const done = callback;
169
178
  let urlOptions;
170
179
  let loggedUrlOptions;
171
180
  if (this.options.serviceClient) {
@@ -186,7 +195,7 @@ class XOAuth2 extends Stream {
186
195
  catch (_err) {
187
196
  const err = new Error("Can't generate token. Check your auth options");
188
197
  err.code = errors.EOAUTH2;
189
- return callback(err);
198
+ return done(err);
190
199
  }
191
200
  urlOptions = {
192
201
  grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer',
@@ -201,7 +210,7 @@ class XOAuth2 extends Stream {
201
210
  if (!this.options.refreshToken) {
202
211
  const err = new Error("Can't create new access token for user");
203
212
  err.code = errors.EOAUTH2;
204
- return callback(err);
213
+ return done(err);
205
214
  }
206
215
  // web app - https://developers.google.com/identity/protocols/OAuth2WebServer
207
216
  urlOptions = {
@@ -227,13 +236,13 @@ class XOAuth2 extends Stream {
227
236
  this.postRequest(this.options.accessUrl, urlOptions, this.options, (error, body) => {
228
237
  let data;
229
238
  if (error) {
230
- return callback(error);
239
+ return done(error);
231
240
  }
232
241
  try {
233
242
  data = JSON.parse(body.toString());
234
243
  }
235
244
  catch (E) {
236
- return callback(E);
245
+ return done(E);
237
246
  }
238
247
  if (!data || typeof data !== 'object') {
239
248
  this.logger.debug({
@@ -243,7 +252,7 @@ class XOAuth2 extends Stream {
243
252
  }, 'Response: %s', (body || '').toString());
244
253
  const err = new Error('Invalid authentication response');
245
254
  err.code = errors.EOAUTH2;
246
- return callback(err);
255
+ return done(err);
247
256
  }
248
257
  const logData = Object.assign({}, data);
249
258
  if (logData.access_token) {
@@ -265,7 +274,7 @@ class XOAuth2 extends Stream {
265
274
  }
266
275
  const err = new Error(errorMessage);
267
276
  err.code = errors.EOAUTH2;
268
- return callback(err);
277
+ return done(err);
269
278
  }
270
279
  if (data.access_token) {
271
280
  this.updateToken(data.access_token, data.expires_in);
@@ -273,7 +282,7 @@ class XOAuth2 extends Stream {
273
282
  }
274
283
  const err = new Error('No access token');
275
284
  err.code = errors.EOAUTH2;
276
- return callback(err);
285
+ return done(err);
277
286
  });
278
287
  }
279
288
  /**
@@ -307,7 +316,10 @@ class XOAuth2 extends Stream {
307
316
  method: 'post',
308
317
  headers: params.customHeaders,
309
318
  body: payload,
310
- allowErrorResponse: true
319
+ allowErrorResponse: true,
320
+ // unset falls back to the fetch default, a stalled token endpoint would otherwise keep
321
+ // `renewing` set and queue every later request
322
+ timeout: params.requestTimeout
311
323
  };
312
324
  // OAuth2 token endpoints are credential-bearing. src/fetch already
313
325
  // validates certs by default; pin rejectUnauthorized:true here so the
@@ -279,6 +279,13 @@
279
279
  "port": 25
280
280
  },
281
281
 
282
+ "MailSenpai": {
283
+ "description": "MailSenpai (SMTP Senpai, EU)",
284
+ "host": "relay.mailsenpai.com",
285
+ "port": 2525,
286
+ "secure": false
287
+ },
288
+
282
289
  "Mailtrap": {
283
290
  "description": "Mailtrap",
284
291
  "host": "live.smtp.mailtrap.io",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nodemailer",
3
- "version": "10.0.10",
3
+ "version": "10.0.14",
4
4
  "description": "Easy as cake e-mail sending from your Node.js applications",
5
5
  "type": "module",
6
6
  "main": "./dist/cjs/nodemailer.js",
@@ -9,6 +9,9 @@
9
9
  "lib/well-known/services.json": [
10
10
  "dist/well-known/services.json"
11
11
  ],
12
+ "lib/well-known/services": [
13
+ "dist/well-known/services.json"
14
+ ],
12
15
  "lib/*": [
13
16
  "dist/cjs/*/index.d.ts",
14
17
  "dist/cjs/*.d.ts"
@@ -97,6 +100,7 @@
97
100
  "require": "./dist/cjs/well-known/index.js"
98
101
  },
99
102
  "./lib/well-known/services.json": "./dist/well-known/services.json",
103
+ "./lib/well-known/services": "./dist/well-known/services.json",
100
104
  "./lib/xoauth2": {
101
105
  "import": "./dist/esm/xoauth2/index.js",
102
106
  "require": "./dist/cjs/xoauth2/index.js"
@@ -147,24 +151,24 @@
147
151
  },
148
152
  "homepage": "https://nodemailer.com/",
149
153
  "devDependencies": {
150
- "@aws-sdk/client-sesv2": "3.1131.0",
154
+ "@aws-sdk/client-sesv2": "3.1146.0",
151
155
  "@types/node": "20.19.43",
152
156
  "bunyan": "1.8.15",
153
157
  "c8": "12.0.0",
154
- "eslint": "10.10.0",
158
+ "eslint": "10.12.0",
155
159
  "eslint-config-prettier": "10.1.8",
156
- "globals": "17.12.0",
157
- "libbase64": "1.3.0",
158
- "libmime": "5.4.3",
159
- "libqp": "2.1.1",
160
- "mailauth": "5.0.3",
161
- "prettier": "3.9.6",
160
+ "globals": "17.13.0",
161
+ "libbase64": "1.3.1",
162
+ "libmime": "5.4.6",
163
+ "libqp": "2.1.2",
164
+ "mailauth": "7.1.0",
165
+ "prettier": "3.9.9",
162
166
  "proxy": "1.0.2",
163
167
  "proxy-test-server": "1.0.0",
164
- "smtp-server": "3.19.11",
165
- "tsx": "4.23.13",
168
+ "smtp-server": "3.19.16",
169
+ "tsx": "4.23.15",
166
170
  "typescript": "6.0.3",
167
- "typescript-eslint": "8.70.0"
171
+ "typescript-eslint": "8.71.0"
168
172
  },
169
173
  "engines": {
170
174
  "node": ">=20.0.0"