@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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@flink-app/email-plugin",
3
- "version": "2.0.0-alpha.74",
4
- "description": "Flink plugin that makes it possible to send email",
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.74"
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.74"
27
+ "@flink-app/flink": ">=2.0.0-alpha.76"
26
28
  },
27
29
  "scripts": {
28
- "test": "echo \"Error: no test specified\"",
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 Flowmailer.
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 three different email providers through a unified client interface:
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 { emailPluginContext } from "@flink-app/email-plugin";
171
+ import { EmailPluginContext } from "@flink-app/email-plugin";
128
172
 
129
- export interface Ctx extends FlinkContext<emailPluginContext> {
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 emailPluginContext {
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