Skip to main content
The @wraps.dev/cdk package provides a WrapsEmail CDK construct that deploys SES infrastructure — IAM roles, configuration sets, event pipelines, and DNS records — directly into your CDK stack. Use it when you manage your AWS infrastructure as code with CDK.
If you prefer to deploy infrastructure with a single command rather than managing it in code, use the CLI instead. Both approaches deploy identical resources.

Installation

npm install @wraps.dev/cdk
The package has peer dependencies on aws-cdk-lib and constructs, which your CDK project already provides:
npm install aws-cdk-lib constructs

Prerequisites

  • Node.js 20+
  • AWS CDK 2.x installed and bootstrapped in your account
  • AWS credentials configured

Quick start

Add WrapsEmail to any CDK stack. At minimum, provide an OIDC configuration so the SDK can authenticate with your infrastructure.
import * as cdk from 'aws-cdk-lib';
import { WrapsEmail } from '@wraps.dev/cdk';

const app = new cdk.App();
const stack = new cdk.Stack(app, 'EmailStack');

// Minimal: Vercel OIDC
const email = new WrapsEmail(stack, 'Email', {
  vercel: {
    teamSlug: 'my-team',
    projectName: 'my-app',
  },
});

// CloudFormation outputs are created automatically:
// WrapsEmailRoleArn, WrapsEmailConfigSetName, etc.
Deploy with:
cdk deploy

Configuration options

Authentication

vercel
VercelOIDCConfig
Vercel OIDC configuration. Mutually exclusive with oidc.
oidc
OIDCConfig
Custom OIDC provider configuration for GitHub Actions, GitLab CI, or other OIDC-compatible platforms. Mutually exclusive with vercel.

Domain

domain
string
Primary sending domain. Creates an SES domain identity with DKIM. DKIM CNAME records are output for manual DNS configuration, or automatically created if you provide hostedZoneId.
hostedZoneId
string
Route53 hosted zone ID for your domain. When provided, the construct automatically creates DKIM, SPF, DMARC, and MAIL FROM DNS records. If omitted, DNS records are printed as CloudFormation outputs.
mailFromSubdomain
string
default:"mail"
Subdomain for the MAIL FROM domain. Combined with domain — e.g. mail + example.commail.example.com. Improves deliverability.

Open/click tracking

tracking
TrackingConfig
Open and click tracking configuration.

Event tracking

events
EventsConfig
Enables the event pipeline: EventBridge → SQS → Lambda → DynamoDB. When set, email send, delivery, bounce, and complaint events are captured and optionally stored.

Email settings

reputationMetrics
boolean
default:"true"
Enable SES reputation metrics in CloudWatch.
tlsRequired
boolean
default:"false"
Require TLS for all outbound connections.
sendingEnabled
boolean
default:"true"
Enable sending on the SES configuration set.
dedicatedIp
boolean
default:"false"
Provision a dedicated sending IP address. Adds approximately $25/month to AWS costs.
suppressionList
SuppressionListConfig
Bounce and complaint suppression.

SMTP

smtp
SMTPConfig
Create an IAM user with SMTP credentials for legacy systems (WordPress, PHP mailers, etc.).

Archiving

archiving
ArchivingConfig
Archive full email content via AWS Mail Manager for compliance or debugging.

Infrastructure

removalPolicy
cdk.RemovalPolicy
default:"cdk.RemovalPolicy.RETAIN"
Removal policy for stateful resources such as the DynamoDB history table. Defaults to RETAIN so infrastructure persists when the stack is deleted.
webhook
WebhookConfig
Forward events to the Wraps hosted dashboard via EventBridge API Destination. Only required if you use the Wraps platform.

Outputs

