Skip to content

feat(transport): SESTransport — send via Amazon SES HTTP API #71

Description

@usernane

Problem Statement

The library currently supports Amazon SES via SMTP (using `SESCredentialHelper` to derive the SMTP password). However, the SES HTTP API (`SendRawEmail`) offers meaningful advantages over SMTP for bulk or high-throughput sending:

  • Higher sending rate limits
  • No SMTP connection overhead
  • Built-in delivery status and bounce handling via SNS
  • Better observability (message IDs, request IDs directly from API response)

Proposed Solution

Add a `SESTransport` implementing `TransportInterface` that delivers email via the SES `SendRawEmail` API using AWS Signature Version 4 signing:

```php
use WebFiori\Mail\SESTransport;

$transport = new SESTransport(
accessKeyId: getenv('AWS_ACCESS_KEY_ID'),
secretAccessKey: getenv('AWS_SECRET_ACCESS_KEY'),
region: 'us-east-1'
);

$email = new Email($account);
$email->setSubject('Sent via SES API');
$email->addTo('recipient@example.com');
$email->send($transport);
```

Implementation notes

  • Signs requests with AWS Signature V4 (HMAC-SHA256) — no AWS SDK dependency
  • Uses cURL for the HTTPS POST to `https://email.{region}.amazonaws.com/v2/email/outbound-emails\` (SES v2) or the v1 query API
  • Builds the raw MIME message from the `Email` object (reuse `SmtpTransport`'s body/header building logic where possible)
  • Returns the SES `MessageId` and sets it on the `Email` instance via `setMessageId()`

Alternatives Considered

  • Continue using SMTP only — works, but misses the throughput and observability benefits of the HTTP API
  • Require the AWS SDK — rejected, introduces a heavy dependency for a targeted feature

Breaking Change

No — `SESTransport` is opt-in via the `send($transport)` parameter. Existing SMTP-based SES usage via `SESCredentialHelper` is unaffected.

Additional Context

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions