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

Sendgrid Mailer Laravel Package

symfony/sendgrid-mailer

Symfony Mailer bridge for SendGrid. Configure SMTP or API transport via DSN, choose region, handle event webhooks with optional signature validation, set suppression group headers, and schedule sends (API) using a Send-At date header.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Install the package:

    composer require symfony/sendgrid-mailer
    
  2. Configure .env with your SendGrid API key and region:

    # SMTP Transport (recommended for most use cases)
    MAILER_DSN=sendgrid+smtp://api_key@default?region=us
    
    # OR API Transport (for advanced features like scheduling)
    MAILER_DSN=sendgrid+api://api_key@default?region=us
    
  3. First email send:

    use Symfony\Component\Mailer\MailerInterface;
    use Symfony\Component\Mime\Email;
    
    public function sendWelcomeEmail(MailerInterface $mailer, string $to)
    {
        $email = (new Email())
            ->from('noreply@example.com')
            ->to($to)
            ->subject('Welcome!')
            ->text('Hello! Thanks for signing up.');
    
        $mailer->send($email);
    }
    
    • Inject MailerInterface via Laravel’s service container (automatically registered by Symfony Mailer).

First Use Case: Transactional Emails

Replace Laravel’s default Mail facade with Symfony’s MailerInterface:

// In a Laravel controller/service
public function __construct(
    private MailerInterface $mailer
) {}

public function sendPasswordReset(string $email, string $token)
{
    $email = (new Email())
        ->from(config('mail.from.address'))
        ->to($email)
        ->subject('Reset Your Password')
        ->html(view('emails.password_reset', ['token' => $token]));

    $this->mailer->send($email);
}
  • Why? Leverages SendGrid’s infrastructure for retries, analytics, and deliverability.

Implementation Patterns

1. Transport Choice: SMTP vs. API

Use Case Transport Example DSN Notes
High-volume transactional sendgrid+smtp sendgrid+smtp://key@default?region=us Lower latency, simpler setup.
Scheduled emails sendgrid+api sendgrid+api://key@default?region=us Supports Send-At header for delays.
Advanced analytics/webhooks Either Same as above API transport exposes more SendGrid features.

Pattern: Use SMTP for 90% of cases. Switch to API only if you need:

  • Email scheduling (Send-At header).
  • SendGrid’s v3 Mail Send API features (e.g., async processing, batching).

2. Webhook Integration for Delivery Events

Workflow:

  1. Configure routing in config/packages/framework.yaml:
    framework:
        webhook:
            routing:
                sendgrid:
                    service: mailer.webhook.request_parser.sendgrid
                    secret: '%env(SENDGRID_WEBHOOK_SECRET)%' # Optional: Validate signatures
    
  2. Create a consumer to handle events:
    #[AsRemoteEventConsumer(name: 'sendgrid')]
    class SendGridDeliveryConsumer implements ConsumerInterface
    {
        public function consume(RemoteEvent|MailerDeliveryEvent $event): void
        {
            if ($event instanceof MailerDeliveryEvent) {
                $this->logDeliveryEvent($event);
                $this->triggerUserNotification($event);
            }
        }
    
        private function logDeliveryEvent(MailerDeliveryEvent $event): void
        {
            // Log to DB or analytics service
            \Log::info('Email delivered', [
                'status' => $event->getStatus(),
                'message_id' => $event->getMessageId(),
            ]);
        }
    }
    
  3. Register the consumer in config/services.yaml:
    services:
        App\Event\SendGridDeliveryConsumer:
            tags: ['messenger.consumer']
    

Pattern: Use webhooks to:

  • Track email opens/clicks (via SendGrid’s Event Webhook).
  • Retry failed emails automatically (e.g., bounce handling).
  • Sync delivery status to your CRM (e.g., Salesforce, HubSpot).

3. Suppression Groups for GDPR Compliance

Use Case: Allow users to opt out of specific email categories (e.g., marketing vs. transactional).

