kcs/mjml

There is no license information available for the latest version (v1.1.1) of this package.

Installs: 278

Dependents: 0

Suggesters: 0

Security: 0

Stars: 0

Watchers: 1

Forks: 0

Open Issues: 0

Language:Rust

Type:php-ext

Ext name:ext-mjml

pkg:composer/kcs/mjml

v1.1.1 2025-05-05 06:49 UTC

This package is auto-updated.

Last update: 2025-10-19 22:55:53 UTC


README

Docs

PHP extension that embeds MRML, the MJML rendering engine written in Rust, so that you can render MJML templates directly from PHP without shelling out to a CLI tool.

Documentation

The full documentation lives under ./docs/ and is published as a MkDocs site. Start with the architecture overview and consult the dedicated guides for installation, configuration, usage, API details, and troubleshooting.

To preview the site locally install MkDocs and run:

composer run docs:serve

This command proxies to mkdocs serve using the navigation defined in mkdocs.yml.

Overview

  • Native MJML rendering – compile templates into responsive HTML emails through a thin PHP wrapper around the Rust engine.
  • File and stream support – render inline strings or files (including stream wrappers) through render and renderFile.
  • Configurable output – control comments, custom fonts, and social icon URLs via constructor options.
  • Exceptions-first API – failed renders surface as Mjml\Exception\RenderException, enabling straightforward error handling.

Requirements

  • PHP 8.0 or newer with the development headers (php-dev, php-devel, or similar).
  • Rust toolchain with Cargo available in PATH (the build uses cargo build).
  • Build dependencies required by MRML, for example build-essential, gcc, make, libclang-dev, openssl, libssl-dev, and git.
  • phpize and php-config from your PHP installation.

Note: On Alpine Linux install php-dev, cargo, clang-dev, openssl-dev, and build-base. On Debian/Ubuntu use apt install php-dev rustc cargo build-essential libclang-dev libssl-dev.

Installation

Build from source

phpize
./configure            # add --enable-cargo-debug to build a debug artefact
make
sudo make install      # installs mjml.so into the active PHP extension dir

After installation, enable the extension in your php.ini (see Configuration). During development you can load the module from the build tree instead of running make install:

php -dextension=./target/release/mjml.so your-script.php

Composer / packaged distribution

The project is published as a Composer package (kcs/mjml). You can pull the extension into your project with:

pie install kcs/mjml

PIE will place the extension artefact under the PHP extension directory (and enable it, if possible).

Configuration

Add one of the following lines to your PHP configuration:

; system-wide configuration
extension=mjml

; or provide an absolute path when running from the build tree
extension=/path/to/mjml-php/target/release/mjml.so

When using PHP-FPM or Apache, restart the service so the new module is loaded.

Usage

<?php

use Mjml\Mjml;
use Mjml\Exception\RenderException;

$mjml = new Mjml(["disable_comments" => true]);

try {
    // Render a MJML string and fetch the body HTML.
    $email = $mjml->render('<mjml><mj-body><mj-text>Hello world!</mj-text></mj-body></mjml>');
    echo $email->getBody();

    // Render from a file or stream. Stream wrappers such as s3:// are supported.
    $newsletter = $mjml->renderFile(__DIR__ . '/templates/newsletter.mjml');
    file_put_contents(__DIR__ . '/build/newsletter.html', $newsletter->getBody());

    // Inspect the default fonts shipped with MRML.
    $fonts = Mjml::defaultFonts();
    printf("Roboto is loaded from %s\n", $fonts['Roboto']);

    // Render a template that includes reusable components.
    $withPartials = $mjml->renderFile(__DIR__ . '/templates/with-includes.mjml');
    echo $withPartials->getTitle();
} catch (RenderException $e) {
    // Handle invalid MJML gracefully (syntax error, missing include, …).
    error_log('MJML render failed: ' . $e->getMessage());
}

render and renderFile both return an instance of Mjml\Email, exposing:

  • getTitle(): string|null
  • getPreview(): string|null
  • getBody(): string

Constructor options

Pass an associative array to new Mjml($options) to tweak the renderer:

Option Type Default Notes
disable_comments bool false Non-boolean values raise a TypeError. When true, HTML comments emitted by MRML are stripped.
social_icon_origin string https://www.mailjet.com/images/theme/v1/icons/ico-social/ Must be a non-empty string. Controls the base URL used by <mj-social-element> icons.
fonts array<string, string> Mjml::defaultFonts() Keys are font names and values the font URL. Passing anything other than string keys/values triggers a validation error.

Default fonts

print_r(Mjml::defaultFonts());

Outputs an associative array similar to:

Font name URL
Open Sans https://fonts.googleapis.com/css?family=Open+Sans:300,400,500,700
Droid Sans https://fonts.googleapis.com/css?family=Droid+Sans:300,400,500,700
Lato https://fonts.googleapis.com/css?family=Lato:300,400,500,700
Roboto https://fonts.googleapis.com/css?family=Roboto:300,400,500,700
Ubuntu https://fonts.googleapis.com/css?family=Ubuntu:300,400,500,700

Troubleshooting

  • configure: error: cargo command missing – install Rust and ensure cargo is in your PATH.
  • phpize not found – install PHP development tools (apt install php-dev, dnf install php-devel, etc.).
  • Missing includes during rendering – check that the mj-include paths exist and that PHP has permission to read them (see tests/0001-include.phpt for an example layout).
  • Segmentation faults or crashes – rebuild in debug mode (./configure --enable-cargo-debug && make clean && make) and open an issue with the failing template.

License

Licensed under the MIT License.

Contributing

  1. Fork the repository and create a feature branch.

  2. Build the extension locally (see Build from source).

  3. Run the PHPT test suite before submitting a pull request:

    php -dextension=./modules/mjml.so run-tests.php tests

    Integration scenarios live under tests/integration/.

  4. Follow the existing coding style and commit conventions, then open a pull request.