How to embed images in a symfony mail?

6.3k Views Asked by At

So I designed an email template for my reset-password system. In the email templates, there are Images (logo).

I placed those images inside a folder called Email_Images and that folder is placed inside the Public folder!

First, I tried to link the images using Asset() twig Function like this:

<img alt="logo 1" src="{{asset('Email_Images/1.png')}}" />
<img alt="logo 2" src="{{asset('Email_Images/2.jpg')}}" />

But none of them works. So I tried to get the image in the controller and send it to the template, like this :

 $email = (new TemplatedEmail())
        ->from(new Address('[email protected]', 'My Subject'))
        ->to($user->getEmail())
        ->subject('Your password reset request');

        $img= $email ->embed(fopen('Email_Images/1.jpg', 'r'), 'img');

        $email->htmlTemplate('reset_password/email.html.twig')
        ->context([
            'resetToken' => $resetToken,

            'img' => $img,

            'tokenLifetime' => $this->resetPasswordHelper->getTokenLifetime(),
        ]);

In the template I did

<img alt="logo 1" src="{{ img }}" />

and I get this error :

An exception has been thrown during the rendering of a template ("Catchable Fatal Error: Object of class Symfony\Bridge\Twig\Mime\TemplatedEmail could not be converted to string").

What is the right way to add/embed an image in an Email?

3

There are 3 best solutions below

2
On

Instead of getting the images in the controller and sending them to the twig page. You can do this :

First, Define a Twig namespace (called img for example) that points to the folder where the images are stored in. In this case, the folder is called Email_Images

Add those lines to config/packages/twig.yaml

twig:
    # ...

    paths:
        # point this wherever your images live
        '%kernel.project_dir%/public/Email_Images': img

Now you can use email.image() twig function to embed the images inside the email.

<img src="{{ email.image('@img/1.png') }}" alt="Logo">
0
On

Personally, I send emails from website AND emails from cron tasks. For emails sent from the website it's fine to use absolute_url(asset(...)), but cron tasks don't know about your domaine name.

So to make things simple, my trick is to define the domaine name as a .env variable, and then :

in .env

DOMAIN_NAME=https://mywebsite.com

in config/package/twig.yaml

twig:
    ...
    globals:
        DOMAIN_NAME: '%env(DOMAIN_NAME)%'

in templates/emails/reset-password.email.twig (or base.email.twig)

<img src="{{ DOMAIN_NAME ~ asset('images/logo.jpg') }}" alt="logo">
4
On

{{ asset('Email_Images/1.png') }} will result in a relative URL like /Email_Images/1.png. But for e-mails you need an absolute URL which you can generate like this <img src="{{ absolute_url(asset('Email_Images/1.png')) }}"/>. Because the e-mail does not know anything about your domain name.

Furthermore I recommend you to configure the following parameters (if you are going to send e-mails via console commands, too):

router.request_context.host:     example.com    # your domain
router.request_context.scheme:   http           # your scheme http or https
asset.request_context.base_path: '%router.request_context.base_url%'
asset.request_context.secure:    true