npm package: @nodelabs/nest-aws-ses
Description: NestJS module for AWS SES (Simple Email Service)
Author: Abiral Neupane
Latest version: 0.0.2

# @nodelabs/nest-aws-ses

A NestJS dynamic module for sending emails via **AWS SES (Simple Email Service)**. Supports both static (`forRoot`) and async (`forRootAsync`) configuration, with optional global registration.

---

## Table of Contents

- [Installation](#installation)
- [Quick Start](#quick-start)
- [Configuration](#configuration)
  - [forRoot (static)](#forroot-static)
  - [forRootAsync (factory)](#forrootasync-factory)
  - [isGlobal](#isglobal)
- [Available Services](#available-services)
  - [AwsSesService](#awssesservice)
- [API Reference](#api-reference)
  - [ISesModuleOptions](#isesmoduleoptions)
  - [ISesModuleAsyncOptions](#isesmoduleasyncoptions)
- [Exports](#exports)

---

## Installation

```bash
npm install @nodelabs/nest-aws-ses @aws-sdk/client-ses
```

### Peer Dependencies

Make sure you have the following installed in your project:

```bash
npm install @nestjs/common @nestjs/config reflect-metadata rxjs
```

---

## Quick Start

```typescript
// app.module.ts
import { Module } from '@nestjs/common';
import { SesModule } from '@nodelabs/nest-aws-ses';

@Module({
  imports: [
    SesModule.forRoot({
      region: 'us-east-1',
      accessKeyId: 'YOUR_ACCESS_KEY_ID',
      secretAccessKey: 'YOUR_SECRET_ACCESS_KEY',
      defaultSender: 'no-reply@example.com',
    }),
  ],
})
export class AppModule {}
```

---

## Configuration

### `forRoot` (static)

Use `forRoot` when your credentials are available at module load time.

```typescript
SesModule.forRoot({
  region: 'us-east-1',
  accessKeyId: 'YOUR_ACCESS_KEY_ID',
  secretAccessKey: 'YOUR_SECRET_ACCESS_KEY',
  defaultSender: 'no-reply@example.com',
  isGlobal: true, // optional — makes the module globally available
})
```

---

### `forRootAsync` (factory)

Use `forRootAsync` when you need to inject configuration dynamically (e.g., from `ConfigService`).

```typescript
import { Module } from '@nestjs/common';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { SesModule } from '@nodelabs/nest-aws-ses';

@Module({
  imports: [
    ConfigModule.forRoot(),
    SesModule.forRootAsync({
      isGlobal: true,
      imports: [ConfigModule],
      inject: [ConfigService],
      useFactory: (config: ConfigService) => ({
        region: config.get<string>('AWS_REGION'),
        accessKeyId: config.get<string>('AWS_ACCESS_KEY_ID'),
        secretAccessKey: config.get<string>('AWS_SECRET_ACCESS_KEY'),
        defaultSender: config.get<string>('AWS_SES_DEFAULT_SENDER'),
      }),
    }),
  ],
})
export class AppModule {}
```

#### Environment variables (example `.env`)

```env
AWS_REGION=us-east-1
AWS_ACCESS_KEY_ID=your_access_key
AWS_SECRET_ACCESS_KEY=your_secret_key
AWS_SES_DEFAULT_SENDER=no-reply@example.com
```

---

### `isGlobal`

Setting `isGlobal: true` registers the module globally so that you do not need to re-import `SesModule` in every feature module. It mirrors the behaviour of `ConfigModule.forRoot({ isGlobal: true })`.

```typescript
SesModule.forRoot({
  // ...options
  isGlobal: true,
});
```

---

## Available Services

### `AwsSesService`

Inject `AwsSesService` into any provider after importing `SesModule`.

```typescript
import { Injectable } from '@nestjs/common';
import { AwsSesService } from '@nodelabs/nest-aws-ses';

@Injectable()
export class NotificationService {
  constructor(private readonly sesService: AwsSesService) {}

  async sendWelcomeEmail(email: string) {
    await this.sesService.sendEmail(
      [email],
      '<h1>Welcome!</h1>',
      'Welcome!',
      'Welcome to Our App',
    );
  }
}
```

#### Methods

| Method | Signature | Description |
|--------|-----------|-------------|
| `sendEmail` | `sendEmail(receivers: string[], htmlBody: string, textBody: string, subject: string): Promise<any>` | Sends an HTML + plain-text email to one or more recipients using the configured `defaultSender`. |
| `execute` | `execute(command: SESCommand): Promise<any \| null>` | Executes a raw `@aws-sdk/client-ses` command directly. Errors are logged and `null` is returned on failure. |

##### `sendEmail` example

```typescript
await sesService.sendEmail(
  ['alice@example.com', 'bob@example.com'],
  '<p>Hello from NestLabs!</p>',
  'Hello from NestLabs!',
  'Greetings',
);
```

##### `execute` (raw command) example

```typescript
import { GetSendQuotaCommand } from '@aws-sdk/client-ses';

const quota = await sesService.execute(new GetSendQuotaCommand({}));
```

---

## API Reference

### `ISesModuleOptions`

```typescript
interface ISesModuleOptions {
  /** AWS region (e.g. 'us-east-1') */
  region: string;

  /** IAM Access Key ID */
  accessKeyId: string;

  /** IAM Secret Access Key */
  secretAccessKey: string;

  /** Default FROM address used by sendEmail() */
  defaultSender: string;
}
```

### `ISesModuleAsyncOptions`

```typescript
interface ISesModuleAsyncOptions {
  /** Register the module globally (mirrors ConfigModule isGlobal) */
  isGlobal?: boolean;

  /** NestJS modules to import before the factory runs */
  imports?: any[];

  /** Providers to inject into useFactory */
  inject?: any[];

  /** Factory function that returns ISesModuleOptions */
  useFactory: (...args: any[]) => ISesModuleOptions | Promise<ISesModuleOptions>;
}
```

---

## Exports

| Symbol | Description |
|--------|-------------|
| `SesModule` | Dynamic NestJS module (`forRoot` / `forRootAsync`) |
| `AwsSesService` | Injectable email service |
| `SES_MODULE_OPTIONS` | Injection token for options object |
| `ISesModuleOptions` | TypeScript interface for module options |
| `ISesModuleAsyncOptions` | TypeScript interface for async options |

---

## License

MIT