@upyo/smtp 0.1.0-dev.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +178 -0
- package/dist/index.cjs +665 -0
- package/dist/index.d.cts +355 -0
- package/dist/index.d.ts +355 -0
- package/dist/index.js +641 -0
- package/package.json +74 -0
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
import { Message, Receipt, Transport, TransportOptions } from "@upyo/core";
|
|
2
|
+
import { Socket } from "node:net";
|
|
3
|
+
import { TLSSocket } from "node:tls";
|
|
4
|
+
|
|
5
|
+
//#region src/config.d.ts
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Configuration interface for SMTP transport connection settings.
|
|
9
|
+
*
|
|
10
|
+
* This interface defines all available options for configuring an SMTP
|
|
11
|
+
* connection including server details, authentication, security, and
|
|
12
|
+
* connection pooling settings.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```typescript
|
|
16
|
+
* const config: SmtpConfig = {
|
|
17
|
+
* host: 'smtp.gmail.com',
|
|
18
|
+
* port: 465,
|
|
19
|
+
* secure: true, // Use TLS from start
|
|
20
|
+
* auth: {
|
|
21
|
+
* user: 'user@gmail.com',
|
|
22
|
+
* pass: 'app-password'
|
|
23
|
+
* },
|
|
24
|
+
* connectionTimeout: 30000,
|
|
25
|
+
* poolSize: 10
|
|
26
|
+
* };
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
interface SmtpConfig {
|
|
30
|
+
/**
|
|
31
|
+
* The SMTP server hostname or IP address.
|
|
32
|
+
*/
|
|
33
|
+
readonly host: string;
|
|
34
|
+
/**
|
|
35
|
+
* The SMTP server port number.
|
|
36
|
+
* @default 587
|
|
37
|
+
*/
|
|
38
|
+
readonly port?: number;
|
|
39
|
+
/**
|
|
40
|
+
* Whether to use secure connection (TLS/SSL).
|
|
41
|
+
* @default true
|
|
42
|
+
*/
|
|
43
|
+
readonly secure?: boolean;
|
|
44
|
+
/**
|
|
45
|
+
* Authentication configuration for the SMTP server.
|
|
46
|
+
*/
|
|
47
|
+
readonly auth?: SmtpAuth;
|
|
48
|
+
/**
|
|
49
|
+
* TLS configuration options.
|
|
50
|
+
*/
|
|
51
|
+
readonly tls?: SmtpTlsOptions;
|
|
52
|
+
/**
|
|
53
|
+
* Connection timeout in milliseconds.
|
|
54
|
+
* @default 60000
|
|
55
|
+
*/
|
|
56
|
+
readonly connectionTimeout?: number;
|
|
57
|
+
/**
|
|
58
|
+
* Socket timeout in milliseconds.
|
|
59
|
+
* @default 60000
|
|
60
|
+
*/
|
|
61
|
+
readonly socketTimeout?: number;
|
|
62
|
+
/**
|
|
63
|
+
* The name to use for the local hostname in the HELO/EHLO command.
|
|
64
|
+
*/
|
|
65
|
+
readonly localName?: string;
|
|
66
|
+
/**
|
|
67
|
+
* Pool connections to reuse them.
|
|
68
|
+
* @default true
|
|
69
|
+
*/
|
|
70
|
+
readonly pool?: boolean;
|
|
71
|
+
/**
|
|
72
|
+
* Maximum number of connections in the pool.
|
|
73
|
+
* @default 5
|
|
74
|
+
*/
|
|
75
|
+
readonly poolSize?: number;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Authentication configuration for SMTP connections.
|
|
79
|
+
*
|
|
80
|
+
* Defines the credentials and authentication method to use when
|
|
81
|
+
* connecting to an SMTP server that requires authentication.
|
|
82
|
+
*
|
|
83
|
+
* @example
|
|
84
|
+
* ```typescript
|
|
85
|
+
* const auth: SmtpAuth = {
|
|
86
|
+
* user: 'username@domain.com',
|
|
87
|
+
* pass: 'password',
|
|
88
|
+
* method: 'plain' // or 'login', 'cram-md5'
|
|
89
|
+
* };
|
|
90
|
+
* ```
|
|
91
|
+
*/
|
|
92
|
+
interface SmtpAuth {
|
|
93
|
+
/**
|
|
94
|
+
* Username for authentication.
|
|
95
|
+
*/
|
|
96
|
+
readonly user: string;
|
|
97
|
+
/**
|
|
98
|
+
* Password for authentication.
|
|
99
|
+
*/
|
|
100
|
+
readonly pass: string;
|
|
101
|
+
/**
|
|
102
|
+
* Authentication method.
|
|
103
|
+
* @default "plain"
|
|
104
|
+
*/
|
|
105
|
+
readonly method?: "plain" | "login" | "cram-md5";
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* TLS/SSL configuration options for secure SMTP connections.
|
|
109
|
+
*
|
|
110
|
+
* These options control the behavior of TLS encryption when connecting
|
|
111
|
+
* to SMTP servers, including certificate validation and client authentication.
|
|
112
|
+
*
|
|
113
|
+
* @example
|
|
114
|
+
* ```typescript
|
|
115
|
+
* const tlsOptions: SmtpTlsOptions = {
|
|
116
|
+
* rejectUnauthorized: true,
|
|
117
|
+
* minVersion: 'TLSv1.2',
|
|
118
|
+
* ca: [fs.readFileSync('ca-cert.pem', 'utf8')]
|
|
119
|
+
* };
|
|
120
|
+
* ```
|
|
121
|
+
*/
|
|
122
|
+
interface SmtpTlsOptions {
|
|
123
|
+
/**
|
|
124
|
+
* Whether to reject unauthorized certificates.
|
|
125
|
+
* @default true
|
|
126
|
+
*/
|
|
127
|
+
readonly rejectUnauthorized?: boolean;
|
|
128
|
+
/**
|
|
129
|
+
* List of trusted certificates.
|
|
130
|
+
*/
|
|
131
|
+
readonly ca?: string[];
|
|
132
|
+
/**
|
|
133
|
+
* Private key for client certificate authentication.
|
|
134
|
+
*/
|
|
135
|
+
readonly key?: string;
|
|
136
|
+
/**
|
|
137
|
+
* Certificate for client certificate authentication.
|
|
138
|
+
*/
|
|
139
|
+
readonly cert?: string;
|
|
140
|
+
/**
|
|
141
|
+
* Minimum TLS version to accept.
|
|
142
|
+
* @default "TLSv1.2"
|
|
143
|
+
*/
|
|
144
|
+
readonly minVersion?: "TLSv1" | "TLSv1.1" | "TLSv1.2" | "TLSv1.3";
|
|
145
|
+
/**
|
|
146
|
+
* Maximum TLS version to accept.
|
|
147
|
+
* @default "TLSv1.3"
|
|
148
|
+
*/
|
|
149
|
+
readonly maxVersion?: "TLSv1" | "TLSv1.1" | "TLSv1.2" | "TLSv1.3";
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Resolved SMTP configuration with all optional fields filled with default values.
|
|
153
|
+
*
|
|
154
|
+
* This type represents the final configuration after applying defaults,
|
|
155
|
+
* used internally by the SMTP transport implementation.
|
|
156
|
+
*/
|
|
157
|
+
type ResolvedSmtpConfig = Omit<Required<SmtpConfig>, "auth" | "tls"> & {
|
|
158
|
+
readonly auth?: SmtpAuth;
|
|
159
|
+
readonly tls?: SmtpTlsOptions;
|
|
160
|
+
};
|
|
161
|
+
/**
|
|
162
|
+
* Creates a resolved SMTP configuration by applying default values to optional fields.
|
|
163
|
+
*
|
|
164
|
+
* This function takes a partial SMTP configuration and returns a complete
|
|
165
|
+
* configuration with all optional fields filled with sensible defaults.
|
|
166
|
+
*
|
|
167
|
+
* @param config - The SMTP configuration with optional fields
|
|
168
|
+
* @returns A resolved configuration with all defaults applied
|
|
169
|
+
*
|
|
170
|
+
* @example
|
|
171
|
+
* ```typescript
|
|
172
|
+
* const resolved = createSmtpConfig({
|
|
173
|
+
* host: 'smtp.example.com',
|
|
174
|
+
* auth: { user: 'user', pass: 'pass' }
|
|
175
|
+
* });
|
|
176
|
+
*
|
|
177
|
+
* // resolved.port will be 587 (default)
|
|
178
|
+
* // resolved.secure will be true (default)
|
|
179
|
+
* // resolved.poolSize will be 5 (default)
|
|
180
|
+
* ```
|
|
181
|
+
*/
|
|
182
|
+
declare function createSmtpConfig(config: SmtpConfig): ResolvedSmtpConfig;
|
|
183
|
+
//#endregion
|
|
184
|
+
//#region src/message-converter.d.ts
|
|
185
|
+
interface SmtpMessage {
|
|
186
|
+
readonly envelope: SmtpEnvelope;
|
|
187
|
+
readonly raw: string;
|
|
188
|
+
}
|
|
189
|
+
interface SmtpEnvelope {
|
|
190
|
+
readonly from: string;
|
|
191
|
+
readonly to: string[];
|
|
192
|
+
}
|
|
193
|
+
//#endregion
|
|
194
|
+
//#region src/smtp-connection.d.ts
|
|
195
|
+
declare class SmtpConnection {
|
|
196
|
+
socket: Socket | TLSSocket | null;
|
|
197
|
+
config: ResolvedSmtpConfig;
|
|
198
|
+
authenticated: boolean;
|
|
199
|
+
capabilities: string[];
|
|
200
|
+
constructor(config: SmtpConfig);
|
|
201
|
+
connect(signal?: AbortSignal): Promise<void>;
|
|
202
|
+
sendCommand(command: string, signal?: AbortSignal): Promise<SmtpResponse>;
|
|
203
|
+
greeting(signal?: AbortSignal): Promise<SmtpResponse>;
|
|
204
|
+
ehlo(signal?: AbortSignal): Promise<void>;
|
|
205
|
+
authenticate(signal?: AbortSignal): Promise<void>;
|
|
206
|
+
private authPlain;
|
|
207
|
+
authLogin(signal?: AbortSignal): Promise<void>;
|
|
208
|
+
sendMessage(message: SmtpMessage, signal?: AbortSignal): Promise<string>;
|
|
209
|
+
extractMessageId(response: string): string;
|
|
210
|
+
quit(): Promise<void>;
|
|
211
|
+
reset(signal?: AbortSignal): Promise<void>;
|
|
212
|
+
}
|
|
213
|
+
interface SmtpResponse {
|
|
214
|
+
readonly code: number;
|
|
215
|
+
readonly message: string;
|
|
216
|
+
readonly raw: string;
|
|
217
|
+
}
|
|
218
|
+
//#endregion
|
|
219
|
+
//#region src/smtp-transport.d.ts
|
|
220
|
+
/**
|
|
221
|
+
* SMTP transport implementation for sending emails via SMTP protocol.
|
|
222
|
+
*
|
|
223
|
+
* This transport provides efficient email delivery with connection pooling,
|
|
224
|
+
* support for authentication, TLS/SSL encryption, and batch sending capabilities.
|
|
225
|
+
*
|
|
226
|
+
* @example
|
|
227
|
+
* ```typescript
|
|
228
|
+
* import { SmtpTransport } from '@upyo/smtp';
|
|
229
|
+
*
|
|
230
|
+
* // Automatic resource cleanup with using statement
|
|
231
|
+
* await using transport = new SmtpTransport({
|
|
232
|
+
* host: 'smtp.gmail.com',
|
|
233
|
+
* port: 465,
|
|
234
|
+
* secure: true, // Use TLS from start
|
|
235
|
+
* auth: {
|
|
236
|
+
* user: 'user@gmail.com',
|
|
237
|
+
* pass: 'app-password'
|
|
238
|
+
* }
|
|
239
|
+
* });
|
|
240
|
+
*
|
|
241
|
+
* const receipt = await transport.send(message);
|
|
242
|
+
* // Connections are automatically closed here
|
|
243
|
+
*
|
|
244
|
+
* // Or manual management
|
|
245
|
+
* const transport2 = new SmtpTransport(config);
|
|
246
|
+
* try {
|
|
247
|
+
* await transport2.send(message);
|
|
248
|
+
* } finally {
|
|
249
|
+
* await transport2.closeAllConnections();
|
|
250
|
+
* }
|
|
251
|
+
* ```
|
|
252
|
+
*/
|
|
253
|
+
declare class SmtpTransport implements Transport, AsyncDisposable {
|
|
254
|
+
config: SmtpConfig;
|
|
255
|
+
connectionPool: SmtpConnection[];
|
|
256
|
+
poolSize: number;
|
|
257
|
+
/**
|
|
258
|
+
* Creates a new SMTP transport instance.
|
|
259
|
+
*
|
|
260
|
+
* @param config SMTP configuration including server details, authentication,
|
|
261
|
+
* and options.
|
|
262
|
+
*/
|
|
263
|
+
constructor(config: SmtpConfig);
|
|
264
|
+
/**
|
|
265
|
+
* Sends a single email message via SMTP.
|
|
266
|
+
*
|
|
267
|
+
* This method converts the message to SMTP format, establishes a connection
|
|
268
|
+
* to the SMTP server, sends the message, and returns a receipt with the result.
|
|
269
|
+
*
|
|
270
|
+
* @example
|
|
271
|
+
* ```typescript
|
|
272
|
+
* const receipt = await transport.send({
|
|
273
|
+
* sender: { address: 'from@example.com' },
|
|
274
|
+
* recipients: [{ address: 'to@example.com' }],
|
|
275
|
+
* subject: 'Hello',
|
|
276
|
+
* content: { text: 'Hello World!' }
|
|
277
|
+
* });
|
|
278
|
+
*
|
|
279
|
+
* if (receipt.successful) {
|
|
280
|
+
* console.log('Message sent with ID:', receipt.messageId);
|
|
281
|
+
* }
|
|
282
|
+
* ```
|
|
283
|
+
*
|
|
284
|
+
* @param message The email message to send.
|
|
285
|
+
* @param options Optional transport options including `AbortSignal` for
|
|
286
|
+
* cancellation.
|
|
287
|
+
* @returns A promise that resolves to a receipt indicating success or
|
|
288
|
+
* failure.
|
|
289
|
+
*/
|
|
290
|
+
send(message: Message, options?: TransportOptions): Promise<Receipt>;
|
|
291
|
+
/**
|
|
292
|
+
* Sends multiple email messages efficiently using a single SMTP connection.
|
|
293
|
+
*
|
|
294
|
+
* This method is optimized for bulk email sending by reusing a single SMTP
|
|
295
|
+
* connection for all messages, which significantly improves performance
|
|
296
|
+
* compared to sending each message individually.
|
|
297
|
+
*
|
|
298
|
+
* @example
|
|
299
|
+
* ```typescript
|
|
300
|
+
* const messages = [
|
|
301
|
+
* { subject: 'Message 1', recipients: [{ address: 'user1@example.com' }], ... },
|
|
302
|
+
* { subject: 'Message 2', recipients: [{ address: 'user2@example.com' }], ... }
|
|
303
|
+
* ];
|
|
304
|
+
*
|
|
305
|
+
* for await (const receipt of transport.sendMany(messages)) {
|
|
306
|
+
* if (receipt.successful) {
|
|
307
|
+
* console.log('Sent:', receipt.messageId);
|
|
308
|
+
* } else {
|
|
309
|
+
* console.error('Failed:', receipt.errorMessages);
|
|
310
|
+
* }
|
|
311
|
+
* }
|
|
312
|
+
* ```
|
|
313
|
+
*
|
|
314
|
+
* @param messages An iterable or async iterable of messages to send.
|
|
315
|
+
* @param options Optional transport options including `AbortSignal` for
|
|
316
|
+
* cancellation.
|
|
317
|
+
* @returns An async iterable of receipts, one for each message.
|
|
318
|
+
*/
|
|
319
|
+
sendMany(messages: Iterable<Message> | AsyncIterable<Message>, options?: TransportOptions): AsyncIterable<Receipt>;
|
|
320
|
+
getConnection(signal?: AbortSignal): Promise<SmtpConnection>;
|
|
321
|
+
connectAndSetup(connection: SmtpConnection, signal?: AbortSignal): Promise<void>;
|
|
322
|
+
returnConnection(connection: SmtpConnection): Promise<void>;
|
|
323
|
+
discardConnection(connection: SmtpConnection): Promise<void>;
|
|
324
|
+
/**
|
|
325
|
+
* Closes all active SMTP connections in the connection pool.
|
|
326
|
+
*
|
|
327
|
+
* This method should be called when shutting down the application
|
|
328
|
+
* to ensure all connections are properly closed and resources are freed.
|
|
329
|
+
*
|
|
330
|
+
* @example
|
|
331
|
+
* ```typescript
|
|
332
|
+
* // At application shutdown
|
|
333
|
+
* await transport.closeAllConnections();
|
|
334
|
+
* ```
|
|
335
|
+
*/
|
|
336
|
+
closeAllConnections(): Promise<void>;
|
|
337
|
+
/**
|
|
338
|
+
* Implements AsyncDisposable interface for automatic resource cleanup.
|
|
339
|
+
*
|
|
340
|
+
* This method is called automatically when using the `using` keyword,
|
|
341
|
+
* ensuring that all SMTP connections are properly closed when the
|
|
342
|
+
* transport goes out of scope.
|
|
343
|
+
*
|
|
344
|
+
* @example
|
|
345
|
+
* ```typescript
|
|
346
|
+
* // Automatic cleanup with using statement
|
|
347
|
+
* await using transport = new SmtpTransport(config);
|
|
348
|
+
* await transport.send(message);
|
|
349
|
+
* // Connections are automatically closed here
|
|
350
|
+
* ```
|
|
351
|
+
*/
|
|
352
|
+
[Symbol.asyncDispose](): Promise<void>;
|
|
353
|
+
}
|
|
354
|
+
//#endregion
|
|
355
|
+
export { SmtpAuth, SmtpConfig, SmtpTlsOptions, SmtpTransport, createSmtpConfig };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
import { Socket } from "node:net";
|
|
2
|
+
import { TLSSocket } from "node:tls";
|
|
3
|
+
import { Message, Receipt, Transport, TransportOptions } from "@upyo/core";
|
|
4
|
+
|
|
5
|
+
//#region src/config.d.ts
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Configuration interface for SMTP transport connection settings.
|
|
9
|
+
*
|
|
10
|
+
* This interface defines all available options for configuring an SMTP
|
|
11
|
+
* connection including server details, authentication, security, and
|
|
12
|
+
* connection pooling settings.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```typescript
|
|
16
|
+
* const config: SmtpConfig = {
|
|
17
|
+
* host: 'smtp.gmail.com',
|
|
18
|
+
* port: 465,
|
|
19
|
+
* secure: true, // Use TLS from start
|
|
20
|
+
* auth: {
|
|
21
|
+
* user: 'user@gmail.com',
|
|
22
|
+
* pass: 'app-password'
|
|
23
|
+
* },
|
|
24
|
+
* connectionTimeout: 30000,
|
|
25
|
+
* poolSize: 10
|
|
26
|
+
* };
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
interface SmtpConfig {
|
|
30
|
+
/**
|
|
31
|
+
* The SMTP server hostname or IP address.
|
|
32
|
+
*/
|
|
33
|
+
readonly host: string;
|
|
34
|
+
/**
|
|
35
|
+
* The SMTP server port number.
|
|
36
|
+
* @default 587
|
|
37
|
+
*/
|
|
38
|
+
readonly port?: number;
|
|
39
|
+
/**
|
|
40
|
+
* Whether to use secure connection (TLS/SSL).
|
|
41
|
+
* @default true
|
|
42
|
+
*/
|
|
43
|
+
readonly secure?: boolean;
|
|
44
|
+
/**
|
|
45
|
+
* Authentication configuration for the SMTP server.
|
|
46
|
+
*/
|
|
47
|
+
readonly auth?: SmtpAuth;
|
|
48
|
+
/**
|
|
49
|
+
* TLS configuration options.
|
|
50
|
+
*/
|
|
51
|
+
readonly tls?: SmtpTlsOptions;
|
|
52
|
+
/**
|
|
53
|
+
* Connection timeout in milliseconds.
|
|
54
|
+
* @default 60000
|
|
55
|
+
*/
|
|
56
|
+
readonly connectionTimeout?: number;
|
|
57
|
+
/**
|
|
58
|
+
* Socket timeout in milliseconds.
|
|
59
|
+
* @default 60000
|
|
60
|
+
*/
|
|
61
|
+
readonly socketTimeout?: number;
|
|
62
|
+
/**
|
|
63
|
+
* The name to use for the local hostname in the HELO/EHLO command.
|
|
64
|
+
*/
|
|
65
|
+
readonly localName?: string;
|
|
66
|
+
/**
|
|
67
|
+
* Pool connections to reuse them.
|
|
68
|
+
* @default true
|
|
69
|
+
*/
|
|
70
|
+
readonly pool?: boolean;
|
|
71
|
+
/**
|
|
72
|
+
* Maximum number of connections in the pool.
|
|
73
|
+
* @default 5
|
|
74
|
+
*/
|
|
75
|
+
readonly poolSize?: number;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Authentication configuration for SMTP connections.
|
|
79
|
+
*
|
|
80
|
+
* Defines the credentials and authentication method to use when
|
|
81
|
+
* connecting to an SMTP server that requires authentication.
|
|
82
|
+
*
|
|
83
|
+
* @example
|
|
84
|
+
* ```typescript
|
|
85
|
+
* const auth: SmtpAuth = {
|
|
86
|
+
* user: 'username@domain.com',
|
|
87
|
+
* pass: 'password',
|
|
88
|
+
* method: 'plain' // or 'login', 'cram-md5'
|
|
89
|
+
* };
|
|
90
|
+
* ```
|
|
91
|
+
*/
|
|
92
|
+
interface SmtpAuth {
|
|
93
|
+
/**
|
|
94
|
+
* Username for authentication.
|
|
95
|
+
*/
|
|
96
|
+
readonly user: string;
|
|
97
|
+
/**
|
|
98
|
+
* Password for authentication.
|
|
99
|
+
*/
|
|
100
|
+
readonly pass: string;
|
|
101
|
+
/**
|
|
102
|
+
* Authentication method.
|
|
103
|
+
* @default "plain"
|
|
104
|
+
*/
|
|
105
|
+
readonly method?: "plain" | "login" | "cram-md5";
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* TLS/SSL configuration options for secure SMTP connections.
|
|
109
|
+
*
|
|
110
|
+
* These options control the behavior of TLS encryption when connecting
|
|
111
|
+
* to SMTP servers, including certificate validation and client authentication.
|
|
112
|
+
*
|
|
113
|
+
* @example
|
|
114
|
+
* ```typescript
|
|
115
|
+
* const tlsOptions: SmtpTlsOptions = {
|
|
116
|
+
* rejectUnauthorized: true,
|
|
117
|
+
* minVersion: 'TLSv1.2',
|
|
118
|
+
* ca: [fs.readFileSync('ca-cert.pem', 'utf8')]
|
|
119
|
+
* };
|
|
120
|
+
* ```
|
|
121
|
+
*/
|
|
122
|
+
interface SmtpTlsOptions {
|
|
123
|
+
/**
|
|
124
|
+
* Whether to reject unauthorized certificates.
|
|
125
|
+
* @default true
|
|
126
|
+
*/
|
|
127
|
+
readonly rejectUnauthorized?: boolean;
|
|
128
|
+
/**
|
|
129
|
+
* List of trusted certificates.
|
|
130
|
+
*/
|
|
131
|
+
readonly ca?: string[];
|
|
132
|
+
/**
|
|
133
|
+
* Private key for client certificate authentication.
|
|
134
|
+
*/
|
|
135
|
+
readonly key?: string;
|
|
136
|
+
/**
|
|
137
|
+
* Certificate for client certificate authentication.
|
|
138
|
+
*/
|
|
139
|
+
readonly cert?: string;
|
|
140
|
+
/**
|
|
141
|
+
* Minimum TLS version to accept.
|
|
142
|
+
* @default "TLSv1.2"
|
|
143
|
+
*/
|
|
144
|
+
readonly minVersion?: "TLSv1" | "TLSv1.1" | "TLSv1.2" | "TLSv1.3";
|
|
145
|
+
/**
|
|
146
|
+
* Maximum TLS version to accept.
|
|
147
|
+
* @default "TLSv1.3"
|
|
148
|
+
*/
|
|
149
|
+
readonly maxVersion?: "TLSv1" | "TLSv1.1" | "TLSv1.2" | "TLSv1.3";
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Resolved SMTP configuration with all optional fields filled with default values.
|
|
153
|
+
*
|
|
154
|
+
* This type represents the final configuration after applying defaults,
|
|
155
|
+
* used internally by the SMTP transport implementation.
|
|
156
|
+
*/
|
|
157
|
+
type ResolvedSmtpConfig = Omit<Required<SmtpConfig>, "auth" | "tls"> & {
|
|
158
|
+
readonly auth?: SmtpAuth;
|
|
159
|
+
readonly tls?: SmtpTlsOptions;
|
|
160
|
+
};
|
|
161
|
+
/**
|
|
162
|
+
* Creates a resolved SMTP configuration by applying default values to optional fields.
|
|
163
|
+
*
|
|
164
|
+
* This function takes a partial SMTP configuration and returns a complete
|
|
165
|
+
* configuration with all optional fields filled with sensible defaults.
|
|
166
|
+
*
|
|
167
|
+
* @param config - The SMTP configuration with optional fields
|
|
168
|
+
* @returns A resolved configuration with all defaults applied
|
|
169
|
+
*
|
|
170
|
+
* @example
|
|
171
|
+
* ```typescript
|
|
172
|
+
* const resolved = createSmtpConfig({
|
|
173
|
+
* host: 'smtp.example.com',
|
|
174
|
+
* auth: { user: 'user', pass: 'pass' }
|
|
175
|
+
* });
|
|
176
|
+
*
|
|
177
|
+
* // resolved.port will be 587 (default)
|
|
178
|
+
* // resolved.secure will be true (default)
|
|
179
|
+
* // resolved.poolSize will be 5 (default)
|
|
180
|
+
* ```
|
|
181
|
+
*/
|
|
182
|
+
declare function createSmtpConfig(config: SmtpConfig): ResolvedSmtpConfig;
|
|
183
|
+
//#endregion
|
|
184
|
+
//#region src/message-converter.d.ts
|
|
185
|
+
interface SmtpMessage {
|
|
186
|
+
readonly envelope: SmtpEnvelope;
|
|
187
|
+
readonly raw: string;
|
|
188
|
+
}
|
|
189
|
+
interface SmtpEnvelope {
|
|
190
|
+
readonly from: string;
|
|
191
|
+
readonly to: string[];
|
|
192
|
+
}
|
|
193
|
+
//#endregion
|
|
194
|
+
//#region src/smtp-connection.d.ts
|
|
195
|
+
declare class SmtpConnection {
|
|
196
|
+
socket: Socket | TLSSocket | null;
|
|
197
|
+
config: ResolvedSmtpConfig;
|
|
198
|
+
authenticated: boolean;
|
|
199
|
+
capabilities: string[];
|
|
200
|
+
constructor(config: SmtpConfig);
|
|
201
|
+
connect(signal?: AbortSignal): Promise<void>;
|
|
202
|
+
sendCommand(command: string, signal?: AbortSignal): Promise<SmtpResponse>;
|
|
203
|
+
greeting(signal?: AbortSignal): Promise<SmtpResponse>;
|
|
204
|
+
ehlo(signal?: AbortSignal): Promise<void>;
|
|
205
|
+
authenticate(signal?: AbortSignal): Promise<void>;
|
|
206
|
+
private authPlain;
|
|
207
|
+
authLogin(signal?: AbortSignal): Promise<void>;
|
|
208
|
+
sendMessage(message: SmtpMessage, signal?: AbortSignal): Promise<string>;
|
|
209
|
+
extractMessageId(response: string): string;
|
|
210
|
+
quit(): Promise<void>;
|
|
211
|
+
reset(signal?: AbortSignal): Promise<void>;
|
|
212
|
+
}
|
|
213
|
+
interface SmtpResponse {
|
|
214
|
+
readonly code: number;
|
|
215
|
+
readonly message: string;
|
|
216
|
+
readonly raw: string;
|
|
217
|
+
}
|
|
218
|
+
//#endregion
|
|
219
|
+
//#region src/smtp-transport.d.ts
|
|
220
|
+
/**
|
|
221
|
+
* SMTP transport implementation for sending emails via SMTP protocol.
|
|
222
|
+
*
|
|
223
|
+
* This transport provides efficient email delivery with connection pooling,
|
|
224
|
+
* support for authentication, TLS/SSL encryption, and batch sending capabilities.
|
|
225
|
+
*
|
|
226
|
+
* @example
|
|
227
|
+
* ```typescript
|
|
228
|
+
* import { SmtpTransport } from '@upyo/smtp';
|
|
229
|
+
*
|
|
230
|
+
* // Automatic resource cleanup with using statement
|
|
231
|
+
* await using transport = new SmtpTransport({
|
|
232
|
+
* host: 'smtp.gmail.com',
|
|
233
|
+
* port: 465,
|
|
234
|
+
* secure: true, // Use TLS from start
|
|
235
|
+
* auth: {
|
|
236
|
+
* user: 'user@gmail.com',
|
|
237
|
+
* pass: 'app-password'
|
|
238
|
+
* }
|
|
239
|
+
* });
|
|
240
|
+
*
|
|
241
|
+
* const receipt = await transport.send(message);
|
|
242
|
+
* // Connections are automatically closed here
|
|
243
|
+
*
|
|
244
|
+
* // Or manual management
|
|
245
|
+
* const transport2 = new SmtpTransport(config);
|
|
246
|
+
* try {
|
|
247
|
+
* await transport2.send(message);
|
|
248
|
+
* } finally {
|
|
249
|
+
* await transport2.closeAllConnections();
|
|
250
|
+
* }
|
|
251
|
+
* ```
|
|
252
|
+
*/
|
|
253
|
+
declare class SmtpTransport implements Transport, AsyncDisposable {
|
|
254
|
+
config: SmtpConfig;
|
|
255
|
+
connectionPool: SmtpConnection[];
|
|
256
|
+
poolSize: number;
|
|
257
|
+
/**
|
|
258
|
+
* Creates a new SMTP transport instance.
|
|
259
|
+
*
|
|
260
|
+
* @param config SMTP configuration including server details, authentication,
|
|
261
|
+
* and options.
|
|
262
|
+
*/
|
|
263
|
+
constructor(config: SmtpConfig);
|
|
264
|
+
/**
|
|
265
|
+
* Sends a single email message via SMTP.
|
|
266
|
+
*
|
|
267
|
+
* This method converts the message to SMTP format, establishes a connection
|
|
268
|
+
* to the SMTP server, sends the message, and returns a receipt with the result.
|
|
269
|
+
*
|
|
270
|
+
* @example
|
|
271
|
+
* ```typescript
|
|
272
|
+
* const receipt = await transport.send({
|
|
273
|
+
* sender: { address: 'from@example.com' },
|
|
274
|
+
* recipients: [{ address: 'to@example.com' }],
|
|
275
|
+
* subject: 'Hello',
|
|
276
|
+
* content: { text: 'Hello World!' }
|
|
277
|
+
* });
|
|
278
|
+
*
|
|
279
|
+
* if (receipt.successful) {
|
|
280
|
+
* console.log('Message sent with ID:', receipt.messageId);
|
|
281
|
+
* }
|
|
282
|
+
* ```
|
|
283
|
+
*
|
|
284
|
+
* @param message The email message to send.
|
|
285
|
+
* @param options Optional transport options including `AbortSignal` for
|
|
286
|
+
* cancellation.
|
|
287
|
+
* @returns A promise that resolves to a receipt indicating success or
|
|
288
|
+
* failure.
|
|
289
|
+
*/
|
|
290
|
+
send(message: Message, options?: TransportOptions): Promise<Receipt>;
|
|
291
|
+
/**
|
|
292
|
+
* Sends multiple email messages efficiently using a single SMTP connection.
|
|
293
|
+
*
|
|
294
|
+
* This method is optimized for bulk email sending by reusing a single SMTP
|
|
295
|
+
* connection for all messages, which significantly improves performance
|
|
296
|
+
* compared to sending each message individually.
|
|
297
|
+
*
|
|
298
|
+
* @example
|
|
299
|
+
* ```typescript
|
|
300
|
+
* const messages = [
|
|
301
|
+
* { subject: 'Message 1', recipients: [{ address: 'user1@example.com' }], ... },
|
|
302
|
+
* { subject: 'Message 2', recipients: [{ address: 'user2@example.com' }], ... }
|
|
303
|
+
* ];
|
|
304
|
+
*
|
|
305
|
+
* for await (const receipt of transport.sendMany(messages)) {
|
|
306
|
+
* if (receipt.successful) {
|
|
307
|
+
* console.log('Sent:', receipt.messageId);
|
|
308
|
+
* } else {
|
|
309
|
+
* console.error('Failed:', receipt.errorMessages);
|
|
310
|
+
* }
|
|
311
|
+
* }
|
|
312
|
+
* ```
|
|
313
|
+
*
|
|
314
|
+
* @param messages An iterable or async iterable of messages to send.
|
|
315
|
+
* @param options Optional transport options including `AbortSignal` for
|
|
316
|
+
* cancellation.
|
|
317
|
+
* @returns An async iterable of receipts, one for each message.
|
|
318
|
+
*/
|
|
319
|
+
sendMany(messages: Iterable<Message> | AsyncIterable<Message>, options?: TransportOptions): AsyncIterable<Receipt>;
|
|
320
|
+
getConnection(signal?: AbortSignal): Promise<SmtpConnection>;
|
|
321
|
+
connectAndSetup(connection: SmtpConnection, signal?: AbortSignal): Promise<void>;
|
|
322
|
+
returnConnection(connection: SmtpConnection): Promise<void>;
|
|
323
|
+
discardConnection(connection: SmtpConnection): Promise<void>;
|
|
324
|
+
/**
|
|
325
|
+
* Closes all active SMTP connections in the connection pool.
|
|
326
|
+
*
|
|
327
|
+
* This method should be called when shutting down the application
|
|
328
|
+
* to ensure all connections are properly closed and resources are freed.
|
|
329
|
+
*
|
|
330
|
+
* @example
|
|
331
|
+
* ```typescript
|
|
332
|
+
* // At application shutdown
|
|
333
|
+
* await transport.closeAllConnections();
|
|
334
|
+
* ```
|
|
335
|
+
*/
|
|
336
|
+
closeAllConnections(): Promise<void>;
|
|
337
|
+
/**
|
|
338
|
+
* Implements AsyncDisposable interface for automatic resource cleanup.
|
|
339
|
+
*
|
|
340
|
+
* This method is called automatically when using the `using` keyword,
|
|
341
|
+
* ensuring that all SMTP connections are properly closed when the
|
|
342
|
+
* transport goes out of scope.
|
|
343
|
+
*
|
|
344
|
+
* @example
|
|
345
|
+
* ```typescript
|
|
346
|
+
* // Automatic cleanup with using statement
|
|
347
|
+
* await using transport = new SmtpTransport(config);
|
|
348
|
+
* await transport.send(message);
|
|
349
|
+
* // Connections are automatically closed here
|
|
350
|
+
* ```
|
|
351
|
+
*/
|
|
352
|
+
[Symbol.asyncDispose](): Promise<void>;
|
|
353
|
+
}
|
|
354
|
+
//#endregion
|
|
355
|
+
export { SmtpAuth, SmtpConfig, SmtpTlsOptions, SmtpTransport, createSmtpConfig };
|