Laravel 5.5 mail with username in it - laravel

I think I miss something really simple here, but I have a script like this:
\Mail::to( User::all() )
->send( new NotificationEmail($notification) );
class NotificationEmail extends Mailable {
use Queueable, SerializesModels;
/**
* Create a new message instance.
*
* #param Notification $notification
*
*/
public function __construct( Notification $notification ) {
$this->notification = $notification;
}
/**
* Build the message.
*
* #return $this
*/
public function build() {
$notification = $this->notification;
return $this
->from( [
'address' => \env( 'MAIL_DEFAULT_SENDER' ),
'name' => \env( 'APP_NAME' )
] )
->view( 'email.notification.ready' );
}
}
Now I'd like the email message to start with something like
Dear {firstname of the user}
But I have no idea how to get the firstname of user who is going to get that email. Is there any way to figure that out?

It is not a recommended way to send a email to all users, because who receive the email can see all the recipients and, they receive the same message that you cannot customize to add first name of the user.
You need to create separate Mailable to each user and queue all the Mailable. Sending email to all users separately is time-consuming task, workers are need to process the queue in background.
$users = User::all();
foreach ($users as $user) {
Mail::to($user)->queue(new NotificationEmail($notification, $user));
}
And now you can pass the $user instance, and first name of the user is available on the view:
public function __construct( Notification $notification , User $user) {
$this->notification = $notification;
$this->user = $user;
}
public function build() {
$notification = $this->notification;
return $this
->from( [
'address' => \env( 'MAIL_DEFAULT_SENDER' ),
'name' => \env( 'APP_NAME' )
] )
->view( 'email.notification.ready' , [
'user' => $this->user
]);
}

Related

How to add queue in sending mails in Laravel?

I already edited my .env to QUEUE_CONNECTION=database and tried to replace from send to queue. I also tried to add implements ShouldQueue to my CertificatEmail but not working. I don't know what's missing.
SendMail Controller
public function sendEmail(Request $request)
{
$users = StudentApplicants::whereIn("id", $request->ids)->get();
foreach ($users as $key => $user) {
$data = [
'fname' => $user->users->first_name,
'mname' => $user->users->middle_name,
'lname' => $user->users->last_name,
'gwa' => $user->gwa,
'sy' => $user->school_year
];
$qrcode = base64_encode(QrCode::format('svg')->color(128, 0, 0)->size(200)->errorCorrection('H')->generate($user->users->stud_num));
$pdf = app('dompdf.wrapper');
$pdf->loadView('admin.send-awardees-certificates.certificate', $data, array('qrcode' => $qrcode));
$pdf->setPaper('A4', 'landscape');
Mail::to(config('mail.notification_recipient'))->queue(new CertificateEmail($user, $pdf));
}
return response()->json(['success' => 'Send email successfully. Refresh the page']);
}
CertificateEmail from mail
class CertificateEmail extends Mailable implements ShouldQueue
{
use Queueable, SerializesModels;
public $pdf;
public $user;
/**
* Create a new message instance.
*
* #return void
*/
public function __construct($user, $pdf)
{
$this->pdf = $pdf;
$this->user = $user;
}
/**
* Build the message.
*
* #return $this
*/
public function build()
{
// return $this->view('view.name');
return $this->from(env('info#gmail.com'))
->subject('Certificate from ABC EFG')
->view('email.certificate-email')
->attachData($this->pdf->output(), 'stock_report.pdf');
}
}
Run these two queries in command
php artisan queue:table # creates a table for queued jobs
php artisan migrate # migrates the table
Then run
php artisan queue:work
In from env I think it doesn't write right please review it should be USER_EMAIL or something like that

Laravel queue email with attachment

