Download the PHP package phattarachai/mail-log-laravel without Composer

On this page you can find all versions of the php package phattarachai/mail-log-laravel. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.

FAQ

After the download, you have to make one include require_once('vendor/autoload.php');. After that you have to import the classes with use statements.

Example:
If you use only one package a project is not needed. But if you use more then one package, without a project it is not possible to import the classes with use statements.

In general, it is recommended to use always a project to download your libraries. In an application normally there is more than one library needed.
Some PHP packages are not free to download and because of that hosted in private repositories. In this case some credentials are needed to access such packages. Please use the auth.json textarea to insert credentials, if a package is coming from a private repository. You can look here for more information.

  • Some hosting areas are not accessible by a terminal or SSH. Then it is not possible to use Composer.
  • To use Composer is sometimes complicated. Especially for beginners.
  • Composer needs much resources. Sometimes they are not available on a simple webspace.
  • If you are using private repositories you don't need to share your credentials. You can set up everything on our site and then you provide a simple download link to your team member.
  • Simplify your Composer build process. Use our own command line tool to download the vendor folder as binary. This makes your build process faster and you don't need to expose your credentials for private repositories.
Please rate this library. Is it a good library?

Informations about the package mail-log-laravel

Mail Log

Latest Version on Packagist Tests Code Style PHP Version Laravel Version Total Downloads

Self-hosted outbound mail logger for Laravel. Captures every Mail::send(...) + Notification mail-channel call, groups identical sends together by Mailable class + Eloquent model, and exposes the result at a /mail-log dashboard. Ships its own Tailwind UI — no Filament, no Livewire-from-the-package, no npm install in the host.

What it gives you

Install

mail-log:install is idempotent. It publishes the package config, the Spatie laravel-medialibrary migration (auto-detected when the media table is missing), and the package's own migrations, then offers to run php artisan migrate. It writes three env keys (MAIL_LOG_ENABLED, MAIL_LOG_RETENTION_DAYS, MAIL_LOG_UI_PATH) only when absent, and prints the snippets you need to paste into AppServiceProvider::boot(), a Mailable, and the scheduler.

Re-run safely. Pass --dry-run to print intended changes without writing.

After install, paste the auth gate snippet:

The default policy blocks /mail-log unless APP_DEBUG=true — loud, safe failure until you opt in.

Per-Mailable opt-in

Drop the trait into a Mailable and tell it what model originated the send:

Now every Mail::to($recipient)->send(new OrderShippedMail($order)) to ANY recipient lands in the same group; sending the same Mailable for a different Order creates a separate group.

Trait hooks

All return safe defaults — override only what you need.

Hook Returns Behavior
mailLogModel(): ?Model null The originating record. Folded into the fingerprint when mode includes 'model' (default).
mailLogNotificationClass(): ?string null The source Notification when the Mailable is constructed inside toMail(). Lets you fingerprint on the notification instead.
mailLogFingerprintHints(): array [] Extra strings (tenant id, A/B variant) folded in when mode includes 'hints'.
mailLogFingerprintMode(): ?array null Per-Mailable override of ['class', 'model']. Valid: class, notification_class, model, hints, subject, body, mailer.
mailLogSkip(): bool false Opt this Mailable out of capture entirely (health-check pings, transactional one-offs).
mailLogModels(): iterable [] Further models this send relates to. Stored per send, searchable, never part of the fingerprint. See Several models per send.
mailLogResendable(): bool false Store this Mailable per send so it can be resent. See Resending.

Group / event model

Two tables in lock-step:

The body shown on the show page is the first send in the group — per-recipient body variation (signed URLs, magic-login tokens, personalized greetings) is NOT captured per row. The package favors fingerprint stability over body fidelity, and per-event body storage is not planned.

Recipients on the dashboard are the distinct to, cc and bcc addresses across every send in the group, in the order they were first mailed (oldest send first; within a send, to before cc before bcc). The index shows the first one plus a +N more count, so the primary recipient of the first send leads.

Sends counts every event in the group, Pending included. sent_count / failed_count only count settled outcomes.

Redacted bodies

Mail sent without the trait goes through the raw fallback path, and its body carries one recipient's secret: Laravel's ResetPassword and VerifyEmail notifications, magic-login links, any signed URL. The group stores the first send's body, so by default the listener masks these before saving:

Each becomes [redacted]. Add your own patterns under redact.patterns in config/mail-log.php (pattern => replacement), or set MAIL_LOG_REDACT_BODIES=false to store bodies verbatim. Rows stored before v0.3.0 keep their original body until they are deleted or pruned.

Model deep links

Implement MailLogLinkable on a model a Mailable returns from mailLogModel(), and the dashboard's Model column (index) and Model row (group page) link back into your app:

