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

Email Bundle Laravel Package

druidvav/email-bundle

Symfony 4 bundle for transactional emails with Twig subject/text/HTML templates, Emogrifier CSS inlining and optional caching, embedded images, lifecycle events, locale switching, and multiple sender profiles via Symfony Mailer.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Bottom line: this is a Symfony 4.4 bundle, not a Laravel package. It cannot be installed into a Laravel application as-is, and it should not be treated as a dependency. It is, however, a compact and readable feature specification for a transactional-email pipeline — and two of its three core mechanisms are already present in modern Laravel. Recommendation: harvest the design, do not adopt the artifact.

Architecture fit

  • The bundle is a Symfony Bundle subclass that depends on FrameworkBundle, TwigBundle, EventDispatcher, Translation, ServiceLocator, and optionally Doctrine/Gedmo Translatable. None of that container wiring, bundle registration (config/bundles.php), or dv_email config tree maps onto Laravel's service providers, config/mail.php, or its event system. There is no compatibility shim worth writing.
  • What it actually delivers is orchestration: Twig-rendered subject/text/HTML, CSS inlining via Pelago Emogrifier, cid: image embedding, four lifecycle events (BeforeRenderHtmlEvent, AfterRenderHtmlEvent, BeforeSendEvent, AfterSendEvent), per-render locale switching with state restore, multiple sender profiles mapped to named MailerInterface services, and an alias-based message locator.
  • Mapped to Laravel, this is a single MailComposer-style service plus a config array. Laravel already ships symfony/mailer (9+) and tijsverkoyen/css-to-inline-styles (used by Markdown mail), and exposes MessageSending/MessageSent events that correspond directly to the bundle's before/after-send hooks. $message->embed() covers cid: images. App::setLocale() covers the locale listener. The bundle's marginal value over native Laravel is roughly the config schema and the event naming convention.

Integration feasibility

  • Direct composer require: not viable. Symfony ^4.4 component constraints (4.4 reached end of life in November 2023) will collide with any Laravel 10/11 install requiring Symfony 6/7 components. The failure mode is dependency-resolution failure, not runtime failure — which at least fails fast.
  • Sidecar microservice (Symfony 4.4 app exposing a render/send endpoint): technically possible, adds a deploy target, a network hop, a second auth surface, and a second EOL framework to patch — all to obtain CSS inlining and image embedding that Laravel does natively. Reject unless a Symfony 4.4 application already exists in the estate and the bundle is being used there.
  • Port the feature set into an internal Laravel package: the realistic path. Scope is small.

Technical risk

  • Licensing (blocking for code reuse): the repository shows no license file or license statement in the README. Copying source into a commercial codebase without a license is a legal exposure. Options are to obtain written permission from the maintainer, or reimplement from the documented behavior rather than the code. Escalate this before any engineering time is spent.
  • Maturity/viability: 0 stars, 0 dependents, single maintainer, README-only documentation (in Russian), and the cited release note is a one-line annotation fix — i.e., the project is on life support and the release does not indicate active feature development. Bus factor is 1.
  • Platform decay: pinned to Symfony 4.4 and PHP ≥7.4. Any fork inherits an unsupported framework baseline.
  • Semantic drift in the source assessment: the earlier TPM note cites SwiftMailer; the current package uses symfony/mailer (SwiftMailer migration documented in MIGRATION.md). Any evaluation relying on that note is stale.
  • Feature-level risk if ported naively: Emogrifier-era CSS inlining does not support flexbox/grid or media queries reliably across Outlook/Gmail; per-render locale mutation is dangerous under queue Workers where state persists across jobs.

Key questions

  1. Is the real requirement "inlined-CSS, image-embedded transactional email with per-recipient locale," or "reuse this code"? Only the first is a valid driver.
  2. Is there an existing Symfony 4.4 application in the estate for which this bundle is genuinely the right answer? If yes, that is the only place it should live.
  3. Can we get written permission or a license grant for derived code, or is clean-room reimplementation required?
  4. What are the delivery volume, latency SLO, and queueing expectations? Volume determines whether a queue is mandatory rather than optional.
  5. Who owns the resulting internal package, and what is the patch policy when Laravel's mail stack changes?

Integration Approach

Stack fit (feature-by-feature mapping)

Bundle capability Laravel-native equivalent Verdict
Twig subject/text/HTML render Blade Mailable::build() / Markdown mail Reimplement in Blade
Emogrifier CSS inlining + cache tijsverkoyen/css-to-inline-styles (already a framework dependency) Free
cid: image embedding $message->embed() / embedData() Free
Before/AfterRenderHtml events Pre-build hook or view composer Trivial
Before/AfterSend events MessageSending / MessageSent listeners Free
Locale switch + restore App::setLocale() / Mail::locale() Free — Laravel has this built in
Multiple sender profiles Named mailers in config/mail.php + Mail::mailer('x') Free
Message locator by alias Container binding / config map Trivial
SMTP failover Mailer DSN failover(...) Free

