πŸ“¬ Open Source — MIT License

Modern Mailjet Bundle
for Symfony 7

Send emails asynchronously with Symfony Messenger, full PHP 8.3 strict types, webhook support, and zero-bloat architecture. Built for professionals and beginners alike.

PHP 8.3+ Symfony 7 Mailjet API v3.1 PHPStan Level 9 MIT License 100% Tested

Everything you need.
Nothing you don't.

Built from scratch in 2026 to use modern PHP and Symfony features properly.

⚑

Async by Default

Send emails without slowing down your HTTP responses. Symfony Messenger queues them in Redis or any transport for background processing.

πŸ”’

Ultra Secure

Webhook signature verification via HMAC-SHA256. Timing-safe comparison. No credentials ever logged. Secrets via environment variables only.

πŸ§ͺ

Fully Tested

Unit tests with MockHttpClient β€” no real API calls needed. PHPUnit 11, PHPStan Level 9. CI runs on every push with GitHub Actions.

🎯

Fluent Builder API

Chain method calls to build emails naturally. Immutable DTOs prevent bugs. Type-safe from creation to delivery.

πŸ“‘

Webhook Receiver

Receive real-time delivery events from Mailjet (bounces, opens, clicks, spam complaints) and react with Symfony Events.

πŸ–οΈ

Sandbox Mode

Validate emails without actually sending them. Enable automatically in dev environments. Zero risk of spamming during development.

πŸ“¦

Batch Sending

Send up to 50 emails in a single API call. Dramatically reduces API overhead for bulk operations like newsletters or notifications.

πŸ“Ž

Attachments

Attach files from disk or from memory. Automatic Base64 encoding. File size validation. Support for inline images in HTML emails.

πŸŽ“

Beginner Friendly

Every file is heavily commented. Code explains itself. Perfect for students learning PHP, Symfony, and professional software practices.

Simple to use.
Powerful underneath.

From basic transactional emails to async batch sending β€” see how it works.

// In your Symfony Controller or Service
use Fabconejo\MailjetBundle\Contract\EmailSenderInterface;
use Fabconejo\MailjetBundle\DTO\EmailMessage;

class RegistrationController
{
    public function __construct(
        // Symfony injects this automatically β€” no new() needed!
        private readonly EmailSenderInterface $emailSender
    ) {}

    public function register(): Response
    {
        $email = EmailMessage::create()
            ->from('noreply@myapp.com', 'My App')
            ->to('newuser@example.com', 'New User')
            ->subject('Welcome to My App! πŸŽ‰')
            ->htmlBody('<h1>Hello!</h1><p>Thanks for joining.</p>')
            ->textBody('Hello! Thanks for joining.');

        // Sends immediately β€” user receives email in seconds
        $this->emailSender->sendNow($email);

        return new Response('Registration successful!');
    }
}
// Async: returns instantly, email sent in background
// Your HTTP response is fast β€” email queued for worker!

$email = EmailMessage::create()
    ->from('newsletter@myapp.com', 'My Newsletter')
    ->to('subscriber@example.com', 'John')
    ->subject('This week in My App')
    ->htmlBody($html);

// ⚑ This returns in <1ms β€” email queued in Redis/DB
$this->emailSender->sendAsync($email);

// Start the background worker (run in a terminal):
// $ php bin/console messenger:consume async --time-limit=3600

// Or in production with Supervisor (keeps the worker running):
// [program:messenger]
// command=php /var/www/html/bin/console messenger:consume async
// Attach a PDF invoice to the email
$email = EmailMessage::create()
    ->from('billing@myapp.com', 'Billing')
    ->to('customer@example.com')
    ->subject('Your Invoice #2026-042')
    ->htmlBody('<p>Please find your invoice attached.</p>')

    // Attach from a file path (most common)
    ->attachFile('/var/invoices/invoice-042.pdf')

    // Attach a file with a custom display name
    ->attachFile('/tmp/report.xlsx', 'Monthly Report.xlsx')

    // Attach raw binary content (e.g. generated in memory)
    ->attach('receipt.pdf', $pdfBinaryContent, 'application/pdf');

$this->emailSender->sendNow($email);
// βœ… Files are automatically Base64-encoded for the API
// Inject the low-level client for batch sending
use Fabconejo\MailjetBundle\Contract\MailjetClientInterface;

class NewsletterService
{
    public function __construct(
        private readonly MailjetClientInterface $mailjet
    ) {}

    public function sendNewsletter(array $subscribers): void
    {
        // Build one email per subscriber
        $messages = [];
        foreach ($subscribers as $subscriber) {
            $messages[] = EmailMessage::create()
                ->from('newsletter@app.com')
                ->to($subscriber['email'], $subscriber['name'])
                ->subject('Weekly Newsletter')
                ->htmlBody($html);
        }

        // Send up to 50 per call β€” dramatically more efficient!
        foreach (array_chunk($messages, 50) as $batch) {
            $this->mailjet->sendBatch($batch);
        }
    }
}

Up and running
in 5 minutes.

No complicated setup. Just install, configure, and send.

1

Install via Composer

Requires PHP 8.3+ and Symfony 7+. Symfony Flex will auto-register the bundle.

composer require fabconejo/symfony-mailjet-bundle
2

Add your Mailjet credentials to .env

Get your API keys at app.mailjet.com/account/apikeys (free account required)

MAILJET_API_KEY=your_api_key_here MAILJET_SECRET_KEY=your_secret_key_here MAILJET_SANDBOX_MODE=true # Set to false in production! MAILJET_WEBHOOK_SECRET= # Optional: random string for webhook security
3

Create config/packages/mailjet.yaml

mailjet: api_key: '%env(MAILJET_API_KEY)%' secret_key: '%env(MAILJET_SECRET_KEY)%' sandbox_mode: '%env(bool:MAILJET_SANDBOX_MODE)%'
4

Inject and send!

The EmailSenderInterface is now available anywhere in your Symfony app via dependency injection.

// In any controller or service: public function __construct( private readonly EmailSenderInterface $emailSender ) {} // Send! $this->emailSender->sendNow( EmailMessage::create() ->from('you@example.com', 'Your App') ->to('user@example.com') ->subject('Hello!') ->htmlBody('<h1>It works!</h1>') );

Built with the best
tools available in 2026.

PHP 8.3 Strict Types
Symfony 7 Framework
Symfony Messenger (Async)
Symfony HttpClient
Mailjet API v3.1
PHPUnit 11 Tests
PHPStan Level 9
PHP CS Fixer
GitHub Actions CI
MIT License