Models without the contract render as Order#42.

Several models per send

mailLogModel() is the primary model: it decides the group. Return further models from mailLogModels() and each send records them too:

Resending

A Mailable opts in with mailLogResendable():

Each send of it then stores the Mailable itself: serialized the way a queued job is (models as identifiers, via SerializesModels) and encrypted with your APP_KEY. Resending restores it and renders it again, with the models' current data and fresh links, so it never replays the stored preview (which is the first send's, and redacted).

The resend is logged as a new send in the same group, marked ↻ resent, with resent_from_id pointing at the original. It goes out immediately, even for a ShouldQueue Mailable.

Things to know:

Outgoing headers and Message-ID

HasMailLog passes its metadata to the listener in X-Mail-* headers (class, model keys, fingerprint hints, the encrypted resend payload). The listener reads them and removes them before the message is handed to the transport, so recipients never see class names or record ids.

Each send is matched to its row by Message-ID: your own if the Mailable sets one (new Headers(messageId: …)), otherwise one the listener assigns. It's stored in mail_logs.message_id, which is what bounce notifications (DSNs) refer to.

Failed and stale sends

Every event starts Pending when Laravel fires MessageSending and becomes Sent on MessageSent. When the transport throws, the listener settles it as Failed with the exception message:

Where the send ran Settled by
Queued Mailable or queued Notification (SendQueuedMailable, SendQueuedNotifications) or your own job JobExceptionOccurred / JobFailed in the same worker. A job with tries > 1 records one Failed row per failed attempt (Attempt 1 failed, the job will retry: …) plus the final outcome.
A job that caught the send exception itself JobProcessed
Synchronous Mail::send() in a request or command (Laravel fires no event for a transport error) the app's exception reporter, with the transport's message, when the exception reaches it. If your code catches it without report(), the app's terminating hook marks the send Failed with a generic note pointing at the log.
A worker killed mid-send, a timeout retried on another worker, a crashed process php artisan mail-log:settle-stale

mail-log:settle-stale marks events still Pending after MAIL_LOG_PENDING_TIMEOUT_MINUTES (default 15) as Failed. Schedule it (see Scheduling); --minutes=N overrides the timeout for one run.

A send that another MessageSending listener cancels after Mail Log logged it also ends up Failed, since it was never delivered.

Config

See Boost skill reference.md walks every key.

Scheduling

Prune old groups daily and settle stale Pending sends every few minutes. In Laravel 12 / 13, in routes/console.php:

Or in bootstrap/app.php:

Events cascade-delete via FK when their parent group is pruned.

Dashboard language

The dashboard's labels, buttons and flash messages are in English. Dates are always in Thai format: day, Thai month abbreviation, two-digit Buddhist-era year and 24-hour time, e.g. 19 พ.ค. 69 · 15:07 for 19 May 2026, 15:07. The format is not configurable yet.

Requirements

Credits

Built by Phattarachai Chaimongkol. Same shipping pattern as Laravel Horizon and Pulse — pre-built CSS + JS committed to dist/, inlined into the layout via MailLog::css() / MailLog::js() helpers, no host-side npm install required.

License

MIT. See LICENSE.

ผู้พัฒนา

พัฒนาและดูแลโดย บริษัท ภัทรชัย อาร์ทิซาน จำกัด (Phattarachai Artisan) บริษัทที่ปรึกษาและพัฒนาเว็บ ที่เรียนรู้และแบ่งปันกับชุมชน Laravel แพ็กเกจนี้แบ่งปันให้ชุมชนนำไปใช้และต่อยอดได้อย่างอิสระ

ดูแพ็กเกจอื่นของเราได้ที่ phattarachai.dev/open-source และติดต่อเราได้ที่ phattarachai.dev


All versions of mail-log-laravel with dependencies

PHP Build Version
Package Version
Requires php Version ^8.4
illuminate/console Version ^12.0 || ^13.0
illuminate/contracts Version ^12.0 || ^13.0
illuminate/database Version ^12.0 || ^13.0
illuminate/http Version ^12.0 || ^13.0
illuminate/mail Version ^12.0 || ^13.0
illuminate/queue Version ^12.0 || ^13.0
illuminate/routing Version ^12.0 || ^13.0
illuminate/support Version ^12.0 || ^13.0
illuminate/view Version ^12.0 || ^13.0
spatie/laravel-medialibrary Version ^11.0
Composer command for our command line client (download client) This client runs in each environment. You don't need a specific PHP version etc. The first 20 API calls are free. Standard composer command

The package phattarachai/mail-log-laravel contains the following files

Loading the files please wait ...