Error when try to sending email in Laravel - laravel

I was try to make some email to send email acticvation code when someone register. so i make it an event called UserRegistered. here's my RegisterController that call the event
public function store(Request $request){
$this->validate( $request,
[
'name' => 'required|min:3',
'username' => 'required|unique:users|min:3',
'email' => 'required|email|unique:users',
'password' => 'required|confirmed|min:12'
]
);
$user = User::create([
'name' => request('name'),
'email' => request('email'),
'username' => request('username'),
'password' => bcrypt(request('password')),
'token' => random(30),
]);
event(new UserRegistered($user));
return back()->with('success','Please check your email to active your account.');
}
On the UserRegistered i pass the user data like this:
class UserRegistered
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $user;
/**
* Create a new event instance.
*
* #return void
*/
public function __construct(User $user)
{
$this->user = $user;
}
/**
* Get the channels the event should broadcast on.
*
* #return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
return new PrivateChannel('channel-name');
}
and here's my listener:
class SendActivationCode
{
/**
* Create the event listener.
*
* #return void
*/
public function __construct()
{
//
}
/**
* Handle the event.
*
* #param UserRegistered $event
* #return void
*/
public function handle(UserRegistered $event)
{
Mail::to($event)->send(new SendActivationMail($event));
}
}
and here the SendActivationMail class:
class SendActivationMail extends Mailable
{
use Queueable, SerializesModels;
protected $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('mails.user.activation')->with([
'name' => $this->user->name,
'token' => $this->user->token,
]);
}
}
but i got this errors:
"Type error: Argument 1 passed to App\Mail\SendActivationMail::__construct() must be an instance of App\User, instance of App\Events\UserRegistered given, called in E:\laragon\www\blog\app\Listeners\SendActivationCode.php on line 33 ◀"
My activation.blade.php:
#component('mail::message')
# Activation Code for {{ config('app.name') }}
Hi {{ $user->name }} You are recieved this because you are registered at our site. To active your account please click the link bellow.
#component('mail::button', ['url' => route('verify').$user->token])
Active Account
#endcomponent
Thanks,<br>
{{ config('app.name') }}
#endcomponent
so what can make me get this errors and how to fix it?

