Installation:
composer require devzair/mail-logger-bundle symfony/mailer symfony/mime
Ensure symfony/mailer is already configured in your project.
Enable the Bundle:
Add to config/bundles.php:
return [
// ...
Devzair\MailLoggerBundle\MailLoggerBundle::class => ['all' => true],
];
Configure in config/packages/mail_logger.yaml:
mail_logger:
enabled: true
# Optional: Customize logged fields
logged_fields: ['subject', 'to', 'html', 'text', 'headers']
First Use Case:
Inject EmailLogger into a service/controller:
use Devzair\MailLoggerBundle\Logger\EmailLogger;
public function sendWelcomeEmail(EmailLogger $emailLogger) {
$emailLogger->logEmail($this->createEmail());
}
Automatic Logging:
The bundle listens to SentMessageEvent and FailedMessageEvent via Symfony’s event dispatcher. No manual logging required for most use cases.
Manual Logging: For custom emails (e.g., CLI commands), use:
$emailLogger->logEmail($message);
Querying Logs:
Use the LoggedEmail entity (auto-created) to fetch logs:
$lastEmails = $entityManager->getRepository(LoggedEmail::class)
->findBy([], ['sentAt' => 'DESC'], 10);
Doctrine Integration:
Ensure Devzair\MailLoggerBundle\Entity\LoggedEmail is mapped in your config/packages/doctrine.yaml under orm/mappings.
Custom Fields:
Extend LoggedEmail to add custom metadata (e.g., campaignId):
// src/Entity/ExtendedLoggedEmail.php
use Devzair\MailLoggerBundle\Entity\LoggedEmail;
class ExtendedLoggedEmail extends LoggedEmail {
#[ORM\Column]
private ?string $campaignId = null;
}
Testing:
Use the mail:test command to simulate emails without sending:
php bin/console mail:test --to=test@example.com --subject="Test"
CLI Inspection: View recent logs with:
php bin/console mail:log --limit=5
Event Dispatcher Conflicts:
If SentMessageEvent/FailedMessageEvent are already handled elsewhere, ensure this bundle’s listener (MailLoggerListener) runs last in the chain. Override the priority in config/packages/mail_logger.yaml:
mail_logger:
listener_priority: 255 # Highest priority
Large Email Content:
Logging HTML/attachments can bloat your database. Configure logged_fields to exclude large payloads:
mail_logger:
logged_fields: ['subject', 'to', 'sentAt', 'status']
Doctrine Migrations:
The LoggedEmail entity is auto-created, but if you customize it, run:
php bin/console make:migration
php bin/console doctrine:migrations:migrate
Symfony 6+ Mailer:
Ensure your MailerInterface is bound to the symfony/mailer service (not a custom implementation).
No Logs Appearing?
Verify mail_logger.enabled is true and the bundle is loaded. Check Symfony’s event dispatcher logs:
php bin/console debug:event-dispatcher | grep MailLogger
Failed Events Not Logged:
Confirm your SMTP transport throws exceptions (e.g., Swift_TransportException). The bundle captures these via FailedMessageEvent.
Custom Logger:
Replace the default EmailLogger by binding a custom implementation:
# config/services.yaml
services:
App\Logger\CustomEmailLogger:
tags: ['mail_logger.logger']
Pre-Log Hooks:
Extend LoggedEmail and override the prePersist lifecycle callback to modify logs before saving.
Async Logging: For high-volume apps, offload logging to a queue (e.g., Symfony Messenger):
use Symfony\Component\Messenger\MessageBusInterface;
public function __construct(MessageBusInterface $bus) {
$this->bus = $bus;
}
public function logEmail($message) {
$this->bus->dispatch(new LogEmailMessage($message));
}
How can I help you explore Laravel packages today?