Beautiful email SDK for AWS SES
npm install @wraps.dev/emailBeautiful email SDK for AWS SES with React.email support.
- Resend-like developer experience but calls your SES directly (BYOC model)
- Full TypeScript support with comprehensive types
- React.email integration for beautiful templates
- Automatic AWS credential chain resolution
- Template management (create, update, delete, list)
- Bulk email sending (up to 50 recipients)
- Zero vendor lock-in - just a thin wrapper around AWS SES
- Dual CJS + ESM builds - works with any bundler or Node.js
``bash`
pnpm add @wraps.dev/email
`typescript
import { WrapsEmail } from '@wraps.dev/email';
const email = new WrapsEmail({ region: 'us-east-1' });
await email.send({
from: 'you@company.com',
to: 'user@example.com',
subject: 'Welcome!',
html: '
Module Format Support
This package supports both CommonJS and ES Modules:
ESM (modern):
`typescript
import { WrapsEmail } from '@wraps.dev/email';
`CommonJS (Node.js):
`javascript
const { WrapsEmail } = require('@wraps.dev/email');
`Authentication
Wraps Email uses the AWS credential chain in the following order:
1. Explicit credentials passed to constructor
2. Environment variables (
AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY)
3. Shared credentials file (~/.aws/credentials)
4. IAM role (EC2, ECS, Lambda)$3
`typescript
const email = new WrapsEmail({
credentials: {
accessKeyId: process.env.AWS_ACCESS_KEY_ID,
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
sessionToken: process.env.AWS_SESSION_TOKEN, // optional
},
region: 'us-west-2',
});
`$3
`bash
export AWS_ACCESS_KEY_ID=your_access_key
export AWS_SECRET_ACCESS_KEY=your_secret_key
export AWS_REGION=us-east-1
``typescript
const email = new WrapsEmail(); // Credentials auto-detected
`Usage Examples
$3
`typescript
const result = await email.send({
from: 'you@company.com',
to: 'user@example.com',
subject: 'Welcome!',
html: 'Hello World
',
text: 'Hello World', // optional
});console.log('Message ID:', result.messageId);
`$3
`typescript
await email.send({
from: 'you@company.com',
to: ['user1@example.com', 'user2@example.com'],
cc: ['manager@company.com'],
bcc: ['archive@company.com'],
subject: 'Team Update',
html: 'Important announcement
',
});
`$3
`typescript
import { EmailTemplate } from './emails/Welcome';await email.send({
from: 'you@company.com',
to: 'user@example.com',
subject: 'Welcome to our platform',
react: ,
});
`$3
Send emails with file attachments (PDFs, images, documents, etc.). The SDK automatically handles MIME encoding and uses AWS SES SendRawEmail under the hood.
`typescript
// Single attachment
const result = await email.send({
from: 'you@company.com',
to: 'user@example.com',
subject: 'Your invoice',
html: 'Please find your invoice attached.
',
attachments: [
{
filename: 'invoice.pdf',
content: Buffer.from('...'), // Buffer or base64 string
contentType: 'application/pdf', // Optional - auto-detected from filename
},
],
});// Multiple attachments
await email.send({
from: 'you@company.com',
to: 'user@example.com',
subject: 'Monthly Report',
html: '
Monthly Report
Reports attached
',
attachments: [
{
filename: 'report.pdf',
content: pdfBuffer,
contentType: 'application/pdf',
},
{
filename: 'chart.png',
content: imageBuffer,
contentType: 'image/png',
},
{
filename: 'data.csv',
content: csvBuffer,
contentType: 'text/csv',
},
],
});// Attachment with base64 string
await email.send({
from: 'you@company.com',
to: 'user@example.com',
subject: 'Document',
html: '
Document attached
',
attachments: [
{
filename: 'document.pdf',
content: 'JVBERi0xLjQKJeLjz9MK...', // base64 string
contentType: 'application/pdf',
},
],
});
`Supported attachment features:
- Automatic MIME type detection from file extension
- Base64 encoding handled automatically
- Up to 100 attachments per email
- Maximum message size: 10 MB (AWS SES limit)
- Works with both HTML and plain text emails
- Compatible with React.email components
$3
`typescript
await email.send({
from: 'you@company.com',
to: 'user@example.com',
subject: 'Newsletter',
html: 'Content
',
tags: {
campaign: 'newsletter-2025-01',
type: 'marketing',
},
});
`Template Management
SES templates allow you to store reusable email designs with variables in your AWS account.
$3
`typescript
await email.templates.create({
name: 'welcome-email',
subject: 'Welcome to {{companyName}}, {{name}}!',
html: Click to confirm: Confirm Account
,
text: 'Welcome {{name}}! Click to confirm: {{confirmUrl}}',
});
`$3
`typescript
await email.templates.createFromReact({
name: 'welcome-email-v2',
subject: 'Welcome to {{companyName}}, {{name}}!',
react: ,
// React component should use {{variable}} syntax for SES placeholders
});
`$3
`typescript
const result = await email.sendTemplate({
from: 'you@company.com',
to: 'user@example.com',
template: 'welcome-email',
templateData: {
name: 'John',
companyName: 'Acme Corp',
confirmUrl: 'https://app.com/confirm/abc123',
},
});
`$3
`typescript
const results = await email.sendBulkTemplate({
from: 'you@company.com',
template: 'weekly-digest',
destinations: [
{
to: 'user1@example.com',
templateData: { name: 'Alice', unreadCount: 5 },
},
{
to: 'user2@example.com',
templateData: { name: 'Bob', unreadCount: 12 },
},
],
});
`$3
`typescript
await email.templates.update({
name: 'welcome-email',
subject: 'Welcome aboard, {{name}}!',
html: 'Welcome {{name}}!
...',
});
`$3
`typescript
const template = await email.templates.get('welcome-email');
console.log(template.name, template.subject);
`$3
`typescript
const templates = await email.templates.list();
templates.forEach(t => console.log(t.name, t.createdTimestamp));
`$3
`typescript
await email.templates.delete('welcome-email');
`Error Handling
`typescript
import { WrapsEmailError, ValidationError, SESError } from '@wraps.dev/email';try {
await email.send({ ... });
} catch (error) {
if (error instanceof ValidationError) {
// Invalid email address, missing required fields, etc.
console.error('Validation error:', error.message);
console.error('Field:', error.field);
} else if (error instanceof SESError) {
// AWS SES error (rate limit, unverified sender, etc.)
console.error('SES error:', error.message);
console.error('Code:', error.code); // 'MessageRejected', 'Throttling', etc.
console.error('Request ID:', error.requestId);
console.error('Retryable:', error.retryable);
} else {
// Other errors (network, auth, etc.)
console.error('Unknown error:', error);
}
}
`Configuration Options
`typescript
interface WrapsEmailConfig {
region?: string; // AWS region (defaults to us-east-1)
credentials?: {
accessKeyId: string;
secretAccessKey: string;
sessionToken?: string;
};
endpoint?: string; // Custom SES endpoint (for testing with LocalStack)
}
`Testing with LocalStack
`typescript
const email = new WrapsEmail({
region: 'us-east-1',
endpoint: 'http://localhost:4566',
});
`API Reference
$3
Main client class for sending emails via AWS SES.
#### Methods
-
send(params: SendEmailParams): Promise - Send an email
- sendTemplate(params: SendTemplateParams): Promise - Send using SES template
- sendBulkTemplate(params: SendBulkTemplateParams): Promise - Bulk send with template
- templates.create(params: CreateTemplateParams): Promise - Create SES template
- templates.createFromReact(params: CreateTemplateFromReactParams): Promise - Create template from React
- templates.update(params: UpdateTemplateParams): Promise - Update template
- templates.get(name: string): Promise - Get template details
- templates.list(): Promise - List all templates
- templates.delete(name: string): Promise - Delete template
- destroy(): void` - Close SES client and clean up resources- Node.js 20+ (LTS)
- AWS SES configured in your AWS account
- Verified sender email addresses in SES
MIT