A package to support logging via email in Laravel
shaffe/laravel-mail-log-channel is a Laravel package for a package to support logging via email in laravel.
It currently has 13 GitHub stars and 94.405 downloads on Packagist (latest version v3.0.2).
Install it with composer require shaffe/laravel-mail-log-channel.
Discover more Laravel packages by shaffe
or browse all Laravel packages to compare alternatives.
Last updated
Receive detailed error emails from your Laravel application. Plug it into Laravel's logging stack and get notified when things break — with full context, stack trace, SQL queries, and more.

Exception::context() and log record contextphp artisan mail-log:test to verify your setupcomposer require shaffe/laravel-mail-log-channel
The package auto-registers its service provider.
| Laravel | Package | |:-------------------|:--------| | 10, 11, 12, 13 | ^3.0 | | 5.6 – 13 | ^2.0 | | 5.6 | ^1.0 |
Add a mail channel to config/logging.php and include it in your stack:
'channels' => [
'stack' => [
'driver' => 'stack',
'channels' => ['daily', 'mail'],
],
'mail' => [
'driver' => 'mail',
'level' => env('LOG_MAIL_LEVEL', 'error'),
'to' => env('LOG_MAIL_ADDRESS'),
],
],
Add the recipient to your .env:
[email protected]
That's it. Unhandled exceptions at or above the configured level will now arrive in your inbox.
All options with their defaults:
'mail' => [
'driver' => 'mail',
'level' => 'error',
// Recipients (see formats below)
'to' => env('LOG_MAIL_ADDRESS'),
// Sender (defaults to mail.from config)
'from' => [
'address' => env('LOG_MAIL_FROM_ADDRESS'),
'name' => env('LOG_MAIL_FROM_NAME', 'Errors'),
],
// Subject line pattern
// Placeholders: %level_name%, %message%, %env%, %context%, %app_name%, %channel%, %datetime%
'subject_format' => '[%level_name%] [%env%] %context% — %message%',
// Throttle identical errors (seconds). Set to 0 or false to disable.
'throttle' => 60,
// Cache store for throttle state (null = default store)
'throttle_cache_store' => null,
// Include last N SQL queries in the email
'log_queries' => true,
// Collapse vendor frames in stack trace
'collapse_vendor_frames' => true,
// Custom Mailable class (receives $content and $records)
// 'mailable' => \App\Mail\CustomLogMail::class,
],
The to option accepts several formats:
// Simple string
'to' => '[email protected]',
// Multiple addresses
'to' => ['[email protected]', '[email protected]'],
// With names
'to' => ['[email protected]' => 'Dev Team'],
// Structured
'to' => [
['address' => '[email protected]', 'name' => 'Dev Team'],
['address' => '[email protected]', 'name' => 'Ops'],
],
Route error emails to different recipients based on log level. Levels without a configured recipient (and no default) won't send any email.
'to' => [
'default' => '[email protected]', // fallback for levels not listed
'critical' => '[email protected]', // critical & emergency → on-call
'emergency' => [
['address' => '[email protected]', 'name' => 'On-Call'],
['address' => '[email protected]', 'name' => 'CTO'],
],
'debug' => null, // explicitly suppress debug emails
'info' => '', // same — no email for info
],
Level keys also accept Monolog Level enum values or their numeric equivalents:
use Monolog\Level;
'to' => [
'default' => '[email protected]',
Level::Critical->value => '[email protected]', // 500
'warning' => '[email protected]', // string works too
Level::Debug->value => null, // 100 — suppressed
],
Rules:
default.null, '', or false → no email is sent, even if default exists.default → no email is sent.to works exactly as before.Each level value accepts the same formats as the standard to option (string, array of strings, named array, structured array).
Identical errors are automatically deduplicated to prevent inbox flooding. When the same error occurs multiple times within the throttle window, only the first occurrence sends an email.
Enabled by default with a 60-second window.
Each log record gets a fingerprint to determine uniqueness:
| Record type | Fingerprint components | |:------------|:-----------------------| | Exception | class + code + message + file + line | | Plain message | channel + level + message |
When an error is throttled and then reappears after the window expires, the next email includes a notice indicating how many times the error has occurred since it first appeared, along with the timestamp of the first occurrence.
For example: "⚠️ This error has occurred 47 times since 15 Mar 2025 14:30:00 UTC."
This gives you immediate visibility into the scale of a recurring issue without flooding your inbox.
// Throttle window in seconds (default: 60)
'throttle' => 60,
// Disable throttling
'throttle' => 0,
// Use a specific cache store (useful for multi-server setups)
'throttle_cache_store' => 'redis',
"User 42 not found") produce distinct fingerprints — they won't be incorrectly grouped together.The last 10 SQL queries leading up to the error are included in the email, with bindings and execution time. This helps understand the database state at the time of failure.
Disable with:
'log_queries' => false,
File paths in error emails are clickable when app.editor is configured. Clicking opens the file at the correct line in your IDE.
// config/app.php
'editor' => 'phpstorm',
Or via .env:
APP_EDITOR=phpstorm
Examples: phpstorm, vscode, vscode-insiders, cursor, sublime, kiro, nova, idea.
Custom URL scheme:
'editor' => [
'href' => 'custom://open?file={file}&line={line}',
],
Remote path remapping (when server paths differ from local):
'editor' => [
'name' => 'phpstorm',
'base_path' => '/local/path/to/project',
],
Each error email includes badges showing the application environment, PHP and Laravel versions, server hostname, peak memory usage, and execution time (time elapsed since LARAVEL_START).
This helps identify errors related to resource exhaustion or slow requests at a glance.
Verify that your mail log channel is properly configured by sending a test email:
php artisan mail-log:test
Options:
# Test with a specific log level
php artisan mail-log:test --level=critical
# Test a specific channel name
php artisan mail-log:test --channel=mail
This sends a fake exception through the configured channel so you can confirm recipients, SMTP settings, and throttle behavior without waiting for a real error.
HtmlFormatter::addRow() has been removedIf you extended HtmlFormatter or parsed the HTML output, review the new format.
This package is a fork of laravel-log-mailer by Steve Porter.
MIT — see LICENSE.