stayallive/laravel-mail-css-inliner
Installation:
composer require stayallive/laravel-mail-css-inliner
The package auto-registers via Laravel’s service provider discovery—no manual configuration required.
First Use Case:
Send an email with embedded CSS (e.g., <style> tags or <link> references) in your Blade template:
Mail::to('user@example.com')->send(new AppMail());
The package automatically inlines CSS during SwiftMailer’s rendering phase. No additional code needed.
Where to Look First:
Stayallive\MailCssInliner\MailCssInlinerServiceProvider (handles SwiftMailer plugin registration).Stayallive\MailCssInliner\SwiftMailer\CssInlinerPlugin (core inlining logic).php artisan vendor:publish --provider="Stayallive\MailCssInliner\MailCssInlinerServiceProvider"
Default Inlining:
Mail facade or SwiftMailer directly.<!-- Before -->
<style>
.button { background: #000; color: #fff; }
</style>
<button class="button">Click</button>
<!-- After (inlined) -->
<button style="background: #000; color: #fff;">Click</button>
Conditional Inlining:
inlineCss() method on SwiftMailer’s Message object to manually control inlining:
$message = (new \Swift_Message())
->setBody($html, 'text/html')
->inlineCss(); // Explicitly inline CSS
Excluding Specific Emails:
$message->getHeaders()->addTextHeader('X-Mail-Css-Inliner', 'false');
Customizing Inlined Styles:
css_inliner.php to:
['allowed_properties' => ['font-size', 'color']]).Integration with Mailable Classes:
Mailable to add custom logic:
public function build()
{
$this->withSwiftMessage(function ($message) {
if ($this->shouldInlineCss()) {
$message->inlineCss();
}
});
}
Testing:
$plugin = new \Stayallive\MailCssInliner\SwiftMailer\CssInlinerPlugin();
$transport = new \Swift_Transport_Memory();
$mailer = new \Swift_Mailer($transport);
$mailer->registerPlugin($plugin);
Markdown mailer (CSS in Markdown files is inlined).Performance Overhead:
CSS Specificity Issues:
/* External */
.button { color: red !important; }
/* Inlined */
<button style="color: blue;">Click</button>
Result: blue wins due to !important in external CSS. Use the allowed_properties config to restrict !important.Media Queries:
@media screen) are stripped. To preserve them:
// In config/css_inliner.php
'preserve_media_queries' => true,
URL Resolution:
<link href="css/styles.css">) must be accessible during inlining. Use absolute URLs or ensure the file is publicly available.SwiftMailer Version Conflicts:
composer require swiftmailer/swiftmailer:^6.0
Debugging Inlined Output:
Message body:
$message->setBody($html)->inlineCss();
\Log::debug($message->getBody());
Custom Inliner Logic:
$this->app->bind(\Stayallive\MailCssInliner\Contracts\CssInliner::class, function () {
return new CustomCssInliner();
});
Whitelisting Properties:
// config/css_inliner.php
'allowed_properties' => ['color', 'font-size', 'font-weight'],
Fallback for Broken Emails:
fallback_css config to inject default styles if inlining fails:
'fallback_css' => '<style>.fallback { color: #000; }</style>',
Testing Edge Cases:
<style> tags.--primary-color).class="btn btn--primary").Monitoring:
inlineCss method:
try {
$this->inliner->inline($message);
} catch (\Exception $e) {
\Log::error("CSS inlining failed: " . $e->getMessage());
}
Performance Tuning:
if ($message->isHtmlPart()) {
$message->inlineCss();
}
How can I help you explore Laravel packages today?