Wraps Logo
DocsHome
Pulumi Reference

@wraps.dev/pulumi

Pulumi component for deploying Wraps email infrastructure to your AWS account. Zero credentials stored, full AWS ownership, SST-style API with transform functions.

Installation

npm install @wraps.dev/pulumi

Requirements: Node.js 20+, Pulumi 3.x, @pulumi/aws 6.x or 7.x

Quick Start

TypeScriptindex.ts
import { WrapsEmail } from "@wraps.dev/pulumi";// Minimal setup with Vercel OIDCconst email = new WrapsEmail("email", {  vercel: {    teamSlug: "my-team",    projectName: "my-app",  },});// Export the role ARN for your Vercel environmentexport const roleArn = email.roleArn;export const configSetName = email.configSetName;export const envVars = email.envVars;

With Domain and Event Tracking

TypeScriptwith-domain.ts
const email = new WrapsEmail("email", {  vercel: {    teamSlug: "my-team",    projectName: "my-app",  },  domain: "example.com",  events: {    types: ["SEND", "DELIVERY", "BOUNCE", "COMPLAINT", "OPEN", "CLICK"],    storeHistory: true,    retention: "90days",  },});// Export DKIM tokens for DNS configurationexport const dkimTokens = email.dkimTokens;

Full Configuration

