Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Nova Mail Laravel Package

kirschbaum-development/nova-mail

A Laravel Nova tool for previewing and testing your application's mailables. Browse mail classes in Nova, inspect rendered emails, and send test messages without temporary routes, speeding up email development and debugging.

View on GitHub
Deep Wiki
Context7

Getting Started

Confirm the baseline before writing any code. Nova Mail is a Nova tool + action; it is only worth installing on a Laravel Nova 4 app. Release 4.9.0 is the Nova 4-compatible line, and there has been no release since 2022-06-21. First move is a constraint check, not an install:

composer show laravel/nova | grep versions
php -v
composer why-not kirschbaum-development/nova-mail

If you are still on Nova 3, stop — sequence this behind the Nova 4 upgrade instead of adopting it independently.

Install and register. Standard Nova package lifecycle:

composer require kirschbaum-development/nova-mail:^4.9
php artisan vendor:publish --provider="KirschbaumDevelopment\NovaMail\NovaMailServiceProvider"

Then register the tool in app/Providers/NovaServiceProvider.php (exact class name will be in the README — verify, the package has been renamed/re-namespaced over its life):

public function tools()
{
    return [
        new \KirschbaumDevelopment\NovaMail\NovaMail(),
    ];
}

Run php artisan nova:publish if the tool ships assets you intend to own.

Look here first, in this order:

  1. config/nova-mail.php — this is the whole integration surface. It is the registry of Mailables exposed in the panel. Everything else is UI.
  2. The package README screenshots — they tell you faster than the code whether the shipped surface is a composer/preview tool, a Model Event trigger config, or both. The description and the 4.9.0 release notes disagree on this; resolve it before you plan anything.
  3. resources/js/ — DetailField.vue and the send-mail modal are what you'll diff on every upgrade.

First use case — one Mailable, staging transport, send to yourself. Do not start with "expose all Mailables." Register exactly one:

// config/nova-mail.php
'mailables' => [
    \App\Mail\OrderConfirmation::class,
],

Point staging at a safe transport (MAIL_MAILER=log, Mailpit, or Mailhog), open the tool in Nova, and render + send. Success looks like: a non-engineer can spot a broken template and get a clear error on a send failure. If it doesn't, you've spent an afternoon and learned the answer cheaply.

Implementation Patterns

Treat the config registry as an allowlist, not a directory scan. Never auto-discover Mailables from app/Mail. Explicit listing is the only thing keeping customer PII templates out of the panel. Review the list with whoever owns data protection before shipping it.

Keep Mailables and recipients in code. The UI composes a send; it should not become the place where layout or audience lives. That keeps git blame, review, and rollback working, and keeps the panel a preview and test-send surface rather than a second, undocumented mail system.

Guard test sends with a hard allowlist in non-production. The single highest-value pattern for day-to-day use:

// app/Providers/AppServiceProvider.php
use Illuminate\Mail\Events\MessageSending;

Event::listen(MessageSending::class, function (MessageSending $event) {
    if (! app()->isProduction()) {
        $event->message->setTo(config('mail.testing_recipient'));
    }
});

Now anyone in the panel can hammer the send button without emailing a real customer.

Gate the action, not just the tool. A tool registered in NovaServiceProvider is visible to every Nova user. Restrict it to support/ops:

public function tools()
{
    return [
        (new \KirschbaumDevelopment\NovaMail\NovaMail())
            ->canSee(fn ($request) => $request->user()->hasAnyRole(['support', 'admin'])),
    ];
}

Give the panel a dedicated mailer. Define mail.testing in config/mail.php pointing at Mailpit. Then .env on staging can switch between "log only" and "real transport" without touching the package config — useful when the whole point is verifying that credentials and transports still resolve.

If you use the Model Event surface, model it as notification triggers and review the stored rows. The 4.9.0 notes describe UI-configured Model Events with column/value conditions. Two rules: (1) any event that was ever switched from Updated to another type may still carry stale column/value conditions from the pre-4.9.0 bug — re-open and re-save each one; (2) write down what each event fires on in a doc or comment, because that logic now lives in a DB row, not in code review.

Customize by publishing and committing, not by editing in place. If you change DetailField.vue or the modal markup, commit the published copy to your repo and note the upstream version in the commit message. That's what makes the next upgrade diffable.

Gotchas and Tips

Feature-surface ambiguity is the real risk. The package description reads like a Mailable preview/test-send tool. The 4.9.0 notes describe Model Event configuration, DetailField.vue visual rework, and send-mail modal HTML changes. Those imply different support burdens. Verify in staging what 4.9.0 actually ships before you document it for your team — otherwise you'll onboard people onto a feature that isn't there.

Published-asset drift is silent. Anything you publish and edit will never receive upstream changes. Re-publish to a scratch directory and diff as a routine step in your Nova upgrade runbook:

php artisan vendor:publish --provider="KirschbaumDevelopment\NovaMail\NovaMailServiceProvider" --force --tag=assets
git diff --stat resources/

Symptom to recognize: "the upgrade didn't work" reports that are actually "our 2022 fork of the modal is still rendering."

DateTime rendering changed in 4.9.0. The unsupported format() call on DateTime fields was removed. Cosmetic in most views, genuinely confusing anywhere a timestamp is the payload (audit views, event detail panes). Spot-check those screens after upgrading.

Existing Model Event rows are not repaired by upgrading. The stale column/value bug is fixed in the code path, not in the data. Sweep them.

Assume the send is synchronous and design around it. Unless the package queues internally — check SendMail action source, don't assume — the SMTP round-trip happens inside the Nova request. Slow or unreachable SMTP means a hanging modal and an opaque Nova error. Test the failure path deliberately (bad host in config/mail.php) so you know what support will see.

Pin the version explicitly and bump deliberately. The maintainer signalled intent to align the package major/minor with Laravel/Nova. If that lands, ^4.9 means something different than it does today. Treat it as a governance event and upgrade alongside Nova, never on a composer update sweep.

Debug by bypassing the panel. When a send fails through Nova but "works in the app," reproduce in Tinker with the same transport and Mailable — that isolates package wiring from mail wiring in about thirty seconds:

php artisan tinker
>>> Mail::to('[email protected]')->send(new App\Mail\OrderConfirmation($order));

Then check storage/logs/laravel.log with MAIL_MAILER=log.

Budget for fork-and-own. 74 stars, zero dependents, a single maintainer, no release since mid-2022. That's fine for auth-gated internal tooling; it is not fine for anything revenue- or compliance-critical. Name an owner, keep your customizations minimal and committed, and know who can patch the package in a day. Extension points, in order of safety: config registry → your own Mailable classes → published views → forking the Vue components. Stay as far left as your needs allow.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource
noith/settings