3

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('myEmail@gmail.com', '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 Answers3

4

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">
Dhia Djobbi
  • 1,176
  • 2
  • 15
  • 35
  • But does this not generate an url like `C:\dev\myawesomeproject\public\Email_Images\1.png`. So it will be a local path? This solution won't work if you are sending these emails to users which don't have the image in that exact same path. Or am I wrong here? – Fabian Schmick Jul 24 '20 at 09:46
  • 1
    Nope, it doesn't generate that URL but it reference images using the syntax `cid:` [Symfony documentation](https://symfony.com/doc/current/mailer.html#mailer-twig-embedding-images) – Dhia Djobbi Jul 24 '20 at 10:08
2

{{ 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
Fabian Schmick
  • 1,616
  • 3
  • 23
  • 32
  • Even after using the `absolute_url()` function and setting those parameters in services.yaml. It still doesnt work . –  Jul 24 '20 at 09:07
  • Does the image simply not apear or is there any other error than a 404? And what happens if you call the generated url in your browser? And what happens if you call the correct URL in your browser? How does they differentiate? Which program do you use to read your e-mails? – Fabian Schmick Jul 24 '20 at 09:38
  • I am recieving/reading those emails on my Gmail account. I did `

    {{ absolute_url(asset('Email_Images/1.png')) }}

    ` too see what it returns.. and the results are http://127.0.0.1:8000/Email_Images/1.png
    –  Jul 24 '20 at 10:38
  • I see, have a look at the explanation https://stackoverflow.com/a/20837071/5947371 why this not works. I would recomment you to use [mailhog](https://github.com/mailhog/MailHog) for your local development to test emails. – Fabian Schmick Jul 24 '20 at 12:05
0

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">
Victor Weiss
  • 366
  • 3
  • 5