How to add queue in sending mails in Laravel? - 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

Related

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.

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

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,
] );
}

Error when try to sending email in 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 {
...
}

Laravel 5.5 mail with username in it

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
]);
}

Resources