Looks like your SendActivatiionMail class doesn't extend Illuminate\Mail\Mailable. Try this in SendActivatiionMail.php:
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
class SendActivatiionMail extends Mailable
{
use Queueable, SerializesModels;
...
and then in your event listener:
use App\Mail\SendActivationMail;
public function handle(UserRegistered $event)
{
Mail::to($event->user->email)->send(new SendActivationMail($event->user));
}

Your SendActivatiionCode must extends the mailable Class.
<?php
use Illuminate\Mail\Mailable;
class SendActivatiionCode extends Mailable {
...
}

Related

Can we send different emails to user and admin at once using single event in laravel?

I am creating a leave request application for employee in an organization where user can create a leave request and admin(s) can approve/reject the request. The user and admin(s) should receive mail each time after making a leave request and after approval too. I am using event listener to send the mail and could send the mail using separate events and listeners(4 events:
making leave request to admin,
making leave request to user,
after accepting/rejecting the request to admin and
accepting/rejecting the request to user
and likewise 4 listeners too)
but it would be better if I could reduce the number of events and listeners in this case since the user mail and email template only are different.
I studied about event subscribers which subscribe to multiple events from within the subscriber class itself which is not what I want.
Is it possible to send multiple emails to multiple user/admin using less number of events/listeners?
I am using laravel 8
Code:
controller is:
public function store(Request $request)
{
DB::beginTransaction();
try{
$request->validate(
[
'leave_type' => 'in:halfday,fullday',
'start_date' => 'required',
'end_date' => 'required',
'assignee' => 'required',
]
);
$datetime1 = new \DateTime($request->start_date);
$datetime2 = new \DateTime($request->end_date);
$interval = $datetime1->diff($datetime2);
$days = $interval->format('%a');//total requested days
$leave_request= new LeaveRequest();
$leave_request->requested_by = auth()->user()->id;
$leave_request->leave_type_id = $request->leave_type_id ;
$leave_request->leave_type = $request->leave_type;
$leave_request->start_date = $request->start_date;
$leave_request->end_date = $request->end_date;
$leave_request->total_days = $days+1;
$leave_request->assignee = $request->assignee;
$leave_request->reviewer = $request->reviewer;
if($leave_request->save()){
$user = User::where('id', auth()->user()->id)->first();
$assignee = User::where('id',$request->assignee)->first();
$assignee->locale = App::currentLocale();
$assignee->requested_by = $user->name;
event(new SendLeaveRequestToAdminEvent($assignee));//send mail to admin asignee
if($request->reviewer !=null){
$reviewer = User::where('id',$request->reviewer)->first();
$reviewer->locale = App::currentLocale();
$reviewer->requested_by = $user->name;
event(new SendLeaveRequestToAdminEvent($reviewer));//send mail to admin reviewer(optional)
}
$user->locale = App::currentLocale();
event(new SendLeaveRequestToUserEvent($user));//send mail to user
DB::commit();
return response()->json([
'message'=> 'Leave requested successfully',
'status_code' => 200,
]);
}
else{
DB::rollback();
return response()->json([
'status_code' => '204',
'message' => 'Leave request failed',
]);
}
} catch (Exception $error) {
DB::rollback();
return response()->json([
'message' => 'Leave request failed',
'error' => $error
]);
}
}
first event to mail to admin(s) i.e; assignee and reviewer after sending leave request is
<?php
namespace App\Events;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
use App\Models\User;
class SendLeaveRequestToAdminEvent
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $admin;
/**
* Create a new event instance.
*
* #return void
*/
public function __construct(User $admin)
{
$this->admin = $admin;
}
/**
* Get the channels the event should broadcast on.
*
* #return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
return new PrivateChannel('channel-name');
}
}
second event to mail to user after sending leave request is
<?php
namespace App\Events;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
use App\Models\User;
class SendLeaveRequestToUserEvent
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $user;
/**
* Create a new event instance.
*
* #return void
*/
public function __construct(User $user)
{
$this->user = $user;
}
/**
* Get the channels the event should broadcast on.
*
* #return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
return new PrivateChannel('channel-name');
}
}
first listener to admin(s):
<?php
namespace App\Listeners;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Support\Facades\Mail;
use App\Mail\LeaveRequestAdmin;
use App\Events\SendLeaveRequestToAdminEvent;
class SendLeaveRequestToAdminListener
{
/**
* Create the event listener.
*
* #return void
*/
public function __construct()
{
//
}
/**
* Handle the event.
*
* #param SendLeaveRequestToAdminEvent $event
* #return void
*/
public function handle(SendLeaveRequestToAdminEvent $event)
{
$email = $event->admin->email;
Mail::to($email)->locale($event->admin->locale)->send(new LeaveRequestAdmin($event->admin));
}
}
second listener to user:
<?php
namespace App\Listeners;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Support\Facades\Mail;
use App\Mail\LeaveRequestUser;
use App\Events\SendLeaveRequestToUserEvent;
class SendLeaveRequestToUserListener
{
/**
* Create the event listener.
*
* #return void
*/
public function __construct()
{
//
}
/**
* Handle the event.
*
* #param SendLeaveRequestToUserEvent $event
* #return void
*/
public function handle(SendLeaveRequestToUserEvent $event)
{
$email = $event->user->email;
Mail::to($email)->locale($event->user->locale)->send(new LeaveRequestUser($event->user));
}
}
mail to admin:
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\URL;
class LeaveRequestAdmin extends Mailable
{
use Queueable, SerializesModels;
public $admin;
/**
* Create a new message instance.
*
* #return void
*/
public function __construct($admin)
{
$this->admin = $admin;
}
/**
* Build the message.
*
* #return $this
*/
public function build()
{
return $this->markdown('email.leaverequestadmin', [
'url' => URL::to('/home'),
'admin' => $this->admin,
])->subject('Incoming Leave Request');
}
}
mail to user:
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\URL;
class LeaveRequestUser extends Mailable
{
use Queueable, SerializesModels;
public $user;
/**
* Create a new message instance.
*
* #return void
*/
public function __construct($user)
{
$this->user = $user;
}
/**
* Build the message.
*
* #return $this
*/
public function build()
{
return $this->markdown('email.leaverequestuser', [
'url' => URL::to('/home'),
'user' => $this->user,
])->subject('Leave Request Received');
}
}
the above code is used after leave request is created which have two separate events/listeners/mail/ blade templates. Like wise I have similar another two events/listeners/mail/ blade templates each which are used after the leave request is accepted/rejected.

send multiple emails using custom job in laravel