Hi everyone i'm just trying to queue my email with attachment in laravel project, but it does not seems to work. when i try to send an attachment without queue my mail it is working absolutely fine, but when i put my email in queue it just stop working. email is sent but attachment doesn't.
here is my code for email in controller
Mail::to($request->email)->send(new ContactUsEmail($contact_us));
and below code is from my mail job
class ContactUsEmail extends Mailable implements ShouldQueue
{
use Queueable, SerializesModels;
/**
* Create a new message instance.
*
* #return void
*/
protected $data;
public function __construct($data)
{
$this->data = $data;
}
/**
* Build the message.
*
* #return $this
*/
public function build()
{
$extension = explode('.',$this->data->attachment)[1];
return $this->subject($this->data->topic)->attach(public_path('/storage/attachments/contact-us/' . $this->data->attachment),
[
'as' => $this->data->attachment,
'mime' => 'application/'. $extension
])->markdown('mail.contact-us' ,[
'subject' => $this->data->subject,
'name' => $this->data->name,
'email' => $this->data->email,
'description' => $this->data->description,
]);
}
}
please let me know if i'm doing something wrong or missing something.
i appreciate your response

Listeners and Events get error: Too few arguments to function App\Events\User\Created::__construct(),

I need have two Listeners in same event, and when an user has been created in the system, Lavarel send my an email with the credentials and another to assign roles of users. It's possible have two listeners in same event? Why does the system show me this message?
When I create an user the system show me:
Too few arguments to function App\Events\User\Created::__construct(), 1 passed in C:\xampp\htdocs\bwm\vendor\laravel\framework\src\Illuminate\Database\Eloquent\Concerns\HasEvents.php on line 205 and exactly 2 expected
This is my Event:
class UserCreated
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $user;
public $password;
/**
* Create a new event instance.
*
* #return void
*/
public function __construct($user,$password)
{
$this->user = $user;
$this->password = $password;
}
/**
* Get the channels the event should broadcast on.
*
* #return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
return new PrivateChannel('channel-name');
}
}
This is my Listener Assign Roles:
class AssignRoles
{
private $request;
/**
* Create the event listener.
*
* #return void
*/
public function __construct(Request $request)
{
$this->request = $request;
}
/**
* Handle the event.
*
* #param Created $event
* #return void
*/
public function handle(UserCreated $event)
{
$event->user;
switch($role = $this->request->role)
{
case $role == 'Asesor':
$event->user->assignRole('Asesor');
$asesoria = Asesoria::orderby('created_at', 'desc')->first();
$asesoria->user_id = $event->user->id;
$asesoria->published = true;
$asesoria->update();
break;
case $role == 'Comprador':
$event->user->assignRole('Comprador');
break;
default:
$event->user->assignRole('Writer');
}
}
}
This is my Listener Send Login Credentials:
class SendLoginCredentials
{
/**
* Create the event listener.
*
* #return void
*/
public function __construct()
{
//
}
/**
* Handle the event.
*
* #param Created $event
* #return void
*/
public function handle(UserCreated $event)
{
Mail::to($event->user)->queue(
new LoginCredentials($event->user, $event->password)
);
}
}
In my function store of my UsersController I call to dispach:
UserCreated::dispatch($user, $password);
In my EventServiceProvider I have this:
protected $listen = [
Registered::class => [
SendEmailVerificationNotification::class,
],
'App\Events\User\UserCreated' => [
'App\Listeners\User\AssignRoles',
'App\Listeners\SendLoginCredentials',
],
];
You have two parameters in your constructor of UserCreated class and you are passing only one because you are dispatching it wrong way.
you can do it several ways:
Event::dispatch(new UserCreated($user, $password))
event(new UserCreated($user, $password))
Try these. Hope it works
I had a protected $dispachesEvents in User Model:
protected $dispatchesEvents = ['created' => 'App\Events\User\Created'];
That's why I got the error:
Too few arguments to function App\Events\User\Created::__construct(), 1 passed in C:\xampp\htdocs\bwm\vendor\laravel\framework\src\Illuminate\Database\Eloquent\Concerns\HasEvents.php on line 205 and exactly 2 expected
I deleted it, and put the call to the dispacher in my RegisterController.
protected function create(array $data)
{
$user = User::create([
'name' => $data['name'],
'email' => $data['email'],
//'password' => Hash::make($data['password']), //mutador en User model
'password' => $data['password'],
'surname1' => $data['surname1'],
'surname2' => $data['surname2'],
'comunidad_id' => $data['cbx_comunidad'],
'provincia_id' => $data['cbx_provincia'],
'municipio_id' => $data['cbx_municipio'],
]);
//dd($data['password']);
event(new Created($user,$data['password']));
return $user;
}
As I had a protected $dispatchesEvents in User Model,this it executes before that my call in the RegisterController.

