laravel 5.4 embed image in mail
Asked Answered
L

9

25

I have just upgraded my 5.2 install of laravel to 5.3 and then to 5.4 following the official upgrading methods.

I am now trying to use one of the new features, to create a markdown formated email.

According to the documentation found at: https://laravel.com/docs/5.4/mail#view-data

To embed an inline image, use the embed method on the $message variable within your email template. Laravel automatically makes the $message variable available to all of your email templates, so you don't need to worry about passing it in manually:

However, this:

<img src="{{ $message->embed(public_path().'/img/official_logo.png') }}">

will produce the following error:

Undefined variable: message

Am I missing something? Or is there something undocumented in the upgrading guides?

Later edit:

I am calling the email function with:

\Mail::to($user)->send(new WelcomeCandidate($user, $request->input('password')));

And WelcomeCandidate looks like:

<?php

namespace App\Mail;

use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Queue\ShouldQueue;

use App\Models\User;

class WelcomeCandidate extends Mailable
{

    use Queueable, SerializesModels;

    public $user;
    public $password;

    /**
     * Create a new message instance.
     *
     * @return void
     */
    public function __construct(User $user, $password)
    {
        //
        $this->user = $user;
        $this->password = $password;
    }

    /**
     * Build the message.
     *
     * @return $this
     */
    public function build()
    {
        $this->subject('Welcome!');
        return $this->markdown('emails.welcome-candidate');
    }
}
Landel answered 28/2, 2017 at 7:58 Comment(5)
show some more code, but what the error is saying is pretty clear. You didn't define the message variable on your mailable class or your notification class or you didn't assign any value to it in the constructor of your mailable / notification. Also if you gonna use markdown, you don't need the image tag.Furmark
I did it according instructions, as you can see in the quoted text. What code should I provide?Landel
the code where you exectute your mailable class: so for example : $message = "hello"; Mail::to($request->user())->send(new OrderShipped($message));Furmark
I have added the code in the question.Landel
Same issue was raised here: github.com/laravel/framework/issues/17629 . No solutions though.Landel
F
26

It seems that the older $message->embed doesn't work nicely with Markdown emails. Like you mentioned in the comments it seems broken since 5.4

But you could just try it like this inside your markdown email:

This is your logo 
![Some option text][logo]

[logo]: {{asset('/img/official_logo.png')}} "Logo"

Like shown here: https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet#images

Asset function reference: https://laravel.com/docs/5.4/helpers#method-asset

Furmark answered 28/2, 2017 at 9:35 Comment(5)
tried that already. I get an empty img <img alt="alt here" title="title here" style="font-family:Avenir,Helvetica,sans-serif;box-sizing:border-box;max-width:100%">Landel
have you tried using {{assets('img/official_log.png')}} ? maybe the issue is in the path?Furmark
The path was the issue. And I was trying the inline method, which might of been another issue.Landel
Glad it helped! Yeah it seems that the embed method is not working very well with markdown currentlyFurmark
Yes. Well, end up doing something like <td class="logo"><img src="{{asset('img/official-logo.png')}}" alt="alt here"></td> in the vews/vendor/mail/html/layout.blade.php as I will put that logo in all emails as a default.Landel
I
15

Try this:

<img src="data:image/png;base64,{{base64_encode(file_get_contents(resource_path('img/email/logo.png')))}}" alt="">

or

![](data:image/png;base64,{{base64_encode(file_get_contents(resource_path('img/email/logo.png')))}})
Idun answered 16/8, 2017 at 9:29 Comment(3)
I like this solution but no dice unfortunately.Polygamist
As much as I love serialized image data mega pasted into an image tag... they are specifically unwelcome on many email services and clients. I love base64 encoded images for certain purposes, don't get me wrong. It is just email is not one of those things specifically for the non-display of images and outright failure to accomplish the single purpose of presenting a visible image. It is the back half of 2018, we'll see how well this comment ages. Maybe it will be less true in a few years...Carmelcarmela
This will cause issues on services such as Gmail where extremely long lines of HTML are force-wrapped at ~10,240 characters; If your image is > 8KB, it'll have spaces inserted into the base64-encoded string, breaking it - <img src="data:...r4ScdV3si deY8TdZ...">Giantism
T
6

Solved my issue!

  <img src="{{ $message->embed(base_path() . '/img/logo.png') }}" />
Controller:


\Mail::send(['html' =>'mail'],
        array(
            'name' => $r->name,
            'email' => $r->email,
            'user_message' => $r->message,
           // 'telephone'=>$r->telephone,
           // 'subject'=>$r->subject
        ), function($message) use ($r)  {

            $message->to('[email protected]')->subject('Contact Form || abc.com');
            $message->from($r->email);
            // ->setBody($r->user_message); // assuming text/plain

        });

If you are in localhost , you can use public_path instead of base_path function

Threshold answered 17/11, 2017 at 17:50 Comment(0)
H
5

You can also use this useful package

https://github.com/eduardokum/laravel-mail-auto-embed

Taken from the readme

Its use is very simple, you write your markdown normally:

@component('mail::message')
# Order Shipped

Your order has been shipped!

@component('mail::button', ['url' => $url])
View Order
@endcomponent

Purchased product:

![product](https://example.com/products/product-1.png)

Thanks,<br>
{{ config('app.name') }}
@endcomponent

When sending, it will replace the link that would normally be generated:

<img src="https://example.com/products/product-1.png">

by an embedded inline attachment of the image:

<img src="cid:[email protected]">
Handclasp answered 18/4, 2018 at 4:59 Comment(0)
T
3

I just encountered the same issue and found a solution.

Before rendering images you have to create a symbolic link from "public/storage" to "storage/app/public" using this command:

php artisan storage:link

In "storage/app/public" you should have a folder "images" Now you can render this code in your markdown.blade.php:

!['alt_tag']({{Storage::url('/images/your_image.png')}})

Second option is similar:

!['alt_text']({{Storage::url($comment->user->image->path)}}) 

Both work fine

Thermograph answered 7/4, 2020 at 12:19 Comment(0)
S
0

You could try the following:

class WelcomeCandidate extends Mailable
{
    use Queueable, SerializesModels;

    public $message;
    public function __construct(User $user)
    {
        $this->user = $user;
        $this->message = (object) array('image' => '/path/to/file');
    }
}
Shelton answered 21/4, 2017 at 14:34 Comment(0)
O
0

The below solution works for me.

<img src="{{ $message->embed(asset('img/logo.png')) }}"/>

In .env file.

For local: APP_URL=http://localhost/project_name

For Production: APP_URL=https://www.example.com

Reference: https://laravel.com/docs/7.x/mail#inline-attachments

Orbit answered 26/6, 2022 at 15:21 Comment(0)
H
0

Laravel supports the embed method in all laravel versions, 7, 8, 9, and 10. How do embed images in laravel?

<img src="{{ $message->embed($pathToImage) }}">

Laravel automatically makes the $message variable available to all of your email templates, so you don't need to worry about passing it in manually:

Hegemony answered 25/3, 2023 at 2:48 Comment(0)
E
-1

In backend i created endpoint for showing images. And put image that i need in resource/img. Laravel code looks like:

 public function getImage($name)
 {
        return response()->file(base_path() . '/resources/img/' . $name . '.png');
 }

Then in my html email template i created div with background-image.

<div style='background: url("https://mysite1.com/api/v1/get_image/logo")'></div>

And it's works for me.

Emeric answered 28/7, 2021 at 9:12 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.