I tried to create a job in order to send emails to all users in the database I have done everything and connected successfully with Mailtrip but still have a problem : (Failed) when implementing the command:
PHP artisan queue:work
this is my ProductEmail class:
class ProductMail extends Mailable implements ShouldQueue
{
use Queueable, SerializesModels;
public $product;
public $user;
/**
* Create a new message instance.
*
* #return void
*/
public function __construct(Product $product, User $user)
{
$this->product = $product;
$this->user = $user;
}
/**
* Build the message.
*
* #return $this
*/
public function build()
{
return $this->subject($this->product->name)
->view('email.product');
}
}
and i have created the view for it>>>>
and here the job class
class NotifyUsersForProduct implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
/**
* Create a new job instance.
*
* #return void
*/
public $product;
public function __construct(Product $product)
{
$this->$product = $product;
}
/**
* Execute the job.
*
* #return void
*/
public function handle()
{
$users = User::all();
$users->map(function(User $user){
Mail::to($user)->send(new ProductMail($this->product, $user));
});
}
}
and here i have use it
try {
$product = Product::create([
'name' => $request->input('name'),
'price' => $request->input('price'),
'quantity' => $request->input('quantity'),
'user_id' => Auth::id(),
]);
NotifyUsersForProduct::dispatch($product);
the error message:
public function __construct(Product $product)
{
$this->$product = $product;
}
This should be:
public function __construct(Product $product)
{
$this->product = $product;
}
Remove $
and also i recommend to do this but not necessary:
public function handle()
{
$users = User::all();
foreach($users as $user){
Mail::to($user)->send(new ProductMail($this->product, $user));
});
}
Hope it helps.

How to add username in welcome email after registration?

I've been searching everywhere for a solution to my issue. I've created a welcome email, created the Mailable, Controller, and View. But for some reason, the $user isn't showing in the email itself. It's blank. Am I missing something?
Mailable
<?php
namespace App\Http\Mail;
use App\User;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Queue\ShouldQueue;
class Welcome extends Mailable
{
use Queueable, SerializesModels;
public $user;
/**
* #return void
*/
public function _construct(User $user)
{
$this->user = $user;
}
/**
*#return $this
*/
public function build()
{
return $this->view('emails.welcome')->subject('Welcome to');
}
}
Controller
<?php
namespace App\Http\Controllers\Auth;
use Mail;
use App\User;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Validator;
use Illuminate\Foundation\Auth\RegistersUsers;
use Illuminate\Support\Facades\Auth;
use App\Http\Mail\Welcome;
class RegisterController extends Controller
{
/*
|--------------------------------------------------------------------------
| Register Controller
|--------------------------------------------------------------------------
|
| This controller handles the registration of new users as well as their
| validation and creation. By default this controller uses a trait to
| provide this functionality without requiring any additional code.
|
*/
use RegistersUsers;
/**
* Where to redirect users after registration.
*
* #var string
*/
protected $redirectTo = '/dashboard';
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('guest');
}
/**
* Get a validator for an incoming registration request.
*
* #param array $data
* #return \Illuminate\Contracts\Validation\Validator
*/
protected function validator(array $data)
{
return Validator::make($data, [
'first_name' => 'required|max:255',
'last_name' => 'required|max:255',
'email' => 'required|email|max:255|unique:users',
'mobile' => 'required',
'password' => 'required|min:6|confirmed',
]);
}
/**
* Create a new user instance after a valid registration.
*
* #param array $data
* #return User
*/
protected function create(array $data)
{
$user = User::create([
'first_name' => $data['first_name'],
'last_name' => $data['last_name'],
'email' => $data['email'],
'mobile' => $data['mobile'],
'password' => bcrypt($data['password']),
'payment_mode' => 'CASH',
]);
Mail::to($data['email'])->send(new Welcome($user));
return $user;
// send welcome email here
}
/**
* Show the application registration form.
*
* #return \Illuminate\Http\Response
*/
public function showRegistrationForm()
{
return view('user.auth.register');
}
}
View (shortened to show problem)
Welcome {{ $user->first_name }}
User
<?php
namespace App;
use Laravel\Passport\HasApiTokens;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
use HasApiTokens,Notifiable;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'first_name', 'last_name', 'email', 'mobile', 'picture', 'password', 'device_type','device_token','login_by', 'payment_mode','social_unique_id','device_id','wallet_balance'
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token', 'created_at', 'updated_at'
];
}
As was mentioned, everything passes successfully, however, in the email itself, the name of the user is blank. Please help!
I got it working for anyone else dealing with same issue. I changed the register controller and just skipped the mailable entirely. In other words, I didn't need a separate mailable. Below is the result.
Mail::send('emails.welcome', [
'first_name' => $data['first_name'],
'email' => $data['email']
], function ($mail) use($data) {
$mail->from('Whatever', 'site/company name');
$mail->to($data['email'])->subject('Whatever');
});
return $user;
And in the view I just pass the first name like so
Welcome {{ $first_name }}

Why the value coming from a get request isn't accessable in the blade file?

