@bernierllc/email-sender 0.2.0

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 (39) hide show
  1. package/LICENSE +7 -0
  2. package/README.md +430 -0
  3. package/dist/core/email-sender.d.ts +71 -0
  4. package/dist/core/email-sender.d.ts.map +1 -0
  5. package/dist/core/email-sender.js +125 -0
  6. package/dist/core/email-sender.js.map +1 -0
  7. package/dist/index.d.ts +14 -0
  8. package/dist/index.d.ts.map +1 -0
  9. package/dist/index.js +47 -0
  10. package/dist/index.js.map +1 -0
  11. package/dist/providers/base.d.ts +63 -0
  12. package/dist/providers/base.d.ts.map +1 -0
  13. package/dist/providers/base.js +132 -0
  14. package/dist/providers/base.js.map +1 -0
  15. package/dist/providers/mailgun.d.ts +40 -0
  16. package/dist/providers/mailgun.d.ts.map +1 -0
  17. package/dist/providers/mailgun.js +525 -0
  18. package/dist/providers/mailgun.js.map +1 -0
  19. package/dist/providers/postmark.d.ts +37 -0
  20. package/dist/providers/postmark.d.ts.map +1 -0
  21. package/dist/providers/postmark.js +482 -0
  22. package/dist/providers/postmark.js.map +1 -0
  23. package/dist/providers/sendgrid.d.ts +80 -0
  24. package/dist/providers/sendgrid.d.ts.map +1 -0
  25. package/dist/providers/sendgrid.js +407 -0
  26. package/dist/providers/sendgrid.js.map +1 -0
  27. package/dist/providers/ses.d.ts +38 -0
  28. package/dist/providers/ses.d.ts.map +1 -0
  29. package/dist/providers/ses.js +404 -0
  30. package/dist/providers/ses.js.map +1 -0
  31. package/dist/providers/smtp.d.ts +61 -0
  32. package/dist/providers/smtp.d.ts.map +1 -0
  33. package/dist/providers/smtp.js +201 -0
  34. package/dist/providers/smtp.js.map +1 -0
  35. package/dist/types/index.d.ts +99 -0
  36. package/dist/types/index.d.ts.map +1 -0
  37. package/dist/types/index.js +10 -0
  38. package/dist/types/index.js.map +1 -0
  39. package/package.json +55 -0