TypeScriptfull-config.ts
const email = new WrapsEmail("email", {  // Authentication (choose one)  vercel: {    teamSlug: "my-team",    projectName: "my-app",  },  // Or custom OIDC:  // oidc: {  //   providerUrl: "https://token.actions.githubusercontent.com",  //   audience: "sts.amazonaws.com",  //   subjectPattern: "repo:my-org/my-repo:*",  // },  // Domain configuration  domain: "example.com",  mailFromSubdomain: "mail", // Creates mail.example.com  // DNS provider (auto-creates DNS records)  dns: {    provider: "route53",    hostedZoneId: "Z1234567890",  },  // Or Cloudflare:  // dns: { provider: "cloudflare", zoneId: "abc123", apiToken: pulumi.secret("token") },  // Event tracking  events: {    types: ["SEND", "DELIVERY", "BOUNCE", "COMPLAINT", "OPEN", "CLICK"],    storeHistory: true,    retention: "90days", // "7days" | "30days" | "90days" | "6months" | "1year" | "unlimited"  },  // Email settings  reputationMetrics: true,  tlsRequired: false,  sendingEnabled: true,  // Suppression list  suppressionList: {    enabled: true,    reasons: ["BOUNCE", "COMPLAINT"],  },  // SMTP credentials (for legacy systems)  smtp: {    enabled: false,  },  // Resource tags  tags: {    Environment: "production",  },  // Transform underlying resources  transform: {    table: (args) => ({      ...args,      billingMode: "PROVISIONED",    }),  },});

Constructor Args

PropertyTypeDescription
vercelVercelOIDCConfigVercel OIDC configuration (teamSlug, projectName)
oidcOIDCConfigCustom OIDC provider (GitHub Actions, GitLab, etc.)
domainstringPrimary sending domain with DKIM
dnsDNSConfigDNS provider for automatic record creation
mailFromSubdomainstringMAIL FROM subdomain (default: "mail")
eventsEventsConfigEvent tracking and history storage
smtpSMTPConfigSMTP credentials for legacy systems
reputationMetricsbooleanEnable SES reputation metrics (default: true)
tagsRecord<string, string>Tags to apply to all resources
transformTransformFunctionsTransform functions for resource customization

Outputs

PropertyTypeDescription
roleArnOutput<string>IAM role ARN for SDK authentication
regionOutput<string>AWS region
configSetNameOutput<string>SES configuration set name
dkimTokensOutput<string[]>DKIM tokens for DNS configuration
tableNameOutput<string>DynamoDB table name (if history enabled)
queueUrlOutput<string>SQS queue URL (if events enabled)
smtpUsernameOutput<string>SMTP username (if SMTP enabled)
smtpPasswordOutput<string>SMTP password (if SMTP enabled)
envVarsOutput<object>Environment variables for your app

Transform Functions

Transform functions let you customize underlying Pulumi resources before creation. Each function receives the default resource args and returns modified args.

TypeScripttransform.ts
const email = new WrapsEmail("email", {  vercel: { teamSlug: "my-team", projectName: "my-app" },  domain: "example.com",  events: { types: ["SEND"], storeHistory: true },  // Transform underlying Pulumi resources before creation  transform: {    // Customize IAM role    role: (args) => ({      ...args,      maxSessionDuration: 7200, // 2 hours    }),    // Customize DynamoDB table    table: (args) => ({      ...args,      billingMode: "PROVISIONED",      readCapacity: 5,      writeCapacity: 5,    }),    // Customize SQS queue    queue: (args) => ({      ...args,      visibilityTimeoutSeconds: 120,    }),    // Customize Lambda function    lambda: (args) => ({      ...args,      memorySize: 1024,      timeout: 60,    }),    // Customize CloudFront distribution    distribution: (args) => ({      ...args,      priceClass: "PriceClass_100", // US/Europe only    }),  },});

Available Transform Functions

FunctionResource TypeWhen Available
roleaws.iam.RoleArgsAlways
oidcProvideraws.iam.OpenIdConnectProviderArgsIf OIDC configured
configSetaws.ses.ConfigurationSetArgsAlways
tableaws.dynamodb.TableArgsIf events.storeHistory
queueaws.sqs.QueueArgsIf events configured
lambdaaws.lambda.FunctionArgsIf events.storeHistory
distributionaws.cloudfront.DistributionArgsIf HTTPS tracking

Accessing Underlying Resources

Access the underlying Pulumi resources via the .nodes property for advanced customization.

TypeScriptnodes.ts
const email = new WrapsEmail("email", { /* ... */ });// Access raw Pulumi resources via .nodesemail.nodes.role;           // aws.iam.Roleemail.nodes.configSet;      // aws.ses.ConfigurationSetemail.nodes.domainIdentity; // aws.ses.DomainIdentity (if domain)email.nodes.domainDkim;     // aws.ses.DomainDkim (if domain)email.nodes.table;          // aws.dynamodb.Table (if events.storeHistory)email.nodes.queue;          // aws.sqs.Queue (if events)email.nodes.dlq;            // aws.sqs.Queue (if events)email.nodes.lambda;         // aws.lambda.Function (if events.storeHistory)email.nodes.eventRule;      // aws.cloudwatch.EventRule (if events)email.nodes.oidcProvider;   // aws.iam.OpenIdConnectProvider (if OIDC)email.nodes.distribution;   // aws.cloudfront.Distribution (if HTTPS tracking)// Example: Add custom policy to roleconst customPolicy = new aws.iam.RolePolicy("custom", {  role: email.nodes.role.name,  policy: JSON.stringify({    Version: "2012-10-17",    Statement: [{      Action: ["ses:ListIdentities"],      Effect: "Allow",      Resource: "*",    }],  }),});

Available Nodes

PropertyTypeWhen Available
roleaws.iam.RoleAlways
oidcProvideraws.iam.OpenIdConnectProviderIf OIDC configured
configSetaws.ses.ConfigurationSetAlways
domainIdentityaws.ses.DomainIdentityIf domain configured
tableaws.dynamodb.TableIf events.storeHistory
queueaws.sqs.QueueIf events configured
lambdaaws.lambda.FunctionIf events.storeHistory
distributionaws.cloudfront.DistributionIf HTTPS tracking

DNS Providers

Automatically create DNS records with your preferred provider.

TypeScriptdns-providers.ts
// Route53 (automatic DNS records)const emailRoute53 = new WrapsEmail("email", {  domain: "example.com",  dns: {    provider: "route53",    hostedZoneId: "Z1234567890",  },});// Cloudflareconst emailCloudflare = new WrapsEmail("email", {  domain: "example.com",  dns: {    provider: "cloudflare",    zoneId: "abc123def456",    apiToken: pulumi.secret(process.env.CLOUDFLARE_API_TOKEN!),  },});// Vercel DNSconst emailVercel = new WrapsEmail("email", {  domain: "example.com",  dns: {    provider: "vercel",    apiToken: pulumi.secret(process.env.VERCEL_TOKEN!),    teamId: "team_xxx",  },});

GitHub Actions OIDC

Use custom OIDC configuration for GitHub Actions or other providers.

TypeScriptgithub-actions.ts
const email = new WrapsEmail("email", {  oidc: {    providerUrl: "https://token.actions.githubusercontent.com",    audience: "sts.amazonaws.com",    subjectPattern: "repo:my-org/my-repo:*",  },  domain: "example.com",});

Environment Variables Output

Convenience output for environment variables to configure your application.

TypeScriptenv-vars.ts
const email = new WrapsEmail("email", { /* ... */ });// Convenience output for environment variablesexport const envVars = email.envVars;// Returns:// {//   WRAPS_AWS_ROLE_ARN: "arn:aws:iam::123456789:role/wraps-email-role",//   WRAPS_AWS_REGION: "us-east-1",//   WRAPS_CONFIG_SET: "wraps-email-tracking",// }

Using with @wraps.dev/email SDK

After deploying, use the @wraps.dev/email SDK to send emails:

TypeScriptsend-email.ts
import { WrapsEmail } from "@wraps.dev/email";const email = new WrapsEmail();await email.send({  from: "hello@example.com",  to: "user@example.com",  subject: "Hello from Wraps!",  html: "<h1>Welcome!</h1>",});

Next Steps

View on npm

Check out the package on npm for the latest version and changelog.

View Package
Email SDK

Learn how to send emails with the @wraps.dev/email SDK.

SDK Reference
Pulumi Docs

Learn more about Pulumi and infrastructure as code.

Pulumi Docs