Email templates: how to use conditionals like if/else?

I found a way to get Twig working within GrapeJS.

It only requires one very small code change:

app\bundles\EmailBundle\Helper\MailHelper.php

After line 359, which is currently:

self::searchReplaceTokens($search, $replace, $this->message);

Add the following lines of code (starting at line 361):

// Custom Twig code handler in email template
$body = $this->message->getHtmlBody();
$isTemplateTwigCode = str_contains($body, '{%');

if ( $isTemplateTwigCode )
{
    if ( empty($this->twig) ) {
        $this->twig = $this->factory->getTwig();
    }

    // $tokens: revert key from "{var}" to "var"
    $cleanTokens = [];
    foreach ( $tokens as $key => $value )
    {
        $key = str_replace(['{', '}'], '', $key);
        $cleanTokens[$key] = $value;
    }

    // execute twig logic and update email body with results
    $body = $this->twig->createTemplate($body)->render($cleanTokens);
    $this->message->html($body);
}

Then just upload and overwrite the existing file of the same name on your server, I didn’t even need to clear cache (from what I remember).

Now when you go into GrapeJS, you can use Twig code directly with API token variables, ie.:

<mj-raw>
    {% if countMessages == 1 %}
        You have one new message from {messageUsername}.
    {% endif %}
</mj-raw>

Or like this:

<mj-raw>{% if countMessages == 1 %}</mj-raw>
You have one new message from {messageUsername}.
<mj-raw>{% endif %}</mj-raw>

Warning: GrapeJS will convert < and > to &lt; and &gt;. So in these situations, you need to add comment blocks around your code to prevent it from being replaced, like this:

<mj-raw><!-- {% if countMessages > 1 %} --></mj-raw>
You have {countMessages} new messages
<mj-raw>{% endif %}</mj-raw>

Notice how you only need to put <!-- ... --> when there is a > or < comparison operator.

I haven’t tried {% for ... %} or {% let var = "some text" %}, but feel free to try it and let me know how it goes. It uses the Twig library so it should have support for all of those.