@flink-app/email-plugin 2.0.0-alpha.74 → 2.0.0-alpha.76
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/CHANGELOG.md +13 -0
- package/dist/index.d.ts +4 -1
- package/dist/index.js +18 -1
- package/dist/schemas/client.d.ts +2 -1
- package/dist/schemas/emailSes.d.ts +60 -0
- package/dist/schemas/emailSes.js +2 -0
- package/dist/ses-types.d.ts +94 -0
- package/dist/ses-types.js +2 -0
- package/dist/sesClient.d.ts +48 -0
- package/dist/sesClient.js +388 -0
- package/package.json +7 -5
- package/readme.md +202 -7
- package/spec/sesClient.spec.ts +464 -0
- package/spec/support/jasmine.json +7 -0
- package/src/index.ts +5 -2
- package/src/schemas/client.ts +2 -1
- package/src/schemas/emailSes.ts +73 -0
- package/src/ses-types.ts +93 -0
- package/src/sesClient.ts +352 -0
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@flink-app/email-plugin",
|
|
3
|
-
"version": "2.0.0-alpha.
|
|
4
|
-
"description": "Flink plugin that
|
|
3
|
+
"version": "2.0.0-alpha.76",
|
|
4
|
+
"description": "Flink plugin that provides multi-provider email sending capabilities with support for SendGrid, SMTP, Flowmailer, and AWS SES",
|
|
5
5
|
"author": "johan@frost.se",
|
|
6
6
|
"publishConfig": {
|
|
7
7
|
"access": "public"
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
"types": "dist/index.d.ts",
|
|
11
11
|
"main": "dist/index.js",
|
|
12
12
|
"dependencies": {
|
|
13
|
+
"@aws-sdk/client-sesv2": "^3.700.0",
|
|
13
14
|
"@sendgrid/mail": "^7.4.5",
|
|
14
15
|
"@types/nodemailer": "^6.4.4",
|
|
15
16
|
"axios": "^0.27.2",
|
|
@@ -17,15 +18,16 @@
|
|
|
17
18
|
"querystring": "^0.2.1"
|
|
18
19
|
},
|
|
19
20
|
"devDependencies": {
|
|
21
|
+
"@types/jasmine": "^3.7.1",
|
|
20
22
|
"@types/node": "22.13.10",
|
|
21
|
-
"@flink-app/flink": "2.0.0-alpha.
|
|
23
|
+
"@flink-app/flink": "2.0.0-alpha.76"
|
|
22
24
|
},
|
|
23
25
|
"gitHead": "4243e3b3cd6d4e1ca001a61baa8436bf2bbe4113",
|
|
24
26
|
"peerDependencies": {
|
|
25
|
-
"@flink-app/flink": ">=2.0.0-alpha.
|
|
27
|
+
"@flink-app/flink": ">=2.0.0-alpha.76"
|
|
26
28
|
},
|
|
27
29
|
"scripts": {
|
|
28
|
-
"test": "
|
|
30
|
+
"test": "jasmine-ts --config=./spec/support/jasmine.json",
|
|
29
31
|
"build": "tsc",
|
|
30
32
|
"clean": "rimraf dist .flink"
|
|
31
33
|
}
|
package/readme.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Email Plugin
|
|
2
2
|
|
|
3
|
-
A Flink plugin that provides multi-provider email sending capabilities with support for SendGrid, SMTP, and
|
|
3
|
+
A Flink plugin that provides multi-provider email sending capabilities with support for SendGrid, SMTP, Flowmailer, and AWS SES.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
@@ -12,7 +12,7 @@ npm install @flink-app/email-plugin
|
|
|
12
12
|
|
|
13
13
|
## Configuration
|
|
14
14
|
|
|
15
|
-
The email plugin supports
|
|
15
|
+
The email plugin supports four different email providers through a unified client interface:
|
|
16
16
|
|
|
17
17
|
### Option 1: SendGrid
|
|
18
18
|
|
|
@@ -118,15 +118,59 @@ interface flowmailerClientOptions {
|
|
|
118
118
|
}
|
|
119
119
|
```
|
|
120
120
|
|
|
121
|
+
### Option 4: AWS SES
|
|
122
|
+
|
|
123
|
+
Configure the plugin with AWS Simple Email Service (SESv2):
|
|
124
|
+
|
|
125
|
+
```typescript
|
|
126
|
+
import { emailPlugin, sesClient } from "@flink-app/email-plugin";
|
|
127
|
+
|
|
128
|
+
function start() {
|
|
129
|
+
new FlinkApp<AppContext>({
|
|
130
|
+
name: "My app",
|
|
131
|
+
plugins: [
|
|
132
|
+
emailPlugin({
|
|
133
|
+
client: new sesClient({
|
|
134
|
+
region: "eu-north-1",
|
|
135
|
+
defaultFrom: "noreply@example.com",
|
|
136
|
+
configurationSet: "my-tracking-set", // optional
|
|
137
|
+
})
|
|
138
|
+
})
|
|
139
|
+
],
|
|
140
|
+
}).start();
|
|
141
|
+
}
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
**SES Client Options:**
|
|
145
|
+
|
|
146
|
+
```typescript
|
|
147
|
+
interface sesClientOptions {
|
|
148
|
+
region?: string; // AWS region (defaults to AWS_REGION env var)
|
|
149
|
+
credentials?: { // Explicit credentials (defaults to AWS credential chain)
|
|
150
|
+
accessKeyId: string;
|
|
151
|
+
secretAccessKey: string;
|
|
152
|
+
sessionToken?: string;
|
|
153
|
+
};
|
|
154
|
+
defaultFrom?: string; // Default sender address
|
|
155
|
+
configurationSet?: string; // Default SES configuration set for tracking
|
|
156
|
+
}
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
Credentials are resolved in this order:
|
|
160
|
+
1. Explicit `credentials` option
|
|
161
|
+
2. Environment variables (`AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`)
|
|
162
|
+
3. IAM instance profile / ECS task role
|
|
163
|
+
4. AWS SSO / credential file
|
|
164
|
+
|
|
121
165
|
## TypeScript Setup
|
|
122
166
|
|
|
123
167
|
Add the plugin context to your app's context type (usually in `Ctx.ts`):
|
|
124
168
|
|
|
125
169
|
```typescript
|
|
126
170
|
import { FlinkContext } from "@flink-app/flink";
|
|
127
|
-
import {
|
|
171
|
+
import { EmailPluginContext } from "@flink-app/email-plugin";
|
|
128
172
|
|
|
129
|
-
export interface Ctx extends FlinkContext<
|
|
173
|
+
export interface Ctx extends FlinkContext<EmailPluginContext> {
|
|
130
174
|
// Your other context properties
|
|
131
175
|
}
|
|
132
176
|
```
|
|
@@ -134,7 +178,7 @@ export interface Ctx extends FlinkContext<emailPluginContext> {
|
|
|
134
178
|
**Plugin Context Interface:**
|
|
135
179
|
|
|
136
180
|
```typescript
|
|
137
|
-
interface
|
|
181
|
+
interface EmailPluginContext {
|
|
138
182
|
emailPlugin: {
|
|
139
183
|
client: client; // Unified email client interface
|
|
140
184
|
};
|
|
@@ -306,7 +350,7 @@ All email clients implement this unified interface:
|
|
|
306
350
|
|
|
307
351
|
```typescript
|
|
308
352
|
interface client {
|
|
309
|
-
send(email: email | emailSendgrid | emailFlowmailer): Promise<boolean>;
|
|
353
|
+
send(email: email | emailSendgrid | emailFlowmailer | emailSes): Promise<boolean>;
|
|
310
354
|
}
|
|
311
355
|
```
|
|
312
356
|
|
|
@@ -400,10 +444,161 @@ if (!success) {
|
|
|
400
444
|
}
|
|
401
445
|
```
|
|
402
446
|
|
|
447
|
+
## AWS SES — Extended Features
|
|
448
|
+
|
|
449
|
+
The SES client supports additional features beyond the basic `send()` interface. Access them by casting the client to `sesClient`:
|
|
450
|
+
|
|
451
|
+
```typescript
|
|
452
|
+
import { sesClient } from "@flink-app/email-plugin";
|
|
453
|
+
const ses = ctx.plugins.emailPlugin.client as sesClient;
|
|
454
|
+
```
|
|
455
|
+
|
|
456
|
+
### Rich Send Results
|
|
457
|
+
|
|
458
|
+
Use `sendEmail()` instead of `send()` for detailed results:
|
|
459
|
+
|
|
460
|
+
```typescript
|
|
461
|
+
const result = await ses.sendEmail({
|
|
462
|
+
from: "noreply@example.com",
|
|
463
|
+
to: ["user@example.com"],
|
|
464
|
+
subject: "Hello",
|
|
465
|
+
html: "<h1>Welcome</h1>",
|
|
466
|
+
tags: { campaign: "welcome", env: "prod" },
|
|
467
|
+
});
|
|
468
|
+
|
|
469
|
+
if (result.success) {
|
|
470
|
+
console.log("Sent:", result.messageId);
|
|
471
|
+
} else {
|
|
472
|
+
console.error(`Failed: ${result.error?.code} - ${result.error?.message}`);
|
|
473
|
+
}
|
|
474
|
+
```
|
|
475
|
+
|
|
476
|
+
### Templated Emails
|
|
477
|
+
|
|
478
|
+
Send emails using SES templates:
|
|
479
|
+
|
|
480
|
+
```typescript
|
|
481
|
+
const result = await ses.sendTemplated({
|
|
482
|
+
to: ["user@example.com"],
|
|
483
|
+
template: "WelcomeEmail",
|
|
484
|
+
templateData: { name: "Joel", company: "Frost" },
|
|
485
|
+
});
|
|
486
|
+
```
|
|
487
|
+
|
|
488
|
+
### Bulk Email
|
|
489
|
+
|
|
490
|
+
Send to many recipients using a single SES template:
|
|
491
|
+
|
|
492
|
+
```typescript
|
|
493
|
+
const result = await ses.sendBulk({
|
|
494
|
+
template: "Newsletter",
|
|
495
|
+
defaultTemplateData: { company: "Frost" },
|
|
496
|
+
destinations: [
|
|
497
|
+
{ to: ["alice@example.com"], templateData: { name: "Alice" } },
|
|
498
|
+
{ to: ["bob@example.com"], templateData: { name: "Bob" } },
|
|
499
|
+
],
|
|
500
|
+
});
|
|
501
|
+
|
|
502
|
+
console.log(`Sent: ${result.successCount}, Failed: ${result.failureCount}`);
|
|
503
|
+
|
|
504
|
+
// Check individual results
|
|
505
|
+
for (const r of result.results) {
|
|
506
|
+
if (!r.success) {
|
|
507
|
+
console.error(`Failed: ${r.error?.code}`);
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
```
|
|
511
|
+
|
|
512
|
+
### Verify Setup
|
|
513
|
+
|
|
514
|
+
Check that your SES credentials and configuration are working:
|
|
515
|
+
|
|
516
|
+
```typescript
|
|
517
|
+
const status = await ses.verifySetup();
|
|
518
|
+
console.log(status);
|
|
519
|
+
// { verified: true, sendingEnabled: true, region: "eu-north-1" }
|
|
520
|
+
```
|
|
521
|
+
|
|
522
|
+
`sendingEnabled: false` means the account is still in the SES sandbox (can only send to verified addresses).
|
|
523
|
+
|
|
524
|
+
### SES Email Type
|
|
525
|
+
|
|
526
|
+
```typescript
|
|
527
|
+
type emailSes = {
|
|
528
|
+
from: string;
|
|
529
|
+
to: string[];
|
|
530
|
+
replyTo?: string[];
|
|
531
|
+
cc?: string[];
|
|
532
|
+
bcc?: string[];
|
|
533
|
+
subject: string;
|
|
534
|
+
text?: string;
|
|
535
|
+
html?: string;
|
|
536
|
+
attachments?: SesAttachment[];
|
|
537
|
+
configurationSet?: string; // Override default config set
|
|
538
|
+
tags?: Record<string, string>; // Event tracking tags
|
|
539
|
+
};
|
|
540
|
+
```
|
|
541
|
+
|
|
542
|
+
## AWS SES Setup Guide
|
|
543
|
+
|
|
544
|
+
### 1. Verify your sending domain
|
|
545
|
+
|
|
546
|
+
```bash
|
|
547
|
+
# Verify a domain (recommended for production)
|
|
548
|
+
aws sesv2 create-email-identity --email-identity example.com --region eu-north-1
|
|
549
|
+
|
|
550
|
+
# Or verify a single email address (for testing)
|
|
551
|
+
aws sesv2 create-email-identity --email-identity sender@example.com --region eu-north-1
|
|
552
|
+
```
|
|
553
|
+
|
|
554
|
+
### 2. Check verification status
|
|
555
|
+
|
|
556
|
+
```bash
|
|
557
|
+
aws sesv2 get-email-identity --email-identity example.com --region eu-north-1
|
|
558
|
+
```
|
|
559
|
+
|
|
560
|
+
For domain verification, add the DKIM CNAME records shown in the response to your DNS.
|
|
561
|
+
|
|
562
|
+
### 3. Check account status
|
|
563
|
+
|
|
564
|
+
```bash
|
|
565
|
+
aws sesv2 get-account --region eu-north-1
|
|
566
|
+
```
|
|
567
|
+
|
|
568
|
+
Look for `"ProductionAccessEnabled": true`. If `false`, you're in the sandbox.
|
|
569
|
+
|
|
570
|
+
### 4. Request production access (exit sandbox)
|
|
571
|
+
|
|
572
|
+
```bash
|
|
573
|
+
aws sesv2 put-account-details \
|
|
574
|
+
--production-access-enabled \
|
|
575
|
+
--mail-type TRANSACTIONAL \
|
|
576
|
+
--website-url "https://example.com" \
|
|
577
|
+
--use-case-description "Sending transactional emails (order confirmations, password resets)" \
|
|
578
|
+
--region eu-north-1
|
|
579
|
+
```
|
|
580
|
+
|
|
581
|
+
### 5. Send a test email
|
|
582
|
+
|
|
583
|
+
```bash
|
|
584
|
+
aws sesv2 send-email \
|
|
585
|
+
--from-email-address sender@example.com \
|
|
586
|
+
--destination '{"ToAddresses":["recipient@example.com"]}' \
|
|
587
|
+
--content '{"Simple":{"Subject":{"Data":"Test"},"Body":{"Text":{"Data":"Hello from SES"}}}}' \
|
|
588
|
+
--region eu-north-1
|
|
589
|
+
```
|
|
590
|
+
|
|
591
|
+
### 6. Create a configuration set (optional, for tracking)
|
|
592
|
+
|
|
593
|
+
```bash
|
|
594
|
+
aws sesv2 create-configuration-set --configuration-set-name my-tracking-set --region eu-north-1
|
|
595
|
+
```
|
|
596
|
+
|
|
403
597
|
## Notes
|
|
404
598
|
|
|
405
599
|
- Either `text` or `html` must be provided (not both required, but at least one)
|
|
406
|
-
- All clients return a boolean indicating success/failure
|
|
600
|
+
- All clients return a boolean indicating success/failure via the `send()` interface
|
|
601
|
+
- The SES client additionally offers `sendEmail()`, `sendTemplated()`, `sendBulk()`, and `verifySetup()` with richer return types
|
|
407
602
|
- Flowmailer automatically handles OAuth token refresh
|
|
408
603
|
- SendGrid attachments must be base64 encoded
|
|
409
604
|
- SMTP client uses nodemailer internally
|