Laravel: Set mail subject from mail blade template - laravel

When using the Laravel 6 mail functionality, I would like to set the message subject in the email's blade template. This seems more natural to me than doing it in the Mail class itself, because whoever is maintaining the mail templates should also be able to customize the subject and use the template variables.
Example of what I am trying to accomplish:
#component('mail::subject')
Sample Message to {{ $user }}
#endcomponent
#component('mail::message')
# Sample Message
This is a sample message
#endcomponent
How could this be done?

I struggled with this as well. It took me a while to find a decent solution but here it is:
The mailable class:
class Mailing extends Mailable {
use Queueable;
use SerializesModels;
...
public function build() {
return $this
->markdown('emails.somemailing')
->with('setSubject', function($subject) { // Use to be able to set the subject from within the markdown blade
$this->subject($subject);
});
}
}
Then in the markdown blade you can call the setSubject like this:
#php
$setSubject('Hooray, it works!');
#endphp
#component('mail::message')
...
#endcomponent
PS You can also set $this->subject directly as a closure:
->with('setSubject', Closure::fromCallable([$this, 'subject']));

In APP - Mail
add this
public function build()
{
return $this->markdown('emails.user')->subject('here subject');
}

Related

Why html tags are not rendered in laravel sent email?

Sending email with
\Mail::to(
method in laravel 8 app
I have html tags in im my email template
#component('mail::message')
<h3 >
You registered at {{ $site_mame }}
</h3>
Best regards, <br>
...
#endcomponent
and code in my app/Mail/UserRegistered.php :
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
class UserRegistered extends Mailable
{
use Queueable, SerializesModels;
public $site_mame;
public $user;
public $confirmation_code;
public function __construct( $site_mame, $user, $confirmation_code )
{
$this->site_mame = $site_mame;
$this->user = $user;
$this->confirmation_code = $confirmation_code;
}
/**
* Build the message.
*
* #return $this
*/
public function build()
{
return $this->markdown('email.UserRegisteredEmail')
->with('site_mame', $this->site_mame)
->with('user', $this->user)
->with('confirmation_code', $this->confirmation_code);
}
}
With sendgrid options in my .env file I got valid emaul at my google account, but html tags are not rendered.
If there is a way to render all html tags? Does it depend on laravel app/emailing options
or setting in my google(or some other account).
What can I do from my side?
UPDATED :
Modified :
$this->view(
I got error :
No hint path defined for [mail]. (View: project/resources/views/email/UserRegisteredEmail.blade.php)
Pointing to my blade file.
Searching in net I found as possible decision :
php artisan vendor:publish --tag=laravel-mail
and clearing all cache
But I still got the same error.
Did I miss some options ?
Thanks in advance!
You are using the markdown() method, which is a method to utilize the pre-built templates and components of mail notifications in your mailables.
This offers a multitude of advantages:
instead of wrapping headings in h1, h2, etc. tags, you can just put a #, ##, etc. at the beginning of the line
no need to wrap lists in <ul>, and list items in <li> tags. In markdown, you can just use a dash (-) for listing elements
italic/bold font can be achieved by putting */** around the text you want to emphasize
You can read more about this on the official Laravel documentation.
https://laravel.com/docs/8.x/mail#markdown-mailables
If you want to use HTML, you can just render a view:
/**
* Build the message.
*
* #return $this
*/
public function build()
{
return $this->view('email.UserRegisteredEmail')
->with('site_mame', $this->site_mame)
->with('user', $this->user)
->with('confirmation_code', $this->confirmation_code);
}

Send A varriable from controller to blade

how can i inject a variable from controller to blade ,it is header
blade so it common for every page but no route url or controller
function is connected with it, please tell me a way to send the data
from Controller To header.blade.php Is there any possible way to
inject the variable?
You can share data with all views using your AppServiceProvider located in your app/Providers/AppServiceProvider.php
In the boot() method, use the view() helper and assign data.
class AppServiceProvider extends ServiceProvider
{
public function boot()
{
view()->share('name', 'My Name');
}
}
You can use it like any other variable in your view like this :
{{ $name }}

How to pass Eloquent Data to blade component?

Hello,
I have a blade Layout called:
profile.blade.php // component
And I have a blade file infos which extends from profile.blade.php component.
On my controller, I have a profile method:
public method profile(User $user) {
return view('infos.blade.php', compact('user'));
}
When I try to use the variable user to the profile.blade.php component, I have an error that says "undefined user variable"
My question is how can I get the data I received from my controller to Blade Component profle ?
Because that part of component will be used many times.
Thanks.
in your app/view/components/profile-
<?php
namespace App\View\Components;
use Illuminate\View\Component;
class profile extends Component
{
public $user; //for consistency
public function __construct($user)
{
$this->user = $user;
}
public function render()
{
return view('components.profile');
}
}
now the component can render a variable ($user),
in your info's blade/infos.blade.php you can feed the
variable to the component like --
<x-profile :user='$user' ></x-profile>
i understand the question was posted quite a long ago
but i had the same issue and the answers posted here
didn't work for me but this method did so.....it may help somebody.
As it's a component you have to pass user parameter each time you call it, for example
#component('profile', ['user' => $user]) #endcomponent // here $user comes from controller

how can I render laravel mailable to variable

I need to get the html of a Mailable class
$mail->html = (new InactivityReminder())->"do something to output the html"
There seems to be no toHtml method or something similar.
Mailable:
class InactivityReminder extends Mailable
{
use Queueable, SerializesModels;
public function __construct()
{
}
public function build()
{
return $this->markdown('mail.it.inactivityReminder');
}
}
In 5.5 the render() method will render the view that you return in Mailable:
$html = (new InactivityReminder)->render()
The interface does not provide that functionality. That means relying on it can cause problems when updating Laravel in the future. If this is not an issue for you you can use the render() method which returns a View object and then call render() on that.
So:
(new InactivityReminder)->render()->render()
alternatively:
(string) (new InactivityReminder)->render()
as __toString() on View will call it's render method.
For fully customizable mails in Laravel, I've had better luck using Mailables rather than Notifiables. Here's what worked for me:
Mailable class:
use Illuminate\Mail\Mailable;
class MyMail extends Mailable
{
public function __construct($someData) {
$this->someData = $someData;
}
public function build() {
return $this->markdown('mail/my-mail-view')
->with([
"someData" => $this->someData
]);
}
}
Mail view (resources/view/mail/my-mail-view.blade.php):
#extends('mail/mail-layout')
#section('content')
<p>Hi {{ $someData->first_name }}</p>
#endsection
Mail layout (resources/view/mail/mail-layout.blade.php):
<div class="myMailBody">
#yield('content')
</div>
Mail css file (resources/views/vendor/mail/html/themes/default.css):
(assuming you already ran "php artisan vendor:publish --tag=laravel-mail")
.myMailBody {
// css styles here
}
Code in controller:
$previewMailHtml = (string) (new \Illuminate\Mail\Markdown(view(), config('mail.markdown')))->render('mail/my-mail-view', [
"someData" => $someData
]);

laravel 5.4 embed image in mail

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');
}
}
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
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')))}})
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:3991f143cf1a86257f8671883736613c#Swift.generated">
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('abc#gmail.com')->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
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
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');
}
}
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
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.

Resources