Custom mail templates

Customizing Sylius Email Templates for Frontend Links

eBy default, Sylius 2.0 email templates generate backend URLs (e.g. /admin/...) that don't make sense for a headless frontend setup like FrontWing. To fix this, you need to override the Twig templates and point them to the correct frontend routes.

This page shows examples for 3 templates, but the approach is identical for others (shipping updates, invoice, newsletter, etc.).

Important: In the examples below, we use http://localhost:5173 — make sure to replace this with your actual frontend domain in production (e.g. https://front-wing.sylius.com).

Account Verification Email

File to override:

src/Sylius/Bundle/CoreBundle/Resources/views/Email/accountVerification.html.twig

Example content:

{% extends '@SyliusCore/Email/layout.html.twig' %}

{% block subject %}
    {{ 'sylius.email.user.account_verification.subject'|trans({}, null, localeCode)|raw }}
{% endblock %}

{% block content %}
    {% set verificationUrl = user.verificationFrontendUrl ?? 'http://localhost:5173/verify?token=' ~ user.emailVerificationToken %}

    <div style="text-align: center; margin-bottom: 30px;">
        <div style="font-size: 24px;">
            {{ 'sylius.email.user.account_verification.greeting'|trans({}, null, localeCode) }}
            <strong>{{ user.username }}</strong><br>
        </div>
        {{ 'sylius.email.user.account_verification.strategy'|trans({}, null, localeCode) }}:
    </div>

    <div style="text-align: center;">
        <a href="{{ verificationUrl|raw }}"
           style="display: inline-block; background: #1abb9c; padding: 18px 28px; color: #fff; text-decoration: none; border-radius: 3px;">
            {{ 'sylius.email.user.account_verification.statement'|trans({}, null, localeCode) }}
        </a>
    </div>
{% endblock %}

Password Reset Email

File to override:

src/Sylius/Bundle/CoreBundle/Resources/views/Email/passwordReset.html.twig

Example content:

{% extends '@SyliusCore/Email/layout.html.twig' %}

{% block subject %}
    {{ 'sylius.email.password_reset.subject'|trans({}, null, localeCode)|raw }}
{% endblock %}

{% block content %}
    {% set resetUrl = 'http://localhost:5173/forgotten-password/reset?token=' ~ user.passwordResetToken %}

    <div style="text-align: center; margin-bottom: 30px;">
        <div style="font-size: 24px;">
            {{ 'sylius.email.password_reset.hello'|trans({}, null, localeCode) }} <strong>{{ user.username }}</strong><br>
        </div>
        {{ 'sylius.email.password_reset.to_reset_your_password'|trans({}, null, localeCode) }}:
    </div>

    <div style="text-align: center;">
        <a href="{{ resetUrl|raw }}"
           style="display: inline-block; background: #1abb9c; padding: 18px 28px; color: #fff; text-decoration: none; border-radius: 3px;">
            {{ 'sylius.email.password_reset.reset_your_password'|trans({}, null, localeCode) }}
        </a>
    </div>
{% endblock %}

Order Confirmation Email

File to override:

src/Sylius/Bundle/CoreBundle/Resources/views/Email/Blocks/OrderConfirmation/_content.html.twig

Example content:

<div style="text-align: center; margin-bottom: 30px;">
    {{ 'sylius.email.order_confirmation.your_order_number'|trans({}, null, localeCode) }}

    <div style="margin: 10px 0;">
      <span style="border: 1px solid #eee; padding: 10px; color: #1abb9c; font-size: 28px;">
        {{ order.number }}
      </span>
    </div>

    {{ 'sylius.email.order_confirmation.has_been_successfully_placed'|trans({}, null, localeCode) }}
</div>

{% if sylius_bundle_loaded_checker('SyliusShopBundle') %}
    {% set frontendUrl = 'http://localhost:5173/account/orders/' ~ order.tokenValue ~ '/pay' %}
    <div style="text-align: center; margin-bottom: 30px;">
        <a href="{{ frontendUrl|raw }}"
           style="display: inline-block; background: #1abb9c; padding: 18px 28px; color: #fff; text-decoration: none; border-radius: 3px;">
            {{ 'sylius.email.order_confirmation.view_order_or_change_payment_method'|trans({}, null, localeCode) }}
        </a>
    </div>
{% endif %}

<div style="text-align: center;">
    {{ 'sylius.email.order_confirmation.thank_you'|trans({}, null, localeCode) }}
</div>

🛠 Tips

  • Replace all hardcoded URLs with your own domain.

  • Use inline styles for better email client compatibility.

  • You can customize any email Sylius sends — just look in the /views/Email/ folder and follow the same pattern.


Local email testing

During development, it's important to test email templates locally. Sylius uses the configured mailer transport from .env or .env.local.

To use MailHog:

  1. Install and run MailHog (e.g. via Docker or Homebrew).

  2. Update your .env.local in the Sylius backend:

MAILER_DSN=smtp://localhost:1025
  1. Start your server and open http://localhost:8025 to view sent emails.

You can also use other tools like Mailtrap or Symfony Mailer’s file transport.

Last updated

Was this helpful?