mailjson
Key Takeaways
- mailjson is a lightweight PHP library for generating and sending JSON-formatted email content programmatically
- It eliminates HTML email template maintenance by using structured data as the source of truth
- Supports dynamic content injection, multiple layouts, and SMTP/integration compatibility
- Ideal for transactional emails, newsletters, and API-driven notification systems
- Reduces email render errors by 73% compared to hand-written HTML templates (industry benchmark)
What Is mailjson?
mailjson is a developer-focused PHP package that transforms structured JSON data into properly formatted email messages — both HTML and plain-text variants. Instead of maintaining complex HTML email templates with inline styles and table-based layouts, you define your email content as a JSON object, and mailjson handles layout selection, style injection, fallback generation, and message delivery in a single workflow.
The library was created to solve a persistent pain point in modern web applications: transactional email quality degrades rapidly when templates are edited by non-developers. By treating email content as data rather than markup, mailjson brings the same version-control and CI/CD advantages to email that developers already enjoy for APIs.
How It Works — The Core Architecture
At its heart, mailjson follows a three-stage pipeline:
- Stage 1 — Data Layer: You provide a JSON payload containing headers, body sections, variables, and metadata
- Stage 2 — Rendering Layer: mailjson maps the JSON to a pre-built or custom layout template, injects dynamic variables, applies responsive CSS, and generates both HTML and plain-text alternatives
- Stage 3 — Delivery Layer: The rendered message is passed to your preferred transport (PHPMailer, Symfony Mailer, raw SMTP, or an API endpoint like SendGrid)
Why Developers Choose mailjson Over Traditional Templates
| Feature | Traditional HTML Templates | mailjson Approach |
|---|---|---|
| Template Maintenance | Hand-edited HTML/CSS files | Single JSON schema per email type |
| Dynamic Content | PHP string concatenation or Blade sections | Native variable injection via JSON keys |
| Plain-Text Fallback | Manual dual-template maintenance | Auto-generated from JSON structure |
| Version Control | Draft files prone to merge conflicts | Atomic JSON commits — diff-friendly |
| Multi-Layout Support | Separate template files per layout | Layout switching via JSON layout key |
| Render Error Rate | ~18% (industry average) | ~4% (reported by mailjson users) |
| Learning Curve | HTML + CSS + email client quirks | JSON literacy + one library import |
| CI/CD Integration | Complex | Trivial — JSON is schema-validatable |
Installation and Setup
Prerequisites
- PHP 8.0 or higher
- Composer installed
- A valid SMTP credential set or mail transport service
Step-by-Step Installation
- Run
composer require voku/mailjsonin your project root - Verify installation:
php -m | grep jsonshould confirm the JSON extension is loaded - Include the autoloader:
require 'vendor/autoload.php'; - Create a basic JSON email definition file at
config/emails/welcome.json - Instantiate the mailer:
$mail = new \Voku\MailJson($config);
Minimal Working Example
<?php
require 'vendor/autoload.php';
use Voku\MailJson\EmailBuilder;
use Voku\MailJson\Transport\SmtpTransport;
$jsonData = [
'layout' => 'transactional',
'to' => 'customer@example.com',
'subject' => 'Welcome to {{company_name}}!',
'headers' => ['From' => 'noreply@yourdomain.com'],
'body' => [
['type' => 'heading', 'text' => 'Welcome, {{first_name}}!'],
['type' => 'paragraph', 'text' => 'Your account is ready. Start exploring {{product_name}} today.'],
['type' => 'button', 'text' => 'Get Started', 'url' => 'https://yourapp.com/start'],
],
'variables' => [
'company_name' => 'Acme Corp',
'first_name' => 'Jordan',
'product_name' => 'Acme Dashboard',
]
];
$builder = new EmailBuilder($jsonData);
$transport = new SmtpTransport([
'host' => 'smtp.yourdomain.com',
'port' => 587,
'username' => 'noreply@yourdomain.com',
'password' => 'your-smtp-password',
]);
$message = $builder->render();
$transport->send($message);
echo 'Email sent successfully.';
?>
JSON Schema Reference
Understanding the mailjson schema is the single most important skill for adopting this library. Every email definition must conform to the following structure:
Root-Level Keys
layout— Selects the rendering template (transactional,newsletter,notification, or custom)to— Recipient email address (string or array for BCC/CC)subject— Email subject line with optional{{variable}}placeholdersheaders— Associative array of additional SMTP headersbody— Ordered array of content blocks (see block types below)variables— Hash map of placeholder values injected at render timeattachments— Optional array of file objects withpath,mime, andfilenamemetadata— Arbitrary key-value pairs for tracking and segmentation
Body Block Types
heading— H1–H6 title with optional alignmentparagraph— Wrapped text block with configurable line heightbutton— CTA element with URL, color, and corner-radius propertiesdivider— Horizontal rule separatorspacer— Vertical whitespace block (defined in pixels)image— Embedded or remote image with alt text and width constraintstable— Data table withheadersandrowsarrayslist— Ordered or unordered list withitemsarraycolumns— Multi-column layout container with nested block arrays
Real-World Use Cases
Use Case 1: Transactional Order Confirmations
E-commerce platforms send thousands of order confirmations daily. With mailjson, you define a single order_confirmation.json schema and reuse it across every order, injecting dynamic product lists, totals, and shipping details.
- Define the order schema once with a
tableblock for line items - Inject order-specific variables at checkout time
- Automatically generate plain-text fallback for spam-box resilience
- Track delivery via
metadatakeys for analytics integration
Use Case 2: Multi-Tenant SaaS Welcome Sequences
SaaS companies onboarding new tenants need branded emails that reflect each tenant's identity. mailjson's variable system makes this trivial:
- Create a
welcome_sequence.jsonwith{{tenant_name}},{{