dophp / laravel-mail-builder
Responsive, slot-based email builder and compiler for Laravel: modular blocks, MJML/HTML import, merge tags, AMP, plain-text fallback, and pre-send audits.
Requires
- php: ^8.3
- ext-dom: *
- ext-libxml: *
- guzzlehttp/guzzle: ^7.8.2 || ^8.0
- laravel/framework: ^12.0 || ^13.0
- tijsverkoyen/css-to-inline-styles: ^2.2.5
Requires (Dev)
- filament/forms: ^5.0
- larastan/larastan: ^3.0
- laravel/pint: ^1.32
- orchestra/testbench: ^10.0 || ^11.0
- pestphp/pest: ^3.8 || ^4.0 || ^5.0
- pestphp/pest-plugin-laravel: ^3.0 || ^4.0 || ^5.0
Suggests
- ext-zip: Required to export template packages as ZIP archives
- filament/forms: Required to use the visual drag-and-drop EmailSlotBuilder component (^5.0)
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-10-01 23:29:21 UTC
README
A modular, Outlook-bulletproof email building, auditing, and compilation engine for Laravel applications.
Requires PHP 8.3+ and Laravel 12 or 13. Maintained by doPHP.
Key Features
- 29 Modular Responsive Slots: Pre-built responsive components that collapse smoothly to 100% width on mobile devices, with Microsoft Outlook MSO conditional table compatibility.
- Universal Compilation Engine: Compile modular slots or structured
EmailDocumentinstances into inlined responsive HTML (EmailSlotCompiler) or interactive AMP for Email (AmpEmailCompiler). - Liquid-Style Personalization: Fast token interpolation supporting uppercase, lowercase, capitalize, date formatting, currency, number, pluralize, default values, and inline conditionals (
{% if condition %}...{% else %}...{% endif %}). - Deliverability & Spam Auditor: Automatic pre-flight auditing calculating spam trigger scores, missing unsubscribe headers, image-to-text ratios, dark mode color inversion contrast, and live DNS deliverability checks (SPF, DMARC, BIMI).
- Multi-Device Screenshot Simulation: Adapter interface for testing email rendering across Outlook Windows (120 DPI), Apple Mail iOS 17 Dark Mode, macOS Sonoma, and Gmail Android.
- Theme & Typography Engine: Built-in design system presets (Corporate Slate, Midnight Indigo, Emerald SaaS, Warm Sunset, Monochrome Minimal) with automatic Google Fonts web font imports and Outlook fallback font stacks.
- Bidirectional Ingestion: Export templates to HTML, Plain Text, MJML, or ZIP packages—and reverse-parse external raw HTML or standard MJML into native modular slots.
- WCAG 2.1 AA Contrast Auditor: Exact mathematical relative luminance algorithm evaluating text and button contrast compliance.
- Enterprise Transport: Send via
TemplateMailablewith RFC 8058 1-click unsubscribe headers, custom attachments, and automatic CID (Content-ID) inline image embedding. - Filament Visual Builder: Full Filament builder schema component with audience targeting and conditional visibility rules.
Installation
composer require dophp/laravel-mail-builder
Publish configuration and views (optional):
php artisan vendor:publish --tag=mail-builder-config php artisan vendor:publish --tag=mail-builder-views
Configuration
config/mail-builder.php sets the default layout theme (width, fonts, colors) and the footer identity used when a slot doesn't provide one:
MAIL_BUILDER_COMPANY_NAME="Acme Inc." # defaults to APP_NAME MAIL_BUILDER_ADDRESS="123 Example St, Springfield"
CAN-SPAM and similar laws require a physical mailing address in marketing email, so set MAIL_BUILDER_ADDRESS or pass address to each footer slot.
Quick Start
1. Building and Compiling an Email
use DoPHP\MailBuilder\MailBuilder; use DoPHP\MailBuilder\Enums\SlotType; // Fluent EmailDocument API $doc = MailBuilder::document( subject: 'Welcome to the Platform, {{ contact.first_name }}!', previewText: 'Get started with your new account in 3 easy steps.' ); $doc->append(SlotType::Header, [ 'brand_name' => 'Acme Corp', 'logo_url' => 'https://example.com/logo.png', ]); $doc->append(SlotType::Hero, [ 'title' => 'Accelerate Your Workflow', 'subtitle' => 'Everything you need to deliver world-class projects.', 'button_text' => 'Get Started', 'button_url' => 'https://example.com/onboarding', ]); $doc->append(SlotType::TwoColumn, [ 'left_title' => 'Cloud Infrastructure', 'left_body' => 'Deploy high-availability services across 30+ edge regions.', 'right_title' => 'RevOps Analytics', 'right_body' => 'Real-time pipeline tracking and automated revenue forecasting.', 'reverse_stack_on_mobile' => true, ]); $doc->append(SlotType::AppBadges, [ 'heading' => 'Download Our Mobile App', 'app_store_url' => 'https://apps.apple.com/app/acme', 'google_play_url' => 'https://play.google.com/store/apps/acme', ]); $doc->append(SlotType::Footer, [ 'company_name' => 'Acme Inc.', 'address' => '548 Market St, San Francisco, CA', 'unsubscribe_url' => '{{ unsubscribe_url }}', ]); // Compile to responsive inlined HTML $html = MailBuilder::compile($doc); // Extract plain text fallback $plainText = MailBuilder::plainText($doc);
2. Personalization & Merge Tags
Personalization supports dot-notation object paths, Liquid filters, and inline conditionals:
$template = "Hello {{ contact.first_name | capitalize }}! Member since {{ contact.created_at | date: 'F Y' }}. Balance: {{ account.balance | currency: 'USD' }}. {% if contact.is_vip %}Your VIP bonus is ready.{% else %}Upgrade today.{% endif %}"; $interpolated = MailBuilder::interpolate($template, [ 'contact' => [ 'first_name' => 'alexandra', 'created_at' => '2026-03-15 10:00:00', 'is_vip' => true, ], 'account' => [ 'balance' => 1250.00, ], ]);
Built-in tags are {{unsubscribe_url}}, {{current_year}}, and {{web_view_url}}. Register your application's own tags so they appear in the Filament builder's tag picker and in previews:
use DoPHP\MailBuilder\MergeTags\MergeTagRegistry; // In a service provider's register() method $this->callAfterResolving(MergeTagRegistry::class, function (MergeTagRegistry $registry): void { $registry->register('Customer', [ '{{customer.first_name}}' => 'Customer first name', '{{customer.plan}}' => 'Subscription plan', ], [ // Sample values used when previewing templates 'customer' => ['first_name' => 'Alex', 'plan' => 'Pro'], ]); });
Available Filters:
capitalize,title,lower,upper,trimdate: 'Format'(PHPdate()formatting)currency: 'USD'number: 2(decimal places)pluralize: 'item', 'items'truncate: 50default: 'fallback value'
3. Ingestion (HTML & MJML Import)
Import external templates into editable modular slots:
// Ingest raw HTML $docFromHtml = MailBuilder::importHtml($rawHtml, 'Imported Newsletter'); // Ingest standard MJML $docFromMjml = MailBuilder::importMjml($mjmlCode, 'Imported Campaign'); // Compile imported documents directly $compiledHtml = MailBuilder::compile($docFromMjml);
4. Deliverability, Performance & Accessibility Audits
// 1. Run Pre-flight Deliverability & Spam Audit $audit = MailBuilder::audit($html); if (! $audit->passes) { // Inspect $audit->critical_issues, $audit->warnings, and $audit->spam_score } // 2. WCAG 2.1 AA/AAA Color Contrast Audit $contrast = MailBuilder::wcagContrast('#2563eb', '#ffffff'); // Returns: ['ratio' => 4.56, 'aa_normal' => true, 'rating' => 'AA'] $themeAudit = MailBuilder::auditContrast($themeArray); // 3. Render Performance Benchmark $benchmark = MailBuilder::benchmarkRender($html); // Returns: dom_nodes_count, nested_table_depth, 3G/4G/5G download times // 4. Sender Domain DNS Validation $dns = MailBuilder::validateDns('yourdomain.com'); // Checks: SPF, DMARC (p=reject/quarantine), and BIMI
5. Sending Emails via TemplateMailable
use DoPHP\MailBuilder\Mail\TemplateMailable; use Illuminate\Support\Facades\Mail; Mail::to('user@example.com')->send( new TemplateMailable( template: $doc, data: [ 'contact' => ['first_name' => 'Sarah'], 'unsubscribe_url' => 'https://example.com/unsubscribe/token', ], subjectLine: 'Exclusive Offer for {{ contact.first_name }}', embedCidImages: true // Embeds local & base64 images as MIME CID parts ) );
6. Filament Visual Builder Integration
Requires filament/forms ^5.0. To integrate the modular slot builder into any Filament Resource:
use DoPHP\MailBuilder\Filament\Components\EmailSlotBuilder; public static function form(Schema $schema): Schema { return $schema->components([ EmailSlotBuilder::make('slots'), ]); }
Supported Slot Types (29 Total)
| Slot Type | Key | Description |
|---|---|---|
| Header & Logo | header |
Branding bar with logo, web-view link, and optional date |
| Hero Banner | hero |
Headline, badge pill, subtext, and bulletproof CTA button |
| Text & Content | body_text |
Editorial rich text with merge tags and alignments |
| CTA Button | button |
Bulletproof Outlook VML action button |
| 2-Column Grid | two_column |
Side-by-side cards with reverse mobile stacking (rtl) |
| 3-Column Grid | three_column |
Three responsive feature cards |
| 4-Column Wall | four_column |
Partner logo trust wall or compact icon links |
| Asymmetric Split | asymmetric_columns |
1/3 + 2/3 editorial sidebar split |
| Feature List | features |
Bulleted list with icons, bold titles, and descriptions |
| Testimonial | testimonial |
Quote callout with star rating and author attribution |
| Stat Box | stat_box |
Key metric numbers and percentage badges |
| Divider Line | divider |
Horizontal rule or spacer with configurable height |
| Labeled Divider | labeled_divider |
Horizontal line with centered text badge (e.g. "OR") |
| Social Links | social_links |
Multi-channel social icon bar |
| App Badges | app_badges |
Official Apple App Store and Google Play buttons |
| Data Table | data_table |
Multi-column comparison table with zebra striping |
| Image Banner | image_banner |
Responsive banner image with alt text and link |
| Video Card | video_card |
Thumbnail with play button overlay linking to video |
| Pricing Grid | pricing_grid |
Multi-tier pricing cards with featured plan highlight |
| Rating Scale | rating_bar |
1-Click NPS or CSAT survey buttons (1-10 or 1-5 scale) |
| Countdown Urgency | countdown_timer |
Urgency banner with deadline and offer CTA |
| Accordion / FAQ | accordion |
Stacked Q&A cards for policies and instructions |
| Dynamic Feed | dynamic_feed |
Product recommendation grid with live JSON hydration |
| Order Receipt | order_receipt |
Itemized invoice summary with taxes and subtotals |
| RSS Article Feed | rss_feed |
Syndicated blog digest with publication dates |
| Product Catalog | product_catalog |
Ecommerce cards with compare-at pricing and buy CTAs |
| Coupon Code | coupon_code |
Promo voucher card with dashed border and expiry |
| Footer & Compliance | footer |
CAN-SPAM / GDPR address and unsubscribe link |
| Custom Raw HTML | html |
Bespoke HTML code component |
Testing
composer install composer test # Pest, via Orchestra Testbench composer analyse # PHPStan level 8 with Larastan
License
The MIT License (MIT). See LICENSE.md.