Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Amazon Mailer Laravel Package

symfony/amazon-mailer

Symfony Mailer transport for Amazon SES. Configure SES via DSNs for SMTP, HTTPS, or API with region, optional session token, and port-based TLS behavior (implicit TLS or STARTTLS with optional require_tls override).

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup for Laravel

  1. Install the Package Add the Symfony Mailer and Amazon Mailer packages via Composer:

    composer require symfony/mailer symfony/amazon-mailer
    
  2. Configure AWS SES Credentials Add the DSN to your .env file. Choose one of the supported schemes:

    # SMTP (recommended for most use cases)
    MAIL_MAILER=amazon_ses
    MAILER_DSN=ses+smtp://AKIAEXAMPLE:SECRETKEY@default?region=us-east-1&session_token=SESSION_TOKEN
    
    # HTTPS (direct API calls)
    MAILER_DSN=ses+https://AKIAEXAMPLE:SECRETKEY@default?region=us-east-1
    
    # API (alternative to HTTPS)
    MAILER_DSN=ses+api://AKIAEXAMPLE:SECRETKEY@default?region=us-east-1
    
    • Replace AKIAEXAMPLE and SECRETKEY with your AWS IAM user credentials.
    • Set region to your AWS SES region (e.g., us-east-1, eu-west-1).
    • For temporary credentials (e.g., from AWS STS), include session_token.
  3. Verify SES Configuration Ensure your AWS SES account is verified for the sender email addresses and domains you plan to use. SES requires verification before sending emails in production.

  4. First Email Send Use Laravel’s Mail facade to send an email:

    use Illuminate\Support\Facades\Mail;
    use App\Mail\WelcomeEmail;
    
    Mail::to('user@example.com')->send(new WelcomeEmail('John Doe'));
    

Implementation Patterns

Workflow: Integrating with Laravel

  1. Transport Configuration Laravel’s config/mail.php can be updated to use the Symfony Mailer transport:

    'default' => env('MAIL_MAILER', 'amazon_ses'),
    'amazon_ses' => [
        'transport' => env('MAILER_DSN', 'ses+smtp://default'),
    ],
    

    Alternatively, configure the DSN directly in .env (as shown above).

  2. Customizing Email Headers Add SES-specific headers (e.g., for list management or tracking):

    $email = (new WelcomeEmail())
        ->withSwiftMessage(function ($message) {
            return $message
                ->getHeaders()
                ->addTextHeader('X-SES-LIST-MANAGEMENT-OPTIONS', '{"Enable": true}');
        });
    
  3. Handling SES Notifications (Bounces/Complaints) Use AWS SNS to subscribe to SES notifications and process them in Laravel:

    • Configure SNS topics in AWS Console to notify a Laravel endpoint (e.g., via API Gateway or SQS).
    • Create a Laravel job to handle bounce/complaint events:
      use Illuminate\Bus\Queueable;
      use Illuminate\Contracts\Queue\ShouldQueue;
      use Illuminate\Foundation\Bus\Dispatchable;
      
      class ProcessSesNotification implements ShouldQueue
      {
          use Dispatchable, Queueable;
      
          public function handle() {
              // Parse SNS message and update user records (e.g., mark email as bounced)
          }
      }
      
  4. Fallback Transport for Development Use a different transport (e.g., log or array) in .env during development:

    MAIL_MAILER=array
    MAILER_DSN=null
    
  5. Testing with SES Sandbox Test emails in AWS SES Sandbox (requires verified identities):

    // Use a verified sender in tests
    Mail::to('verified@example.com')->send(new WelcomeEmail());
    

Integration Tips

  • Laravel Mailables: Extend Laravel’s Mailable class to leverage Symfony Mailer features:

    use Symfony\Component\Mailer\MailerInterface;
    use Illuminate\Mail\Mailable;
    
    class WelcomeEmail extends Mailable
    {
        public function build()
        {
            return $this->markdown('emails.welcome')
                        ->withSwiftMessage(function ($message) {
                            $message->getHeaders()
                                    ->addTextHeader('Reply-To', 'support@example.com');
                        });
        }
    }
    
  • Retry Logic: SES may throttle requests. Configure Symfony Mailer’s retry strategy in config/mail.php:

    'amazon_ses' => [
        'transport' => env('MAILER_DSN'),
        'retry_strategy' => [
            'max_retries' => 3,
            'delay' => 1000, // milliseconds
        ],
    ],
    
  • Logging: Enable Symfony Mailer logging to debug issues:

    // In a service provider
    $this->app->bind(MailerInterface::class, function ($app) {
        $mailer = new Mailer(new AmazonMailerTransport(env('MAILER_DSN')));
        $mailer->on('message', function ($message) {
            \Log::debug('Sent message:', ['subject' => $message->getSubject()]);
        });
        return $mailer;
    });
    