The construct automatically creates CloudFormation outputs for the most commonly referenced values (WrapsEmailRoleArn, WrapsEmailConfigSetName, etc.) that you can read in your CDK app or retrieve with the AWS CLI after deploying. Access the underlying CDK resource objects directly via .resources:
PropertyTypeDescription
resources.roleiam.IRoleIAM role for SDK authentication
resources.configSetses.IConfigurationSetSES configuration set
resources.emailIdentityses.IEmailIdentity | undefinedSES email identity (if domain configured)
resources.oidcProvideriam.IOpenIdConnectProvider | undefinedOIDC provider (if OIDC configured)
resources.tabledynamodb.ITable | undefinedDynamoDB history table (if events enabled)
resources.queuesqs.IQueue | undefinedSQS event queue (if events configured)
resources.dlqsqs.IQueue | undefinedSQS dead-letter queue (if events configured)
resources.eventProcessorlambda.IFunction | undefinedEvent processor Lambda (if history enabled)
resources.eventRuleevents.IRule | undefinedEventBridge rule (if events configured)
resources.smtpUseriam.IUser | undefinedSMTP IAM user (if SMTP enabled)
resources.smtpAccessKeyiam.AccessKey | undefinedSMTP access key (if SMTP enabled)

Grant methods

The construct provides CDK-style grant methods that return iam.Grant for chaining.
import * as lambda from 'aws-cdk-lib/aws-lambda';

const email = new WrapsEmail(stack, 'Email', { /* ... */ });

const myFunction = new lambda.Function(stack, 'MyFunction', { /* ... */ });

// Grant SES send permissions scoped to this configuration set
email.grantSend(myFunction);

// Grant read access to the email history DynamoDB table
email.grantReadHistory(myFunction);

// Grant permission to consume events from the SQS queue
email.grantConsumeEvents(myFunction);
grantReadHistory() and grantConsumeEvents() throw if called when events is not configured.

Accessing underlying resources

All CDK constructs are accessible via .resources for advanced customization such as adding tags, modifying removal policies, or wiring additional IAM grants:
const email = new WrapsEmail(stack, 'Email', { /* ... */ });

// Always present
email.resources.role;       // iam.IRole
email.resources.configSet;  // ses.IConfigurationSet

// Present when domain is configured
email.resources.emailIdentity; // ses.IEmailIdentity

// Present when events are configured
email.resources.table;          // dynamodb.ITable
email.resources.queue;          // sqs.IQueue
email.resources.dlq;            // sqs.IQueue
email.resources.eventProcessor; // lambda.IFunction
email.resources.eventRule;      // events.IRule

// Present when OIDC is configured
email.resources.oidcProvider; // iam.IOpenIdConnectProvider

// Present when SMTP is enabled
email.resources.smtpUser;      // iam.IUser
email.resources.smtpAccessKey; // iam.AccessKey

Full example stack

import * as cdk from 'aws-cdk-lib';
import * as lambda from 'aws-cdk-lib/aws-lambda';
import { WrapsEmail } from '@wraps.dev/cdk';

export class EmailStack extends cdk.Stack {
  constructor(scope: cdk.App, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    const email = new WrapsEmail(this, 'Email', {
      // Vercel OIDC authentication
      vercel: {
        teamSlug: 'my-team',
        projectName: 'my-app',
      },

      // Domain with automatic Route53 DNS
      domain: 'example.com',
      hostedZoneId: 'Z1234567890ABCDEF',
      mailFromSubdomain: 'mail',

      // Event tracking with 90-day history
      events: {
        types: ['SEND', 'DELIVERY', 'BOUNCE', 'COMPLAINT', 'OPEN', 'CLICK'],
        storeHistory: true,
        retention: '90days',
      },

      // Keep history table if stack is deleted
      removalPolicy: cdk.RemovalPolicy.RETAIN,
    });

    // Grant a Lambda function permission to send email
    const sender = new lambda.Function(this, 'Sender', {
      runtime: lambda.Runtime.NODEJS_22_X,
      handler: 'index.handler',
      code: lambda.Code.fromInline('exports.handler = () => {}'),
      environment: {
        WRAPS_ROLE_ARN: email.roleArn,
        WRAPS_REGION: this.region,
      },
    });

    email.grantSend(sender);
  }
}

Build docs developers (and LLMs) love