The honest read of this table: eight of nine capabilities are already in the framework. The port is a thin configuration-driven facade, not a migration project.

Migration path

  1. Spike (1–2 days): attempt composer require druidvav/email-bundle in a throwaway Laravel 11 app and record the exact constraint conflict. Deliverable: a one-paragraph "why not" that closes the door permanently and prevents re-litigation.
  2. Behavior extraction (2–3 days): document the dv_email config schema and event contract as the spec for an internal acme/mail-kit package. Implement render → inline → embed → dispatch → send with Blade views and the framework's existing inliner.
  3. Parity build (3–5 days): one Mailable per template, config-driven sender alias and locale, feature-flagged dispatch.
  4. Cutover: migrate template-by-template behind a flag; in staging, dual-send and diff the resulting HTML and headers before switching.
  5. Decommission: remove the old mail paths, delete the flag.

Compatibility

  • If the sidecar route were ever chosen: pin PHP 8.x, fork the bundle onto Symfony 5.4/6.4 LTS, and run composer why-not against the target stack first. Budget for a security-patch cadence the upstream project does not provide.
  • If porting: no compatibility surface remains, which is the point. Laravel's MessageSending/MessageSent event payloads are stable public API; Blade and the CSS inliner are framework-level and versioned with Laravel itself.

Sequencing Legal/license clearance → spike to prove incompatibility → spec extraction from README and behavior → internal package → flagged rollout → flag removal. Do the licensing check before step 2; it is the only step that can invalidate the plan.


Operational Impact

Maintenance

  • As a dependency: you would inherit an EOL Symfony baseline, a single unpaid maintainer, and a Russian-language documentation set. Not acceptable for production.
  • As an internal port: ~200–400 lines under your own CI, PHP-version matrix, and code review. Maintenance cost is effectively zero until Laravel changes its mail internals, which it does rarely and with deprecation notice.
  • Do not vendor the source. If the code is ever copied, record the license grant in the repo.

Support

  • Upstream support is effectively absent: no dependents, no issue activity signal, no stated SLA. Any production incident is yours to diagnose. This is a strong argument for the port — you cannot escalate to a maintainer who has no incentive to respond.
  • Translation burden: the README and release notes are in Russian. The behavioral surface is small enough that a single engineer can absorb it, but do not assume the wider team can read the docs unaided.

Scaling

  • Rendering is CPU-bound: template compile plus CSS inlining per message. The bundle caches preprocessed HTML in kernel.cache_dir, which is a per-host cache and not safe to rely on across a horizontally scaled fleet without thinking about invalidation.
  • Anything above low-hundreds of messages per minute needs a queue in front of it. Laravel Queues + Horizon with a dedicated mail queue is the answer; the bundle's design has no queueing concept at all (failover is delegated to the Mailer DSN, which is transport resilience, not throughput).
  • Embedded images inflate payload size — enforce image budgets and prefer hosted-with-fallback over inline for large assets.

Failure modes to design against

  • Locale state leakage under workers. The bundle mutates RequestContext and translator locale, then restores. In a long-lived queue Worker, an exception mid-render leaves the process in the wrong locale for the next job. Port must use try/finally or, better, pass locale explicitly per message.
  • CSS inlining limits. No reliable flexbox/grid, media queries stripped or unsupported in Outlook. Templates must be table-based; QA on real clients, not just a browser.
  • Broken images in Outlook/Gmail if cid: embedding is skipped and remote URLs are used behind authentication.
  • Config/alias typos fail at send time, not boot time. Validate sender-alias and template-path configuration at deploy time via an artisan command or a boot-time assertion.
  • Silent drops. Neither the bundle nor Laravel surfaces asynchronous bounces out of the box; add webhook ingestion (SES/Postmark/SendGrid) if delivery assurance is a requirement.
  • Cache directory permissions in containerized deploys where kernel.cache_dir may be read-only.

Ramp-up

  • Reading and understanding the feature set: half a day for a mid-level Laravel engineer.
  • Port plus tests: roughly 1–2 engineer-weeks, including the spike, spec, internal package, per-template migration, and staging dual-send verification.
  • Ongoing ownership: nominally none, realistically a few hours per quarter for dependency updates. Assign a named owner anyway — unowned internal mail packages are a classic silent-rot failure.
  • No Twig expertise is required for the port; Twig knowledge is only needed if someone insists on forking the original.
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.
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core