{"version":3,"sources":["../src/errors.ts","../src/react.ts","../src/utils/html-to-text.ts","../src/utils/headers.ts","../src/utils/validation.ts","../src/batch.ts","../src/events.ts","../src/utils/html-escape.ts","../src/utils/mime.ts","../src/inbox.ts","../src/reply-token-codec.ts","../src/reply-threading.ts","../src/suppression.ts","../src/utils/credentials.ts","../src/client.ts"],"names":["email","zEmail","rawMessageData","command","SendRawEmailCommand"],"mappings":"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","file":"index.mjs","sourcesContent":["export class WrapsEmailError extends Error {\n  constructor(message: string) {\n    super(message);\n    this.name = 'WrapsEmailError';\n  }\n}\n\nexport class ValidationError extends WrapsEmailError {\n  public readonly field?: string;\n\n  constructor(message: string, field?: string) {\n    super(message);\n    this.name = 'ValidationError';\n    this.field = field;\n  }\n}\n\nexport class SESError extends WrapsEmailError {\n  public readonly code: string;\n  public readonly requestId: string;\n  public readonly retryable: boolean;\n\n  constructor(message: string, code: string, requestId: string, retryable: boolean) {\n    super(message);\n    this.name = 'SESError';\n    this.code = code;\n    this.requestId = requestId;\n    this.retryable = retryable;\n  }\n}\n\nexport class DynamoDBError extends WrapsEmailError {\n  public readonly code: string;\n  public readonly requestId: string;\n  public readonly retryable: boolean;\n\n  constructor(message: string, code: string, requestId: string, retryable: boolean) {\n    super(message);\n    this.name = 'DynamoDBError';\n    this.code = code;\n    this.requestId = requestId;\n    this.retryable = retryable;\n  }\n}\n\nexport class BatchError extends WrapsEmailError {\n  public readonly results: import('./types').BatchEntryResult[];\n  public readonly successCount: number;\n  public readonly failureCount: number;\n\n  constructor(\n    message: string,\n    results: import('./types').BatchEntryResult[],\n    successCount: number,\n    failureCount: number\n  ) {\n    super(message);\n    this.name = 'BatchError';\n    this.results = results;\n    this.successCount = successCount;\n    this.failureCount = failureCount;\n  }\n}\n\n/**\n * Map an AWS SDK v3 client error into a {@link SESError}. AWS SDK errors carry\n * `$metadata` (with `requestId`) and an optional `$retryable.throttling` flag.\n * Non-AWS errors are returned unchanged.\n *\n * @param error - The caught error from an AWS SDK `.send()` call.\n * @param fallbackMessage - Message used when the error has no `.message`.\n * @returns A `SESError` when the error looks like an AWS SDK error, else the\n *   original error.\n */\nexport function mapAwsSdkError(error: unknown, fallbackMessage = 'SES request failed'): Error {\n  const err = error as {\n    $metadata?: { requestId?: string };\n    $retryable?: { throttling?: boolean };\n    message?: string;\n    name?: string;\n  };\n  if (err.$metadata) {\n    return new SESError(\n      err.message || fallbackMessage,\n      err.name || 'Unknown',\n      err.$metadata.requestId || 'unknown',\n      err.$retryable?.throttling || false\n    );\n  }\n  return error as Error;\n}\n","import type React from 'react';\n\n/**\n * Render React.email component to HTML string\n */\nexport async function renderReactEmail(\n  component: React.ReactElement\n): Promise<{ html: string; text: string }> {\n  try {\n    // Dynamically import @react-email/components to make it optional\n    const { render } = await import('@react-email/components');\n\n    // Render to HTML\n    const html = await render(component, {\n      pretty: false, // Minified for email\n    });\n\n    // Render to plain text (react-email provides this)\n    const text = await render(component, {\n      plainText: true,\n    });\n\n    return { html, text };\n  } catch (error: unknown) {\n    const err = error as { code?: string; message?: string };\n    if (err.code === 'MODULE_NOT_FOUND') {\n      throw new Error(\n        'React Email not installed. Install @react-email/components to use React templates.'\n      );\n    }\n    throw new Error(`Failed to render React email component: ${err.message || 'Unknown error'}`);\n  }\n}\n","/**\n * Convert HTML to plain text for email fallback.\n *\n * Handles common email HTML patterns: block elements, line breaks,\n * lists, links, and HTML entities. No external dependencies.\n */\nexport function htmlToPlainText(html: string): string {\n  let text = html;\n\n  // Replace <br> variants with newlines\n  text = text.replace(/<br\\s*\\/?>/gi, '\\n');\n\n  // Replace <hr> with a separator\n  text = text.replace(/<hr\\s*\\/?>/gi, '\\n---\\n');\n\n  // Extract href from links: <a href=\"url\">text</a> → text (url)\n  text = text.replace(/<a[^>]+href=\"([^\"]*)\"[^>]*>([\\s\\S]*?)<\\/a>/gi, (_, href, linkText) => {\n    const cleaned = linkText.replace(/<[^>]+>/g, '').trim();\n    if (!cleaned || cleaned === href) return href;\n    return `${cleaned} (${href})`;\n  });\n\n  // Add newlines before block-level elements\n  text = text.replace(\n    /<\\/(p|div|h[1-6]|tr|blockquote|section|article|header|footer|main|aside|nav)>/gi,\n    '\\n\\n'\n  );\n  text = text.replace(\n    /<(p|div|h[1-6]|tr|blockquote|section|article|header|footer|main|aside|nav)[\\s>]/gi,\n    '\\n'\n  );\n\n  // Handle list items\n  text = text.replace(/<li(?:\\s[^>]*)?>/gi, '\\n- ');\n  text = text.replace(/<\\/li>/gi, '');\n\n  // Handle table cells with spacing\n  text = text.replace(/<\\/td>/gi, '\\t');\n  text = text.replace(/<\\/th>/gi, '\\t');\n\n  // Strip remaining HTML tags\n  text = text.replace(/<[^>]+>/g, '');\n\n  // Decode HTML entities\n  text = text\n    .replace(/&nbsp;/gi, ' ')\n    .replace(/&amp;/gi, '&')\n    .replace(/&lt;/gi, '<')\n    .replace(/&gt;/gi, '>')\n    .replace(/&quot;/gi, '\"')\n    .replace(/&#39;/gi, \"'\")\n    .replace(/&apos;/gi, \"'\")\n    .replace(/&#(\\d+);/g, (match, code) => {\n      const cp = Number.parseInt(code, 10);\n      return cp <= 0x10ffff ? String.fromCodePoint(cp) : match;\n    })\n    .replace(/&#x([0-9a-f]+);/gi, (match, hex) => {\n      const cp = Number.parseInt(hex, 16);\n      return cp <= 0x10ffff ? String.fromCodePoint(cp) : match;\n    });\n\n  // Collapse runs of whitespace (but preserve newlines)\n  text = text.replace(/[^\\S\\n]+/g, ' ');\n\n  // Collapse 3+ consecutive newlines into 2\n  text = text.replace(/\\n{3,}/g, '\\n\\n');\n\n  // Trim each line\n  text = text\n    .split('\\n')\n    .map((line) => line.trim())\n    .join('\\n');\n\n  return text.trim();\n}\n","import { ValidationError } from '../errors';\n\n/**\n * Reject a value destined for a MIME header line if it contains CR or LF.\n * Embedded newlines are the email-header-injection vector.\n */\nexport function assertNoHeaderInjection(value: string, field: string): void {\n  if (/[\\r\\n]/.test(value)) {\n    throw new ValidationError(`Illegal newline in header field: ${field}`, field);\n  }\n}\n\n/** Same check, returns the value for inline use. */\nexport function sanitizeHeaderValue(value: string, field: string): string {\n  assertNoHeaderInjection(value, field);\n  return value;\n}\n","import { safeParse, email as zEmail } from 'zod/mini';\nimport { ValidationError } from '../errors';\nimport type { EmailAddress, SendEmailParams } from '../types';\nimport { assertNoHeaderInjection } from './headers';\n\n/**\n * Normalize email address to string format\n */\nexport function normalizeEmailAddress(address: string | EmailAddress): string {\n  if (typeof address === 'string') {\n    return address;\n  }\n\n  if (address.name) {\n    return `\"${address.name}\" <${address.email}>`;\n  }\n\n  return address.email;\n}\n\n/**\n * Normalize array of email addresses to string array\n */\nexport function normalizeEmailAddresses(\n  addresses: string | string[] | EmailAddress | EmailAddress[] | (string | EmailAddress)[]\n): string[] {\n  const addressArray = Array.isArray(addresses) ? addresses : [addresses];\n  return addressArray.map(normalizeEmailAddress);\n}\n\n/**\n * Validate email parameters\n */\nexport function validateEmailParams(params: SendEmailParams): void {\n  // Validate required fields\n  if (!params.from) {\n    throw new ValidationError('Missing required field: from', 'from');\n  }\n\n  if (!params.to) {\n    throw new ValidationError('Missing required field: to', 'to');\n  }\n\n  if (!params.subject) {\n    throw new ValidationError('Missing required field: subject', 'subject');\n  }\n\n  // Validate that either html or react is provided (but not both)\n  if (!params.html && !params.react && !params.text) {\n    throw new ValidationError('Must provide at least one of: html, text, or react', 'html');\n  }\n\n  if (params.html && params.react) {\n    throw new ValidationError('Cannot provide both \"html\" and \"react\" parameters', 'html');\n  }\n\n  // Validate email addresses (basic validation)\n  validateEmailAddress(params.from, 'from');\n\n  const toAddresses = Array.isArray(params.to) ? params.to : [params.to];\n  for (const [idx, addr] of toAddresses.entries()) {\n    validateEmailAddress(addr, `to[${idx}]`);\n  }\n\n  if (params.cc) {\n    const ccAddresses = Array.isArray(params.cc) ? params.cc : [params.cc];\n    for (const [idx, addr] of ccAddresses.entries()) {\n      validateEmailAddress(addr, `cc[${idx}]`);\n    }\n  }\n\n  if (params.bcc) {\n    const bccAddresses = Array.isArray(params.bcc) ? params.bcc : [params.bcc];\n    for (const [idx, addr] of bccAddresses.entries()) {\n      validateEmailAddress(addr, `bcc[${idx}]`);\n    }\n  }\n\n  if (params.replyTo) {\n    const replyToAddresses = Array.isArray(params.replyTo) ? params.replyTo : [params.replyTo];\n    for (const [idx, addr] of replyToAddresses.entries()) {\n      validateEmailAddress(addr, `replyTo[${idx}]`);\n    }\n  }\n}\n\n/**\n * Extract email from RFC 5322 format strings like \"Name <email>\" or \"email\"\n */\nfunction extractEmail(address: string): string {\n  // Match email in angle brackets: \"Name <email>\" or just \"<email>\"\n  const angleMatch = address.match(/<([^>]+)>/);\n  if (angleMatch) {\n    return angleMatch[1].trim();\n  }\n\n  // No angle brackets - treat as plain email address\n  return address.trim();\n}\n\n/**\n * Basic email address validation using Zod\n * Zod's email validation is safer than custom regex patterns and avoids ReDoS vulnerabilities\n * Supports RFC 5322 format: \"Display Name <email@example.com>\" or plain \"email@example.com\"\n */\nfunction validateEmailAddress(address: string | EmailAddress, field: string): void {\n  // Reject CRLF in the full address string or in EmailAddress fields\n  if (typeof address === 'string') {\n    assertNoHeaderInjection(address, field);\n  } else {\n    assertNoHeaderInjection(address.email, field);\n    if (address.name) {\n      assertNoHeaderInjection(address.name, field);\n    }\n  }\n\n  // Extract email portion from string or EmailAddress object\n  const email = typeof address === 'string' ? extractEmail(address) : address.email;\n\n  if (!email) {\n    throw new ValidationError(`Invalid email address in field: ${field}`, field);\n  }\n\n  // Zod Mini email validator — tree-shakeable; avoids bundling all of zod at the\n  // edge. Behavior is identical to z.string().email() (verified). See plan 002.\n  const result = safeParse(zEmail(), email);\n\n  if (!result.success) {\n    throw new ValidationError(`Invalid email format in field: ${field} (${email})`, field);\n  }\n}\n","import { type SESv2Client, SendBulkEmailCommand } from '@aws-sdk/client-sesv2';\nimport { mapAwsSdkError, SESError, ValidationError } from './errors';\nimport { renderReactEmail } from './react';\nimport type { BatchEmailEntry, BatchEntryResult, SendBatchParams, SendBatchResult } from './types';\nimport { htmlToPlainText } from './utils/html-to-text';\nimport { normalizeEmailAddress, normalizeEmailAddresses } from './utils/validation';\n\nconst MAX_ENTRIES = 100;\nconst CHUNK_SIZE = 50;\n\ninterface ResolvedEntry {\n  to: string;\n  subject: string;\n  html: string;\n  text: string;\n  tags?: Record<string, string>;\n}\n\n/**\n * Pre-process entries: validate and render React components\n */\nasync function resolveEntries(entries: BatchEmailEntry[]): Promise<ResolvedEntry[]> {\n  const resolved: ResolvedEntry[] = [];\n\n  for (let i = 0; i < entries.length; i++) {\n    const entry = entries[i];\n\n    if (!entry.subject) {\n      throw new ValidationError(\n        `Entry ${i}: missing required field \"subject\"`,\n        `entries[${i}].subject`\n      );\n    }\n\n    if (!entry.to) {\n      throw new ValidationError(`Entry ${i}: missing required field \"to\"`, `entries[${i}].to`);\n    }\n\n    if (!entry.html && !entry.text && !entry.react) {\n      throw new ValidationError(\n        `Entry ${i}: must provide at least one of \"html\", \"text\", or \"react\"`,\n        `entries[${i}]`\n      );\n    }\n\n    if (entry.html && entry.react) {\n      throw new ValidationError(\n        `Entry ${i}: cannot provide both \"html\" and \"react\"`,\n        `entries[${i}]`\n      );\n    }\n\n    let html = entry.html || '';\n    let text = entry.text || '';\n\n    if (entry.react) {\n      const rendered = await renderReactEmail(entry.react);\n      html = rendered.html;\n      text = text || rendered.text;\n    }\n\n    // Auto-generate plain text from HTML when not explicitly provided\n    if (html && !text) {\n      text = htmlToPlainText(html);\n    }\n\n    resolved.push({\n      to: normalizeEmailAddress(entry.to),\n      subject: entry.subject,\n      html,\n      text,\n      tags: entry.tags,\n    });\n  }\n\n  return resolved;\n}\n\n/**\n * Send a chunk of up to 50 entries via SES v2 SendBulkEmailCommand\n */\nasync function sendChunk(\n  sesv2Client: SESv2Client,\n  params: SendBatchParams,\n  resolvedEntries: ResolvedEntry[],\n  startIndex: number\n): Promise<BatchEntryResult[]> {\n  const command = new SendBulkEmailCommand({\n    FromEmailAddress: normalizeEmailAddress(params.from),\n    ReplyToAddresses: params.replyTo ? normalizeEmailAddresses(params.replyTo) : undefined,\n    DefaultContent: {\n      Template: {\n        TemplateContent: {\n          Subject: '{{subject}}',\n          Html: '{{htmlContent}}',\n          Text: '{{textContent}}',\n        },\n        TemplateData: JSON.stringify({ subject: '', htmlContent: '', textContent: '' }),\n      },\n    },\n    BulkEmailEntries: resolvedEntries.map((entry) => ({\n      Destination: {\n        ToAddresses: [entry.to],\n      },\n      ReplacementEmailContent: {\n        ReplacementTemplate: {\n          ReplacementTemplateData: JSON.stringify({\n            subject: entry.subject,\n            htmlContent: entry.html,\n            textContent: entry.text,\n          }),\n        },\n      },\n      ReplacementTags: entry.tags\n        ? Object.entries(entry.tags).map(([Name, Value]) => ({ Name, Value }))\n        : undefined,\n    })),\n    DefaultEmailTags: params.tags\n      ? Object.entries(params.tags).map(([Name, Value]) => ({ Name, Value }))\n      : undefined,\n    ConfigurationSetName: params.configurationSetName,\n  });\n\n  try {\n    const response = await sesv2Client.send(command);\n\n    if (!response.BulkEmailEntryResults) {\n      throw new Error('Invalid response from SES: missing BulkEmailEntryResults');\n    }\n\n    return response.BulkEmailEntryResults.map((result, i) => {\n      const status = result.Status === 'SUCCESS' ? 'success' : 'failure';\n      return {\n        index: startIndex + i,\n        messageId: result.MessageId,\n        status,\n        error: result.Error,\n      } as BatchEntryResult;\n    });\n  } catch (error) {\n    throw handleSESv2Error(error);\n  }\n}\n\nfunction handleSESv2Error(error: unknown): Error {\n  return mapAwsSdkError(error);\n}\n\nfunction describeChunkError(error: unknown): string {\n  const mapped = mapAwsSdkError(error);\n  if (mapped instanceof SESError) {\n    return `${mapped.code}: ${mapped.message}${mapped.retryable ? ' (retryable)' : ''}`;\n  }\n  if (mapped instanceof Error) {\n    return mapped.message;\n  }\n  return 'Chunk-level SES error';\n}\n\n/**\n * Send batch emails with unique content per recipient.\n *\n * Uses SES v2 `SendBulkEmailCommand` with inline template content.\n * Each entry can have its own subject, html, and text.\n *\n * @param sesv2Client - SES v2 client instance\n * @param params - Batch send parameters\n * @returns Aggregated results for all entries\n */\nexport async function sendBatch(\n  sesv2Client: SESv2Client,\n  params: SendBatchParams\n): Promise<SendBatchResult> {\n  if (!params.entries || params.entries.length === 0) {\n    throw new ValidationError('entries array must not be empty', 'entries');\n  }\n\n  if (params.entries.length > MAX_ENTRIES) {\n    throw new ValidationError(\n      `Maximum ${MAX_ENTRIES} entries allowed per batch (got ${params.entries.length})`,\n      'entries'\n    );\n  }\n\n  const resolved = await resolveEntries(params.entries);\n\n  const chunkOffsets: number[] = [];\n  for (let offset = 0; offset < resolved.length; offset += CHUNK_SIZE) {\n    chunkOffsets.push(offset);\n  }\n\n  const chunkResultSets = await Promise.all(\n    chunkOffsets.map(async (offset) => {\n      const chunk = resolved.slice(offset, offset + CHUNK_SIZE);\n      try {\n        return await sendChunk(sesv2Client, params, chunk, offset);\n      } catch (error) {\n        const detail = describeChunkError(error);\n        return chunk.map((_, i) => ({\n          index: offset + i,\n          status: 'failure' as const,\n          error: detail,\n        }));\n      }\n    })\n  );\n\n  const allResults: BatchEntryResult[] = chunkResultSets.flat().sort((a, b) => a.index - b.index);\n\n  const successCount = allResults.filter((r) => r.status === 'success').length;\n  const failureCount = allResults.filter((r) => r.status === 'failure').length;\n\n  return {\n    results: allResults,\n    successCount,\n    failureCount,\n  };\n}\n","import type { DynamoDBDocumentClient } from '@aws-sdk/lib-dynamodb';\nimport { QueryCommand } from '@aws-sdk/lib-dynamodb';\nimport { DynamoDBError, ValidationError } from './errors';\nimport type { EmailEvent, EmailListOptions, EmailListResult, EmailStatus } from './types';\n\nconst EVENT_TYPE_MAP: Record<string, EmailStatus['status']> = {\n  send: 'sent',\n  delivery: 'delivered',\n  open: 'opened',\n  click: 'clicked',\n  bounce: 'bounced',\n  complaint: 'complained',\n  suppressed: 'suppressed',\n};\n\nconst STATUS_PRIORITY: Record<string, number> = {\n  sent: 3,\n  delivered: 4,\n  opened: 5,\n  clicked: 6,\n  suppressed: 7,\n  complained: 8,\n  bounced: 9,\n};\n\nfunction deriveStatus(events: EmailEvent[]): EmailStatus['status'] {\n  let highest: EmailStatus['status'] = 'sent';\n  let highestPriority = STATUS_PRIORITY.sent;\n\n  for (const event of events) {\n    const normalized = event.type.toLowerCase();\n    const mapped = EVENT_TYPE_MAP[normalized] || normalized;\n    const priority = STATUS_PRIORITY[mapped] || 0;\n    if (priority > highestPriority) {\n      highest = mapped as EmailStatus['status'];\n      highestPriority = priority;\n    }\n  }\n\n  return highest;\n}\n\nexport class WrapsEmailEvents {\n  constructor(\n    private client: DynamoDBDocumentClient,\n    private tableName: string\n  ) {}\n\n  /**\n   * Get all events for a single email by messageId\n   * Returns null if no events found\n   */\n  async get(messageId: string): Promise<EmailStatus | null> {\n    if (!messageId) {\n      throw new ValidationError('messageId is required', 'messageId');\n    }\n\n    try {\n      const response = await this.client.send(\n        new QueryCommand({\n          TableName: this.tableName,\n          KeyConditionExpression: 'messageId = :mid',\n          ExpressionAttributeValues: {\n            ':mid': messageId,\n          },\n          ScanIndexForward: true,\n        })\n      );\n\n      if (!response.Items || response.Items.length === 0) {\n        return null;\n      }\n\n      return this.aggregateStatus(response.Items);\n    } catch (error) {\n      throw this.handleDynamoDBError(error);\n    }\n  }\n\n  /**\n   * List emails with events, queried via the accountId-sentAt GSI\n   * Requires accountId for efficient querying\n   */\n  async list(options: EmailListOptions): Promise<EmailListResult> {\n    if (!options.accountId) {\n      throw new ValidationError('accountId is required for listing events', 'accountId');\n    }\n\n    const limit = options.maxResults || 50;\n\n    let keyCondition = 'accountId = :aid';\n    const expressionValues: Record<string, unknown> = {\n      ':aid': options.accountId,\n    };\n\n    if (options.startTime && options.endTime) {\n      keyCondition += ' AND sentAt BETWEEN :start AND :end';\n      expressionValues[':start'] = options.startTime.getTime();\n      expressionValues[':end'] = options.endTime.getTime();\n    } else if (options.startTime) {\n      keyCondition += ' AND sentAt >= :start';\n      expressionValues[':start'] = options.startTime.getTime();\n    } else if (options.endTime) {\n      keyCondition += ' AND sentAt <= :end';\n      expressionValues[':end'] = options.endTime.getTime();\n    }\n\n    let exclusiveStartKey: Record<string, unknown> | undefined;\n    if (options.continuationToken) {\n      try {\n        exclusiveStartKey = JSON.parse(\n          Buffer.from(options.continuationToken, 'base64').toString('utf-8')\n        );\n      } catch {\n        throw new ValidationError('Invalid continuation token', 'continuationToken');\n      }\n    }\n\n    try {\n      const response = await this.client.send(\n        new QueryCommand({\n          TableName: this.tableName,\n          IndexName: 'accountId-sentAt-index',\n          KeyConditionExpression: keyCondition,\n          ExpressionAttributeValues: expressionValues,\n          ScanIndexForward: false,\n          Limit: limit,\n          ExclusiveStartKey: exclusiveStartKey,\n        })\n      );\n\n      const items = response.Items || [];\n\n      // Group items by messageId\n      const grouped = new Map<string, Record<string, unknown>[]>();\n      for (const item of items) {\n        const mid = item.messageId as string;\n        const group = grouped.get(mid) ?? [];\n        group.push(item);\n        grouped.set(mid, group);\n      }\n\n      // Aggregate each group into an EmailStatus\n      const emails: EmailStatus[] = [];\n      for (const groupItems of grouped.values()) {\n        emails.push(this.aggregateStatus(groupItems));\n      }\n\n      let nextToken: string | undefined;\n      if (response.LastEvaluatedKey) {\n        nextToken = Buffer.from(JSON.stringify(response.LastEvaluatedKey)).toString('base64');\n      }\n\n      return { emails, nextToken };\n    } catch (error) {\n      throw this.handleDynamoDBError(error);\n    }\n  }\n\n  private aggregateStatus(items: Record<string, unknown>[]): EmailStatus {\n    const first = items[0];\n\n    const events: EmailEvent[] = items.map((item) => {\n      let metadata: Record<string, unknown> | undefined;\n      if (item.additionalData) {\n        try {\n          metadata = JSON.parse(item.additionalData as string);\n        } catch {\n          // If parsing fails, skip metadata\n        }\n      }\n\n      return {\n        type: (item.eventType as string).toLowerCase(),\n        timestamp: item.sentAt as number,\n        metadata,\n      };\n    });\n\n    // Sort events chronologically\n    events.sort((a, b) => a.timestamp - b.timestamp);\n\n    const to = Array.isArray(first.to) ? (first.to as string[]) : [first.to as string];\n\n    return {\n      messageId: first.messageId as string,\n      from: first.from as string,\n      to,\n      subject: (first.subject as string) || '',\n      status: deriveStatus(events),\n      sentAt: events[0].timestamp,\n      lastEventAt: events[events.length - 1].timestamp,\n      events,\n    };\n  }\n\n  private handleDynamoDBError(error: unknown): Error {\n    const err = error as {\n      $metadata?: { requestId?: string };\n      $retryable?: { throttling?: boolean };\n      message?: string;\n      name?: string;\n    };\n    if (err.$metadata) {\n      return new DynamoDBError(\n        err.message || 'DynamoDB request failed',\n        err.name || 'Unknown',\n        err.$metadata.requestId || 'unknown',\n        err.$retryable?.throttling || false\n      );\n    }\n    return error instanceof Error ? error : new Error(String(error));\n  }\n}\n","/**\n * Escape a string for safe interpolation into HTML text/attribute context.\n * Escapes the five characters that can break out of HTML: & < > \" '.\n *\n * @param value - Untrusted string (e.g. an inbound email subject or sender name).\n * @returns The HTML-escaped string.\n */\nexport function escapeHtml(value: string): string {\n  return value\n    .replace(/&/g, '&amp;')\n    .replace(/</g, '&lt;')\n    .replace(/>/g, '&gt;')\n    .replace(/\"/g, '&quot;')\n    .replace(/'/g, '&#39;');\n}\n","import type { Attachment, EmailAddress } from '../types';\nimport { assertNoHeaderInjection, sanitizeHeaderValue } from './headers';\n\n/**\n * Generate a random boundary string for MIME multipart messages\n */\nfunction generateBoundary(prefix = 'boundary'): string {\n  return `${prefix}_${Date.now()}_${Math.random().toString(36).substring(2, 15)}`;\n}\n\n/**\n * Encode email address with optional name\n */\nfunction formatEmailAddress(address: string | EmailAddress): string {\n  let out: string;\n  if (typeof address === 'string') {\n    out = address;\n  } else if (address.name) {\n    // Properly quote and escape name if it contains special characters\n    const name = address.name.replace(/\\\\/g, '\\\\\\\\').replace(/\"/g, '\\\\\"');\n    out = `\"${name}\" <${address.email}>`;\n  } else {\n    out = address.email;\n  }\n  assertNoHeaderInjection(out, 'address');\n  return out;\n}\n\n/**\n * Encode email addresses array\n */\nfunction formatEmailAddresses(\n  addresses: string | string[] | EmailAddress | EmailAddress[]\n): string {\n  const addressArray = Array.isArray(addresses) ? addresses : [addresses];\n  return addressArray.map(formatEmailAddress).join(', ');\n}\n\n/**\n * Encode attachment content to base64 and split into 76-character lines (RFC 2045)\n */\nfunction encodeAttachment(content: Buffer | string): string {\n  const buffer = typeof content === 'string' ? Buffer.from(content, 'base64') : content;\n  const base64 = buffer.toString('base64');\n  // Split into 76-character lines as per RFC 2045\n  return base64.match(/.{1,76}/g)?.join('\\r\\n') || base64;\n}\n\n/**\n * Get MIME type from filename if not provided\n */\nfunction getMimeType(filename: string, providedType?: string): string {\n  if (providedType) {\n    return providedType;\n  }\n\n  // Basic MIME type detection based on extension\n  const ext = filename.split('.').pop()?.toLowerCase();\n  const mimeTypes: Record<string, string> = {\n    pdf: 'application/pdf',\n    doc: 'application/msword',\n    docx: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',\n    xls: 'application/vnd.ms-excel',\n    xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',\n    png: 'image/png',\n    jpg: 'image/jpeg',\n    jpeg: 'image/jpeg',\n    gif: 'image/gif',\n    txt: 'text/plain',\n    html: 'text/html',\n    csv: 'text/csv',\n    zip: 'application/zip',\n    json: 'application/json',\n  };\n\n  return mimeTypes[ext || ''] || 'application/octet-stream';\n}\n\nexport interface BuildRawEmailParams {\n  from: string | EmailAddress;\n  to: string | string[] | EmailAddress | EmailAddress[];\n  cc?: string | string[] | EmailAddress | EmailAddress[];\n  bcc?: string | string[] | EmailAddress | EmailAddress[];\n  replyTo?: string | string[] | EmailAddress | EmailAddress[];\n  subject: string;\n  html?: string;\n  text?: string;\n  attachments?: Attachment[];\n  customHeaders?: Record<string, string>;\n}\n\n/**\n * Build a MIME-formatted raw email message with attachments\n */\nexport function buildRawEmailMessage(params: BuildRawEmailParams): string {\n  const lines: string[] = [];\n\n  // Generate boundaries\n  const mainBoundary = generateBoundary('main');\n  const altBoundary = generateBoundary('alt');\n\n  // Email headers\n  lines.push(`From: ${formatEmailAddress(params.from)}`);\n  lines.push(`To: ${formatEmailAddresses(params.to)}`);\n\n  if (params.cc) {\n    lines.push(`Cc: ${formatEmailAddresses(params.cc)}`);\n  }\n\n  if (params.bcc) {\n    lines.push(`Bcc: ${formatEmailAddresses(params.bcc)}`);\n  }\n\n  if (params.replyTo) {\n    lines.push(`Reply-To: ${formatEmailAddresses(params.replyTo)}`);\n  }\n\n  lines.push(`Subject: ${sanitizeHeaderValue(params.subject, 'subject')}`);\n\n  // Add custom headers (e.g., In-Reply-To, References for threading)\n  if (params.customHeaders) {\n    for (const [name, value] of Object.entries(params.customHeaders)) {\n      assertNoHeaderInjection(name, 'customHeaders.name');\n      assertNoHeaderInjection(value, 'customHeaders.value');\n      lines.push(`${name}: ${value}`);\n    }\n  }\n\n  lines.push('MIME-Version: 1.0');\n\n  const hasAttachments = params.attachments && params.attachments.length > 0;\n\n  if (!hasAttachments) {\n    // No attachments — simple message (text, html, or multipart/alternative)\n    const altBoundarySimple = generateBoundary('alt');\n\n    if (params.text && params.html) {\n      lines.push(`Content-Type: multipart/alternative; boundary=\"${altBoundarySimple}\"`);\n      lines.push('');\n      lines.push(`--${altBoundarySimple}`);\n      lines.push('Content-Type: text/plain; charset=UTF-8');\n      lines.push('Content-Transfer-Encoding: 7bit');\n      lines.push('');\n      lines.push(params.text);\n      lines.push('');\n      lines.push(`--${altBoundarySimple}`);\n      lines.push('Content-Type: text/html; charset=UTF-8');\n      lines.push('Content-Transfer-Encoding: 7bit');\n      lines.push('');\n      lines.push(params.html);\n      lines.push('');\n      lines.push(`--${altBoundarySimple}--`);\n    } else if (params.html) {\n      lines.push('Content-Type: text/html; charset=UTF-8');\n      lines.push('Content-Transfer-Encoding: 7bit');\n      lines.push('');\n      lines.push(params.html);\n    } else if (params.text) {\n      lines.push('Content-Type: text/plain; charset=UTF-8');\n      lines.push('Content-Transfer-Encoding: 7bit');\n      lines.push('');\n      lines.push(params.text);\n    }\n\n    return lines.join('\\r\\n');\n  }\n\n  lines.push(`Content-Type: multipart/mixed; boundary=\"${mainBoundary}\"`);\n  lines.push(''); // Blank line separates headers from body\n\n  // Start main multipart/mixed (for attachments)\n  lines.push(`--${mainBoundary}`);\n\n  // Check if we need multipart/alternative for text and HTML\n  if (params.text && params.html) {\n    // Both text and HTML - use multipart/alternative\n    lines.push(`Content-Type: multipart/alternative; boundary=\"${altBoundary}\"`);\n    lines.push('');\n\n    // Text version\n    lines.push(`--${altBoundary}`);\n    lines.push('Content-Type: text/plain; charset=UTF-8');\n    lines.push('Content-Transfer-Encoding: 7bit');\n    lines.push('');\n    lines.push(params.text);\n    lines.push('');\n\n    // HTML version\n    lines.push(`--${altBoundary}`);\n    lines.push('Content-Type: text/html; charset=UTF-8');\n    lines.push('Content-Transfer-Encoding: 7bit');\n    lines.push('');\n    lines.push(params.html);\n    lines.push('');\n\n    lines.push(`--${altBoundary}--`);\n  } else if (params.html) {\n    // HTML only\n    lines.push('Content-Type: text/html; charset=UTF-8');\n    lines.push('Content-Transfer-Encoding: 7bit');\n    lines.push('');\n    lines.push(params.html);\n  } else if (params.text) {\n    // Text only\n    lines.push('Content-Type: text/plain; charset=UTF-8');\n    lines.push('Content-Transfer-Encoding: 7bit');\n    lines.push('');\n    lines.push(params.text);\n  }\n\n  lines.push('');\n\n  // Add attachments (guaranteed non-empty by hasAttachments guard above)\n  for (const attachment of params.attachments as Attachment[]) {\n    const mimeType = getMimeType(attachment.filename, attachment.contentType);\n    const encoding = attachment.encoding || 'base64';\n\n    lines.push(`--${mainBoundary}`);\n    assertNoHeaderInjection(mimeType, 'attachment.contentType');\n    assertNoHeaderInjection(attachment.filename, 'attachment.filename');\n    lines.push(`Content-Type: ${mimeType}; name=\"${attachment.filename}\"`);\n    lines.push(`Content-Disposition: attachment; filename=\"${attachment.filename}\"`);\n    lines.push(`Content-Transfer-Encoding: ${encoding}`);\n    lines.push('');\n\n    if (encoding === 'base64') {\n      lines.push(encodeAttachment(attachment.content));\n    } else {\n      // For other encodings, assume content is already properly encoded\n      const content =\n        typeof attachment.content === 'string' ? attachment.content : attachment.content.toString();\n      lines.push(content);\n    }\n\n    lines.push('');\n  }\n\n  // End main boundary\n  lines.push(`--${mainBoundary}--`);\n\n  // Join with CRLF (required by MIME spec)\n  return lines.join('\\r\\n');\n}\n","import {\n  DeleteObjectsCommand,\n  GetObjectCommand,\n  ListObjectsV2Command,\n  type S3Client,\n} from '@aws-sdk/client-s3';\nimport { type SESClient, SendRawEmailCommand } from '@aws-sdk/client-ses';\nimport { getSignedUrl } from '@aws-sdk/s3-request-presigner';\nimport { SESError, ValidationError } from './errors';\nimport type {\n  InboxEmail,\n  InboxEmailSummary,\n  InboxForwardOptions,\n  InboxGetAttachmentOptions,\n  InboxListOptions,\n  InboxListResult,\n  InboxReplyOptions,\n  SendEmailResult,\n} from './types';\nimport { assertNoHeaderInjection } from './utils/headers';\nimport { escapeHtml } from './utils/html-escape';\nimport { buildRawEmailMessage } from './utils/mime';\nimport { normalizeEmailAddress, normalizeEmailAddresses } from './utils/validation';\n\n/**\n * WrapsInbox - Read and manage inbound emails stored in S3\n *\n * Emails are stored by the inbound Lambda processor:\n *   raw/{messageId}           - Raw MIME from SES\n *   parsed/{emailId}.json     - Parsed email JSON\n *   attachments/{emailId}/    - Extracted attachments\n */\nexport class WrapsInbox {\n  private s3Client: S3Client;\n  private bucketName: string;\n  private sesClient: SESClient | null;\n\n  constructor(s3Client: S3Client, bucketName: string, sesClient?: SESClient) {\n    this.s3Client = s3Client;\n    this.bucketName = bucketName;\n    this.sesClient = sesClient ?? null;\n  }\n\n  private requireSES(): SESClient {\n    if (!this.sesClient) {\n      throw new ValidationError(\n        'SES client is required for forward() and reply(). The inbox was initialized without a SES client. ' +\n          'Ensure the WrapsEmail client has SES configured.'\n      );\n    }\n    return this.sesClient;\n  }\n\n  /**\n   * List parsed inbound emails\n   */\n  async list(options: InboxListOptions = {}): Promise<InboxListResult> {\n    const { maxResults = 50, continuationToken } = options;\n\n    try {\n      const response = await this.s3Client.send(\n        new ListObjectsV2Command({\n          Bucket: this.bucketName,\n          Prefix: 'parsed/',\n          MaxKeys: maxResults,\n          ContinuationToken: continuationToken,\n        })\n      );\n\n      const emails: InboxEmailSummary[] = (response.Contents || [])\n        .filter((obj) => obj.Key?.endsWith('.json'))\n        .map((obj) => {\n          // Extract emailId from key: parsed/{emailId}.json\n          const key = obj.Key as string; // guaranteed by filter above\n          const emailId = key.replace('parsed/', '').replace('.json', '');\n          return {\n            emailId,\n            key,\n            lastModified: obj.LastModified || new Date(),\n            size: obj.Size || 0,\n          };\n        });\n\n      return {\n        emails,\n        nextToken: response.NextContinuationToken,\n      };\n    } catch (error) {\n      throw this.handleError(error);\n    }\n  }\n\n  /**\n   * Get a parsed inbound email by ID\n   */\n  async get(emailId: string): Promise<InboxEmail> {\n    try {\n      const response = await this.s3Client.send(\n        new GetObjectCommand({\n          Bucket: this.bucketName,\n          Key: `parsed/${emailId}.json`,\n        })\n      );\n\n      const body = await response.Body?.transformToString();\n      if (!body) throw new Error('Empty response body from S3');\n      return JSON.parse(body) as InboxEmail;\n    } catch (error) {\n      throw this.handleError(error);\n    }\n  }\n\n  /**\n   * Get a presigned URL for an attachment\n   */\n  async getAttachment(\n    emailId: string,\n    attachmentId: string,\n    options: InboxGetAttachmentOptions = {}\n  ): Promise<string> {\n    const { expiresIn = 3600 } = options; // Default 1 hour\n\n    // List objects in the attachment prefix to find the right one\n    try {\n      const listResponse = await this.s3Client.send(\n        new ListObjectsV2Command({\n          Bucket: this.bucketName,\n          Prefix: `attachments/${emailId}/${attachmentId}-`,\n          MaxKeys: 1,\n        })\n      );\n\n      const key = listResponse.Contents?.[0]?.Key;\n      if (!key) {\n        throw new Error(`Attachment not found: ${attachmentId} for email ${emailId}`);\n      }\n\n      const command = new GetObjectCommand({\n        Bucket: this.bucketName,\n        Key: key,\n      });\n\n      return await getSignedUrl(this.s3Client, command, { expiresIn });\n    } catch (error) {\n      throw this.handleError(error);\n    }\n  }\n\n  /**\n   * Get a presigned URL for the raw MIME email\n   */\n  async getRaw(emailId: string): Promise<string> {\n    try {\n      // First get the parsed email to find the rawS3Key\n      const email = await this.get(emailId);\n\n      const command = new GetObjectCommand({\n        Bucket: this.bucketName,\n        Key: email.rawS3Key,\n      });\n\n      return await getSignedUrl(this.s3Client, command, {\n        expiresIn: 3600,\n      });\n    } catch (error) {\n      throw this.handleError(error);\n    }\n  }\n\n  /**\n   * Delete an inbound email and all associated files\n   */\n  async delete(emailId: string): Promise<void> {\n    try {\n      // Get the parsed email to find the rawS3Key\n      let rawS3Key: string | undefined;\n      try {\n        const email = await this.get(emailId);\n        rawS3Key = email.rawS3Key;\n      } catch {\n        // Email may already be partially deleted\n      }\n\n      // List all attachments\n      const attachmentKeys: string[] = [];\n      const listResponse = await this.s3Client.send(\n        new ListObjectsV2Command({\n          Bucket: this.bucketName,\n          Prefix: `attachments/${emailId}/`,\n        })\n      );\n      if (listResponse.Contents) {\n        for (const obj of listResponse.Contents) {\n          if (obj.Key) attachmentKeys.push(obj.Key);\n        }\n      }\n\n      // Build list of all objects to delete\n      const keysToDelete: string[] = [`parsed/${emailId}.json`, ...attachmentKeys];\n      if (rawS3Key) {\n        keysToDelete.push(rawS3Key);\n      }\n\n      // Delete all objects in a single batch (up to 1000)\n      if (keysToDelete.length > 0) {\n        await this.s3Client.send(\n          new DeleteObjectsCommand({\n            Bucket: this.bucketName,\n            Delete: {\n              Objects: keysToDelete.map((Key) => ({ Key })),\n              Quiet: true,\n            },\n          })\n        );\n      }\n    } catch (error) {\n      throw this.handleError(error);\n    }\n  }\n\n  /**\n   * Forward an inbound email to new recipients\n   *\n   * Two modes:\n   * - passthrough (default): Re-sends raw MIME with rewritten From/To/Subject headers\n   * - wrapped: Builds a new message wrapping the original content\n   */\n  async forward(emailId: string, options: InboxForwardOptions): Promise<SendEmailResult> {\n    const ses = this.requireSES();\n    const passthrough = options.passthrough !== false;\n\n    if (passthrough) {\n      // Passthrough mode: get raw MIME and rewrite headers\n      const email = await this.get(emailId);\n      const rawResponse = await this.s3Client.send(\n        new GetObjectCommand({\n          Bucket: this.bucketName,\n          Key: email.rawS3Key,\n        })\n      );\n      const rawBody = await rawResponse.Body?.transformToString();\n      if (!rawBody) throw new Error('Empty raw email body from S3');\n      let rawMime = rawBody;\n\n      // Rewrite From header\n      const fromStr = normalizeEmailAddress(options.from);\n      assertNoHeaderInjection(fromStr, 'from');\n      rawMime = rawMime.replace(/^From:\\s*.+$/im, `From: ${fromStr}`);\n\n      // Rewrite To header\n      const toStr = normalizeEmailAddresses(options.to).join(', ');\n      assertNoHeaderInjection(toStr, 'to');\n      rawMime = rawMime.replace(/^To:\\s*.+$/im, `To: ${toStr}`);\n\n      // Optionally prefix subject\n      if (options.addPrefix) {\n        assertNoHeaderInjection(options.addPrefix, 'addPrefix');\n        rawMime = rawMime.replace(/^Subject:\\s*(.+)$/im, `Subject: ${options.addPrefix} $1`);\n      }\n\n      const rawMessageData = new TextEncoder().encode(rawMime);\n      const command = new SendRawEmailCommand({\n        RawMessage: { Data: rawMessageData },\n        Source: fromStr,\n        Destinations: normalizeEmailAddresses(options.to),\n      });\n\n      try {\n        const response = await ses.send(command);\n        return {\n          messageId: response.MessageId || '',\n          requestId: response.$metadata.requestId || '',\n        };\n      } catch (error) {\n        throw this.handleError(error);\n      }\n    }\n\n    // Wrapped mode: build new message containing original content\n    const email = await this.get(emailId);\n    const prefix = options.addPrefix ?? 'Fwd:';\n    const subject = `${prefix} ${email.subject}`;\n\n    const forwardBanner = '---------- Forwarded message ----------';\n    const fromInfo = `From: ${email.from.name ? `${email.from.name} <${email.from.address}>` : email.from.address}`;\n    const dateInfo = `Date: ${email.date}`;\n    const subjectInfo = `Subject: ${email.subject}`;\n    const toInfo = `To: ${email.to.map((t) => (t.name ? `${t.name} <${t.address}>` : t.address)).join(', ')}`;\n\n    let text: string | undefined;\n    if (options.text || email.text) {\n      text =\n        (options.text ? `${options.text}\\n\\n` : '') +\n        `${forwardBanner}\\n${fromInfo}\\n${dateInfo}\\n${subjectInfo}\\n${toInfo}\\n\\n` +\n        (email.text || '');\n    }\n\n    let html: string | undefined;\n    if (options.html || email.html) {\n      const fromHtml = `From: ${\n        email.from.name\n          ? `${escapeHtml(email.from.name)} &lt;${escapeHtml(email.from.address)}&gt;`\n          : escapeHtml(email.from.address)\n      }`;\n      const dateHtml = `Date: ${escapeHtml(email.date)}`;\n      const subjectHtml = `Subject: ${escapeHtml(email.subject)}`;\n      const toHtml = `To: ${email.to\n        .map((t) =>\n          t.name ? `${escapeHtml(t.name)} &lt;${escapeHtml(t.address)}&gt;` : escapeHtml(t.address)\n        )\n        .join(', ')}`;\n      const headerHtml = `<br><br><div style=\"border-top:1px solid #ccc;padding-top:10px\"><b>${forwardBanner}</b><br>${fromHtml}<br>${dateHtml}<br>${subjectHtml}<br>${toHtml}<br><br>`;\n      html =\n        (options.html || '') +\n        headerHtml +\n        (email.html || `<pre>${escapeHtml(email.text || '')}</pre>`) +\n        '</div>';\n    }\n\n    const rawMessage = buildRawEmailMessage({\n      from: options.from,\n      to: options.to,\n      subject,\n      text,\n      html,\n    });\n\n    const rawMessageData = new TextEncoder().encode(rawMessage);\n    const command = new SendRawEmailCommand({\n      RawMessage: { Data: rawMessageData },\n    });\n\n    try {\n      const response = await ses.send(command);\n      return {\n        messageId: response.MessageId || '',\n        requestId: response.$metadata.requestId || '',\n      };\n    } catch (error) {\n      throw this.handleError(error);\n    }\n  }\n\n  /**\n   * Reply to an inbound email with proper threading headers (In-Reply-To, References)\n   */\n  async reply(emailId: string, options: InboxReplyOptions): Promise<SendEmailResult> {\n    const ses = this.requireSES();\n    const email = await this.get(emailId);\n\n    // Build threading headers\n    const customHeaders: Record<string, string> = {};\n    if (email.messageId) {\n      assertNoHeaderInjection(email.messageId, 'In-Reply-To');\n      customHeaders['In-Reply-To'] = email.messageId;\n      const existingRefs = email.headers?.references || email.headers?.References || '';\n      const references = existingRefs ? `${existingRefs} ${email.messageId}` : email.messageId;\n      assertNoHeaderInjection(references, 'References');\n      customHeaders.References = references;\n    }\n\n    // Subject: prepend Re: if not already present\n    const subject = /^Re:/i.test(email.subject) ? email.subject : `Re: ${email.subject}`;\n    assertNoHeaderInjection(subject, 'subject');\n\n    // Reply to the original sender\n    const replyTo = email.from.name\n      ? `${email.from.name} <${email.from.address}>`\n      : email.from.address;\n\n    const rawMessage = buildRawEmailMessage({\n      from: options.from,\n      to: replyTo,\n      subject,\n      text: options.text,\n      html: options.html,\n      attachments: options.attachments,\n      customHeaders,\n    });\n\n    const rawMessageData = new TextEncoder().encode(rawMessage);\n    const command = new SendRawEmailCommand({\n      RawMessage: { Data: rawMessageData },\n    });\n\n    try {\n      const response = await ses.send(command);\n      return {\n        messageId: response.MessageId || '',\n        requestId: response.$metadata.requestId || '',\n      };\n    } catch (error) {\n      throw this.handleError(error);\n    }\n  }\n\n  private handleError(error: unknown): Error {\n    const err = error as {\n      $metadata?: { requestId?: string };\n      message?: string;\n      name?: string;\n    };\n    if (err.$metadata) {\n      return new SESError(\n        err.message || 'S3 request failed',\n        err.name || 'Unknown',\n        err.$metadata.requestId || 'unknown',\n        false\n      );\n    }\n    return error as Error;\n  }\n}\n","// Duplicated from @wraps/core — must stay byte-identical.\n// When @wraps/core is published, this file should be replaced with:\n//   export { encodeReplyToken, generateConversationId, generateSendId } from '@wraps/core';\n// The verifier Lambda uses @wraps/core's decodeReplyToken/verifyReplyToken; this encoder\n// MUST produce bytes that the verifier accepts. See KAT in reply-threading.test.ts.\n\nimport { createHmac, randomBytes } from 'node:crypto';\n\nexport const REPLY_TOKEN_VERSION = 1;\nconst PAYLOAD_LEN = 22;\nconst HMAC_LEN = 16;\n\nexport type EncodeReplyTokenInput = {\n  kid: number;\n  convId: Buffer;\n  sendId: Buffer;\n  exp: number;\n  secret: Buffer;\n};\n\nfunction hmac16(payload: Buffer, secret: Buffer): Buffer {\n  return createHmac('sha256', secret).update(payload).digest().subarray(0, HMAC_LEN);\n}\n\nfunction toBase64Url(buf: Buffer): string {\n  return buf.toString('base64').replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '');\n}\n\n/**\n * Encode a signed reply token.\n *\n * Produces the 51-char base64url local-part that the inbound Lambda verifies.\n * Byte-identical to `@wraps/core`'s `encodeReplyToken`.\n */\nexport function encodeReplyToken(input: EncodeReplyTokenInput): string {\n  if (input.convId.length !== 8) {\n    throw new Error('convId must be 8 bytes');\n  }\n  if (input.sendId.length !== 8) {\n    throw new Error('sendId must be 8 bytes');\n  }\n  const payload = Buffer.alloc(PAYLOAD_LEN);\n  payload.writeUInt8(REPLY_TOKEN_VERSION, 0);\n  payload.writeUInt8(input.kid & 0xff, 1);\n  input.convId.copy(payload, 2);\n  input.sendId.copy(payload, 10);\n  payload.writeUInt32BE(input.exp >>> 0, 18);\n\n  const mac = hmac16(payload, input.secret);\n  return toBase64Url(Buffer.concat([payload, mac]));\n}\n\n/**\n * Generate a random 11-char base64url conversation id (8 random bytes).\n */\nexport function generateConversationId(): string {\n  return toBase64Url(randomBytes(8));\n}\n\n/**\n * Generate a random 11-char base64url send id (8 random bytes).\n */\nexport function generateSendId(): string {\n  return toBase64Url(randomBytes(8));\n}\n","import { GetParameterCommand, type SSMClient } from '@aws-sdk/client-ssm';\nimport { ValidationError } from './errors';\nimport { encodeReplyToken, generateConversationId, generateSendId } from './reply-token-codec';\n\nconst DEFAULT_CACHE_TTL_MS = 5 * 60 * 1000; // 5 minutes\nconst DEFAULT_TTL_SECONDS = 90 * 86_400; // 90 days\n\ntype CachedSecret = {\n  kid: number;\n  current: Buffer;\n  previous?: Buffer;\n  fetchedAt: number;\n};\n\ntype StoredSecret = {\n  kid: number;\n  current: string; // base64\n  previous?: string; // base64\n};\n\nexport type WrapsReplyThreadingOptions = {\n  /**\n   * SSM client used to fetch per-domain signing secrets.\n   * Injected (not constructed inline) for testability.\n   */\n  ssmClient: SSMClient;\n\n  /**\n   * SSM parameter name prefix. Full name = prefix + fromDomain.\n   * Typically `\"/wraps/email/reply-secret/\"`.\n   */\n  parameterPrefix: string;\n\n  /**\n   * Per-domain secret cache TTL in milliseconds. Defaults to 5 minutes.\n   */\n  cacheTtlMs?: number;\n\n  /**\n   * Default exp (seconds from now) baked into tokens. Defaults to 90 days.\n   * `0` means infinite (no expiry).\n   */\n  defaultTtlSeconds?: number;\n\n  /**\n   * Constructor-level override for the reply domain. If unset, the reply\n   * domain is auto-derived as `r.mail.{fromDomain}`. Per-call `replyDomain`\n   * still wins over this.\n   */\n  defaultReplyDomainOverride?: string;\n};\n\nexport type GenerateReplyToParams = {\n  fromDomain: string;\n  replyDomain?: string;\n  conversationId?: string;\n  sendId?: string;\n  /**\n   * Override default TTL for this token. `0` = infinite.\n   */\n  ttlSeconds?: number;\n};\n\nexport type GenerateReplyToResult = {\n  /** Full signed reply-to address: `<51-char-token>@{replyDomain}` */\n  address: string;\n  conversationId: string;\n  sendId: string;\n  /** Unix seconds when the token expires; `null` when infinite. */\n  expiresAt: number | null;\n};\n\n/**\n * WrapsReplyThreading - Mint signed reply-to addresses for email threading.\n *\n * Per-domain secrets are fetched from SSM and cached for `cacheTtlMs`\n * (default 5 minutes) so rotation eventually-converges without constant\n * SSM traffic. One instance handles N sending domains transparently.\n */\nexport class WrapsReplyThreading {\n  private ssmClient: SSMClient;\n  private parameterPrefix: string;\n  private cacheTtlMs: number;\n  private defaultTtlSeconds: number;\n  private defaultReplyDomainOverride?: string;\n  private cache: Map<string, CachedSecret> = new Map();\n\n  constructor(opts: WrapsReplyThreadingOptions) {\n    this.ssmClient = opts.ssmClient;\n    this.parameterPrefix = opts.parameterPrefix;\n    this.cacheTtlMs = opts.cacheTtlMs ?? DEFAULT_CACHE_TTL_MS;\n    this.defaultTtlSeconds = opts.defaultTtlSeconds ?? DEFAULT_TTL_SECONDS;\n    this.defaultReplyDomainOverride = opts.defaultReplyDomainOverride;\n  }\n\n  /**\n   * Generate a new conversation id (11-char base64url from 8 random bytes).\n   * Synchronous — no SSM call.\n   */\n  newConversation(): string {\n    return generateConversationId();\n  }\n\n  /**\n   * Mint a signed reply-to address for the given sending domain.\n   *\n   * @throws {ValidationError} if reply threading is not enabled for `fromDomain`\n   *   (SSM parameter missing).\n   */\n  async generateReplyTo(params: GenerateReplyToParams): Promise<GenerateReplyToResult> {\n    const fromDomain = params.fromDomain.toLowerCase();\n    const replyDomain =\n      params.replyDomain ?? this.defaultReplyDomainOverride ?? `r.mail.${fromDomain}`;\n\n    const secret = await this.getSecret(fromDomain);\n\n    const conversationId = params.conversationId ?? generateConversationId();\n    const sendId = params.sendId ?? generateSendId();\n\n    const convBytes = b64urlToBuffer8(conversationId, 'conversationId');\n    const sendBytes = b64urlToBuffer8(sendId, 'sendId');\n\n    const ttlSeconds = params.ttlSeconds ?? this.defaultTtlSeconds;\n    const nowSeconds = Math.floor(Date.now() / 1000);\n    const exp = ttlSeconds > 0 ? nowSeconds + ttlSeconds : 0;\n    const expiresAt = ttlSeconds > 0 ? exp : null;\n\n    const token = encodeReplyToken({\n      kid: secret.kid,\n      convId: convBytes,\n      sendId: sendBytes,\n      exp,\n      secret: secret.current,\n    });\n\n    return {\n      address: `${token}@${replyDomain}`,\n      conversationId,\n      sendId,\n      expiresAt,\n    };\n  }\n\n  private async getSecret(fromDomain: string): Promise<CachedSecret> {\n    const cached = this.cache.get(fromDomain);\n    const now = Date.now();\n    if (cached && now - cached.fetchedAt < this.cacheTtlMs) {\n      return cached;\n    }\n\n    const paramName = this.parameterPrefix + fromDomain;\n    try {\n      const response = await this.ssmClient.send(\n        new GetParameterCommand({ Name: paramName, WithDecryption: true })\n      );\n      const value = response.Parameter?.Value;\n      if (!value) {\n        throw new ValidationError(\n          `Reply threading not enabled for domain ${fromDomain}`,\n          'fromDomain'\n        );\n      }\n      const parsed = JSON.parse(value) as StoredSecret;\n      const entry: CachedSecret = {\n        kid: parsed.kid,\n        current: Buffer.from(parsed.current, 'base64'),\n        previous: parsed.previous ? Buffer.from(parsed.previous, 'base64') : undefined,\n        fetchedAt: now,\n      };\n      this.cache.set(fromDomain, entry);\n      return entry;\n    } catch (error) {\n      const name = (error as { name?: string })?.name;\n      if (name === 'ParameterNotFound') {\n        throw new ValidationError(\n          `Reply threading not enabled for domain ${fromDomain}`,\n          'fromDomain'\n        );\n      }\n      throw error;\n    }\n  }\n}\n\n/**\n * Convert an 11-char base64url id back to 8 raw bytes for encoding.\n * Rejects any input that does not cleanly round-trip — silent truncation\n * would cause the Lambda to emit a `conversationId` that does not match\n * what the caller supplied, breaking threading lookups. Callers must use\n * `generateConversationId()` / `generateSendId()` (or preserve ids from\n * previous send results) to ensure round-trip fidelity.\n */\nfunction b64urlToBuffer8(s: string, fieldName: string): Buffer {\n  if (typeof s !== 'string' || s.length !== 11 || !/^[A-Za-z0-9_-]{11}$/.test(s)) {\n    throw new ValidationError(\n      `${fieldName} must be an 11-character base64url id (use WrapsReplyThreading#newConversation or a value returned by send())`,\n      fieldName\n    );\n  }\n  const pad = s.length % 4 === 0 ? '' : '='.repeat(4 - (s.length % 4));\n  const raw = Buffer.from(s.replace(/-/g, '+').replace(/_/g, '/') + pad, 'base64');\n  if (raw.length !== 8) {\n    throw new ValidationError(`${fieldName} must decode to exactly 8 bytes`, fieldName);\n  }\n  return raw;\n}\n","import type { SESv2Client } from '@aws-sdk/client-sesv2';\nimport {\n  DeleteSuppressedDestinationCommand,\n  GetSuppressedDestinationCommand,\n  ListSuppressedDestinationsCommand,\n  PutSuppressedDestinationCommand,\n} from '@aws-sdk/client-sesv2';\nimport { SESError, ValidationError } from './errors';\nimport type {\n  SuppressionEntry,\n  SuppressionListOptions,\n  SuppressionListResult,\n  SuppressionReason,\n} from './types';\n\nexport class WrapsEmailSuppression {\n  constructor(private client: SESv2Client) {}\n\n  /**\n   * Check if an email is on the suppression list\n   * Returns the entry if suppressed, null if not\n   */\n  async get(email: string): Promise<SuppressionEntry | null> {\n    if (!email) {\n      throw new ValidationError('Email address is required', 'email');\n    }\n\n    try {\n      const response = await this.client.send(\n        new GetSuppressedDestinationCommand({ EmailAddress: email })\n      );\n\n      const dest = response.SuppressedDestination;\n      if (!dest?.EmailAddress || !dest.LastUpdateTime) {\n        return null;\n      }\n      return {\n        email: dest.EmailAddress,\n        reason: dest.Reason as SuppressionReason,\n        lastUpdated: dest.LastUpdateTime,\n        messageId: dest.Attributes?.MessageId,\n        feedbackId: dest.Attributes?.FeedbackId,\n      };\n    } catch (error) {\n      if ((error as { name?: string }).name === 'NotFoundException') {\n        return null;\n      }\n      throw this.handleError(error);\n    }\n  }\n\n  /**\n   * Add an email to the suppression list\n   * Idempotent — succeeds silently if already suppressed\n   */\n  async add(email: string, reason: SuppressionReason): Promise<void> {\n    if (!email) {\n      throw new ValidationError('Email address is required', 'email');\n    }\n    if (reason !== 'BOUNCE' && reason !== 'COMPLAINT') {\n      throw new ValidationError('Reason must be BOUNCE or COMPLAINT', 'reason');\n    }\n\n    try {\n      await this.client.send(\n        new PutSuppressedDestinationCommand({\n          EmailAddress: email,\n          Reason: reason,\n        })\n      );\n    } catch (error) {\n      throw this.handleError(error);\n    }\n  }\n\n  /**\n   * Remove an email from the suppression list\n   * Idempotent — silently succeeds if email is not on the list\n   */\n  async remove(email: string): Promise<void> {\n    if (!email) {\n      throw new ValidationError('Email address is required', 'email');\n    }\n\n    try {\n      await this.client.send(new DeleteSuppressedDestinationCommand({ EmailAddress: email }));\n    } catch (error) {\n      if ((error as { name?: string }).name === 'NotFoundException') {\n        return;\n      }\n      throw this.handleError(error);\n    }\n  }\n\n  /**\n   * List suppressed emails with optional filters\n   */\n  async list(options: SuppressionListOptions = {}): Promise<SuppressionListResult> {\n    try {\n      const response = await this.client.send(\n        new ListSuppressedDestinationsCommand({\n          Reasons: options.reason ? [options.reason] : undefined,\n          StartDate: options.startDate,\n          EndDate: options.endDate,\n          PageSize: options.maxResults || 100,\n          NextToken: options.continuationToken,\n        })\n      );\n\n      const entries: SuppressionEntry[] = [];\n      for (const s of response.SuppressedDestinationSummaries || []) {\n        if (!s.EmailAddress || !s.LastUpdateTime) {\n          continue;\n        }\n        entries.push({\n          email: s.EmailAddress,\n          reason: s.Reason as SuppressionReason,\n          lastUpdated: s.LastUpdateTime,\n        });\n      }\n\n      return {\n        entries,\n        nextToken: response.NextToken,\n      };\n    } catch (error) {\n      throw this.handleError(error);\n    }\n  }\n\n  private handleError(error: unknown): Error {\n    const err = error as {\n      $metadata?: { requestId?: string };\n      $retryable?: { throttling?: boolean };\n      message?: string;\n      name?: string;\n    };\n    if (err.$metadata) {\n      return new SESError(\n        err.message || 'SES request failed',\n        err.name || 'Unknown',\n        err.$metadata.requestId || 'unknown',\n        err.$retryable?.throttling || false\n      );\n    }\n    return error instanceof Error ? error : new Error(String(error));\n  }\n}\n","import { SESClient, type SESClientConfig } from '@aws-sdk/client-ses';\nimport { fromTokenFile } from '@aws-sdk/credential-providers';\nimport type { WrapsEmailConfig } from '../types';\n\nexport function createSESClient(config: WrapsEmailConfig): SESClient {\n  // Priority 1: If pre-configured client is provided, use it directly\n  if (config.client) {\n    return config.client;\n  }\n\n  // Priority 2+: Create client based on config options\n  const clientConfig: SESClientConfig = {\n    region: config.region || 'us-east-1',\n  };\n\n  // Resolve roleArn from config or AWS_ROLE_ARN environment variable\n  const roleArn = config.roleArn || process.env.AWS_ROLE_ARN;\n\n  if (roleArn) {\n    const roleSessionName = config.roleSessionName || 'wraps-email-session';\n\n    if (process.env.VERCEL) {\n      // Vercel uses @vercel/oidc-aws-credentials-provider for OIDC token exchange.\n      // Dynamic import keeps it out of the bundle and defers loading to credential resolution time.\n      clientConfig.credentials = async () => {\n        let awsCredentialsProvider: typeof import('@vercel/oidc-aws-credentials-provider').awsCredentialsProvider;\n\n        // Only the import is guarded — a missing package is the one failure we\n        // can give actionable advice for. Everything after this rethrows as-is\n        // so real STS/OIDC failures aren't misreported as a missing dependency.\n        try {\n          ({ awsCredentialsProvider } = await import('@vercel/oidc-aws-credentials-provider'));\n        } catch (err) {\n          const error = new Error(\n            'On Vercel with roleArn requires @vercel/oidc-aws-credentials-provider. Install it: pnpm add @vercel/oidc-aws-credentials-provider'\n          );\n          // Assigned rather than passed to the constructor: this package targets\n          // ES2020, which predates the Error `cause` option.\n          (error as Error & { cause?: unknown }).cause = err;\n          throw error;\n        }\n\n        return awsCredentialsProvider({ roleArn, roleSessionName })();\n      };\n    } else {\n      // EKS, GitHub Actions, and other OIDC environments use AWS_WEB_IDENTITY_TOKEN_FILE\n      clientConfig.credentials = fromTokenFile({\n        roleArn,\n        roleSessionName,\n      });\n    }\n  }\n  // If explicit credentials provided, use them\n  else if (config.credentials) {\n    // Check if it's a credential provider (function) or static credentials (object with accessKeyId)\n    if (typeof config.credentials === 'function' || !('accessKeyId' in config.credentials)) {\n      // It's a credential provider - pass it directly to SESClient\n      clientConfig.credentials = config.credentials;\n    } else {\n      // It's static credentials - structure them correctly\n      clientConfig.credentials = {\n        accessKeyId: config.credentials.accessKeyId,\n        secretAccessKey: config.credentials.secretAccessKey,\n        sessionToken: config.credentials.sessionToken,\n      };\n    }\n  }\n  // Otherwise, AWS SDK will use credential chain:\n  // 1. Environment variables (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY)\n  // 2. Shared credentials file (~/.aws/credentials)\n  // 3. ECS container credentials\n  // 4. EC2 instance metadata\n\n  // Custom endpoint for testing\n  if (config.endpoint) {\n    clientConfig.endpoint = config.endpoint;\n  }\n\n  return new SESClient(clientConfig);\n}\n","import { DynamoDBClient } from '@aws-sdk/client-dynamodb';\nimport { S3Client } from '@aws-sdk/client-s3';\nimport {\n  CreateTemplateCommand,\n  DeleteTemplateCommand,\n  GetTemplateCommand,\n  ListTemplatesCommand,\n  type SESClient,\n  SendBulkTemplatedEmailCommand,\n  SendEmailCommand,\n  SendRawEmailCommand,\n  SendTemplatedEmailCommand,\n  UpdateTemplateCommand,\n} from '@aws-sdk/client-ses';\nimport { SESv2Client } from '@aws-sdk/client-sesv2';\nimport { SSMClient } from '@aws-sdk/client-ssm';\nimport { DynamoDBDocumentClient } from '@aws-sdk/lib-dynamodb';\nimport { sendBatch as sendBatchImpl } from './batch';\nimport { mapAwsSdkError, ValidationError } from './errors';\nimport { WrapsEmailEvents } from './events';\nimport { WrapsInbox } from './inbox';\nimport { renderReactEmail } from './react';\nimport { WrapsReplyThreading } from './reply-threading';\nimport { WrapsEmailSuppression } from './suppression';\nimport type {\n  CreateTemplateFromReactParams,\n  CreateTemplateParams,\n  EmailAddress,\n  SendBatchParams,\n  SendBatchResult,\n  SendBulkTemplateParams,\n  SendBulkTemplateResult,\n  SendEmailParams,\n  SendEmailResult,\n  SendTemplateParams,\n  Template,\n  TemplateMetadata,\n  UpdateTemplateParams,\n  WrapsEmailConfig,\n} from './types';\nimport { createSESClient } from './utils/credentials';\nimport { htmlToPlainText } from './utils/html-to-text';\nimport { buildRawEmailMessage } from './utils/mime';\nimport {\n  normalizeEmailAddress,\n  normalizeEmailAddresses,\n  validateEmailParams,\n} from './utils/validation';\n\nexport class WrapsEmail {\n  private sesClient: SESClient;\n  private sesv2Client: SESv2Client;\n\n  /**\n   * Inbox for reading inbound emails\n   * Only available when inboxBucketName is configured\n   */\n  public readonly inbox: WrapsInbox | null;\n\n  /**\n   * Email event history from DynamoDB\n   * Only available when historyTableName is configured\n   */\n  public readonly events: WrapsEmailEvents | null;\n\n  /**\n   * Suppression list management (SES v2)\n   * Always available when credentials are configured\n   */\n  public readonly suppression: WrapsEmailSuppression;\n\n  /**\n   * Signed reply-to threading\n   * Only available when `replyThreading` is configured\n   */\n  public readonly replyThreading: WrapsReplyThreading | null;\n\n  /**\n   * Constructor-level `replyDomain` override, preserved so per-send\n   * resolution can honor it without re-reading config.\n   */\n  private readonly replyDomainOverride: string | undefined;\n\n  /** Clients this instance created itself and is responsible for closing. */\n  private readonly ownedClients: Array<{ destroy(): void }> = [];\n\n  /**\n   * Template management methods\n   */\n  public readonly templates: {\n    create: (params: CreateTemplateParams) => Promise<void>;\n    createFromReact: (params: CreateTemplateFromReactParams) => Promise<void>;\n    update: (params: UpdateTemplateParams) => Promise<void>;\n    get: (name: string) => Promise<Template>;\n    list: () => Promise<TemplateMetadata[]>;\n    delete: (name: string) => Promise<void>;\n  };\n\n  constructor(config: WrapsEmailConfig = {}) {\n    this.sesClient = createSESClient(config);\n\n    // Initialize inbox if bucket name provided\n    if (config.inboxBucketName) {\n      if (config.s3Client) {\n        this.inbox = new WrapsInbox(config.s3Client, config.inboxBucketName, this.sesClient);\n      } else {\n        const s3Config: Record<string, unknown> = {\n          region: config.region || 'us-east-1',\n        };\n        if (config.credentials) {\n          s3Config.credentials = config.credentials;\n        }\n        if (config.endpoint) {\n          s3Config.endpoint = config.endpoint;\n        }\n        const s3Client = new S3Client(s3Config);\n        this.ownedClients.push(s3Client);\n        this.inbox = new WrapsInbox(s3Client, config.inboxBucketName, this.sesClient);\n      }\n    } else {\n      this.inbox = null;\n    }\n\n    // Initialize events API (requires historyTableName)\n    if (config.historyTableName) {\n      if (config.dynamodbClient) {\n        this.events = new WrapsEmailEvents(config.dynamodbClient, config.historyTableName);\n      } else {\n        const dynamoConfig: Record<string, unknown> = {\n          region: config.region || 'us-east-1',\n        };\n        if (config.credentials) {\n          dynamoConfig.credentials = config.credentials;\n        }\n        if (config.endpoint) {\n          dynamoConfig.endpoint = config.endpoint;\n        }\n        const ddbClient = new DynamoDBClient(dynamoConfig);\n        this.ownedClients.push(ddbClient);\n        const docClient = DynamoDBDocumentClient.from(ddbClient, {\n          marshallOptions: { removeUndefinedValues: true },\n        });\n        this.events = new WrapsEmailEvents(docClient, config.historyTableName);\n      }\n    } else {\n      this.events = null;\n    }\n\n    // Initialize SES v2 client (used by suppression and batch)\n    if (config.sesv2Client) {\n      this.sesv2Client = config.sesv2Client;\n    } else {\n      const sesv2Config: Record<string, unknown> = {\n        region: config.region || 'us-east-1',\n      };\n      if (config.credentials) {\n        sesv2Config.credentials = config.credentials;\n      }\n      if (config.endpoint) {\n        sesv2Config.endpoint = config.endpoint;\n      }\n      this.sesv2Client = new SESv2Client(sesv2Config);\n    }\n    this.suppression = new WrapsEmailSuppression(this.sesv2Client);\n\n    // Initialize reply threading if configured\n    this.replyDomainOverride = config.replyThreading?.replyDomain;\n    if (config.replyThreading) {\n      let ssmClient = config.replyThreading.ssmClient;\n      if (!ssmClient) {\n        const ssmConfig: Record<string, unknown> = {\n          region: config.region || 'us-east-1',\n        };\n        if (config.credentials) {\n          ssmConfig.credentials = config.credentials;\n        }\n        if (config.endpoint) {\n          ssmConfig.endpoint = config.endpoint;\n        }\n        ssmClient = new SSMClient(ssmConfig);\n        this.ownedClients.push(ssmClient);\n      }\n      this.replyThreading = new WrapsReplyThreading({\n        ssmClient: ssmClient as NonNullable<typeof ssmClient>,\n        parameterPrefix: config.replyThreading.parameterPrefix ?? '/wraps/email/reply-secret/',\n        cacheTtlMs: config.replyThreading.cacheTtlMs,\n        defaultTtlSeconds: config.replyThreading.ttlSeconds,\n        defaultReplyDomainOverride: config.replyThreading.replyDomain,\n      });\n    } else {\n      this.replyThreading = null;\n    }\n\n    // Initialize templates namespace\n    this.templates = {\n      create: this.createTemplate.bind(this),\n      createFromReact: this.createTemplateFromReact.bind(this),\n      update: this.updateTemplate.bind(this),\n      get: this.getTemplate.bind(this),\n      list: this.listTemplates.bind(this),\n      delete: this.deleteTemplate.bind(this),\n    };\n  }\n\n  async send(params: SendEmailParams): Promise<SendEmailResult> {\n    // Validate parameters\n    validateEmailParams(params);\n\n    // Resolve reply-to (signed token when conversationId is set)\n    const replyToResolved = await this.resolveReplyTo({\n      from: params.from,\n      replyTo: params.replyTo,\n      conversationId: params.conversationId,\n      sendId: params.sendId,\n      replyTtlSeconds: params.replyTtlSeconds,\n    });\n\n    // Handle React.email rendering\n    let html = params.html;\n    let text = params.text;\n\n    if (params.react) {\n      if (params.html) {\n        throw new ValidationError('Cannot provide both \"html\" and \"react\" parameters');\n      }\n      const rendered = await renderReactEmail(params.react);\n      html = rendered.html;\n      text = text || rendered.text;\n    }\n\n    // Auto-generate plain text from HTML when not explicitly provided\n    if (html && !text) {\n      text = htmlToPlainText(html);\n    }\n\n    // Handle attachments (requires SES v2 SendRawEmail)\n    if (params.attachments && params.attachments.length > 0) {\n      return this.sendWithAttachments(params, replyToResolved);\n    }\n\n    // Build SES SendEmail command\n    const command = new SendEmailCommand({\n      Source: normalizeEmailAddress(params.from),\n      Destination: {\n        ToAddresses: normalizeEmailAddresses(params.to),\n        CcAddresses: params.cc ? normalizeEmailAddresses(params.cc) : undefined,\n        BccAddresses: params.bcc ? normalizeEmailAddresses(params.bcc) : undefined,\n      },\n      ReplyToAddresses: replyToResolved.replyToAddresses,\n      Message: {\n        Subject: {\n          Data: params.subject,\n          Charset: 'UTF-8',\n        },\n        Body: {\n          Html: html\n            ? {\n                Data: html,\n                Charset: 'UTF-8',\n              }\n            : undefined,\n          Text: text\n            ? {\n                Data: text,\n                Charset: 'UTF-8',\n              }\n            : undefined,\n        },\n      },\n      Tags: params.tags\n        ? Object.entries(params.tags).map(([Name, Value]) => ({\n            Name,\n            Value,\n          }))\n        : undefined,\n      ConfigurationSetName: params.configurationSetName,\n    });\n\n    // Send email\n    try {\n      const response = await this.sesClient.send(command);\n\n      if (!response.MessageId || !response.$metadata.requestId) {\n        throw new Error('Invalid response from SES: missing MessageId or requestId');\n      }\n\n      const result: SendEmailResult = {\n        messageId: response.MessageId,\n        requestId: response.$metadata.requestId,\n      };\n      if (replyToResolved.conversationId) {\n        result.conversationId = replyToResolved.conversationId;\n        result.sendId = replyToResolved.sendId;\n      }\n      return result;\n    } catch (error) {\n      throw this.handleSESError(error);\n    }\n  }\n\n  private async sendWithAttachments(\n    params: SendEmailParams,\n    preResolvedReplyTo?: {\n      replyToAddresses?: string[];\n      conversationId?: string;\n      sendId?: string;\n    }\n  ): Promise<SendEmailResult> {\n    // Validate that we have attachments\n    if (!params.attachments || params.attachments.length === 0) {\n      throw new ValidationError('sendWithAttachments called without attachments');\n    }\n\n    // Validate attachment count (AWS limit: 10MB total message size, max 500 MIME parts)\n    if (params.attachments.length > 100) {\n      throw new ValidationError('Maximum 100 attachments allowed per email');\n    }\n\n    // Handle React rendering if needed\n    let html = params.html;\n    let text = params.text;\n\n    if (params.react) {\n      if (params.html) {\n        throw new ValidationError('Cannot provide both \"html\" and \"react\" parameters');\n      }\n      const rendered = await renderReactEmail(params.react);\n      html = rendered.html;\n      text = text || rendered.text;\n    }\n\n    // Auto-generate plain text from HTML when not explicitly provided\n    if (html && !text) {\n      text = htmlToPlainText(html);\n    }\n\n    // Resolve reply-to (may mint a signed token)\n    const replyToResolved =\n      preResolvedReplyTo ??\n      (await this.resolveReplyTo({\n        from: params.from,\n        replyTo: params.replyTo,\n        conversationId: params.conversationId,\n        sendId: params.sendId,\n        replyTtlSeconds: params.replyTtlSeconds,\n      }));\n\n    // Build raw MIME message\n    const rawMessage = buildRawEmailMessage({\n      from: params.from,\n      to: params.to,\n      cc: params.cc,\n      bcc: params.bcc,\n      replyTo: replyToResolved.replyToAddresses,\n      subject: params.subject,\n      html,\n      text,\n      attachments: params.attachments,\n    });\n\n    // Convert to Uint8Array for SES\n    const rawMessageData = new TextEncoder().encode(rawMessage);\n\n    // Build SendRawEmail command\n    const command = new SendRawEmailCommand({\n      RawMessage: {\n        Data: rawMessageData,\n      },\n      Tags: params.tags\n        ? Object.entries(params.tags).map(([Name, Value]) => ({\n            Name,\n            Value,\n          }))\n        : undefined,\n      ConfigurationSetName: params.configurationSetName,\n    });\n\n    // Send email\n    try {\n      const response = await this.sesClient.send(command);\n\n      if (!response.MessageId || !response.$metadata.requestId) {\n        throw new Error('Invalid response from SES: missing MessageId or requestId');\n      }\n\n      const result: SendEmailResult = {\n        messageId: response.MessageId,\n        requestId: response.$metadata.requestId,\n      };\n      if (replyToResolved.conversationId) {\n        result.conversationId = replyToResolved.conversationId;\n        result.sendId = replyToResolved.sendId;\n      }\n      return result;\n    } catch (error) {\n      throw this.handleSESError(error);\n    }\n  }\n\n  /**\n   * Resolve the `ReplyToAddresses` for a send, optionally minting a signed\n   * reply-to address when `conversationId` is set and reply threading is\n   * configured.\n   */\n  private async resolveReplyTo(params: {\n    from: string | EmailAddress;\n    replyTo?: string | string[] | EmailAddress | EmailAddress[];\n    conversationId?: string;\n    sendId?: string;\n    replyTtlSeconds?: number;\n  }): Promise<{\n    replyToAddresses?: string[];\n    conversationId?: string;\n    sendId?: string;\n  }> {\n    if (params.replyTo && params.conversationId) {\n      throw new ValidationError('replyTo and conversationId cannot both be set', 'conversationId');\n    }\n\n    if (params.conversationId && this.replyThreading) {\n      const fromStr = normalizeEmailAddress(params.from);\n      const atIndex = fromStr.lastIndexOf('@');\n      if (atIndex === -1) {\n        throw new ValidationError('from address must contain @', 'from');\n      }\n      const fromDomain = fromStr.slice(atIndex + 1).toLowerCase();\n      const result = await this.replyThreading.generateReplyTo({\n        fromDomain,\n        replyDomain: this.replyDomainOverride,\n        conversationId: params.conversationId,\n        sendId: params.sendId,\n        ttlSeconds: params.replyTtlSeconds,\n      });\n      return {\n        replyToAddresses: [result.address],\n        conversationId: result.conversationId,\n        sendId: result.sendId,\n      };\n    }\n\n    if (params.replyTo) {\n      return { replyToAddresses: normalizeEmailAddresses(params.replyTo) };\n    }\n    return {};\n  }\n\n  private handleSESError(error: unknown): Error {\n    return mapAwsSdkError(error);\n  }\n\n  /**\n   * Send email using an SES template\n   */\n  async sendTemplate(params: SendTemplateParams): Promise<SendEmailResult> {\n    const replyToResolved = await this.resolveReplyTo({\n      from: params.from,\n      replyTo: params.replyTo,\n      conversationId: params.conversationId,\n      sendId: params.sendId,\n      replyTtlSeconds: params.replyTtlSeconds,\n    });\n\n    const toAddresses: (string | EmailAddress)[] = Array.isArray(params.to)\n      ? params.to\n      : [params.to];\n    const command = new SendTemplatedEmailCommand({\n      Source: normalizeEmailAddress(params.from),\n      Destination: {\n        ToAddresses: normalizeEmailAddresses(toAddresses),\n        CcAddresses: params.cc ? normalizeEmailAddresses(params.cc) : undefined,\n        BccAddresses: params.bcc ? normalizeEmailAddresses(params.bcc) : undefined,\n      },\n      ReplyToAddresses: replyToResolved.replyToAddresses,\n      Template: params.template,\n      TemplateData: JSON.stringify(params.templateData),\n      Tags: params.tags\n        ? Object.entries(params.tags).map(([Name, Value]) => ({\n            Name,\n            Value,\n          }))\n        : undefined,\n      ConfigurationSetName: params.configurationSetName,\n    });\n\n    try {\n      const response = await this.sesClient.send(command);\n\n      if (!response.MessageId || !response.$metadata.requestId) {\n        throw new Error('Invalid response from SES: missing MessageId or requestId');\n      }\n\n      const result: SendEmailResult = {\n        messageId: response.MessageId,\n        requestId: response.$metadata.requestId,\n      };\n      if (replyToResolved.conversationId) {\n        result.conversationId = replyToResolved.conversationId;\n        result.sendId = replyToResolved.sendId;\n      }\n      return result;\n    } catch (error) {\n      throw this.handleSESError(error);\n    }\n  }\n\n  /**\n   * Send bulk emails using an SES template (up to 50 recipients)\n   */\n  async sendBulkTemplate(params: SendBulkTemplateParams): Promise<SendBulkTemplateResult> {\n    if (params.destinations.length > 50) {\n      throw new ValidationError('Maximum 50 destinations allowed per bulk send');\n    }\n\n    const replyToResolved = await this.resolveReplyTo({\n      from: params.from,\n      replyTo: params.replyTo,\n      conversationId: params.conversationId,\n      sendId: params.sendId,\n      replyTtlSeconds: params.replyTtlSeconds,\n    });\n\n    const command = new SendBulkTemplatedEmailCommand({\n      Source: normalizeEmailAddress(params.from),\n      ReplyToAddresses: replyToResolved.replyToAddresses,\n      Template: params.template,\n      DefaultTemplateData: params.defaultTemplateData\n        ? JSON.stringify(params.defaultTemplateData)\n        : undefined,\n      Destinations: params.destinations.map((dest) => {\n        const destToAddresses: (string | EmailAddress)[] = Array.isArray(dest.to)\n          ? dest.to\n          : [dest.to];\n        return {\n          Destination: {\n            ToAddresses: normalizeEmailAddresses(destToAddresses),\n          },\n          ReplacementTemplateData: JSON.stringify(dest.templateData),\n          ReplacementTags: dest.replacementTags\n            ? Object.entries(dest.replacementTags).map(([Name, Value]) => ({\n                Name,\n                Value,\n              }))\n            : undefined,\n        };\n      }),\n      DefaultTags: params.tags\n        ? Object.entries(params.tags).map(([Name, Value]) => ({\n            Name,\n            Value,\n          }))\n        : undefined,\n      ConfigurationSetName: params.configurationSetName,\n    });\n\n    try {\n      const response = await this.sesClient.send(command);\n\n      if (!response.Status || !response.$metadata.requestId) {\n        throw new Error('Invalid response from SES: missing Status or requestId');\n      }\n\n      const result: SendBulkTemplateResult = {\n        status: response.Status.map((s) => ({\n          messageId: s.MessageId,\n          status: s.Status as 'success' | 'failure',\n          error: s.Error,\n        })),\n        requestId: response.$metadata.requestId,\n      };\n      if (replyToResolved.conversationId) {\n        result.conversationId = replyToResolved.conversationId;\n        result.sendId = replyToResolved.sendId;\n      }\n      return result;\n    } catch (error) {\n      throw this.handleSESError(error);\n    }\n  }\n\n  /**\n   * Send batch emails with unique content per recipient (max 100 entries).\n   *\n   * Unlike `sendBulkTemplate()` which requires a pre-created SES template,\n   * `sendBatch()` lets you provide different subject/html/text per recipient\n   * inline without creating a template first.\n   *\n   * Uses SES v2 `SendBulkEmailCommand` with inline template content.\n   *\n   * **Note:** Literal `{{` and `}}` in HTML content will be interpreted as\n   * SES template placeholders.\n   *\n   * @example\n   * ```typescript\n   * const result = await wraps.sendBatch({\n   *   from: 'hello@example.com',\n   *   entries: [\n   *     { to: 'alice@example.com', subject: 'Hi Alice', html: '<p>Hello Alice!</p>' },\n   *     { to: 'bob@example.com', subject: 'Hi Bob', html: '<p>Hello Bob!</p>' },\n   *   ],\n   * });\n   * console.log(result.successCount); // 2\n   * ```\n   */\n  async sendBatch(params: SendBatchParams): Promise<SendBatchResult> {\n    return sendBatchImpl(this.sesv2Client, params);\n  }\n\n  /**\n   * Create a new SES template\n   */\n  private async createTemplate(params: CreateTemplateParams): Promise<void> {\n    const command = new CreateTemplateCommand({\n      Template: {\n        TemplateName: params.name,\n        SubjectPart: params.subject,\n        HtmlPart: params.html,\n        TextPart: params.text,\n      },\n    });\n\n    try {\n      await this.sesClient.send(command);\n    } catch (error) {\n      throw this.handleSESError(error);\n    }\n  }\n\n  /**\n   * Create template from React.email component\n   */\n  private async createTemplateFromReact(params: CreateTemplateFromReactParams): Promise<void> {\n    const { html, text } = await renderReactEmail(params.react);\n\n    await this.createTemplate({\n      name: params.name,\n      subject: params.subject,\n      html,\n      text,\n    });\n  }\n\n  /**\n   * Update an existing SES template\n   */\n  private async updateTemplate(params: UpdateTemplateParams): Promise<void> {\n    const command = new UpdateTemplateCommand({\n      Template: {\n        TemplateName: params.name,\n        SubjectPart: params.subject,\n        HtmlPart: params.html,\n        TextPart: params.text,\n      },\n    });\n\n    try {\n      await this.sesClient.send(command);\n    } catch (error) {\n      throw this.handleSESError(error);\n    }\n  }\n\n  /**\n   * Get template details\n   */\n  private async getTemplate(name: string): Promise<Template> {\n    const command = new GetTemplateCommand({\n      TemplateName: name,\n    });\n\n    try {\n      const response = await this.sesClient.send(command);\n\n      if (!response.Template?.TemplateName || !response.Template.SubjectPart) {\n        throw new Error('Invalid template response from SES: missing template data');\n      }\n\n      return {\n        name: response.Template.TemplateName,\n        subject: response.Template.SubjectPart,\n        htmlPart: response.Template.HtmlPart,\n        textPart: response.Template.TextPart,\n        createdTimestamp: new Date(), // SES doesn't return timestamp in GetTemplate\n      };\n    } catch (error) {\n      throw this.handleSESError(error);\n    }\n  }\n\n  /**\n   * List all templates\n   */\n  private async listTemplates(): Promise<TemplateMetadata[]> {\n    const command = new ListTemplatesCommand({\n      MaxItems: 100, // Can be paginated if needed\n    });\n\n    try {\n      const response = await this.sesClient.send(command);\n\n      return (response.TemplatesMetadata || [])\n        .filter((t) => t.Name && t.CreatedTimestamp)\n        .map((t) => ({\n          name: t.Name as string,\n          createdTimestamp: t.CreatedTimestamp as Date,\n        }));\n    } catch (error) {\n      throw this.handleSESError(error);\n    }\n  }\n\n  /**\n   * Delete a template\n   */\n  private async deleteTemplate(name: string): Promise<void> {\n    const command = new DeleteTemplateCommand({\n      TemplateName: name,\n    });\n\n    try {\n      await this.sesClient.send(command);\n    } catch (error) {\n      throw this.handleSESError(error);\n    }\n  }\n\n  /**\n   * Close the SES client and clean up resources\n   */\n  destroy(): void {\n    this.sesClient.destroy();\n    this.sesv2Client.destroy();\n    for (const client of this.ownedClients) {\n      client.destroy();\n    }\n  }\n}\n"]}