async-aws/ses
Async AWS SES client for PHP: send emails and use Amazon SES features with non-blocking, PSR-friendly requests. Lightweight alternative to the full AWS SDK, designed for modern apps and easy integration with your existing HTTP client and event loop.
Installation
composer require async-aws/ses
Ensure async-aws/core is also installed (dependency).
Configuration
Add AWS credentials to .env:
AWS_ACCESS_KEY_ID=your_key
AWS_SECRET_ACCESS_KEY=your_secret
AWS_DEFAULT_REGION=us-east-1
Publish the config (if needed):
php artisan vendor:publish --provider="AsyncAws\Ses\SesServiceProvider"
First Use Case: Send a Simple Email
use AsyncAws\Ses\SesClient;
use AsyncAws\Ses\ValueObject\SendEmailRequest;
$client = app(SesClient::class);
$response = $client->sendEmail(new SendEmailRequest([
'Source' => 'sender@example.com',
'Destination' => ['ToAddresses' => ['recipient@example.com']],
'Message' => [
'Subject' => ['Data' => 'Hello from Laravel!'],
'Body' => [
'Text' => ['Data' => 'This is a test email.'],
],
],
]));
Sending Emails with Templates Use SES templates for dynamic content:
$client->sendTemplatedEmail(new SendTemplatedEmailRequest([
'Source' => 'sender@example.com',
'Template' => 'welcome-template',
'TemplateData' => json_encode(['name' => 'John']),
'Destination' => ['ToAddresses' => ['user@example.com']],
]));
Batch Operations Send emails in bulk (e.g., for newsletters):
$client->sendBulkTemplatedEmail(new SendBulkTemplatedEmailRequest([
'Source' => 'sender@example.com',
'Template' => 'newsletter-template',
'DefaultTemplateData' => json_encode(['campaign' => 'Q1']),
'Destinations' => [
['ToAddresses' => ['user1@example.com'], 'ReplacementTemplateData' => json_encode(['name' => 'Alice'])],
['ToAddresses' => ['user2@example.com'], 'ReplacementTemplateData' => json_encode(['name' => 'Bob'])],
],
]));
Verification and Identity Management Verify email addresses or domains:
$client->verifyEmailIdentity(new VerifyEmailIdentityRequest(['EmailAddress' => 'user@example.com']));
Event-Driven Integrations
Use Laravel's queue:work to process SES events (e.g., bounces, complaints):
// In a queue worker
$client->getSendStatistics(new GetSendStatisticsRequest());
Laravel Mail Integration
Extend Laravel's Mailable to use async-aws/ses:
use AsyncAws\Ses\SesClient;
use AsyncAws\Ses\ValueObject\SendEmailRequest;
class CustomMailer extends Mailable
{
public function build()
{
$client = app(SesClient::class);
$request = new SendEmailRequest([
'Source' => $this->from,
'Destination' => ['ToAddresses' => [$this->to]],
'Message' => [
'Subject' => ['Data' => $this->subject],
'Body' => ['Text' => ['Data' => $this->content]],
],
]);
return $client->sendEmail($request);
}
}
Async Queue Jobs Offload email sending to queues for scalability:
use AsyncAws\Ses\SesClient;
use AsyncAws\Ses\ValueObject\SendEmailRequest;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
class SendEmailJob implements ShouldQueue
{
use Dispatchable, Queueable;
public function handle(SesClient $client)
{
$client->sendEmail(new SendEmailRequest([/* ... */]));
}
}
AWS Credentials and Permissions
ses:SendEmail, ses:SendRawEmail, and ses:SendTemplatedEmail permissions..env or AWS IAM roles (for EC2/Lambda).SES Sending Limits
$client->getSendQuota(new GetSendQuotaRequest());
Template Errors
$client->createTemplate(new CreateTemplateRequest([
'Template' => [
'TemplateName' => 'welcome-template',
'SubjectPart' => 'Welcome!',
'HtmlPart' => '<h1>Hello {{name}}</h1>',
'TextPart' => 'Hello {{name}}',
],
]));
Character Encoding
mb_convert_encoding() if needed:
$subject = mb_convert_encoding($subject, 'UTF-8');
Enable Debugging Configure the AWS SDK for verbose logging:
$client = new SesClient([
'region' => 'us-east-1',
'debug' => true, // Enable debug logging
'logger' => new \Monolog\Logger('ses'),
]);
Common Errors
MessageRejected: Check for invalid characters in email content or attachments.Throttling: Implement exponential backoff for retries:
use AsyncAws\Core\Exception\ThrottlingException;
try {
$client->sendEmail($request);
} catch (ThrottlingException $e) {
sleep($e->getRetryAfter());
retry();
}
Use Laravel's Mail Facade with SES
Combine Laravel's Mail facade with async-aws/ses for consistency:
Mail::to('user@example.com')->send(new CustomMailer());
// Under the hood, use SesClient for sending.
Leverage SES Analytics Track email engagement:
$client->getSendStatistics(new GetSendStatisticsRequest());
$client->getSuppressionList(new GetSuppressionListRequest());
Environment-Specific Config Use Laravel's config caching to switch between SES and other mailers:
// config/mail.php
'driver' => env('MAIL_DRIVER', 'ses'),
Testing
Use Laravel's MailFake for testing, then switch to SES in production:
// In tests
Mail::fake();
Mail::to('user@example.com')->send(new CustomMailer());
// In production
Mail::to('user@example.com')->send(new CustomMailer());
// Uses SesClient under the hood.
Performance Optimization
sendRawEmail for high-volume plain-text emails to avoid template overhead.How can I help you explore Laravel packages today?