use Symfony\Component\Mailer\Bridge\Sendgrid\Header\SuppressionGroupHeader;

$email = (new Email())
    ->from('noreply@example.com')
    ->to('user@example.com')
    ->subject('Monthly Newsletter')
    ->text('Your monthly updates...')
    ->getHeaders()
    ->add(new SuppressionGroupHeader('marketing_newsletter', ['marketing']));
  • GROUP_ID: Your SendGrid suppression group ID (e.g., marketing_newsletter).
  • GROUPS_TO_DISPLAY: Array of group IDs shown to users in their preferences (e.g., ['marketing', 'promotions']).

Pattern: Create suppression groups in SendGrid UI and map them to Laravel user preferences:

// In a User model
public function toggleEmailPreference(string $groupId, bool $enabled)
{
    $this->email_preferences[$groupId] = $enabled;
    $this->save();

    // Update SendGrid suppression list via API (optional)
    SendGrid::suppression()->update($this->id, $groupId, !$enabled);
}

4. Email Scheduling with Send-At

Use Case: Delay emails (e.g., "Send this reminder in 2 hours").

$email = (new Email())
    ->from('noreply@example.com')
    ->to('user@example.com')
    ->subject('Your Reminder')
    ->text('Don’t forget!')
    ->getHeaders()
    ->addDateHeader('Send-At', new \DateTimeImmutable('+2 hours'));

Requirements:

  • Must use sendgrid+api transport.
  • Send-At must be a DateTimeImmutable object (not a string).

Pattern: Combine with Laravel’s job queue for reliability:

// Dispatch a delayed job
SendGridEmailJob::dispatch($email)->delay(now()->addHours(2));

5. Dynamic Templates (SendGrid Feature)

Use Case: Reuse SendGrid templates with dynamic content.

$email = (new Email())
    ->from('noreply@example.com')
    ->to('user@example.com')
    ->subject('Your Order Confirmation')
    ->html(view('emails.order_confirmation', ['order' => $order]))
    ->getHeaders()
    ->addTextHeader('X-SMTPAPI', json_encode([
        'template_id' => '1234', // Your SendGrid template ID
        'dynamic_template_data' => [
            'order_id' => $order->id,
            'items' => $order->items,
        ],
    ]));

Pattern:

  1. Create templates in SendGrid UI.
  2. Use X-SMTPAPI header to inject dynamic data.
  3. Cache template IDs in Laravel config (config/sendgrid.php).

Gotchas and Tips

1. DSN Configuration Pitfalls

  • Issue: Emails fail silently with no errors. Fix: Verify the DSN format:

    # Correct (SMTP)
    MAILER_DSN=sendgrid+smtp://api_key:password@default?region=us
    
    # Correct (API)
    MAILER_DSN=sendgrid+api://api_key@default?region=us
    
    • Gotcha: Missing region parameter defaults to us, but may cause routing delays for EU/APAC users.
    • Tip: Use global region for multi-region redundancy (requires SendGrid Business plan).
  • Debugging: Enable Symfony Mailer debug mode:

    $mailer = new Mailer(new TransportFactory(), [
        'debug' => true, // Logs raw SendGrid API responses
    ]);
    

2. Webhook Signature Validation

  • Issue: Webhook payloads are rejected due to invalid signatures. Fix: Configure the secret in framework.webhook.routing.sendgrid:
    secret: '%env(SENDGRID_WEBHOOK_SECRET)%' # Must match SendGrid webhook settings
    
    • **
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.
nexmo/api-specification
capell-app/block-library
axium/identity
cetria/laravel-dummy-models
cetria/reflection-helper
agropredict/sso-auth-bundle
evolvestudio/spam-protection
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony
develia/geo-bundle
dreamzy/livewire-charts
touchestate-sdk/php-sdk
ecotone/kafka
22h/doctrine-garbage-collection-bundle
agtp/agtp-php
agtp/mod-php
splash/sonata-admin
splash/metadata