Skip to content

feat: add SES service with all 44 operations and email retrospection#9

Merged
tyrchen merged 5 commits intomasterfrom
feat/ses-service
Mar 20, 2026
Merged

feat: add SES service with all 44 operations and email retrospection#9
tyrchen merged 5 commits intomasterfrom
feat/ses-service

Conversation

@tyrchen
Copy link
Owner

@tyrchen tyrchen commented Mar 19, 2026

Summary

  • Add AWS Simple Email Service (SES) v1 (awsQuery) and v2 (restJson1) support with 44 operations across 4 phases
  • All emails captured in memory and exposed via /_aws/ses REST retrospection endpoint for test assertions
  • Smithy-generated model types from official AWS SES Smithy model (ses-2010-12-01.json)
  • SigV4 Credential service name routing (email for v1, ses for v2) to disambiguate from SNS

Phase 0: Core Sending + Identities (12 ops)

VerifyEmailIdentity, VerifyDomainIdentity, ListIdentities, DeleteIdentity, GetIdentityVerificationAttributes, VerifyEmailAddress, DeleteVerifiedEmailAddress, ListVerifiedEmailAddresses, SendEmail, SendRawEmail, GetSendQuota, GetSendStatistics

Phase 1: Templates + Configuration Sets (10 ops)

CreateTemplate, GetTemplate, UpdateTemplate, DeleteTemplate, ListTemplates, SendTemplatedEmail, CreateConfigurationSet, DeleteConfigurationSet, DescribeConfigurationSet, ListConfigurationSets

Phase 2: Event Destinations + Receipt Rules (8 ops)

CreateConfigurationSetEventDestination, UpdateConfigurationSetEventDestination, DeleteConfigurationSetEventDestination, CreateReceiptRuleSet, DeleteReceiptRuleSet, CreateReceiptRule, DeleteReceiptRule, DescribeReceiptRuleSet, CloneReceiptRuleSet, DescribeActiveReceiptRuleSet, SetActiveReceiptRuleSet

Phase 3: Notifications, DKIM, Policies (14 ops)

SetIdentityNotificationTopic, SetIdentityFeedbackForwardingEnabled, GetIdentityNotificationAttributes, VerifyDomainDkim, GetIdentityDkimAttributes, SetIdentityMailFromDomain, GetIdentityMailFromDomainAttributes, GetIdentityPolicies, PutIdentityPolicy, DeleteIdentityPolicy, ListIdentityPolicies + SES v2 routing infrastructure

New crates

  • ruststack-ses-model — auto-generated types from Smithy
  • ruststack-ses-http — awsQuery (v1) + restJson1 (v2) protocol layer
  • ruststack-ses-core — business logic, storage, retrospection

Test plan

  • 78+ unit tests across model/http/core crates
  • 23 integration tests covering all 4 phases (using aws-sdk-ses)
  • cargo clippy -- -D warnings clean
  • cargo +nightly fmt clean
  • cargo deny check clean
  • All pre-commit hooks pass
  • CI pipeline passes
  • Third-party LocalStack SES test suite validation

🤖 Generated with Claude Code

tyrchen and others added 5 commits March 19, 2026 08:32
)

Add AWS Simple Email Service (SES) v1 and v2 support to RustStack.
SES v1 uses the awsQuery protocol (same as SNS) and SES v2 uses
restJson1 with path-based routing under /v2/email/.

All sent emails are captured in memory and exposed via the /_aws/ses
REST endpoint for test retrospection - the primary value for local
development and CI testing.

Implementation covers all 4 phases:
- Phase 0: Core sending (SendEmail, SendRawEmail) + identity management
  (VerifyEmailIdentity, VerifyDomainIdentity, ListIdentities, etc.) +
  statistics (GetSendQuota, GetSendStatistics) - 12 operations
- Phase 1: Template CRUD + SendTemplatedEmail with {{variable}}
  substitution + configuration set management - 10 operations
- Phase 2: Configuration set event destinations + receipt rule set
  management including CloneReceiptRuleSet - 8 operations
- Phase 3: Identity notifications, DKIM, mail-from, sending
  authorization policies + SES v2 core operations - 14 operations

Key features:
- Smithy-generated model types from official AWS SES Smithy model
- SigV4 Credential service name routing (email for v1, ses for v2)
- Email retrospection endpoint (GET/DELETE /_aws/ses)
- Auto-verify identities in local dev mode
- Template rendering with simple {{variable}} substitution
- 23 integration tests covering all phases

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Fix TOCTOU races in TemplateStore, ConfigurationSetStore, and
  ReceiptRuleSetStore by using DashMap's atomic entry() API instead
  of separate contains_key() + insert() calls
- Return error on invalid base64 in SendRawEmail instead of silently
  falling back to raw bytes
- Fix retrospection query param from 'source' to 'email' per spec
- Use case-insensitive matching for From: header in raw email parsing
- Extract validate_message_tags() and convert_tags() helpers to
  eliminate DRY violations across send methods

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
AWS CLI smoke tests covering all 4 phases:
- Phase 0: VerifyEmailIdentity, ListIdentities, SendEmail, SendRawEmail,
  GetSendQuota, GetSendStatistics + retrospection endpoint verification
- Phase 1: Template CRUD, SendTemplatedEmail, ConfigurationSet CRUD
- Phase 2: ReceiptRuleSet CRUD with CloneReceiptRuleSet
- Phase 3: Identity notifications, DKIM, sending authorization policies
- Rust integration tests via aws-sdk-ses

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The AWS SDK and CLI sign SES v1 requests with service name "ses" in
the SigV4 Credential field, not "email" as originally documented.
Updated the gateway router to match on both "ses" and "email" for
backwards compatibility with older SDKs.

This was causing all SES requests to fall through to the SNS router,
resulting in "Unrecognized operation" errors.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The AWS CLI ses send-templated-email command uses --source, not --from.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@tyrchen tyrchen merged commit f8983af into master Mar 20, 2026
16 checks passed
@tyrchen tyrchen deleted the feat/ses-service branch March 20, 2026 00:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant