Search code examples
phpsymfonyswiftmailer

Symfony - Unable to add image in an email


I am working on a cron job and trying to send email using SwiftMailer

Inside the cron Action I am using foreach loop to iterate through the loop and sending emails to user.

foreach($hostDinners as $key => $hostDinner) {
    //generate email
$message = \Swift_Message::newInstance()
    ->setSubject("This is a demo subject")
    ->setFrom($this->container->getParameter('mailer_user'))
    ->setTo($key)

    ->setBody(
        $this->renderView(
            'AppBundle:emails:cron-job-request-and-invitations.html.twig',
            array(
            'dinners' => $hostDinner
            )
        )
    )
    ->setContentType('text/html');
$this->get('mailer')->send($message);


}

I am then passing array to the email template as well and inside the email i am using the loop again to display the email content. Everything works fine except that I am unable to display the images.

{% for dinner in dinners %}
<img style="display: block;" src="{{ absolute_url(asset('uploads/' ~ dinner.guest_profile_image)) }}" alt="image1" class="section-img" height="auto" width="128">
{% endfor %}

Update

When I dump the image variable dinner.guest_profile_image this is what i get http://127.0.0.1:8000/uploads/42c5681b253c4dc6a1d145f744e6c3cd.jpeg and if i access it directly on browser i can see the image i need the email to display.

The $message dump is pretty huge since there is alot of css and html in it so i here is the screenshot of the dump where the image tag is

enter image description here

What am i missing here? What do i need to do to get the images to display.


Solution

  • Try with asset_url

    <img style="display: block;" src="{{ asset_url('uploads/' ~ dinner.guest_profile_image) }}" alt="...">
    

    or you can try embedding your images in base64 like this:

    <img style="display: block;" src="data:image/png;base64,iVBORw0KG....(this represent the base64 of your image)..." alt="..."/>
    

    UPDATE 1


    foreach($hostDinners as $key => $hostDinner) {
    
        //Encode img in base64
        foreach ($hostDinner as &$item) {
            $path = $item['guest_profile_image']; //use symfony2 functions to get the abs upload path
            $type = pathinfo($path, PATHINFO_EXTENSION);
            $data = file_get_contents($path);
            $item["guest_profile_image"] = 'data:image/' . $type . ';base64,' . base64_encode($data);
        }
        unset($item); // break the reference with the last element
    
        //generate email
        $message = \Swift_Message::newInstance()
            ->setSubject("This is a demo subject")
            ->setFrom($this->container->getParameter('mailer_user'))
            ->setTo($key)
    
            ->setBody(
                $this->renderView(
                    'AppBundle:emails:cron-job-request-and-invitations.html.twig',
                    array(
                    'dinners' => $hostDinner
                    )
                )
            )
            ->setContentType('text/html');
        $this->get('mailer')->send($message);
    }
    

    and in the view:

    {% for dinner in dinners %}
          <img style="display: block;" src="{{ dinner.guest_profile_image }}" alt="image..." class="section-img" height="auto" width="128"/>
    {% endfor %}
    

    UPDATE 2


    In this line $item["guest_profile_image"] = 'data:image/' . $type . ';base64,' . base64_encode($data); you have everything you need to put in the attribute src of the img tag (you can see in the view I only print print the content of the array src="{{ dinner.guest_profile_image }}"). The alt attribute is used to html's good practices, but it isn't necessary alt attribute.

    Official PHP documentation of &: In order to be able to directly modify array elements within the loop precede $value with &. In that case the value will be assigned by reference.

    So, in the loop, I'm replacing the image paths from your array to each base64 codification. In this way you don't have to modify anything in your code, your array have the same size than before, but instead of have the image paths in the array... you have your images decode in base64 in those positions of the array. More information about & in Oficial php documentation

    Take look (base64 on img tag) [https://en.wikipedia.org/wiki/Data_URI_scheme]

    I wish this explanation can help you.