@@ -0,0 +1,404 @@
1
+ "use strict";
2
+ /*
3
+ Copyright (c) 2025 Bernier LLC
4
+
5
+ This file is licensed to the client under a limited-use license.
6
+ The client may use and modify this code *only within the scope of the project it was delivered for*.
7
+ Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.SesProvider = void 0;
11
+ /**
12
+ * AWS SES Email Provider
13
+ * Handles email sending through Amazon Simple Email Service
14
+ */
15
+ const base_1 = require("./base");
16
+ class SesProvider extends base_1.EmailProvider {
17
+ constructor(config) {
18
+ super(config);
19
+ this.initializeClient();
20
+ }
21
+ initializeClient() {
22
+ try {
23
+ // Dynamically import AWS SDK to avoid bundling issues
24
+ const AWS = require('aws-sdk');
25
+ this.sesClient = new AWS.SES({
26
+ accessKeyId: this.config.apiKey,
27
+ secretAccessKey: this.config.secretKey,
28
+ region: this.config.region,
29
+ endpoint: this.config.endpoint,
30
+ apiVersion: '2010-12-01'
31
+ });
32
+ }
33
+ catch (error) {
34
+ throw new Error(`Failed to initialize AWS SES client: ${error instanceof Error ? error.message : 'Unknown error'}`);
35
+ }
36
+ }
37
+ async sendEmail(message) {
38
+ try {
39
+ const sesMessage = this.convertToSesMessage(message);
40
+ const params = {
41
+ ...sesMessage,
42
+ ConfigurationSetName: this.config.sandbox ? 'sandbox' : undefined
43
+ };
44
+ const result = await this.sesClient.sendEmail(params).promise();
45
+ return {
46
+ success: true,
47
+ messageId: result.MessageId,
48
+ providerResponse: result,
49
+ metadata: {
50
+ provider: 'ses',
51
+ region: this.config.region,
52
+ timestamp: new Date().toISOString()
53
+ }
54
+ };
55
+ }
56
+ catch (error) {
57
+ return {
58
+ success: false,
59
+ errorMessage: this.formatSesError(error),
60
+ providerResponse: error,
61
+ metadata: {
62
+ provider: 'ses',
63
+ region: this.config.region,
64
+ timestamp: new Date().toISOString()
65
+ }
66
+ };
67
+ }
68
+ }
69
+ async sendBatch(emails) {
70
+ try {
71
+ const batchSize = Math.min(emails.length, this.getCapabilities().maxBatchSize);
72
+ const results = [];
73
+ // Process emails in batches
74
+ for (let i = 0; i < emails.length; i += batchSize) {
75
+ const batch = emails.slice(i, i + batchSize);
76
+ const batchResults = await this.sendBatchChunk(batch);
77
+ results.push(...batchResults);
78
+ }
79
+ return results;
80
+ }
81
+ catch (error) {
82
+ // If batch fails, return individual error results
83
+ return emails.map(() => ({
84
+ success: false,
85
+ errorMessage: this.formatSesError(error),
86
+ metadata: {
87
+ provider: 'ses',
88
+ region: this.config.region,
89
+ timestamp: new Date().toISOString()
90
+ }
91
+ }));
92
+ }
93
+ }
94
+ async sendBatchChunk(emails) {
95
+ try {
96
+ const batchRequests = emails.map(email => ({
97
+ Id: `email-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
98
+ ...this.convertToSesMessage(email)
99
+ }));
100
+ const params = {
101
+ Source: this.config.fromEmail,
102
+ Destinations: batchRequests
103
+ };
104
+ const result = await this.sesClient.sendBulkTemplatedEmail(params).promise();
105
+ return batchRequests.map((_, index) => {
106
+ const status = result.Status[index];
107
+ return {
108
+ success: status.Status === 'Success',
109
+ messageId: status.MessageId,
110
+ errorMessage: status.Status === 'Failed' ? status.Error : undefined,
111
+ providerResponse: status,
112
+ metadata: {
113
+ provider: 'ses',
114
+ region: this.config.region,
115
+ timestamp: new Date().toISOString()
116
+ }
117
+ };
118
+ });
119
+ }
120
+ catch (error) {
121
+ return emails.map(() => ({
122
+ success: false,
123
+ errorMessage: this.formatSesError(error),
124
+ metadata: {
125
+ provider: 'ses',
126
+ region: this.config.region,
127
+ timestamp: new Date().toISOString()
128
+ }
129
+ }));
130
+ }
131
+ }
132
+ async sendTemplateEmail(templateId, toEmail, variables) {
133
+ try {
134
+ const params = {
135
+ Source: this.config.fromEmail,
136
+ Destination: {
137
+ ToAddresses: [toEmail]
138
+ },
139
+ Template: templateId,
140
+ TemplateData: JSON.stringify(variables)
141
+ };
142
+ const result = await this.sesClient.sendTemplatedEmail(params).promise();
143
+ return {
144
+ success: true,
145
+ messageId: result.MessageId,
146
+ providerResponse: result,
147
+ metadata: {
148
+ provider: 'ses',
149
+ region: this.config.region,
150
+ templateId,
151
+ timestamp: new Date().toISOString()
152
+ }
153
+ };
154
+ }
155
+ catch (error) {
156
+ return {
157
+ success: false,
158
+ errorMessage: this.formatSesError(error),
159
+ providerResponse: error,
160
+ metadata: {
161
+ provider: 'ses',
162
+ region: this.config.region,
163
+ templateId,
164
+ timestamp: new Date().toISOString()
165
+ }
166
+ };
167
+ }
168
+ }
169
+ async createTemplate(template) {
170
+ try {
171
+ const params = {
172
+ Template: {
173
+ TemplateName: template.name,
174
+ SubjectPart: template.subject,
175
+ HtmlPart: template.htmlContent,
176
+ TextPart: template.textContent
177
+ }
178
+ };
179
+ await this.sesClient.createTemplate(params).promise();
180
+ return template.name; // SES uses template name as ID
181
+ }
182
+ catch (error) {
183
+ throw new Error(`Failed to create SES template: ${this.formatSesError(error)}`);
184
+ }
185
+ }
186
+ async updateTemplate(template) {
187
+ try {
188
+ const params = {
189
+ Template: {
190
+ TemplateName: template.id,
191
+ SubjectPart: template.subject,
192
+ HtmlPart: template.htmlContent,
193
+ TextPart: template.textContent
194
+ }
195
+ };
196
+ await this.sesClient.updateTemplate(params).promise();
197
+ }
198
+ catch (error) {
199
+ throw new Error(`Failed to update SES template: ${this.formatSesError(error)}`);
200
+ }
201
+ }
202
+ async deleteTemplate(templateId) {
203
+ try {
204
+ const params = {
205
+ TemplateName: templateId
206
+ };
207
+ await this.sesClient.deleteTemplate(params).promise();
208
+ }
209
+ catch (error) {
210
+ throw new Error(`Failed to delete SES template: ${this.formatSesError(error)}`);
211
+ }
212
+ }
213
+ async getTemplate(templateId) {
214
+ try {
215
+ const params = {
216
+ TemplateName: templateId
217
+ };
218
+ const result = await this.sesClient.getTemplate(params).promise();
219
+ const template = result.Template;
220
+ return {
221
+ id: template.TemplateName,
222
+ name: template.TemplateName,
223
+ subject: template.SubjectPart,
224
+ htmlContent: template.HtmlPart,
225
+ textContent: template.TextPart,
226
+ variables: [], // SES doesn't provide variable list
227
+ createdAt: new Date(), // SES doesn't provide creation date
228
+ updatedAt: new Date() // SES doesn't provide update date
229
+ };
230
+ }
231
+ catch (error) {
232
+ if (error.code === 'TemplateDoesNotExist') {
233
+ return null;
234
+ }
235
+ throw new Error(`Failed to get SES template: ${this.formatSesError(error)}`);
236
+ }
237
+ }
238
+ async listTemplates() {
239
+ try {
240
+ const result = await this.sesClient.listTemplates().promise();
241
+ const templates = [];
242
+ for (const template of result.TemplatesMetadata || []) {
243
+ const fullTemplate = await this.getTemplate(template.Name);
244
+ if (fullTemplate) {
245
+ templates.push(fullTemplate);
246
+ }
247
+ }
248
+ return templates;
249
+ }
250
+ catch (error) {
251
+ throw new Error(`Failed to list SES templates: ${this.formatSesError(error)}`);
252
+ }
253
+ }
254
+ async getDeliveryStatus(messageId) {
255
+ try {
256
+ // SES doesn't provide direct delivery status via API
257
+ // This would typically be handled via SNS notifications
258
+ return {
259
+ messageId,
260
+ status: 'sent', // Default status
261
+ metadata: {
262
+ provider: 'ses',
263
+ region: this.config.region
264
+ }
265
+ };
266
+ }
267
+ catch (error) {
268
+ return null;
269
+ }
270
+ }
271
+ async processWebhook(_payload, _signature) {
272
+ // SES uses SNS for webhooks, not direct webhooks
273
+ // This would need to be implemented based on SNS message format
274
+ return [];
275
+ }
276
+ async testConnection() {
277
+ try {
278
+ // Test by getting sending statistics
279
+ await this.sesClient.getSendStatistics().promise();
280
+ return true;
281
+ }
282
+ catch (error) {
283
+ return false;
284
+ }
285
+ }
286
+ validateConfiguration() {
287
+ const errors = [];
288
+ const warnings = [];
289
+ if (!this.config.apiKey) {
290
+ errors.push('AWS Access Key ID is required');
291
+ }
292
+ if (!this.config.secretKey) {
293
+ errors.push('AWS Secret Access Key is required');
294
+ }
295
+ if (!this.config.region) {
296
+ errors.push('AWS region is required');
297
+ }
298
+ if (!this.config.fromEmail) {
299
+ errors.push('From email is required');
300
+ }
301
+ if (this.config.sandbox) {
302
+ warnings.push('SES sandbox mode is enabled - emails can only be sent to verified addresses');
303
+ }
304
+ return {
305
+ isValid: errors.length === 0,
306
+ errors,
307
+ warnings
308
+ };
309
+ }
310
+ validateEmailMessage(message) {
311
+ const errors = [];
312
+ const warnings = [];
313
+ if (!message.toEmail) {
314
+ errors.push('Recipient email is required');
315
+ }
316
+ else if (!this.isValidEmail(message.toEmail)) {
317
+ errors.push('Invalid recipient email format');
318
+ }
319
+ if (!message.subject) {
320
+ errors.push('Email subject is required');
321
+ }
322
+ if (!message.htmlContent && !message.textContent) {
323
+ errors.push('Either HTML or text content is required');
324
+ }
325
+ if (message.attachments && message.attachments.length > 0) {
326
+ warnings.push('SES has limited attachment support - consider using S3 for large files');
327
+ }
328
+ return {
329
+ isValid: errors.length === 0,
330
+ errors,
331
+ warnings
332
+ };
333
+ }
334
+ getCapabilities() {
335
+ return {
336
+ supportsBatch: true,
337
+ supportsTemplates: true,
338
+ supportsWebhooks: false, // SES uses SNS for notifications
339
+ supportsAttachments: true,
340
+ supportsDeliveryTracking: true,
341
+ maxBatchSize: 50,
342
+ maxAttachmentSize: 10 * 1024 * 1024 // 10MB
343
+ };
344
+ }
345
+ convertToSesMessage(message) {
346
+ const sesMessage = {
347
+ Source: message.fromEmail || this.config.fromEmail,
348
+ Destination: {
349
+ ToAddresses: [message.toEmail]
350
+ },
351
+ Message: {
352
+ Subject: {
353
+ Data: message.subject,
354
+ Charset: 'UTF-8'
355
+ },
356
+ Body: {}
357
+ }
358
+ };
359
+ if (message.htmlContent) {
360
+ sesMessage.Message.Body.Html = {
361
+ Data: message.htmlContent,
362
+ Charset: 'UTF-8'
363
+ };
364
+ }
365
+ if (message.textContent) {
366
+ sesMessage.Message.Body.Text = {
367
+ Data: message.textContent,
368
+ Charset: 'UTF-8'
369
+ };
370
+ }
371
+ if (message.replyTo) {
372
+ sesMessage.ReplyToAddresses = [message.replyTo];
373
+ }
374
+ if (message.headers) {
375
+ // Convert headers to SES tags
376
+ sesMessage.Tags = Object.entries(message.headers).map(([key, value]) => ({
377
+ Name: key,
378
+ Value: value
379
+ }));
380
+ }
381
+ return sesMessage;
382
+ }
383
+ formatSesError(error) {
384
+ if (error.code) {
385
+ switch (error.code) {
386
+ case 'MessageRejected':
387
+ return 'Message rejected by SES';
388
+ case 'MailFromDomainNotVerified':
389
+ return 'From domain is not verified in SES';
390
+ case 'ConfigurationSetDoesNotExist':
391
+ return 'Configuration set does not exist';
392
+ case 'TemplateDoesNotExist':
393
+ return 'Template does not exist';
394
+ case 'InvalidParameterValue':
395
+ return 'Invalid parameter value provided';
396
+ default:
397
+ return `SES Error (${error.code}): ${error.message || 'Unknown error'}`;
398
+ }
399
+ }
400
+ return error.message || 'Unknown SES error';
401
+ }
402
+ }
403
+ exports.SesProvider = SesProvider;
404
+ //# sourceMappingURL=ses.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ses.js","sourceRoot":"","sources":["../../src/providers/ses.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,61 @@
1
+ import { EmailProvider } from './base';
2
+ import { EmailMessage, SendResult, DeliveryStatus, WebhookEvent, EmailProviderConfig } from '../types';
3
+ export declare class SmtpProvider extends EmailProvider {
4
+ private transporter;
5
+ constructor(config: EmailProviderConfig);
6
+ /**
7
+ * Initialize the nodemailer transporter
8
+ */
9
+ private initializeTransporter;
10
+ /**
11
+ * Send a single email
12
+ */
13
+ sendEmail(email: EmailMessage): Promise<SendResult>;
14
+ /**
15
+ * Send multiple emails
16
+ */
17
+ sendBatch(emails: EmailMessage[]): Promise<SendResult[]>;
18
+ /**
19
+ * Get delivery status for a message
20
+ * Note: SMTP doesn't provide delivery tracking by default
21
+ */
22
+ getDeliveryStatus(_messageId: string): Promise<DeliveryStatus | null>;
23
+ /**
24
+ * Process webhook events from the provider
25
+ * Note: SMTP doesn't support webhooks by default
26
+ */
27
+ processWebhook(_payload: any, _signature: string): Promise<WebhookEvent[]>;
28
+ /**
29
+ * Override capabilities for SMTP
30
+ */
31
+ getCapabilities(): {
32
+ supportsBatch: boolean;
33
+ supportsTemplates: boolean;
34
+ supportsWebhooks: boolean;
35
+ supportsAttachments: boolean;
36
+ supportsDeliveryTracking: boolean;
37
+ maxBatchSize: number;
38
+ maxAttachmentSize: number;
39
+ };
40
+ /**
41
+ * Test the SMTP connection
42
+ */
43
+ testConnection(): Promise<boolean>;
44
+ /**
45
+ * Format from address
46
+ */
47
+ private formatFromAddress;
48
+ /**
49
+ * Format to address
50
+ */
51
+ private formatToAddress;
52
+ /**
53
+ * Override configuration validation for SMTP
54
+ */
55
+ validateConfiguration(): {
56
+ isValid: boolean;
57
+ errors: string[];
58
+ warnings: string[];
59
+ };
60
+ }
61
+ //# sourceMappingURL=smtp.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"smtp.d.ts","sourceRoot":"","sources":["../../src/providers/smtp.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,cAAc,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAEvG,qBAAa,YAAa,SAAQ,aAAa;IAC7C,OAAO,CAAC,WAAW,CAAuC;gBAE9C,MAAM,EAAE,mBAAmB;IAKvC;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAkB7B;;OAEG;IACG,SAAS,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,UAAU,CAAC;IA0DzD;;OAEG;IACG,SAAS,CAAC,MAAM,EAAE,YAAY,EAAE,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IAW9D;;;OAGG;IACG,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;IAK3E;;;OAGG;IACG,cAAc,CAAC,QAAQ,EAAE,GAAG,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IAKhF;;OAEG;IACM,eAAe;;;;;;;;;IAYxB;;OAEG;IACY,cAAc,IAAI,OAAO,CAAC,OAAO,CAAC;IAajD;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAWzB;;OAEG;IACH,OAAO,CAAC,eAAe;IAQvB;;OAEG;IACM,qBAAqB;;;;;CA0B/B"}
@@ -0,0 +1,201 @@
1
+ "use strict";
2
+ /*
3
+ Copyright (c) 2025 Bernier LLC
4
+
5
+ This file is licensed to the client under a limited-use license.
6
+ The client may use and modify this code *only within the scope of the project it was delivered for*.
7
+ Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
8
+ */
9
+ var __importDefault = (this && this.__importDefault) || function (mod) {
10
+ return (mod && mod.__esModule) ? mod : { "default": mod };
11
+ };
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.SmtpProvider = void 0;
14
+ /**
15
+ * SMTP Email Provider implementation using nodemailer
16
+ */
17
+ const nodemailer_1 = __importDefault(require("nodemailer"));
18
+ const base_1 = require("./base");
19
+ class SmtpProvider extends base_1.EmailProvider {
20
+ constructor(config) {
21
+ super(config);
22
+ this.transporter = null;
23
+ this.initializeTransporter();
24
+ }
25
+ /**
26
+ * Initialize the nodemailer transporter
27
+ */
28
+ initializeTransporter() {
29
+ if (this.config.provider !== 'smtp') {
30
+ throw new Error('SmtpProvider requires provider to be "smtp"');
31
+ }
32
+ const smtpConfig = {
33
+ host: this.config.host,
34
+ port: this.config.port,
35
+ secure: this.config.secure ?? false,
36
+ auth: {
37
+ user: this.config.username,
38
+ pass: this.config.password,
39
+ },
40
+ };
41
+ this.transporter = nodemailer_1.default.createTransport(smtpConfig);
42
+ }
43
+ /**
44
+ * Send a single email
45
+ */
46
+ async sendEmail(email) {
47
+ try {
48
+ // Validate email message
49
+ const validation = this.validateEmailMessage(email);
50
+ if (!validation.isValid) {
51
+ return {
52
+ success: false,
53
+ errorMessage: `Email validation failed: ${validation.errors.join(', ')}`,
54
+ };
55
+ }
56
+ if (!this.transporter) {
57
+ throw new Error('SMTP transporter not initialized');
58
+ }
59
+ // Prepare nodemailer options
60
+ const mailOptions = {
61
+ from: this.formatFromAddress(email.fromEmail, email.fromName),
62
+ to: this.formatToAddress(email.toEmail, email.toName),
63
+ subject: email.subject,
64
+ html: email.htmlContent,
65
+ text: email.textContent,
66
+ replyTo: email.replyTo,
67
+ headers: email.headers,
68
+ };
69
+ // Add attachments if present
70
+ if (email.attachments && email.attachments.length > 0) {
71
+ mailOptions.attachments = email.attachments.map(attachment => ({
72
+ filename: attachment.filename,
73
+ content: Buffer.from(attachment.content, 'base64'),
74
+ contentType: attachment.contentType,
75
+ contentDisposition: attachment.disposition,
76
+ }));
77
+ }
78
+ // Send email
79
+ const result = await this.transporter.sendMail(mailOptions);
80
+ return {
81
+ success: true,
82
+ messageId: result.messageId,
83
+ providerResponse: result,
84
+ metadata: {
85
+ accepted: result.accepted,
86
+ rejected: result.rejected,
87
+ response: result.response,
88
+ },
89
+ };
90
+ }
91
+ catch (error) {
92
+ return {
93
+ success: false,
94
+ errorMessage: error instanceof Error ? error.message : 'Unknown error occurred',
95
+ providerResponse: error,
96
+ };
97
+ }
98
+ }
99
+ /**
100
+ * Send multiple emails
101
+ */
102
+ async sendBatch(emails) {
103
+ const results = [];
104
+ for (const email of emails) {
105
+ const result = await this.sendEmail(email);
106
+ results.push(result);
107
+ }
108
+ return results;
109
+ }
110
+ /**
111
+ * Get delivery status for a message
112
+ * Note: SMTP doesn't provide delivery tracking by default
113
+ */
114
+ async getDeliveryStatus(_messageId) {
115
+ // SMTP doesn't provide delivery tracking
116
+ return null;
117
+ }
118
+ /**
119
+ * Process webhook events from the provider
120
+ * Note: SMTP doesn't support webhooks by default
121
+ */
122
+ async processWebhook(_payload, _signature) {
123
+ // SMTP doesn't support webhooks
124
+ return [];
125
+ }
126
+ /**
127
+ * Override capabilities for SMTP
128
+ */
129
+ getCapabilities() {
130
+ return {
131
+ supportsBatch: true,
132
+ supportsTemplates: false,
133
+ supportsWebhooks: false,
134
+ supportsAttachments: true,
135
+ supportsDeliveryTracking: false,
136
+ maxBatchSize: 100,
137
+ maxAttachmentSize: 25 * 1024 * 1024, // 25MB
138
+ };
139
+ }
140
+ /**
141
+ * Test the SMTP connection
142
+ */
143
+ async testConnection() {
144
+ try {
145
+ if (!this.transporter) {
146
+ return false;
147
+ }
148
+ await this.transporter.verify();
149
+ return true;
150
+ }
151
+ catch {
152
+ return false;
153
+ }
154
+ }
155
+ /**
156
+ * Format from address
157
+ */
158
+ formatFromAddress(email, name) {
159
+ const fromEmail = email || this.config.fromEmail;
160
+ const fromName = name || this.config.fromName;
161
+ if (fromName) {
162
+ return `"${fromName}" <${fromEmail}>`;
163
+ }
164
+ return fromEmail;
165
+ }
166
+ /**
167
+ * Format to address
168
+ */
169
+ formatToAddress(email, name) {
170
+ if (name) {
171
+ return `"${name}" <${email}>`;
172
+ }
173
+ return email;
174
+ }
175
+ /**
176
+ * Override configuration validation for SMTP
177
+ */
178
+ validateConfiguration() {
179
+ const errors = [];
180
+ const warnings = [];
181
+ if (!this.config.host) {
182
+ errors.push('SMTP host is required');
183
+ }
184
+ if (!this.config.port) {
185
+ errors.push('SMTP port is required');
186
+ }
187
+ if (this.config.username && !this.config.password) {
188
+ warnings.push('SMTP username provided but no password');
189
+ }
190
+ if (this.config.password && !this.config.username) {
191
+ warnings.push('SMTP password provided but no username');
192
+ }
193
+ return {
194
+ isValid: errors.length === 0,
195
+ errors,
196
+ warnings,
197
+ };
198
+ }
199
+ }
200
+ exports.SmtpProvider = SmtpProvider;
201
+ //# sourceMappingURL=smtp.js.map