Weave 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

Mailjet Mailer Laravel Package

symfony/mailjet-mailer

Symfony Mailjet Mailer provides a Mailjet transport bridge for Symfony Mailer, letting applications send transactional and bulk email through Mailjet’s API with standard Symfony Mailer integration.

Deep Wiki
Context7

Getting Started

This is a Symfony Mailer bridge, not a Laravel package. Laravel 9+ ships Symfony Mailer internally, so it slots in — but only if you register a custom transport; there is no built-in mailjet driver in MailManager.

  1. Install (the bridge pulls in symfony/mailer and symfony/http-client):
    composer require symfony/mailjet-mailer
    
  2. Get credentials — Mailjet Dashboard → Account → API Key Management. Use a Send-only key. Public key = username, private key = password.
  3. Register the transport in app/Providers/AppServiceProvider.php:
    use Illuminate\Support\Facades\Mail;
    use Symfony\Component\Mailer\Transport;
    
    public function boot(): void
    {
        Mail::extend('mailjet', function (array $config) {
            return Transport::fromDsn($config['dsn']);
        });
    }
    
  4. Configure config/mail.php:
    'mailers' => [
        'mailjet' => [
            'transport' => 'mailjet',
            'dsn' => env('MAILJET_DSN'),
        ],
    ],
    
    And .env:
    MAILJET_DSN=mailjet+api://PUBLIC_KEY:PRIVATE_KEY@default
    MAIL_MAILER=mailjet
    
  5. First use case — nothing in your app changes; Mail::to($user)->send(new WelcomeMail($user)) now goes through Mailjet's POST /v3.1/send endpoint.

Where to look first in the package: src/Transport/MailjetApiTransport.php (payload shape, header mapping, error handling) and src/Transport/MailjetTransportFactory.php (the exact DSN scheme it accepts). Baseline alternative: if you only need transactional mail and your network allows outbound SMTP, skip this package — Mailjet's SMTP relay works with Laravel out of the box (MAIL_HOST=in-v3.mailjet.com, MAIL_PORT=587, username = API key). The bridge's real value is HTTPS/443-only environments, structured JSON errors, and HttpClient middleware hooks.

Implementation Patterns

Mailables stay untouched. Everything is driven from config. You can override per-send with $mail->mailer('mailjet') on the Mailable, or Mail::mailer('mailjet')->to(...).

Multiple accounts / API keys. Wrap transports with Symfony's RoundRobinTransport inside your Mail::extend callback to spread sends across keys (useful when you run multiple Mailjet sub-accounts or want failover between API and SMTP):

return new \Symfony\Component\Mailer\Transport\RoundRobinTransport([
    Transport::fromDsn($apiDsn),
    Transport::fromDsn($smtpDsn),
]);

Rate limiting. Free-tier Mailjet is ~4 req/s. Wrap with Symfony\Component\Mailer\Transport\Smtp\…-style limiter or, more simply, push to a Laravel queue and use queue rate limiting. The transport is synchronous; it won't throttle for you.

Correlation and webhooks. Attach Mailjet-recognised headers so events (opens, bounces, spam) can be reconciled against your system:

$mail->getHeaders()->addTextHeader('X-MJ-CustomID', $order->uuid);
$mail->getHeaders()->addTextHeader('X-MJ-EventPayload', json_encode(['tenant' => $tenant->id]));

Register the webhook in Mailjet → Event callbacks, then consume it in a Laravel webhook controller. Custom headers in Symfony's Headers block are passed through to Mailjet's JSON payload — verify the specific X-MJ-* field survives for the version you install.

Logging integration. Hook Laravel's Illuminate\Mail\Events\MessageSending and MessageSent for audit trails. To inspect the raw HTTP request/response, instantiate the transport yourself with a logging HttpClientInterface and return it from Mail::extend — this is the main seam for observability.

Attachments, Reply-To, Bcc, inline images all work through standard Symfony Email APIs — no Mailjet-specific code.

Gotchas and Tips

  • The DSN scheme is mailjet+api://, not mailjet://. Transport::fromDsn() will throw UnsupportedSchemeException on the wrong scheme. This is the #1 setup failure.
  • URL-encode credentials in the DSN if they contain @, :, /, etc. Mailjet keys are typically hex-like and safe, but don't assume.
  • HTTP 200 ≠ delivered. Mailjet's Send API returns 200 with a Messages[].Status of "error" for rejected recipients. The bridge throws TransportException on per-message failures in current versions — wrap Mail::send() in try/catch when your UI needs to distinguish "queued" from "rejected". MessageSent only fires on success; MessageSending fires regardless.
  • Verify your sender domain. SPF/DKIM must be configured in Mailjet under Senders & Domains. Unverified senders produce either a 4xx at request time or a per-message error in a 200 response — the latter is the one that sneaks past naive try/catch.
  • No server-side template support. The bridge only sends Symfony-built Email objects. To use Mailjet template IDs with variables (TemplateID, Variables in the API body), you must call the API directly or use mailjet/mailjet-apiv3-php. Plan for this if you want marketing-owned templates editable in the Mailjet UI.
  • No sandbox mode exposed. Set sandbox at the account/sub-account level, or lean on Mail::fake() for tests. There's no mailjet+sandbox:// DSN.
  • One message per HTTP call. Symfony doesn't batch. Mailjet supports up to 50 messages per request via the raw API; you don't get that here. For bulk mail, use Mailjet Campaigns or queue with throttling.
  • Size cap: 15 MB per message including attachments and base64 inflation.
  • Message-ID and threading headers — set In-Reply-To and References explicitly if you need conversation threading; don't assume the bridge or Mailjet preserves a custom Message-ID.
  • Version pinning. Current releases require PHP 8.2+ and Symfony 6.4/7.x. Laravel 9 ships Symfony Mailer 6.2 — you'll need an older bridge branch or an upgrade. Check with composer why symfony/mailjet-mailer before debugging phantom class-not-found errors.
  • Fastest smoke test:
    Mail::mailer('mailjet')->raw('test body', function ($m) {
        $m->to('[email protected]')->subject('bridge check');
    });
    
    Run in tinker with APP_DEBUG=true to see the TransportException message verbatim; it usually names the exact Mailjet error (e.g. sendertype mismatch, unverified sender, quota exceeded).
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.
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle
glavweb/extra-bundle
glavweb/api-bundle
glavweb/admin-bundle
adachsoft/api-version-bundle
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager