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

Mandrill Bundle Laravel Package

astonishdesign/mandrill-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require astonishdesign/mandrill-bundle
    

    Enable the bundle in config/bundles.php:

    return [
        // ...
        AstonishDesign\MandrillBundle\AstonishMandrillBundle::class => ['all' => true],
    ];
    
  2. Configuration: Add Mandrill API key and defaults to config/packages/astonish_mandrill.yaml:

    astonish_mandrill:
        api_key: '%env(MANDRILL_API_KEY)%'  # Use env vars in production
        disable_delivery: true  # Set to false in production
        default:
            sender: 'noreply@example.com'
            sender_name: 'Your App'
            subaccount: 'default'  # Optional subaccount
    
  3. First Email: Inject the Dispatcher service and send a message:

    use AstonishDesign\MandrillBundle\Message;
    use AstonishDesign\MandrillBundle\Dispatcher;
    
    public function sendWelcomeEmail(Dispatcher $dispatcher): void
    {
        $message = (new Message())
            ->addTo('user@example.com')
            ->setSubject('Welcome!')
            ->setHtml('<h1>Hello!</h1>');
    
        $dispatcher->send($message);
    }
    

Implementation Patterns

Core Workflow

  1. Message Composition: Chain methods on Message for clarity:

    $message = (new Message())
        ->setFromEmail('support@example.com')
        ->setFromName('Support Team')
        ->addTo('user@example.com')
        ->addTo('backup@example.com')  // Supports multiple recipients
        ->setSubject('Your Request Status')
        ->setHtml($this->twig->render('emails/request_status.html.twig'))
        ->setText($this->twig->render('emails/request_status.txt.twig'))
        ->setHeaders(['Reply-To' => 'reply@example.com']);
    
  2. Templates & Reusability: Create a service to generate reusable email templates:

    // src/Service/EmailTemplateService.php
    class EmailTemplateService
    {
        public function createPasswordReset(Message $message, string $token): Message
        {
            return $message
                ->setSubject('Reset Your Password')
                ->setHtml($this->twig->render('emails/password_reset.html.twig', ['token' => $token]));
        }
    }
    
  3. Event-Driven Emails: Trigger emails from Symfony events (e.g., KernelEvents::TERMINATE):

    // src/EventListener/EmailListener.php
    class EmailListener
    {
        public function onKernelTerminate(KernelEvent $event, Dispatcher $dispatcher): void
        {
            if ($event->getRequest()->attributes->get('send_welcome_email')) {
                $dispatcher->send($this->createWelcomeEmail());
            }
        }
    }
    
  4. Async Processing: Use Symfony Messenger to queue emails for background processing:

    # config/packages/messenger.yaml
    framework:
        messenger:
            transports:
                mandrill: '%env(MESSENGER_TRANSPORT_DSN)%'
            routing:
                'AstonishDesign\MandrillBundle\Message': mandrill
    

Integration Tips

  • FOSUserBundle: Override the mailer service in config/packages/fos_user.yaml:

    fos_user:
        service:
            mailer: astonish_mandrill.fos_user.mailer
    
  • Twig Integration: Pass Twig environment to render dynamic content:

    $message->setHtml($this->twig->render('emails/invoice.html.twig', ['invoice' => $invoice]));
    
  • Testing: Mock the Dispatcher service in tests:

    $dispatcher = $this->createMock(Dispatcher::class);
    $dispatcher->expects($this->once())
        ->method('send')
        ->with($this->isInstanceOf(Message::class));
    

Gotchas and Tips

Common Pitfalls

  1. API Key Exposure:

    • Issue: Hardcoding API keys in config.yml leaks credentials.
    • Fix: Use environment variables (%env(MANDRILL_API_KEY)%) and .env files.
      # config/packages/astonish_mandrill.yaml
      astonish_mandrill:
          api_key: '%env(MANDRILL_API_KEY)%'
      
  2. Disable Delivery in Production:

    • Issue: Forgetting to set disable_delivery: false in production.
    • Fix: Use a parameter or environment variable:
      astonish_mandrill:
          disable_delivery: '%kernel.debug%'  # Auto-disables in dev
      
  3. Recipient Validation:

    • Issue: Mandrill rejects invalid email formats silently.
    • Fix: Validate emails before sending:
      if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
          throw new \InvalidArgumentException('Invalid email address');
      }
      
  4. Rate Limits:

    • Issue: Mandrill throttles requests during spikes.
    • Fix: Implement exponential backoff in the Dispatcher or use a queue.

Debugging Tips

  • Response Handling: Mandrill returns an array with a status key. Check for errors:

    $result = $dispatcher->send($message);
    if ($result['status'] !== 'sent') {
        throw new \RuntimeException('Email failed: ' . $result['_substatus']);
    }
    
  • Logging: Enable logging in config/packages/monolog.yaml:

    services:
        AstonishDesign\MandrillBundle\Dispatcher:
            calls:
                - [setLogger, ['@monolog.logger.mandrill']]
    
  • API Debugging: Use Mandrill’s webhooks to debug failed sends:

    astonish_mandrill:
        webhook_url: 'https://your-app.com/mandrill/webhook'
    

Extension Points

  1. Custom Message Classes: Extend Message to add domain-specific methods:

    class InvoiceMessage extends Message
    {
        public function setInvoice(Invoice $invoice): self
        {
            return $this
                ->setSubject("Invoice #{$invoice->getNumber()}")
                ->setHtml($this->twig->render('emails/invoice.html.twig', ['invoice' => $invoice]));
        }
    }
    
  2. Event Subscribers: Listen to MandrillEvents::SEND to modify messages:

    use AstonishDesign\MandrillBundle\Event\MandrillEvent;
    
    public function onSend(MandrillEvent $event): void
    {
        $message = $event->getMessage();
        $message->setHeader('X-Custom-ID', uniqid());
    }
    
  3. Transport Layer: Override the default MandrillTransport to add retries or logging:

    // src/Mandrill/MandrillTransport.php
    class CustomMandrillTransport extends MandrillTransport
    {
        public function send(Message $message): array
        {
            $this->logger->info('Sending email to ' . $message->getTo());
            return parent::send($message);
        }
    }
    
  4. Testing with Fake Transport: Replace the transport in tests:

    // tests/Service/MandrillTest.php
    $container->set('astonish_mandrill.transport', $this->createMock(MandrillTransport::class));
    
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.
amashukov/lnd-client-php
althinect/enum-permission
andydefer/laravel-actions
aimeos/prisma
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky