idci/aws-ses-bundle
Symfony bundle that integrates Amazon SES so your application can send email through AWS. Provides service configuration, transport wiring, and a mailer-friendly setup for delivering messages via SES in Symfony projects.
This is a Symfony 2 bundle, not a Laravel package — before anything else, decide whether you actually belong here. If you're in a Laravel app, the bundle is unusable as-is; what transfers is the shape of the integration (a container binding around daniel-zaharie/php-aws-ses), which you'd reproduce with a service provider and Mail driver. If you're on Symfony 2, it's a thin wrapper: the real API surface is the underlying SimpleEmailService class, not the bundle.
Minimal steps:
Install via Composer. Given the package's age, don't expect a clean stable release; pin explicitly.
composer require idci/aws-ses-bundle:dev-master
If Packagist resolution fails, point at the VCS repo and "minimum-stability": "dev".
Register the bundle in app/AppKernel.php:
new IDCI\Bundle\AwsSesBundle\IDCIAwsSesBundle(),
Configure credentials in app/config/config.yml (or better, parameters.yml):
idci_aws_ses:
access_key: "%aws_access_key%"
secret_key: "%aws_secret_key%"
region: "eu-west-1"
Find the service id. Open vendor/idci/aws-ses-bundle/Resources/config/services.xml — that file plus DependencyInjection/Configuration.php is the entire bundle. The service you want wraps SimpleEmailService.
First use case: send one transactional email from a controller to confirm the pipe works end to end:
$ses = $this->get('idci_aws_ses'); // verify the actual id in services.xml
$response = $ses->sendEmail('[email protected]', ['[email protected]'], 'Hello', 'Body text');
if (!$response->isOk()) { /* log getResponseBody() */ }
Where to look first, in order: services.xml (service ids and whether the client is public), Configuration.php (which config keys are actually wired — some bundle config is often declared but ignored), then vendor/daniel-zaharie/php-aws-ses/src/SimpleEmailService.php. That last file is your documentation; there is no meaningful bundle-level API.
Inject, never fetch from the container. $this->get('...') is the Symfony 2 habit, but the bundle is trivial to inject into a constructor and that makes it swappable later — which you will want, because this dependency is a dead end long-term.
class Notifier
{
private $ses;
public function __construct($ses) { $this->ses = $ses; }
public function notify($to, $subject, $text, $html = null)
{
$resp = $this->ses->sendEmail('[email protected]', [$to], $subject, $text, $html);
if (!$resp->isOk()) {
throw new \RuntimeException('SES: '.$resp->getResponseBody());
}
return $resp->getResponseBody()->MessageId;
}
}
Define your own interface over it. Because the bundle exposes the raw library object, every call site becomes coupled to php-aws-ses semantics (isOk(), no exceptions). Write a one-method Mailer interface now, implement it with SES today and aws-sdk-php or Symfony Mailer tomorrow. This is the single highest-value thing you can do in a repo running this bundle.
HTML + text pairs. Pass both bodies in one sendEmail call — SES multipart/alternative is handled by the library. Don't hand-build MIME for the common case.
Attachments and raw MIME. The library has no attachment API. Build a Swift_Message, call toString(), and use sendRawEmail() with the base64 blob. Keep this in one adapter method; raw-MIME encoding bugs are miserable to debug scattered across a codebase.
Register it as a mailer transport. Instead of calling the service directly, implement Swift_Transport (or Symfony 2's Swift_SmtpTransport-style interface) delegating to sendRawEmail. Then $mailer->send($message) routes through SES and the rest of the application — including third-party bundles that send mail — benefits without knowing about SES.
Environment-specific config. Credentials via parameters.yml / env vars, never committed. Region per environment (us-east-1 in dev, EU region in prod for data residency).
Test with a fake. Override the service in the test container with a stub exposing sendEmail()/sendRawEmail() returning a canned response object. Because the bundle does no work of its own, mocking the library is the only test seam you need.
Laravel parallel, if you're porting: the bundle is exactly a service provider singleton(SimpleEmailService::class, ...) plus config publishing. In Laravel you'd almost certainly skip it entirely — configure the ses mail driver or bind Aws\Ses\SesClient — but the abstraction advice above applies identically.
scope vs shared, unresolvable %parameters%). Assume you're pinning the framework, or vendor the two relevant files into your own bundle.php-aws-ses releases sign requests with legacy SigV2-style HMAC. Regions and edges of AWS have been moving away from that. Verify with a real send against your target region first — a 403 SignatureDoesNotMatch or InvalidSignature here means the whole approach is a fork-and-patch job.isOk() instead of exceptions. The library doesn't throw on 4xx/5xx. If you don't check isOk() and log getResponseBody(), failed sends vanish silently. Wrap every call.MessageRejected. It looks like a code bug and isn't. Verify the domain, add DKIM, then request production access.us-east-1. Sending works in dev and fails or surprises in prod if you forget to set region — especially EU data-residency requirements.curl-per-send wrapper. Add retry-with-jitter and structured logging in your adapter, or you'll be paged for a transient SES 5xx.aws-sdk-php, which handles the chain natively.decoration needs a newer Symfony than you probably have), or replace it with aws-sdk-php's SesClient behind your own interface. The last option is the recommendation; this bundle adds configuration convenience but no capability, and its underlying library is the actual liability.How can I help you explore Laravel packages today?