dmcbrn/laravel-email-database-log
Log every email your Laravel app sends straight to the database. Captures recipients, subject, HTML and text bodies, headers, and send status for easy debugging, auditing, and resending, with configurable logging rules and a queryable Eloquent model.
Architecture fit. The package is a thin, event-driven add-on: it hooks Laravel's mail lifecycle events (MessageSending / MessageSent) and persists recipient, subject, headers, and body to a dedicated database table. It does not touch the Mail facade, transport, or queue internals, so it composes cleanly with a conventional Laravel application and any transport (SMTP, SES, Mailgun, Postmark). There is no service provider sprawl, no external dependency, and no runtime service to operate — the only persistent artifact is one table plus a config file. For a TPM, this is squarely "low architectural surface area."
Integration feasibility. Install is composer require, publish config and migration, php artisan migrate, and set options. A Laravel developer can complete a dev-environment spike in under a day. The real gating item is version compatibility: Laravel 9+ replaced SwiftMailer with Symfony Mailer, and mail event payload shapes changed. With 16 stars and a single maintainer, the composer.json constraints and CI matrix must be verified against our target Laravel/PHP versions before we commit — not inferred from the README.
Technical risk.
Key questions for the maintainer / spike.
Mail::mailer() overrides?Stack fit. Standard Laravel app on MySQL/Postgres; also works on SQLite for local dev. No infrastructure additions — no Redis, no queue worker required (though queuing the listener is desirable at volume). Fits both monolith and modular codebases.
Migration path. Additive and reversible: one migration, one config file, no changes to existing mail code. Rollback is migrate:rollback plus removing the provider. This makes it a low-blast-radius change we can land behind a config flag and disable instantly.
Compatibility. Pin an exact version, verify composer.json constraints against our Laravel/PHP baseline, and run the test suite against the version we actually deploy. If constraints are loose or absent, treat the package as "vendored source" rather than a dependency.
Sequencing.
to, created_at, and subject for the support workflow, and an admin/read-only UI or query path.app/Support — an estimated 1–3 days of engineering, which is the true ceiling on this dependency.Maintenance. Minimal ongoing code maintenance, but non-zero ownership: version pinning, upgrade testing on each Laravel major, and a standing fork contingency. The package's small size is both the reason it's cheap to own and the reason it's cheap to replace.
Support. Community-only, no SLA, effectively no upstream support contract. Internal ownership must be explicit — name a team and a person. Documentation is likely a README; expect to write our own runbook for the table and retention job.
Scaling. Write amplification is one insert per outbound email. At low thousands/day this is a non-issue. At high volume, plan for: queuing the listener (ShouldQueue) to decouple from the send path, partitioning or archiving the table by month, and dropping body storage in favor of metadata. Email log tables are a classic unbounded-growth problem — retention must ship with the feature, not after.
Failure modes.
Ramp-up. Hours, not days, for any Laravel developer. The learning curve is not the package — it's the retention policy, the PII decision, and the support workflow built on top. Budget TPM/product time for the compliance call, not engineering time for the install.
Recommendation. Adopt as a low-cost, reversible audit capability, with three conditions: (1) verify Laravel/PHP compatibility in a spike before committing; (2) make body storage an explicit, reviewed decision rather than a default; (3) ship retention and a canary test in the same release. Treat the dependency as forkable from day one.
How can I help you explore Laravel packages today?