@shogo-ai/email 1.4.1
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/LICENSE +21 -0
- package/README.md +29 -0
- package/dist/chunk-VPWVZHAC.js +882 -0
- package/dist/index.cjs +923 -0
- package/dist/index.d.cts +136 -0
- package/dist/index.d.ts +136 -0
- package/dist/index.js +37 -0
- package/dist/server.cjs +1059 -0
- package/dist/server.d.cts +109 -0
- package/dist/server.d.ts +109 -0
- package/dist/server.js +404 -0
- package/dist/types-CCHryvHe.d.cts +196 -0
- package/dist/types-CCHryvHe.d.ts +196 -0
- package/package.json +74 -0
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { b as EmailConfig, a as EmailAddress, g as IEmailService } from './types-CCHryvHe.cjs';
|
|
2
|
+
export { f as EmailResult, E as EmailTemplate, S as SendEmailParams, h as SendTemplateParams } from './types-CCHryvHe.cjs';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Email Service - Server Side
|
|
6
|
+
*
|
|
7
|
+
* Main entry point for server-side email functionality.
|
|
8
|
+
* Use this in server functions, API routes, etc.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```typescript
|
|
12
|
+
* import { createEmail } from '@shogo-ai/sdk/email/server'
|
|
13
|
+
*
|
|
14
|
+
* // Auto-configured from environment variables
|
|
15
|
+
* const email = createEmail()
|
|
16
|
+
*
|
|
17
|
+
* // Send a templated email
|
|
18
|
+
* await email.sendTemplate({
|
|
19
|
+
* to: 'user@example.com',
|
|
20
|
+
* template: 'welcome',
|
|
21
|
+
* data: { name: 'Alice', appName: 'MyApp' },
|
|
22
|
+
* })
|
|
23
|
+
*
|
|
24
|
+
* // Send raw email
|
|
25
|
+
* await email.send({
|
|
26
|
+
* to: 'user@example.com',
|
|
27
|
+
* subject: 'Hello!',
|
|
28
|
+
* html: '<h1>Hello World</h1>',
|
|
29
|
+
* })
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Options for creating an email service
|
|
35
|
+
*/
|
|
36
|
+
interface CreateEmailOptions {
|
|
37
|
+
/**
|
|
38
|
+
* Email provider configuration.
|
|
39
|
+
* If not provided, auto-detects from environment variables.
|
|
40
|
+
*/
|
|
41
|
+
config?: EmailConfig;
|
|
42
|
+
/**
|
|
43
|
+
* Default sender address.
|
|
44
|
+
* Can also be set via EMAIL_FROM or SMTP_FROM_EMAIL env var.
|
|
45
|
+
*/
|
|
46
|
+
defaultFrom?: EmailAddress;
|
|
47
|
+
/**
|
|
48
|
+
* Include built-in templates (welcome, password-reset, invitation, notification).
|
|
49
|
+
* Default: true
|
|
50
|
+
*/
|
|
51
|
+
includeBuiltins?: boolean;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Create an email service instance.
|
|
55
|
+
*
|
|
56
|
+
* If no config is provided, auto-detects provider from environment variables:
|
|
57
|
+
* - SMTP: SMTP_HOST, SMTP_PORT, SMTP_USER, SMTP_PASSWORD
|
|
58
|
+
* - SES: AWS_REGION or SES_REGION
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* ```typescript
|
|
62
|
+
* // Auto-configured from env
|
|
63
|
+
* const email = createEmail()
|
|
64
|
+
*
|
|
65
|
+
* // With explicit SMTP config
|
|
66
|
+
* const email = createEmail({
|
|
67
|
+
* config: {
|
|
68
|
+
* provider: 'smtp',
|
|
69
|
+
* defaultFrom: 'noreply@myapp.com',
|
|
70
|
+
* smtp: {
|
|
71
|
+
* host: 'smtp.example.com',
|
|
72
|
+
* port: 587,
|
|
73
|
+
* user: 'user',
|
|
74
|
+
* password: 'pass',
|
|
75
|
+
* },
|
|
76
|
+
* },
|
|
77
|
+
* })
|
|
78
|
+
*
|
|
79
|
+
* // With SES config
|
|
80
|
+
* const email = createEmail({
|
|
81
|
+
* config: {
|
|
82
|
+
* provider: 'ses',
|
|
83
|
+
* defaultFrom: 'noreply@myapp.com',
|
|
84
|
+
* ses: {
|
|
85
|
+
* region: 'us-east-1',
|
|
86
|
+
* },
|
|
87
|
+
* },
|
|
88
|
+
* })
|
|
89
|
+
* ```
|
|
90
|
+
*/
|
|
91
|
+
declare function createEmail(options?: CreateEmailOptions): IEmailService;
|
|
92
|
+
/**
|
|
93
|
+
* Create an email service, returning null if not configured.
|
|
94
|
+
* Useful for optional email functionality.
|
|
95
|
+
*
|
|
96
|
+
* @example
|
|
97
|
+
* ```typescript
|
|
98
|
+
* const email = createEmailOptional()
|
|
99
|
+
*
|
|
100
|
+
* if (email) {
|
|
101
|
+
* await email.send({ ... })
|
|
102
|
+
* } else {
|
|
103
|
+
* console.log('Email not configured, skipping')
|
|
104
|
+
* }
|
|
105
|
+
* ```
|
|
106
|
+
*/
|
|
107
|
+
declare function createEmailOptional(options?: CreateEmailOptions): IEmailService | null;
|
|
108
|
+
|
|
109
|
+
export { type CreateEmailOptions, EmailConfig, IEmailService, createEmail, createEmailOptional };
|
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { b as EmailConfig, a as EmailAddress, g as IEmailService } from './types-CCHryvHe.js';
|
|
2
|
+
export { f as EmailResult, E as EmailTemplate, S as SendEmailParams, h as SendTemplateParams } from './types-CCHryvHe.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Email Service - Server Side
|
|
6
|
+
*
|
|
7
|
+
* Main entry point for server-side email functionality.
|
|
8
|
+
* Use this in server functions, API routes, etc.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```typescript
|
|
12
|
+
* import { createEmail } from '@shogo-ai/sdk/email/server'
|
|
13
|
+
*
|
|
14
|
+
* // Auto-configured from environment variables
|
|
15
|
+
* const email = createEmail()
|
|
16
|
+
*
|
|
17
|
+
* // Send a templated email
|
|
18
|
+
* await email.sendTemplate({
|
|
19
|
+
* to: 'user@example.com',
|
|
20
|
+
* template: 'welcome',
|
|
21
|
+
* data: { name: 'Alice', appName: 'MyApp' },
|
|
22
|
+
* })
|
|
23
|
+
*
|
|
24
|
+
* // Send raw email
|
|
25
|
+
* await email.send({
|
|
26
|
+
* to: 'user@example.com',
|
|
27
|
+
* subject: 'Hello!',
|
|
28
|
+
* html: '<h1>Hello World</h1>',
|
|
29
|
+
* })
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Options for creating an email service
|
|
35
|
+
*/
|
|
36
|
+
interface CreateEmailOptions {
|
|
37
|
+
/**
|
|
38
|
+
* Email provider configuration.
|
|
39
|
+
* If not provided, auto-detects from environment variables.
|
|
40
|
+
*/
|
|
41
|
+
config?: EmailConfig;
|
|
42
|
+
/**
|
|
43
|
+
* Default sender address.
|
|
44
|
+
* Can also be set via EMAIL_FROM or SMTP_FROM_EMAIL env var.
|
|
45
|
+
*/
|
|
46
|
+
defaultFrom?: EmailAddress;
|
|
47
|
+
/**
|
|
48
|
+
* Include built-in templates (welcome, password-reset, invitation, notification).
|
|
49
|
+
* Default: true
|
|
50
|
+
*/
|
|
51
|
+
includeBuiltins?: boolean;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Create an email service instance.
|
|
55
|
+
*
|
|
56
|
+
* If no config is provided, auto-detects provider from environment variables:
|
|
57
|
+
* - SMTP: SMTP_HOST, SMTP_PORT, SMTP_USER, SMTP_PASSWORD
|
|
58
|
+
* - SES: AWS_REGION or SES_REGION
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* ```typescript
|
|
62
|
+
* // Auto-configured from env
|
|
63
|
+
* const email = createEmail()
|
|
64
|
+
*
|
|
65
|
+
* // With explicit SMTP config
|
|
66
|
+
* const email = createEmail({
|
|
67
|
+
* config: {
|
|
68
|
+
* provider: 'smtp',
|
|
69
|
+
* defaultFrom: 'noreply@myapp.com',
|
|
70
|
+
* smtp: {
|
|
71
|
+
* host: 'smtp.example.com',
|
|
72
|
+
* port: 587,
|
|
73
|
+
* user: 'user',
|
|
74
|
+
* password: 'pass',
|
|
75
|
+
* },
|
|
76
|
+
* },
|
|
77
|
+
* })
|
|
78
|
+
*
|
|
79
|
+
* // With SES config
|
|
80
|
+
* const email = createEmail({
|
|
81
|
+
* config: {
|
|
82
|
+
* provider: 'ses',
|
|
83
|
+
* defaultFrom: 'noreply@myapp.com',
|
|
84
|
+
* ses: {
|
|
85
|
+
* region: 'us-east-1',
|
|
86
|
+
* },
|
|
87
|
+
* },
|
|
88
|
+
* })
|
|
89
|
+
* ```
|
|
90
|
+
*/
|
|
91
|
+
declare function createEmail(options?: CreateEmailOptions): IEmailService;
|
|
92
|
+
/**
|
|
93
|
+
* Create an email service, returning null if not configured.
|
|
94
|
+
* Useful for optional email functionality.
|
|
95
|
+
*
|
|
96
|
+
* @example
|
|
97
|
+
* ```typescript
|
|
98
|
+
* const email = createEmailOptional()
|
|
99
|
+
*
|
|
100
|
+
* if (email) {
|
|
101
|
+
* await email.send({ ... })
|
|
102
|
+
* } else {
|
|
103
|
+
* console.log('Email not configured, skipping')
|
|
104
|
+
* }
|
|
105
|
+
* ```
|
|
106
|
+
*/
|
|
107
|
+
declare function createEmailOptional(options?: CreateEmailOptions): IEmailService | null;
|
|
108
|
+
|
|
109
|
+
export { type CreateEmailOptions, EmailConfig, IEmailService, createEmail, createEmailOptional };
|
package/dist/server.js
ADDED
|
@@ -0,0 +1,404 @@
|
|
|
1
|
+
import {
|
|
2
|
+
EmailError,
|
|
3
|
+
EmailTemplateRegistry,
|
|
4
|
+
createShogoTemplateRegistry,
|
|
5
|
+
formatEmailAddress
|
|
6
|
+
} from "./chunk-VPWVZHAC.js";
|
|
7
|
+
|
|
8
|
+
// src/providers/smtp.ts
|
|
9
|
+
var SmtpProvider = class {
|
|
10
|
+
// nodemailer.Transporter - lazy loaded
|
|
11
|
+
constructor(config) {
|
|
12
|
+
this.validateConfig(config);
|
|
13
|
+
this.config = config;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Validate required config fields
|
|
17
|
+
*/
|
|
18
|
+
validateConfig(config) {
|
|
19
|
+
const required = ["host", "port", "user", "password"];
|
|
20
|
+
for (const field of required) {
|
|
21
|
+
if (!config[field]) {
|
|
22
|
+
throw EmailError.configMissing(`smtp.${field}`);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Lazy-load nodemailer and create transporter
|
|
28
|
+
*/
|
|
29
|
+
async getTransporter() {
|
|
30
|
+
if (this.transporter) {
|
|
31
|
+
return this.transporter;
|
|
32
|
+
}
|
|
33
|
+
const nodemailer = await import("nodemailer");
|
|
34
|
+
this.transporter = nodemailer.createTransport({
|
|
35
|
+
host: this.config.host,
|
|
36
|
+
port: this.config.port,
|
|
37
|
+
secure: this.config.secure ?? this.config.port === 465,
|
|
38
|
+
auth: {
|
|
39
|
+
user: this.config.user,
|
|
40
|
+
pass: this.config.password
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
return this.transporter;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Format recipients for nodemailer
|
|
47
|
+
*/
|
|
48
|
+
formatRecipients(addresses) {
|
|
49
|
+
const list = Array.isArray(addresses) ? addresses : [addresses];
|
|
50
|
+
return list.map(formatEmailAddress).join(", ");
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Strip HTML tags to create plain text version
|
|
54
|
+
*/
|
|
55
|
+
stripHtml(html) {
|
|
56
|
+
return html.replace(/<style[^>]*>.*?<\/style>/gi, "").replace(/<script[^>]*>.*?<\/script>/gi, "").replace(/<[^>]+>/g, "").replace(/\s+/g, " ").trim();
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Check if provider is configured
|
|
60
|
+
*/
|
|
61
|
+
isConfigured() {
|
|
62
|
+
return !!(this.config.host && this.config.port && this.config.user && this.config.password);
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Send an email via SMTP
|
|
66
|
+
*/
|
|
67
|
+
async send(params) {
|
|
68
|
+
const { to, subject, html, text, from, replyTo, cc, bcc } = params;
|
|
69
|
+
if (!from) {
|
|
70
|
+
throw EmailError.configMissing("from address");
|
|
71
|
+
}
|
|
72
|
+
try {
|
|
73
|
+
const transporter = await this.getTransporter();
|
|
74
|
+
const mailOptions = {
|
|
75
|
+
from: formatEmailAddress(from),
|
|
76
|
+
to: this.formatRecipients(to),
|
|
77
|
+
subject,
|
|
78
|
+
html,
|
|
79
|
+
text: text || this.stripHtml(html)
|
|
80
|
+
};
|
|
81
|
+
if (replyTo) {
|
|
82
|
+
mailOptions.replyTo = formatEmailAddress(replyTo);
|
|
83
|
+
}
|
|
84
|
+
if (cc) {
|
|
85
|
+
mailOptions.cc = this.formatRecipients(cc);
|
|
86
|
+
}
|
|
87
|
+
if (bcc) {
|
|
88
|
+
mailOptions.bcc = this.formatRecipients(bcc);
|
|
89
|
+
}
|
|
90
|
+
const info = await transporter.sendMail(mailOptions);
|
|
91
|
+
return {
|
|
92
|
+
success: true,
|
|
93
|
+
messageId: info.messageId
|
|
94
|
+
};
|
|
95
|
+
} catch (error) {
|
|
96
|
+
const errorMessage = error.message || "Failed to send email";
|
|
97
|
+
const errorCode = this.mapErrorCode(error);
|
|
98
|
+
return {
|
|
99
|
+
success: false,
|
|
100
|
+
error: `[${errorCode}] ${errorMessage}`
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Map nodemailer error to error code
|
|
106
|
+
*/
|
|
107
|
+
mapErrorCode(error) {
|
|
108
|
+
const code = error.code || error.errno || "";
|
|
109
|
+
const message = (error.message || "").toLowerCase();
|
|
110
|
+
if (code === "ECONNREFUSED" || code === "ENOTFOUND" || message.includes("connection")) {
|
|
111
|
+
return "connection_error";
|
|
112
|
+
}
|
|
113
|
+
if (code === "EAUTH" || message.includes("auth") || message.includes("credentials")) {
|
|
114
|
+
return "authentication_error";
|
|
115
|
+
}
|
|
116
|
+
if (message.includes("recipient") || message.includes("mailbox") || message.includes("not found")) {
|
|
117
|
+
return "invalid_recipient";
|
|
118
|
+
}
|
|
119
|
+
return "send_failed";
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
function createSmtpProviderFromEnv() {
|
|
123
|
+
const host = process.env.SMTP_HOST;
|
|
124
|
+
const port = process.env.SMTP_PORT;
|
|
125
|
+
const user = process.env.SMTP_USER;
|
|
126
|
+
const password = process.env.SMTP_PASSWORD;
|
|
127
|
+
if (!host || !port || !user || !password) {
|
|
128
|
+
return null;
|
|
129
|
+
}
|
|
130
|
+
return new SmtpProvider({
|
|
131
|
+
host,
|
|
132
|
+
port: parseInt(port, 10),
|
|
133
|
+
user,
|
|
134
|
+
password,
|
|
135
|
+
secure: process.env.SMTP_SECURE === "true" ? true : void 0
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// src/providers/ses.ts
|
|
140
|
+
var SesProvider = class {
|
|
141
|
+
// SESClient - lazy loaded
|
|
142
|
+
constructor(config) {
|
|
143
|
+
this.validateConfig(config);
|
|
144
|
+
this.config = config;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Validate required config fields
|
|
148
|
+
*/
|
|
149
|
+
validateConfig(config) {
|
|
150
|
+
if (!config.region) {
|
|
151
|
+
throw EmailError.configMissing("ses.region");
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Lazy-load AWS SDK and create client
|
|
156
|
+
*/
|
|
157
|
+
async getClient() {
|
|
158
|
+
if (this.client) {
|
|
159
|
+
return this.client;
|
|
160
|
+
}
|
|
161
|
+
const { SESClient } = await import("@aws-sdk/client-ses");
|
|
162
|
+
const clientConfig = {
|
|
163
|
+
region: this.config.region
|
|
164
|
+
};
|
|
165
|
+
if (this.config.accessKeyId && this.config.secretAccessKey) {
|
|
166
|
+
clientConfig.credentials = {
|
|
167
|
+
accessKeyId: this.config.accessKeyId,
|
|
168
|
+
secretAccessKey: this.config.secretAccessKey
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
this.client = new SESClient(clientConfig);
|
|
172
|
+
return this.client;
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Format recipients as array of strings
|
|
176
|
+
*/
|
|
177
|
+
formatRecipients(addresses) {
|
|
178
|
+
const list = Array.isArray(addresses) ? addresses : [addresses];
|
|
179
|
+
return list.map(
|
|
180
|
+
(addr) => typeof addr === "string" ? addr : addr.email
|
|
181
|
+
);
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Strip HTML tags to create plain text version
|
|
185
|
+
*/
|
|
186
|
+
stripHtml(html) {
|
|
187
|
+
return html.replace(/<style[^>]*>.*?<\/style>/gi, "").replace(/<script[^>]*>.*?<\/script>/gi, "").replace(/<[^>]+>/g, "").replace(/\s+/g, " ").trim();
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Check if provider is configured
|
|
191
|
+
*/
|
|
192
|
+
isConfigured() {
|
|
193
|
+
return !!this.config.region;
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Send an email via SES
|
|
197
|
+
*/
|
|
198
|
+
async send(params) {
|
|
199
|
+
const { to, subject, html, text, from, replyTo, cc, bcc } = params;
|
|
200
|
+
if (!from) {
|
|
201
|
+
throw EmailError.configMissing("from address");
|
|
202
|
+
}
|
|
203
|
+
try {
|
|
204
|
+
const client = await this.getClient();
|
|
205
|
+
const { SendEmailCommand } = await import("@aws-sdk/client-ses");
|
|
206
|
+
const destination = {
|
|
207
|
+
ToAddresses: this.formatRecipients(to)
|
|
208
|
+
};
|
|
209
|
+
if (cc) {
|
|
210
|
+
destination.CcAddresses = this.formatRecipients(cc);
|
|
211
|
+
}
|
|
212
|
+
if (bcc) {
|
|
213
|
+
destination.BccAddresses = this.formatRecipients(bcc);
|
|
214
|
+
}
|
|
215
|
+
const command = new SendEmailCommand({
|
|
216
|
+
Source: formatEmailAddress(from),
|
|
217
|
+
Destination: destination,
|
|
218
|
+
Message: {
|
|
219
|
+
Subject: {
|
|
220
|
+
Data: subject,
|
|
221
|
+
Charset: "UTF-8"
|
|
222
|
+
},
|
|
223
|
+
Body: {
|
|
224
|
+
Html: {
|
|
225
|
+
Data: html,
|
|
226
|
+
Charset: "UTF-8"
|
|
227
|
+
},
|
|
228
|
+
Text: {
|
|
229
|
+
Data: text || this.stripHtml(html),
|
|
230
|
+
Charset: "UTF-8"
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
},
|
|
234
|
+
ReplyToAddresses: replyTo ? [formatEmailAddress(replyTo)] : void 0
|
|
235
|
+
});
|
|
236
|
+
const response = await client.send(command);
|
|
237
|
+
return {
|
|
238
|
+
success: true,
|
|
239
|
+
messageId: response.MessageId
|
|
240
|
+
};
|
|
241
|
+
} catch (error) {
|
|
242
|
+
const errorMessage = error.message || "Failed to send email";
|
|
243
|
+
return {
|
|
244
|
+
success: false,
|
|
245
|
+
error: `[ses_error] ${errorMessage}`
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
};
|
|
250
|
+
function createSesProviderFromEnv() {
|
|
251
|
+
const region = process.env.SES_REGION || process.env.AWS_REGION;
|
|
252
|
+
if (!region) {
|
|
253
|
+
return null;
|
|
254
|
+
}
|
|
255
|
+
return new SesProvider({
|
|
256
|
+
region,
|
|
257
|
+
accessKeyId: process.env.AWS_ACCESS_KEY_ID,
|
|
258
|
+
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// src/providers/oci-email.ts
|
|
263
|
+
var OciEmailProvider = class {
|
|
264
|
+
constructor(config) {
|
|
265
|
+
this.fromAddress = config.fromAddress;
|
|
266
|
+
this.smtp = new SmtpProvider({
|
|
267
|
+
host: config.host,
|
|
268
|
+
port: config.port,
|
|
269
|
+
user: config.user,
|
|
270
|
+
password: config.password,
|
|
271
|
+
secure: config.port === 465
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
isConfigured() {
|
|
275
|
+
return this.smtp.isConfigured();
|
|
276
|
+
}
|
|
277
|
+
async send(params) {
|
|
278
|
+
const effective = {
|
|
279
|
+
...params,
|
|
280
|
+
from: params.from ?? this.fromAddress
|
|
281
|
+
};
|
|
282
|
+
return this.smtp.send(effective);
|
|
283
|
+
}
|
|
284
|
+
};
|
|
285
|
+
function createOciEmailProviderFromEnv() {
|
|
286
|
+
const host = process.env.OCI_EMAIL_SMTP_HOST;
|
|
287
|
+
const user = process.env.OCI_EMAIL_SMTP_USER;
|
|
288
|
+
const password = process.env.OCI_EMAIL_SMTP_PASS;
|
|
289
|
+
if (!host || !user || !password) {
|
|
290
|
+
return null;
|
|
291
|
+
}
|
|
292
|
+
const port = parseInt(process.env.OCI_EMAIL_SMTP_PORT || "587", 10);
|
|
293
|
+
return new OciEmailProvider({
|
|
294
|
+
host,
|
|
295
|
+
port,
|
|
296
|
+
user,
|
|
297
|
+
password,
|
|
298
|
+
fromAddress: process.env.OCI_EMAIL_FROM_ADDRESS
|
|
299
|
+
});
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
// src/providers/index.ts
|
|
303
|
+
function createProviderFromEnv() {
|
|
304
|
+
const explicitProvider = process.env.EMAIL_PROVIDER;
|
|
305
|
+
if (explicitProvider === "smtp") {
|
|
306
|
+
return createSmtpProviderFromEnv();
|
|
307
|
+
}
|
|
308
|
+
if (explicitProvider === "ses") {
|
|
309
|
+
return createSesProviderFromEnv();
|
|
310
|
+
}
|
|
311
|
+
if (explicitProvider === "oci-email") {
|
|
312
|
+
return createOciEmailProviderFromEnv();
|
|
313
|
+
}
|
|
314
|
+
if (process.env.OCI_EMAIL_SMTP_HOST) {
|
|
315
|
+
return createOciEmailProviderFromEnv();
|
|
316
|
+
}
|
|
317
|
+
if (process.env.SMTP_HOST) {
|
|
318
|
+
return createSmtpProviderFromEnv();
|
|
319
|
+
}
|
|
320
|
+
if (process.env.SES_REGION || process.env.AWS_REGION) {
|
|
321
|
+
return createSesProviderFromEnv();
|
|
322
|
+
}
|
|
323
|
+
return null;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
// src/server.ts
|
|
327
|
+
var EmailService = class {
|
|
328
|
+
constructor(provider, templates, defaultFrom) {
|
|
329
|
+
this.provider = provider;
|
|
330
|
+
this.templates = templates;
|
|
331
|
+
this.defaultFrom = defaultFrom;
|
|
332
|
+
}
|
|
333
|
+
/**
|
|
334
|
+
* Check if the service is configured and ready
|
|
335
|
+
*/
|
|
336
|
+
isConfigured() {
|
|
337
|
+
return this.provider.isConfigured();
|
|
338
|
+
}
|
|
339
|
+
/**
|
|
340
|
+
* Register a custom email template
|
|
341
|
+
*/
|
|
342
|
+
registerTemplate(template) {
|
|
343
|
+
this.templates.register(template);
|
|
344
|
+
}
|
|
345
|
+
/**
|
|
346
|
+
* Send a raw email
|
|
347
|
+
*/
|
|
348
|
+
async send(params) {
|
|
349
|
+
const emailParams = {
|
|
350
|
+
...params,
|
|
351
|
+
from: params.from ?? this.defaultFrom
|
|
352
|
+
};
|
|
353
|
+
return this.provider.send(emailParams);
|
|
354
|
+
}
|
|
355
|
+
/**
|
|
356
|
+
* Send a templated email
|
|
357
|
+
*/
|
|
358
|
+
async sendTemplate(params) {
|
|
359
|
+
const { template: templateName, data, ...rest } = params;
|
|
360
|
+
const { subject, html, text } = this.templates.render(templateName, data);
|
|
361
|
+
return this.send({
|
|
362
|
+
...rest,
|
|
363
|
+
subject,
|
|
364
|
+
html,
|
|
365
|
+
text
|
|
366
|
+
});
|
|
367
|
+
}
|
|
368
|
+
};
|
|
369
|
+
function createEmail(options = {}) {
|
|
370
|
+
const { config, defaultFrom, includeBuiltins = true } = options;
|
|
371
|
+
let provider = null;
|
|
372
|
+
if (config) {
|
|
373
|
+
if (config.provider === "smtp" && config.smtp) {
|
|
374
|
+
provider = new SmtpProvider(config.smtp);
|
|
375
|
+
} else if (config.provider === "ses" && config.ses) {
|
|
376
|
+
provider = new SesProvider(config.ses);
|
|
377
|
+
} else if (config.provider === "oci-email" && config.ociEmail) {
|
|
378
|
+
provider = new OciEmailProvider(config.ociEmail);
|
|
379
|
+
}
|
|
380
|
+
} else {
|
|
381
|
+
provider = createProviderFromEnv();
|
|
382
|
+
}
|
|
383
|
+
if (!provider) {
|
|
384
|
+
throw EmailError.providerNotConfigured();
|
|
385
|
+
}
|
|
386
|
+
const from = defaultFrom ?? config?.defaultFrom ?? process.env.EMAIL_FROM ?? process.env.SMTP_FROM_EMAIL ?? process.env.SES_FROM_EMAIL ?? process.env.OCI_EMAIL_FROM_ADDRESS;
|
|
387
|
+
if (!from) {
|
|
388
|
+
throw EmailError.configMissing("defaultFrom (or EMAIL_FROM env var)");
|
|
389
|
+
}
|
|
390
|
+
const templates = includeBuiltins ? createShogoTemplateRegistry() : new EmailTemplateRegistry();
|
|
391
|
+
return new EmailService(provider, templates, from);
|
|
392
|
+
}
|
|
393
|
+
function createEmailOptional(options = {}) {
|
|
394
|
+
try {
|
|
395
|
+
return createEmail(options);
|
|
396
|
+
} catch {
|
|
397
|
+
return null;
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
export {
|
|
401
|
+
createEmail,
|
|
402
|
+
createEmailOptional
|
|
403
|
+
};
|
|
404
|
+
//# sourceMappingURL=server.js.map
|