Weave Code
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

Fin Mail Laravel Package

finity-labs/fin-mail

FinMail adds an email template manager and composer to Filament. Create dynamic, translatable templates with token/merge-tag replacement, CTA blocks, and versioning. Send from any resource via a reusable action, with full email logging and status tracking.

View on GitHub
Deep Wiki
Context7
v1.13.1

Fixed

  • Nested {% if %} conditionals now work at any depth, with {% else %} supported on every level. Previously the first {% endif %} closed the outermost {% if %}, so any nested conditional produced broken output. Conditionals are now parsed in a single pass with a frame stack, and malformed markup (a stray {% else %}/{% endif %} or an unclosed {% if %}) stays visible in the output instead of silently losing content (thanks @Pycckoe, whose fork flagged the limitation)

Full Changelog: https://github.com/finity-labs/fin-mail/compare/v1.13.0...v1.13.1

v1.13.0

Added

  • Extendable resources — register your own subclass of any built-in resource on the plugin: ->emailTemplateResource(MyResource::class), ->emailThemeResource(...), ->sentEmailResource(...) (#22)
  • Authorization without Shield — the policyNamespace() policy mapping now registers policies whenever the classes exist, with or without Shield installed. Settings pages can be gated by defining Gate abilities named after the page class (page_ManageGeneralSettings, …); pages without a defined ability stay open as before (#21)
  • Per-email branding overridesTemplateMail::withoutLogo() sends without the branding logo, and overrideBranding([...]) overrides any branding key (logo, colors, footer links, …) for a single email while the rest falls through to the saved settings (#8)

Full Changelog: https://github.com/finity-labs/fin-mail/compare/v1.12.0...v1.13.0

v1.12.0

Added

  • New auth_emails.store_rendered_body config option (default false). When enabled, the password reset and verification overrides store their rendered body in the Sent Emails log like any other email, for teams that want a full audit trail of exactly what was sent. Left off, the signed reset/verification URLs stay out of the database

Fixed

  • Files uploaded in the Compose Email page's Attachments section are now actually attached to the sent email and recorded in the log. The upload field dehydrated under a key the sender never read, so uploads were silently discarded while the UI reported success
  • Editing the preheader on the Compose Email page now affects the delivered email. The form collected the value and the preview showed it, but the sender had no way to pass it through — TemplateMail gained overridePreheader() and the compose path uses it. Tokens in the overridden preheader are replaced like in the body
  • Sending from the composer no longer throws a TypeError when the configured editor stores the body as a TipTap document array (e.g. the Tiptap editor). The preview already converted the document to HTML; the send path now does the same, using the template's theme colors for custom blocks
  • The requested template locale now survives every queue path: log creation and stored-body rendering are wrapped in the mailable's locale, so a TemplateMail whose log entry is first created after queue serialization (e.g. dispatch-time log insert failed, or the mailable was re-dispatched from a stored job) no longer renders in the worker's app locale
  • Auth email overrides no longer break authentication when their template is unavailable: if user-verify-email or user-password-reset is missing, deactivated, or errors during lookup, the notification falls back to Laravel's default mail instead of throwing — deactivating a template can no longer take down password reset app-wide
  • Verification and password reset emails sent through the auth overrides no longer store their rendered body in the Sent Emails log. The bodies contain signed URLs; the log entry itself is still created, as the documentation always described
  • Locked templates now enforce their key and category protection server-side. The fields were only disabled() in the form but still dehydrated, so a crafted request could rewrite a locked system template's key — which the auth email overrides depend on
  • Switching languages while editing a template no longer discards unsaved work. The edit page now stashes in-progress translations per locale (like the create page always did), restores them when switching back, keeps unsaved non-translatable edits (theme, tags, sender) intact across the switch, and persists every stashed locale on save
  • Only one theme can be the default now, enforced on the model for every write path. Previously the uniqueness lived in a form callback that only ran when editing an existing theme — creating a new theme with "default" toggled on produced two defaults, and which one actually applied was undefined. The premature form callback (which rewrote other themes before the form was even saved) is gone
  • Deleting themes in bulk now detaches their templates like single deletes always did. The detach logic moved from two duplicated action callbacks into a model deleting hook, so every delete path behaves the same — including on SQLite databases without foreign key enforcement (enforcing databases were already covered by the FK's nullOnDelete)
  • The stored-email viewers now render the email HTML in a sandboxed iframe (sandbox="allow-same-origin"), matching the template preview. Stored bodies can contain recipient-influenced content, and the unsandboxed frames allowed scripts to run inside the admin panel
  • Replicating a template now suggests a readable, collision-free key (invoice-copy, invoice-copy-2, …) instead of a -copy-<timestamp> suffix that could collide when two replications happened in the same second
  • Resending from the Sent Emails relation manager now behaves exactly like resending from the Sent Emails page: stored HTML sent verbatim (no re-wrapping in the layout, no re-running token replacement) and original attachments re-attached when they still exist. The two actions had drifted apart — the relation manager was still re-wrapping the full stored document (the bug fixed for the resource in 1.11.3) and silently dropped attachments. Both now share one SentEmailResender service

Full Changelog: https://github.com/finity-labs/fin-mail/compare/v1.11.4...v1.12.0

v1.11.4

Fixed

  • The language switcher dropdown on the email template view page now highlights the newly selected language immediately. The active-state color was evaluated while the header actions were being cached — before the locale switch ran — so the highlight lagged one click behind the button label and the page content (#27, thanks @Brett-Mulder)

Full Changelog: https://github.com/finity-labs/fin-mail/compare/v1.11.3...v1.11.4

v1.11.3

Fixed

  • The scheduled fin-mail:cleanup command now registers reliably: registration uses callAfterResolving(), so it also works when the schedule was already resolved before the package booted — previously the command could silently never appear in schedule:list (#26, thanks @agencetwogether)
  • Resending an email from the Sent Emails log now sends the stored HTML verbatim through a new raw passthrough mode on TemplateMail, instead of re-wrapping the full stored document in the email layout — which produced a nested document with two doctypes and broken logo/footer sections (#25, thanks @agencetwogether)
  • Resent emails re-attach the original files when they still exist on disk; previously the new log entry listed the attachments but the resent email carried none

Full Changelog: https://github.com/finity-labs/fin-mail/compare/v1.11.2...v1.11.3

v1.11.2

Fixed

  • Saving the logging settings no longer throws (or, where warnings are silenced, silently resets the cleanup schedule to Daily) when Filament hands the cleanup frequency back as an enum instance instead of a scalar (#24, thanks @agencetwogether)

Full Changelog: https://github.com/finity-labs/fin-mail/compare/v1.11.1...v1.11.2

v1.11.1

Fixed

  • The "individual emails sent" notification now pluralizes correctly: ComposeEmail picks the right form via trans_choice(), and 37 locales gained singular|plural variants for the notification body. Locales without grammatical plural after numerals keep their single form

Full Changelog: https://github.com/finity-labs/fin-mail/compare/v1.11.0...v1.11.1

v1.11.0

Added

  • Automatic logging for programmatic sendsTemplateMail now creates a Sent Emails log entry on its own whenever logging is enabled in the settings, so emails sent from code show up in the log just like ones sent from the admin panel. Queued mail is logged at dispatch time with a Queued status and updated to Sent or Failed once the worker processes it. Log creation failures are reported but never block the email from going out (#23, thanks @gazohu)
  • Log entries now record who sent the email: the authenticated user at the time the mailable is built is carried across queueing, so queued mail is attributed to the person who triggered it instead of nobody. System-triggered mail (jobs, listeners, guest-initiated resets) is logged without a user
  • TemplateMail::withoutLogging() opts a single email out of logging
  • TemplateMail::withLogging() called without an argument now forces a log entry even when logging is disabled in the settings. Passing a SentEmail still hands over an externally created record, as before — previously a bare withLogging() call silently did nothing
  • TemplateMail::withoutStoringRenderedBody() logs the email but keeps the rendered HTML out of the database

Changed

  • The built-in welcome, password reset, and email verification notifications now appear in the Sent Emails log when logging is enabled. Reset and verification emails never store their rendered body, since it contains signed URLs

Full Changelog: https://github.com/finity-labs/fin-mail/compare/v1.10.0...v1.11.0

v1.10.0

Added

  • Delivery-mode chooser for multi-recipient composes — when the Compose Email "To" field holds more than one address, the send confirmation now asks whether to deliver a separate email to each recipient (recipients don't see each other) or one combined email addressed to everyone, with a note that the full recipient list is visible in that case (#20, thanks @mrsafalpiya)
  • EmailSender gained a notify constructor flag so callers batching multiple sends can suppress the per-send notification and show an aggregate one instead

Changed

  • The send-mode help texts spell out how CC/BCC behave in each mode: in individual mode CC/BCC contacts receive a copy of every email, and in combined mode the "To" and CC lists are visible to every recipient (BCC stays hidden)
  • All 59 non-English locales received translations for the new send-mode strings

Full Changelog: https://github.com/finity-labs/fin-mail/compare/v1.9.0...v1.10.0

v1.9.0

Added

  • App-relative logo resolution — branding logos configured as relative paths (e.g. /images/logo.png) are now resolved to absolute URLs at render time via BrandingSettings::resolvedLogo(), so they display in email clients. Absolute URLs, protocol-relative URLs, and data URIs pass through unchanged (#19, thanks @mrsafalpiya)

Fixed

  • Button and other custom blocks were replaced with plain text when a template was loaded into the Compose Email editor, and were missing from the sent email. EmailTemplate::render() gained a renderBlocks flag so blocks round-trip in the editor, and TemplateMail now expands blocks in overridden bodies (#17, thanks @mrsafalpiya)
  • Templates without an assigned theme now fall back to the user-configured default theme instead of the package's hardcoded colors — in the preview, the body infolist, and the sent email. New helpers: EmailTheme::resolvedDefaultColors() and EmailTemplate::resolvedThemeColors() (#18, thanks @mrsafalpiya)
  • Theme colors stored as null or an empty string (cleared ColorPickers) no longer override the hardcoded defaults when resolving colors

Full Changelog: https://github.com/finity-labs/fin-mail/compare/v1.8.1...v1.9.0

v1.8.1

Fixed

  • Undefined array key "cleanup_frequency" when saving the Logging settings with Enable Schedule Cleanup turned off. The frequency field is hidden in that state, so it isn't submitted — the save mutation now casts it only when it's present and leaves the stored value untouched otherwise (#16, thanks @Wijnands)

Full Changelog: https://github.com/finity-labs/fin-mail/compare/v1.8.0...v1.8.1

v1.8.0

Added

  • Per-email view override — New overrideView() method on TemplateMail renders an email with your own Blade layout instead of the package's fin-mail::email.default, while keeping database-driven templates, token replacement, theming, logging, and attachments. The custom view receives the same variables as the default one ($body, $preheader, $theme, $branding) plus anything passed via with() or extraData(). Existing emails are unaffected if you don't call it (#14, thanks @agencetwogether)

Full Changelog: https://github.com/finity-labs/fin-mail/compare/v1.7.1...v1.8.0

v1.7.1

Fixed

  • MissingSettings exception during artisan boot when scheduled cleanup is registered before the fin-mail-logging settings have been migrated. The catch around app(LoggingSettings::class) didn't cover the lazy property access that actually triggers the load, so the exception escaped and broke package:discover and fin-mail:install in some setups (#13, thanks @devrizzz)

Notes

  • spatie/laravel-settings is now mentioned explicitly in the README as an auto-installed dependency

Full Changelog: https://github.com/finity-labs/fin-mail/compare/v1.7.0...v1.7.1

v1.7.0

Added

  • Permission gating for custom actionsPreview, SendTest, Compose (Email Templates) and Resend (Sent Emails) are now hidden from the UI when Filament Shield is installed and the authenticated user lacks the corresponding permission. Falls back to the previous always-visible behavior when Shield is absent, so existing installs are unaffected (#12, thanks @agencetwogether)
  • FinMailPlugin::isShieldAvailable() helper for checking Shield presence
  • preview_heading translation key for the preview modal header, populated across all 58 supported locales

Changed

  • InstallCommand now seeds preview, sendTest, compose, and resend into the Filament Shield config so shield:generate produces the matching policy methods and permissions
  • Bulk delete on the Email Templates table now uses authorizeIndividualRecords('delete') when Shield is active

Notes

  • After upgrading on a Shield-enabled install, run php artisan shield:generate --panel=admin --option=policies_and_permissions to register the new permissions

Full Changelog: https://github.com/finity-labs/fin-mail/compare/v1.6.0...v1.7.0

v1.6.0

Added

  • Pass extra view data to email templates — New extraData() method (and native with() support) on TemplateMail for passing variables directly to the Blade view, separate from the token replacement system. Useful for view-only data that doesn't need to flow through the token engine (#10, thanks @agencetwogether)

Fixed

  • Reply-To section was missing from the email template infolist (view page). It's now displayed alongside the Custom Sender section (#11, thanks @agencetwogether)
v1.5.0

Added

  • Reply-To support for templates — Each template can now have its own reply-to address and name, configurable from the template settings tab. Falls back to null if not set, so existing templates are unaffected. The TemplateMail mailable also gains an overrideReplyTo() setter for runtime overrides (#9, thanks @agencetwogether)
  • Reply-to translations added to all 58 supported locales

Notes

A new migration is included (add_reply_to_on_email_templates_table). Run php artisan migrate after upgrading.

v1.4.1

Fixed

  • Migrations now use configured table names from fin-mail.php config instead of hardcoded defaults, fixing issues with foreign key references when table names are customized (#7, thanks @agencetwogether)
v1.4.0

Added

  • Custom block registration — Register your own editor blocks via FinMailPlugin::make()->customBlocks([...]). Custom blocks now render correctly in the editor, preview mode, and sent emails. ButtonBlock is always included by default. Closes #6

Changed

  • Block rendering in EmailTemplate, TipTapConverter, and DefaultEditor now reads from a dynamic plugin-level registry instead of a hardcoded list
v1.3.0

What's new

  • Configurable date formattingdate_format and datetime_format config options with per-locale array support
  • Token fields in test email modal — Input fields for documented tokens, pre-filled with example values
  • Full rendered body storage — Sent emails store the complete HTML as delivered, not just inner body
  • Sent email infolist — Proper Filament infolist replaces the old blade view
  • Laravel 13 support

Fixes

  • Test emails from template list now logged in sent emails
  • Sent email preview renders with full styling
  • Missing translations for 58 languages

See CHANGELOG.md for full details.

v1.2.0

What's new

Added

  • Version History UI — Version history now displays in a proper Filament table with per-row preview and restore actions
  • Version Preview — Preview any version's email content directly from the version history modal
  • Version Restore — Restore any previous version with one click; current content is automatically saved as a new version first
  • Upgrade Command — New php artisan fin-mail:upgrade command to migrate existing data after package updates (supports --dry-run)

Fixed

  • Versioning not working — Version cleanup query was deleting all versions instead of keeping the most recent ones
  • Version history crash — Subject column was passed as an array to Str::limit(), causing a TypeError
  • Seeded template buttons stripped by editor — Inline-styled <a> tags in seeded templates were stripped by TipTap; buttons now use the native customBlock format
  • Custom blocks not rendered in previews — Button blocks were not converted to visible HTML in the View and Compose page previews
  • Button preview ignores theme colors — Button block preview in the RichEditor now reflects the selected template theme

Changed

  • Added blocks and versioning translation keys for all 59 supported languages
  • Button block default labels now use translation keys instead of hardcoded English

Upgrading from v1.1.0

composer update finity-labs/fin-mail
php artisan fin-mail:upgrade

Full changelog: https://github.com/finity-labs/fin-mail/blob/main/CHANGELOG.md

v1.1.0

What's New

Merge Tags — Tokens are now available directly in the editor toolbar. No more switching to the Tokens tab to remember what's available.

CTA Button Block — Insert styled call-to-action buttons from the custom blocks panel. Set the text, URL, and alignment — theme colors are applied automatically.

Inline Link Styling — Links in email body now render with the correct theme color in all email clients, including those that strip <style> blocks.

Live Theme Preview — Change a color in the theme editor and see it update instantly.

Custom Theme Auto-Setup — The install command now detects your custom Filament theme CSS and offers to register FinMail styles automatically.

Bug Fixes

  • Email preview shows current form content instead of last saved state
  • Token replacement works properly in compose page emails
  • Replicate action shows editable modal and redirects to edit page
  • Fixed uninstall with fluent plugin configuration
  • Fixed Portuguese translations

Full Changelog: https://github.com/finity-labs/fin-mail/compare/v1.0.1...v1.1.0

v1.0.1

Fixed

  • Install command now publishes and runs the spatie/laravel-settings migration automatically if the settings table doesn't exist yet — no more crashes on fresh installs
  • Resources (Templates, Themes, Sent Emails) were hidden when Filament Shield wasn't installed, because the bundled policies denied access unconditionally. Removed the bundled policies — without Shield, everything is accessible by default

Added

  • policyNamespace() option on the plugin, so Shield-generated policies can live anywhere (defaults to App\Policies)
  • Dependency conflict workaround documented in README for projects with phpdocumentor/reflection-docblock 6.x

Changed

  • Shield policy mapping now happens in the service provider via Gate::policy() instead of relying on bundled policy files. This means Shield generates the policies (as it should), and FinMail just wires them up to the right models
v1.0.0
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.
calmfox/watch-sylius
damienfern/grpc-symfony-bundle
atoolo/index-bundle
atoolo/genai-bundle
coprotoai/laravel-ticket
davidjln/llm-carbon-bundle
cryonighter/valid-request-bundle
coolms/taxonomy-bundle
coolms/field-bundle
articulate-orm/symfony
aaix/laravel-tall-architect
ephoto/akeneo-connector
emmanuelballery/eb-plantumlbundle
emielburgman/symfony-visitor-beacon
emielburgman/symfony-visit-storage
emielburgman/symfony-security-headers
emielburgman/symfony-log-viewer
emarref/xdebug-bundle
emarref/pubnub-bundle
elriseio/finance-money-bundle