pelago/emogrifier
Emogrifier converts CSS styles into inline style attributes in your HTML, ensuring reliable display in email clients and mobile readers that lack stylesheet support. Useful for Outlook 2007 and Gmail quirks. Install via Composer: pelago/emogrifier.
Assessment reviewed against upstream release v8.3.0 (previous baseline: 8.2.x). Changes below are marked [v8.3.0] where they alter prior conclusions.
Mailable classes / Mailables).thecodingmachine/safe dependency has been removed (still dev-only for the upstream test suite), and sabberworm/php-css-parser is now pinned to >= 9.5.0 — so the runtime dependency graph is smaller but not zero.HtmlPruner, CssToAttributeConverter) still align with Laravel service-layer patterns. Unchanged.EmailServiceProvider exposing a CssInliner binding/facade). Unchanged.@emogrify) to inline CSS during template rendering. Unchanged.trigger_error() in production instead of throwing, returning the original string unmodified; exceptions only when the debug option is set.render() internal DOMDocument error → now throws instead of returning an empty string.
Net effect: the integration wrapper needs a try/catch and an error-handler/'debug' config strategy. This is a modest but real added integration task.debug option in non-production environments, (b) installing a Laravel error handler / set_error_handler that routes trigger_error() into your log channel and alerts, (c) canary template rendering in CI.render() throwing on internal DOMDocument failure is a safer default (previously an empty string could result in a blank email being delivered), but it converts a "silent blank" into a hard failure. Any caller assuming string return needs a fallback (e.g., send raw HTML, or fail the job with retry).:hover, @media beyond all|screen|print). Unchanged; mitigate via allowlisting.sabberworm/php-css-parser >= 9.5.0 may conflict with other packages in a large Laravel app (e.g., PDF/HTML rendering libs). Needs a Composer resolution check before upgrade.DOMDocument-based and memory-intensive for malformed HTML; validate input.trigger_error handler wired to alerting, and is 'debug' => true set in staging?render() throws, what is the desired user-facing behaviour — retry the job, fall back to raw HTML, or fail loudly? This must be a product decision, not a framework default.CssInliner::fromHtml() against production-scale templates.@font-face) handled — graceful degradation via addExcludedCssSelector()?sabberworm/php-css-parser >= 9.5.0 resolve cleanly alongside our existing dependency tree?CssInliner in a dedicated renderer rather than inlining logic inside every Mailable::build() — keeps the blast radius of the v8.3.0 exception change to one class.set_error_handler (or Laravel's Log:: + report() bridge) to capture trigger_error() emissions from regex blowouts.@emogrify) to inline CSS during compilation.CssInliner; add explicit tests for (a) the thrown-on-DOMDocument-error path and (b) the "returns original string unmodified" degradation path [v8.3.0].sabberworm/php-css-parser >= 9.5.0 resolves with the existing lockfile. Use a throwaway branch and composer why-not before committing to the upgrade.CssInliner; diff output against manual inlining (Premailer).EmailRenderer service that isolates the new exception and degradation semantics:
class EmailRenderer
{
public function render(Mailable $mailable): string
{
$html = $mailable->render();
try {
return CssInliner::fromHtml($html)
->inlineCss($mailable->css())
->render();
} catch (\Throwable $e) {
report($e); // surfaces the new DOMDocument exception
return $html; // fall back to un-inlined HTML
}
}
}
'debug' option from app()->environment().RenderEmailJob with retries + exponential backoff; decide whether a thrown render error retries or falls back.HtmlPruner; cache static templates via Cache::remember().sabberworm/php-css-parser >= 9.5.0 required; thecodingmachine/safe removed (smaller footprint).catch blocks that now never fire.@apply sparingly); Bootstrap utility classes.data-* attributes.php-css-parser and confirm PHP versions.EmailRenderer with fallback.'debug' => true in staging to surface blowouts as exceptions.render(), and trigger_error emissions from the inliner.safe removed) but the parser floor rises to >= 9.5.0. Re-run composer update --dry-run in CI to catch conflicts early.^8.3 and schedule review.DOMDocument errors, (c) deeply nested tables, (d) high-invocation loops (memory). These map 1:1 to v8.3.0 changes and are cheap to write.log channel via the error handler; use ->getDomDocument()->saveHTML() to inspect intermediate HTML.'debug' option semantics per environment, and production degradation behaviour (returns original string).'debug' => true.DOMDocument internal error now throws. Solution: try/catch with raw-HTML fallback.:nth-child). Solution: manual overrides / addExcludedCssSelector().| Failure Scenario | Impact | Mitigation |
|---|---|---|
| Malformed HTML input | DOMDocument internal error |
[v8.3.0] render() now throws (previously returned ""). Catch and fall back to raw HTML; validate input. |
| Regex blowout (pathological CSS/HTML) | Silent — un-inlined HTML delivered (changed) | [v8.3.0] Production: trigger_error() + returns original string. Set 'debug' => true below production and route errors to alerting. |
| Unsupported CSS selectors | Partial rendering | Log warnings; addExcludedCssSelector(). |
| High memory usage | Worker timeouts | [v8.3.0] Per-invocation cache clearing reduces build-up; still bound template size and set memory_limit. |
| Very deeply nested HTML | Render failure | [v8.3.0] Fixed — no longer a failure mode. |
| Queue job failures | Delayed emails | Retries with exponential backoff; distinguish transient vs. render exceptions. |
| CSS variable evaluation failures | Un-resolved values in output | Pre-resolve variables at build time; exclude unsupported declarations. |
Dependency conflict on php-css-parser |
Deploy/upgrade blocked | [v8.3.0] Validate resolution pre-upgrade in CI. |
| PHP 7.3 runtime | Unsupported / deprecated | [v8.3.0] Confirm all runtimes on PHP 8.1+; plan for v9.0. |
How can I help you explore Laravel packages today?