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

Sendinblue Bundle Laravel Package

allprogrammic/sendinblue-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation

    composer require allprogrammic/sendinblue-bundle
    

    For Symfony 4/5, add to config/bundles.php:

    return [
        // ...
        AllProgrammic\Bundle\SendinBlueBundle\AllProgrammicSendinBlueBundle::class => ['all' => true],
    ];
    
  2. Configuration Add your SendinBlue API key to config/packages/sendinblue.yaml:

    sendinblue:
        api:
            key: '%env(SENDINBLUE_API_KEY)%'
    

    Set the env variable in .env:

    SENDINBLUE_API_KEY=your_api_key_here
    
  3. First Use Case Inject the client into a service/controller:

    use AllProgrammic\Bundle\SendinBlueBundle\Api\TransactionalMessage;
    use AllProgrammic\Bundle\SendinBlueBundle\SendinBlueApiClientInterface;
    
    public function __construct(private SendinBlueApiClientInterface $sendinBlueClient) {}
    
    public function sendWelcomeEmail(string $email)
    {
        $message = new TransactionalMessage('Welcome!');
        $message
            ->from('noreply@example.com', 'My App')
            ->addTo($email)
            ->html($this->twig->render('emails/welcome.html.twig'))
            ->text($this->twig->render('emails/welcome.txt.twig'));
    
        $this->sendinBlueClient->sendTransactional($message);
    }
    

Implementation Patterns

Core Workflows

  1. Transactional Emails

    • Use TransactionalMessage for one-off emails (e.g., password resets, notifications).
    • Chain methods for clarity:
      $message
          ->setTemplateId(123) // Optional: Use SendinBlue templates
          ->addCc('cc@example.com')
          ->addAttachment('/path/to/file.pdf', 'filename.pdf');
      
  2. Batch Processing

    • Loop through recipients and send in bulk (avoid rate limits):
      foreach ($users as $user) {
          $message = (new TransactionalMessage('Monthly Report'))
              ->from('reports@example.com', 'Reports Team')
              ->addTo($user->email)
              ->html($this->renderReport($user));
      
          $this->sendinBlueClient->sendTransactional($message);
      }
      
  3. Template Management

    • Fetch templates to reuse IDs:
      $templates = $this->sendinBlueClient->getTemplates();
      $template = $templates->find(fn($t) => $t->name === 'Welcome Email');
      
  4. Error Handling

    • Wrap calls in try-catch:
      try {
          $this->sendinBlueClient->sendTransactional($message);
      } catch (\AllProgrammic\Bundle\SendinBlueBundle\Exception\SendinBlueException $e) {
          $this->logger->error('SendinBlue error: ' . $e->getMessage());
          // Retry logic or fallback (e.g., queue the email)
      }
      

Integration Tips

  • Symfony Mailer Bridge: Combine with symfony/mailer for hybrid setups:
    if ($useSendinBlue) {
        $this->sendinBlueClient->sendTransactional($message);
    } else {
        $this->mailer->send($email);
    }
    
  • Event Listeners: Trigger emails on user actions (e.g., registration):
    // src/EventListener/UserRegisteredListener.php
    public function onUserRegistered(UserRegisteredEvent $event)
    {
        $message = new TransactionalMessage('Account Created');
        $message->addTo($event->getUser()->email);
        $this->sendinBlueClient->sendTransactional($message);
    }
    
  • Queue Emails: Use Symfony Messenger to defer sending:
    $this->messageBus->dispatch(new SendEmailMessage($message));
    

Gotchas and Tips

Pitfalls

  1. API Key Exposure

    • Never hardcode keys in config files. Always use %env() or .env.
    • Restrict the key to "Transactional Emails" only in SendinBlue settings.
  2. Rate Limits

    • SendinBlue limits to 100 emails/hour for free plans. Monitor usage via:
      $stats = $this->sendinBlueClient->getAccount()->getStats();
      
    • Implement exponential backoff for retries:
      $attempt = 0;
      while ($attempt < 3) {
          try {
              $this->sendinBlueClient->sendTransactional($message);
              break;
          } catch (RateLimitException $e) {
              sleep(2 ** $attempt); // Exponential delay
              $attempt++;
          }
      }
      
  3. Template IDs

    • IDs are not stable. Re-fetch them if your app updates templates:
      $template = $this->sendinBlueClient->getTemplates()->find(fn($t) => $t->name === 'Welcome');
      if (!$template) {
          throw new \RuntimeException('Template not found!');
      }
      
  4. HTML/Text Mismatch

    • SendinBlue requires both HTML and text parts. Omit one to trigger errors:
      // ❌ Missing text part
      $message->html('...');
      
      // ✅ Correct
      $message->html('...')->text(strip_tags('...'));
      

Debugging

  • Enable Guzzle Debugging: Add to config/packages/dev/sendinblue.yaml:

    sendinblue:
        api:
            debug: true
    

    Logs will appear in var/log/dev.log.

  • Validate API Responses: Inspect raw responses for errors:

    $response = $this->sendinBlueClient->sendTransactional($message);
    if ($response->getStatusCode() !== 200) {
        $body = json_decode($response->getBody(), true);
        throw new \RuntimeException($body['message'] ?? 'Unknown error');
    }
    

Extension Points

  1. Custom Response Handling Extend the client to add logic:

    class CustomSendinBlueClient extends AbstractSendinBlueClient
    {
        public function sendTransactional(TransactionalMessage $message)
        {
            $response = parent::sendTransactional($message);
            if ($response->getStatusCode() === 200) {
                $this->trackEmailSent($message);
            }
            return $response;
        }
    }
    

    Register as a service in config/services.yaml:

    services:
        App\Service\CustomSendinBlueClient:
            decorates: 'sendinblue.api.client'
            arguments: ['@sendinblue.api.client']
    
  2. Add Custom Endpoints Use the underlying Guzzle client:

    $client = $this->get('sendinblue.api.client')->getClient();
    $response = $client->get('smtp/email', [
        'query' => ['limit' => 10]
    ]);
    
  3. Mock for Testing Replace the client in tests:

    // tests/Service/SendinBlueTest.php
    public function testSendEmail()
    {
        $mockClient = $this->createMock(SendinBlueApiClientInterface::class);
        $mockClient->expects($this->once())
            ->method('sendTransactional')
            ->with($this->isInstanceOf(TransactionalMessage::class));
    
        $this->container->set('sendinblue.api.client', $mockClient);
        // Test your service...
    }
    
  4. Webhook Validation Verify SendinBlue webhook signatures:

    use AllProgrammic\Bundle\SendinBlueBundle\Webhook\WebhookValidator;
    
    public function handleWebhook(Request $request)
    {
        $validator = new WebhookValidator($this->getParameter('sendinblue.api.key'));
        if (!$validator->validate($request->getContent(), $request->headers->get('X-Signature'))) {
            throw new \RuntimeException('Invalid webhook signature');
        }
        // Process webhook...
    }
    
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.
babenkoivan/elastic-client
innmind/static-analysis
innmind/coding-standard
datacore/hub-sdk
alengo/sulu-http-cache-bundle
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony
develia/geo-bundle
dreamzy/livewire-charts
touchestate-sdk/php-sdk
22h/doctrine-garbage-collection-bundle
imbo/imbo-coding-standard
visualbuilder/filament-lottie
servicioslineaonce/starter-kit
atomcoder/laravel-reorderable
irajul/filament-shadcn-theme
agtp/agtp-php
agtp/mod-php
centraldesktop/protobuf-php