Gotchas and Tips

Pitfalls

  1. SES Sandbox Restrictions

    • In production, AWS SES requires verified email addresses or domains. In the Sandbox, only verified identities can send emails.
    • Fix: Verify sender identities in the AWS SES Console before switching to production.
  2. TLS/STARTTLS Configuration

    • Using ses+smtp with port 587 (STARTTLS) may fail if the SES server does not support it. Port 465 (implicit TLS) is more reliable.
    • Fix: Use ses+smtp://...?port=465 or explicitly set require_tls=1:
      MAILER_DSN=ses+smtp://...?port=465&require_tls=1
      
  3. Custom Headers Encoding

    • SES API may misencode custom headers (e.g., non-ASCII characters). Use addTextHeader for safe encoding:
      $message->getHeaders()->addTextHeader('Custom-Header', 'Value');
      
  4. IAM Permissions

    • The IAM user/role must have ses:SendEmail, ses:SendRawEmail, and ses:SendBulkTemplatedEmail permissions.
    • Fix: Attach the AmazonSESFullAccess policy or create a custom policy with minimal permissions.
  5. Rate Limits

    • SES has sending limits (e.g., 14 emails/sec for production accounts). Exceeding limits may cause throttling.
    • Fix: Implement exponential backoff in your retry strategy or use SES’s bulk sending features.
  6. Laravel-Specific Quirks

    • Laravel’s Mail facade may not expose all Symfony Mailer features (e.g., custom transports). Use Symfony’s MailerInterface directly for advanced use cases:
      use Symfony\Component\Mailer\MailerInterface;
      use Symfony\Component\Mailer\Transport\AmazonMailerTransport;
      
      $mailer = new Mailer(new AmazonMailerTransport(env('MAILER_DSN')));
      $mailer->send((new Email())->to('user@example.com')->subject('Test'));
      

Debugging Tips

  • Enable Verbose Logging Add this to your .env to debug SMTP/API issues:

    SYMFONY_MAILER_DEBUG=true
    
  • Check SES Metrics Monitor SES metrics in AWS CloudWatch for delivery stats, bounces, and complaints.

  • Test with telnet Verify SMTP connectivity manually:

    telnet ses.smtp.us-east-1.amazonaws.com 465
    

Extension Points

  1. Custom Transport Extend AmazonMailerTransport to add Laravel-specific logic:

    use Symfony\Component\Mailer\Transport\AmazonMailerTransport as BaseTransport;
    
    class LaravelAmazonMailerTransport extends BaseTransport
    {
        public function __construct(string $dsn, array $options = [])
        {
            parent::__construct($dsn, $options);
            // Add Laravel-specific logic (e.g., event listeners)
        }
    }
    
  2. Event Listeners Subscribe to Symfony Mailer events to log or modify messages:

    use Symfony\Component\Mailer\EventListener\MessageEvent;
    
    $mailer->on('message', function (MessageEvent $event) {
        \Log::info('Sending email to: ' . $event->getMessage()->getTo());
    });
    
  3. SES Templates Use SES templates for dynamic emails:

    $message = (new Email())
        ->to('user@example.com')
        ->subject('Welcome!')
        ->html('<h1>Hello!</h1>')
        ->getSwiftMessage()
        ->getHeaders()
        ->addTextHeader('X-SES-MESSAGE-TAGS', 'welcome,template=welcome-template');
    
  4. **

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
directorytree/privacy-filter-classifier
directorytree/privacy-filter
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony
develia/geo-bundle
dreamzy/livewire-charts
touchestate-sdk/php-sdk
22h/doctrine-garbage-collection-bundle
agtp/agtp-php
agtp/mod-php
splash/sonata-admin
splash/metadata
splash/openapi
splash/scopes
splash/toolkit
testo/output-teamcity
testo/bridge-symfony
spatie/flare-daemon-runtime