I have the following controller method, where I would like to make the $clientId able to be accessed in mails.projectRequest blade file.
I tried to do that through the ProjectRequestMailclass but it does not work. Is there something wrong or this is not the way to do that?
My controller method:
public function sendProjectTeam($projectClientId) {
$projectClientEmail = Client::where('id', $projectClientId)->value('email');
Mail::to($projectClientEmail)->send(new ProjectRequestMail($projectClientId));
return ['success' => true, 'message' => 'Email was sent'];
}
ProjectRequestMail class:
class ProjectRequestMail extends Mailable implements ShouldQueue
{
use Queueable, SerializesModels;
/**
* #var
*/
public $projectClientId;
/**
* Create a new message instance.
*
* #param $user
*/
public function __construct($projectClientId)
{
//
$this->project_client_id = $projectClientId;
}
/**
* Build the message.
*
* #return $this
*/
public function build()
{
$this->from('hello#signifly.com');
$this->subject('New Project Request from Signifly');
return $this->markdown('mails.projectRequest');
}
}
and finally ProjectRequest blade
#component('mail::message')
Hello,
You have received a new request regarding your project.
#component('mail::button', ['url' => env('APP_URL'). '/#/project-requests/' . $projectClientId ])
See request
#endcomponent
Best regards,<br>
The ... team
#endcomponent

Laravel queues issues when I pass data from controller to jobs

I'm having issue fixing the queue part for Laravel.
I have a contact form which works perfectly. I submit the form and a mail is being sent to me with the input details from the form.
But the issue is that if you do not use the Laravel Queues then the UX is lacking because of the waiting time before the mail is being sent and after getting the success message.
So now I want to implement the queuing part, but im not doing it right. Im still a noob at it...
Here is my controller
KontaktformController.php
<?php
namespace App\Http\Controllers;
use App\Jobs\SendEmailJob;
use Carbon\Carbon;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Session;
use App\Kontaktform;
use Illuminate\Http\Request;
use App\Mail\SendEmailMailable;
class KontaktformController extends Controller
{
public function create()
{
return view('kontakt');
}
public function store(Request $request) {
$this->validate($request, [
'name' => 'required|string',
'mobile' => 'required',
'email' => 'required|email',
'subject' => 'required',
'message' => 'required',
]);
/*
Add mail functionality here.*/
$kontakt = new Kontaktform([
'navn' => $request['name'],
'mobilnr' => $request['mobile'],
'fastnetnr' => $request['landline'],
'mail' => $request['email'],
'emne' => $request['subject'],
'beskrivelse' => $request['message']
]);
$kontakt->save();
//$user['email'] = 'test#test.com';
$job = (new SendEmailJob($request['email']))
->delay(Carbon::now()->addSeconds(3));
dispatch($job);
}
}
SendEmailJob.php
<?php
namespace App\Jobs;
use App\Mail\SendEmailMailable;
use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Support\Facades\Mail;
class SendEmailJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
protected $user;
/**
* Create a new job instance.
*
* #return void
*/
public function __construct($user)
{
$this->user = $user;
}
/**
* Execute the job.
*
* #return void
*/
public function handle()
{
$email = new SendEmailMailable('test#test.dk');
Mail::to('admin#admin.dk')->send($email);
}
}
SendEmailMailable.php
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Queue\ShouldQueue;
class SendEmailMailable extends Mailable
{
use Queueable, SerializesModels;
public $request;
/**
* Create a new message instance.
*
* #return void
*/
public function __construct($request)
{
$this->request = $request;
}
/**
* Build the message.
*
* #return $this
*/
public function build()
{
return $this->from('test#test.dk')->view('mail.kontaktform');
}
}
kontaktform.blad.php
{{$request['email']}}
In your kontaktform.blad.php (which should be named kontaktform.blade.php btw), you expect the data to be an array because you try to fetch the index ['email'] though in your SendEmailJob.php in the method handle() you pass your email as a string.
So what you should change it to the following:
$email = new SendEmailMailable(['email' => 'test#test.dk']);
or do the following in the controller & in the job:
Controller:
$job = (new SendEmailJob($request))
->delay(Carbon::now()->addSeconds(3));
Job:
protected $request;
/**
* Create a new job instance.
*
* #return void
*/
public function __construct($request)
{
$this->request = $request;
}
/**
* Execute the job.
*
* #return void
*/
public function handle()
{
$mailable = new SendEmailMailable($this->request);
Mail::to('admin#admin.dk')->send($mailable);
}
Now all data from the request is should be available in your blade template.
I found the issue. I didnt pass data from mailable to my blade
public function build()
{
return $this->view( 'mail.kontaktform' )->with( [
'request' => $this->request,
] );
}

Resources