Install the Bundle
composer require antilop/mailjet-bundle
Add to config/bundles.php:
return [
// ...
Antilop\Bundle\MailjetBundle\MailjetBundle::class => ['all' => true],
];
Configure Mailjet
Add mailjet.yml to config/packages/ (Symfony 5+) or config/ (older):
mailjet:
client:
api_key: '%env(MAILJET_API_KEY)%'
api_secret_key: '%env(MAILJET_API_SECRET)%'
templates:
welcome_email:
id: '12345'
from_email: 'noreply@example.com'
from_name: 'Example App'
First Use Case: Send a Template Email
Inject the MailjetMailer service and use it in a controller/service:
use Antilop\Bundle\MailjetBundle\Mailer\MailjetMailer;
class UserController
{
public function __construct(private MailjetMailer $mailjetMailer) {}
public function sendWelcomeEmail(User $user)
{
$this->mailjetMailer->sendTemplate(
'welcome_email', // Template name from config
$user->email,
['name' => $user->name] // Template variables
);
}
}
Sending Emails
mailjet.yml for structured emails:
$mailer->sendTemplate('template_name', 'recipient@example.com', ['var1' => 'value']);
$mailer->sendEmail(
'subject',
'recipient@example.com',
'html_content',
'text_content'
);
Dynamic Templates Override template configurations dynamically (e.g., per environment):
# config/packages/mailjet_dev.yml (for dev)
mailjet:
templates:
welcome_email:
from_email: 'dev-team@example.com'
Event Listeners
Trigger emails from domain events (e.g., UserRegisteredEvent):
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class EmailSubscriber implements EventSubscriberInterface
{
public static function getSubscribedEvents()
{
return [
UserRegisteredEvent::class => 'onUserRegistered',
];
}
public function onUserRegistered(UserRegisteredEvent $event)
{
$this->mailjetMailer->sendTemplate('welcome_email', $event->getUser()->email, [...]);
}
}
Batch Processing
Use Symfony’s Messenger component to queue emails for async sending:
$this->mailjetMailer->sendTemplateAsync('template', 'user@example.com', [...]);
MAILJET_API_KEY and MAILJET_API_SECRET in .env.MailjetMailer in PHPUnit:
$this->mailjetMailer = $this->createMock(MailjetMailer::class);
$this->mailjetMailer->expects($this->once())
->method('sendTemplate')
->with('welcome_email', 'test@example.com', ['name' => 'Test']);
# config/packages/monolog.yaml
handlers:
mailjet:
type: stream
path: "%kernel.logs_dir%/mailjet.log"
level: debug
Template IDs
mailjet.yml may break if Mailjet template IDs change. Use environment variables or a database-backed solution for production.API Rate Limits
Mailjet\Client\Exception\ApiException gracefully:
try {
$mailer->sendTemplate(...);
} catch (ApiException $e) {
$this->logger->error('Mailjet API error: ' . $e->getMessage());
// Retry or notify admin
}
Configuration Overrides
mailjet.yml.Deprecated Methods
mailjet-apiv3-php library (v1.5) is outdated. Monitor for breaking changes if upgrading.Enable Verbose Logging
Add to mailjet.yml:
client:
debug: true
Logs will appear in var/log/dev.log.
Validate API Keys Test connectivity early:
$client = $this->mailjetMailer->getClient();
$client->getContact()->getContact(1); // Trigger a dummy API call
Template Variables
Ensure template variables match Mailjet’s expected format (e.g., {{var}} syntax). Test templates in the Mailjet UI first.
Custom Mailer
Extend MailjetMailer for additional features:
class CustomMailjetMailer extends MailjetMailer
{
public function sendTransactional(string $template, string $to, array $vars)
{
// Add logic for transactional emails
}
}
Register as a service in config/services.yaml:
services:
App\Mailer\CustomMailjetMailer:
decorates: 'antilop.mailjet.mailer'
arguments: ['@.inner']
Event Dispatching Dispatch custom events after sending:
$mailer->sendTemplate(..., [
'onSend' => function (EmailSentEvent $event) {
$this->eventDispatcher->dispatch($event);
}
]);
Template Repository
Replace the static mailjet.yml with a dynamic repository (e.g., Doctrine):
// Override MailjetBundle's template loader
services:
antilop.mailjet.template_loader:
class: App\Mailjet\DynamicTemplateLoader
arguments: ['@doctrine.orm.entity_manager']
How can I help you explore Laravel packages today?