{"id":22794538,"url":"https://github.com/alekitto/mjml-php","last_synced_at":"2026-04-15T16:32:23.242Z","repository":{"id":266571630,"uuid":"898730448","full_name":"alekitto/mjml-php","owner":"alekitto","description":"PHP extension to render MJML emails","archived":false,"fork":false,"pushed_at":"2026-03-27T19:50:38.000Z","size":95,"stargazers_count":4,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-03-28T02:39:44.948Z","etag":null,"topics":["email","mjml","mjml-to-html","php","php-ext","php-extension"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/alekitto.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2024-12-04T23:31:34.000Z","updated_at":"2026-03-27T19:40:54.000Z","dependencies_parsed_at":"2025-05-29T23:21:33.778Z","dependency_job_id":"087dae9e-2332-4dda-9327-8ffadb5cf5d3","html_url":"https://github.com/alekitto/mjml-php","commit_stats":null,"previous_names":["alekitto/mjml-php"],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/alekitto/mjml-php","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alekitto%2Fmjml-php","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alekitto%2Fmjml-php/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alekitto%2Fmjml-php/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alekitto%2Fmjml-php/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/alekitto","download_url":"https://codeload.github.com/alekitto/mjml-php/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alekitto%2Fmjml-php/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31849740,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-15T15:24:51.572Z","status":"ssl_error","status_checked_at":"2026-04-15T15:24:39.138Z","response_time":63,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["email","mjml","mjml-to-html","php","php-ext","php-extension"],"created_at":"2024-12-12T04:09:10.346Z","updated_at":"2026-04-15T16:32:23.236Z","avatar_url":"https://github.com/alekitto.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# mjml-php\n\n[![Docs](https://img.shields.io/badge/docs-mkdocs-blue)](./docs/index.md)\n\nPHP extension that embeds [MRML](https://github.com/jdrouet/mrml), the [MJML](https://mjml.io) rendering engine written in Rust, so that you can render MJML templates directly from PHP without shelling out to a CLI tool.\n\n## Documentation\n\nThe full documentation lives under [`./docs/`](./docs/index.md) and is published as a MkDocs site. Start with the [architecture overview](./docs/index.md) and consult the dedicated guides for [installation](./docs/installation.md), [configuration](./docs/configuration.md), [usage](./docs/usage.md), [API details](./docs/api.md), and [troubleshooting](./docs/troubleshooting.md).\n\nTo preview the site locally install MkDocs and run:\n\n```sh\ncomposer run docs:serve\n```\n\nThis command proxies to `mkdocs serve` using the navigation defined in [`mkdocs.yml`](./mkdocs.yml).\n\n## Overview\n\n- **Native MJML rendering** – compile templates into responsive HTML emails through a thin PHP wrapper around the Rust engine.\n- **File and stream support** – render inline strings or files (including stream wrappers) through `render` and `renderFile`.\n- **Configurable output** – control comments, custom fonts, and social icon URLs via constructor options.\n- **Exceptions-first API** – failed renders surface as `Mjml\\Exception\\RenderException`, enabling straightforward error handling.\n\n## Requirements\n\n- PHP **8.0 or newer** with the development headers (`php-dev`, `php-devel`, or similar).\n- [Rust](https://www.rust-lang.org/) toolchain with **Cargo** available in `PATH` (the build uses `cargo build`).\n- Build dependencies required by MRML, for example `build-essential`, `gcc`, `make`, `libclang-dev`, `openssl`, `libssl-dev`, and `git`.\n- `phpize` and `php-config` from your PHP installation.\n\n\u003e **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`.\n\n## Installation\n\n### Build from source\n\n```sh\nphpize\n./configure            # add --enable-cargo-debug to build a debug artefact\nmake\nsudo make install      # installs mjml.so into the active PHP extension dir\n```\n\nAfter installation, enable the extension in your `php.ini` (see [Configuration](#configuration)). During development you can load the module from the build tree instead of running `make install`:\n\n```sh\nphp -dextension=./target/release/mjml.so your-script.php\n```\n\n### Composer / packaged distribution\n\nThe project is published as a Composer package (`kcs/mjml`). You can pull the extension into your project with:\n\n```sh\npie install kcs/mjml\n```\n\nPIE will place the extension artefact under the PHP extension directory (and enable it, if possible).\n\n### Configuration\n\nAdd one of the following lines to your PHP configuration:\n\n```ini\n; system-wide configuration\nextension=mjml\n\n; or provide an absolute path when running from the build tree\nextension=/path/to/mjml-php/target/release/mjml.so\n```\n\nWhen using PHP-FPM or Apache, restart the service so the new module is loaded.\n\n## Usage\n\n```php\n\u003c?php\n\nuse Mjml\\Mjml;\nuse Mjml\\Exception\\RenderException;\n\n$mjml = new Mjml([\"disable_comments\" =\u003e true]);\n\ntry {\n    // Render a MJML string and fetch the body HTML.\n    $email = $mjml-\u003erender('\u003cmjml\u003e\u003cmj-body\u003e\u003cmj-text\u003eHello world!\u003c/mj-text\u003e\u003c/mj-body\u003e\u003c/mjml\u003e');\n    echo $email-\u003egetBody();\n\n    // Render from a file or stream. Stream wrappers such as s3:// are supported.\n    $newsletter = $mjml-\u003erenderFile(__DIR__ . '/templates/newsletter.mjml');\n    file_put_contents(__DIR__ . '/build/newsletter.html', $newsletter-\u003egetBody());\n\n    // Inspect the default fonts shipped with MRML.\n    $fonts = Mjml::defaultFonts();\n    printf(\"Roboto is loaded from %s\\n\", $fonts['Roboto']);\n\n    // Render a template that includes reusable components.\n    $withPartials = $mjml-\u003erenderFile(__DIR__ . '/templates/with-includes.mjml');\n    echo $withPartials-\u003egetTitle();\n} catch (RenderException $e) {\n    // Handle invalid MJML gracefully (syntax error, missing include, …).\n    error_log('MJML render failed: ' . $e-\u003egetMessage());\n}\n```\n\n`render` and `renderFile` both return an instance of `Mjml\\Email`, exposing:\n\n- `getTitle(): string|null`\n- `getPreview(): string|null`\n- `getBody(): string`\n\n## Constructor options\n\nPass an associative array to `new Mjml($options)` to tweak the renderer:\n\n| Option               | Type                    | Default                                                     | Notes                                                                                                                    |\n|----------------------|-------------------------|-------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------|\n| `disable_comments`   | `bool`                  | `false`                                                     | Non-boolean values raise a `TypeError`. When `true`, HTML comments emitted by MRML are stripped.                         |\n| `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 `\u003cmj-social-element\u003e` icons.                                   |\n| `fonts`              | `array\u003cstring, string\u003e` | `Mjml::defaultFonts()`                                      | Keys are font names and values the font URL. Passing anything other than string keys/values triggers a validation error. |\n\n### Default fonts\n\n```php\nprint_r(Mjml::defaultFonts());\n```\n\nOutputs an associative array similar to:\n\n| Font name  | URL                                                                |\n|------------|--------------------------------------------------------------------|\n| Open Sans  | https://fonts.googleapis.com/css?family=Open+Sans:300,400,500,700  |\n| Droid Sans | https://fonts.googleapis.com/css?family=Droid+Sans:300,400,500,700 |\n| Lato       | https://fonts.googleapis.com/css?family=Lato:300,400,500,700       |\n| Roboto     | https://fonts.googleapis.com/css?family=Roboto:300,400,500,700     |\n| Ubuntu     | https://fonts.googleapis.com/css?family=Ubuntu:300,400,500,700     |\n\n## Troubleshooting\n\n- **`configure: error: cargo command missing`** – install Rust and ensure `cargo` is in your `PATH`.\n- **`phpize` not found** – install PHP development tools (`apt install php-dev`, `dnf install php-devel`, etc.).\n- **Missing includes during rendering** – check that the `mj-include` paths exist and that PHP has permission to read them (see [`tests/0001-include.phpt`](./tests/0001-include.phpt) for an example layout).\n- **Segmentation faults or crashes** – rebuild in debug mode (`./configure --enable-cargo-debug \u0026\u0026 make clean \u0026\u0026 make`) and open an issue with the failing template.\n\n## License\n\nLicensed under the [MIT License](./LICENSE).\n\n## Contributing\n\n1. Fork the repository and create a feature branch.\n2. Build the extension locally (see [Build from source](#build-from-source)).\n3. Run the PHPT test suite before submitting a pull request:\n\n   ```sh\n   php -dextension=./modules/mjml.so run-tests.php tests\n   ```\n\n   Integration scenarios live under [`tests/integration/`](./tests/integration/).\n4. Follow the existing coding style and commit conventions, then open a pull request.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falekitto%2Fmjml-php","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Falekitto%2Fmjml-php","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falekitto%2Fmjml-php/lists"}