Access Controller resources based on Laravel/Spatie Permissions

I am working on Laravel passport api in which i am using spatie package for user role's and permission's. I have to perform certain operation ('store','view','update','delete') based on user permission's.
For this purpose i have created a trait and used in controller but it is not working correctly.
On every api request it throw's an exception "This action is unauthorized" either the user has permission or not.
Authorize Trait :
<?php
namespace App;
/*
* A trait to handle authorization based on users permissions for given controller
*/
trait Authorizable
{
/**
* Abilities
*
* #var array
*/
private $abilities = [
'index' => 'view',
'edit' => 'edit',
'show' => 'view',
'update' => 'edit',
'create' => 'add',
'store' => 'add',
'destroy' => 'delete'
];
/**
* Override of callAction to perform the authorization before it calls the action
*
* #param $method
* #param $parameters
* #return mixed
*/
public function callAction($method, $parameters)
{
if( $ability = $this->getAbility($method) ) {
$this->authorize($ability);
}
return parent::callAction($method, $parameters);
}
/**
* Get ability
*
* #param $method
* #return null|string
*/
public function getAbility($method)
{
$routeName = explode('.', \Request::route()->getName());
$action = array_get($this->getAbilities(), $method);
return $action ? $action . '_' . $routeName[0] : null;
}
/**
* #return array
*/
private function getAbilities()
{
return $this->abilities;
}
/**
* #param array $abilities
*/
public function setAbilities($abilities)
{
$this->abilities = $abilities;
}
}
Routes:
Route::middleware('auth:api')->group(function () {
Route::post('user', 'ApiController#user');
Route::post('view_department', 'DepartmentController#index');
Route::post('add_department', 'DepartmentController#store');
Route::post('edit_department', 'DepartmentController#update');
Route::post('delete_department', 'DepartmentController#destroy');
Route::post('/logout', 'ApiController#logout');
}); // auth middleware ends
Controller:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Carbon\Carbon;
use App\User;
use App\Authorizable;
use Illuminate\Support\Facades\Validator;
use App\Department;
use Spatie\Permission\Models\Role;
use Spatie\Permission\Models\Permission;
class DepartmentController extends Controller
{
use Authorizable;
//
public function index(Request $request) {
// return response
return response()->json([
'success' => 'You have the permission to view departments!']);
}
//
public function store(Request $request) {
// validate the posted data
$validator = Validator::make($request->all(), [
'name' => 'required|string|unique:departments',
]);
// return errors
if ($validator->fails())
{
return response(['errors'=>$validator->errors()->all()]);
}
$department = new Department;
$department->name = $request->name;
$department->save();
// return response
return response()->json([
'success' => 'Successfully created department!']);
}
}
I am badly stack at it, don't know where i am going wrong. I would highly appreciate if anyone guide me through this.
Thanks,

Variables are not passed in the email template

I'm having this method in my controller
public function update(UserUpdateRequest $request)
{
$request->user()->update([
'name' => $request->username,
]);
Mail::to($request->user())->send(
new UserUpdated( $request->user() )
);
return redirect()->route('account.index');
}
So when the user updates the username an email is send
public $user;
/**
* Create a new message instance.
*
* #return void
*/
public function __construct(User $user)
{
$this->user = $user;
}
/**
* Build the message.
*
* #return $this
*/
public function build()
{
return $this->markdown('emails.user.updated');
}
And this is the email template
Hi {{ $user->username }},
We would like to inform you that your username has been updated successfully.
If this action wasn't done by you, you need to contact with our support.
But this is throwing an exception in the queues
ErrorException: Undefined variable: user in /storage/framework/views/
Any ideas what I'm doing wrong?
Try passing it to the view via with method and make user variable protected:
protected $user;
public function build()
{
return $this->view('emails.user.updated')->with(['username' => $this->user->username]);
}
And then you can access it like {{ $username }} in your view.
Try this and then access the $user in your view
public function update(UserUpdateRequest $request)
{
$request->user()->update([
'name' => $request->username,
]);
$user = $request->user();
Mail::to($request->user())
->send(new UserUpdated($user));
return redirect()->route('account.index');
}
You can't send $request directly to you email template may this is the reason why you are not able to access the $user

Resources