Send email from queued event handler - laravel

I use Lumen 5.1 and Redis for queues. And I have a pretty standard event handler that should send an email:
<?php
namespace App\Handlers\Events;
use Illuminate\Contracts\Queue\ShouldQueue;
use App\Events\UserHasRegistered;
use Illuminate\Contracts\Mail\Mailer;
class SendWelcomeEmail implements ShouldQueue
{
protected $mailer;
public function __construct(Mailer $mailer)
{
$this->mailer = $mailer;
}
public function handle(UserHasRegistered $event)
{
$user = $event->user;
$this->mailer->raw('Test Mail', function ($m) use ($user) {
$name = $user->getFirstName().''.$user->getLastName();
$m->to($user->auth()->getEmail(), $name)->subject('This is a test.');
});
}
}
The email is sent when I don't use the ShouldQueue interface. But when I push the event handler to the queue (i. e. use the ShouldQueue interface), the email is not sent and I don't get any error messages.
Do you have any ideas how to solve or debug this?

It was not a bug, just an unexpected behaviour.
I am using Xampp on Windows and the php mail driver for development. For some reason the queued mails were not saved in the default mailoutput folder within the Xampp directory. Instead a new mailoutput folder was automatically created within the Lumen directory.
There I found all the missed mails. :)

Related

Laravel Echo does not received message from channel

I stuck very bad . in real-time laravel(version 9) project using pusher for websocket.
backend can get message but problem is Echo does not received message which sent from backend ...
Event :
class MessageSent implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $message ;
public function __construct($message){
$this->message=$message;
}
public function broadcastOn()
{
\Log::debug("{$this->message}");
return new Channel('chat');
}
public function broadcatAs(){
return 'chat';
}
}
JS :
Echo.channel('.chat').listen('MessageSent', (e) => {
alert(e.message)
});
further information :
1- according to Event I can log message to laravel.log file which means message sent from frontend to backend .
2-there is no error in console area
3-see debug console of pusher official site
There are 3 issues I believe. The first is you should not need to do .chat in your channel function on the frontend. The second is you mispelled broadcastAs function as broadcatAs customizes the event that is being listened for in the frontend. However, because it is mispelled you are referring to the event correctly though if you update it you will then need to change your listener to .chat . The last issue is you may not have started your queue. You need to run a daemon to handle that.
Echo.channel('chat').listen('MessageSent', (e) => {
alert(e.message)
});
however, if you update your broadcastAs spelling correctly it will need to be
Echo.channel('chat').listen('chat', (e) => {
alert(e.message)
});

How to get parameter value from dialogflow with botman

I tried to call intent in dialogflow. My intent is detect geo-city from message. This is my dialogflow page. My problem is when I run the application and send message in botman it doesn't send me the geo-city value.
I tried send in botman 'My city is colombo' but no any responce or reply in botman.
I setup my api json file in .env file
GOOGLE_CLOUD_PROJECT="project_id"
GOOGLE_APPLICATION_CREDENTIALS="pathtojsonfile"
In dialogflow::create() function did I call the security key correctly?
<?php
namespace App\Http\Controllers;
use App\Botman\MainConversation;
use Illuminate\Http\Request;
use BotMan\BotMan\Middleware\ApiAi;
use BotMan\BotMan\Middleware\Dialogflow;
class BotManController extends Controller
{
public function handle()
{
$botman = app('botman');
$dialogflow = Dialogflow::create('en');
$botman->middleware->received($dialogflow);
$botman->hears('getzone', function ($bot) {
$extras = $bot->getMessage()->getExtras('apiParameters');
$apiReply = $extras['geo-city'];
$bot->reply('hi');
})->middleware($dialogflow);
$botman->listen();
}
}

Cannot get Laravel Mail::to()->later() to work

I'm trying to send a time-delayed email via a Redis queue and Mailgun using the following code...
$when = \Carbon\Carbon::now()->addMinutes(5);
Mail::to($demoDownloader->Email)->later($when, new DemoRequestFollowUp($demoDownloader));
I can see that the job is added to the redis queue (using Redis Desktop Manager) and stays in the queue for 5 minutes before disappearing from the queue. Unfortunately, it never appears in the Mailgun logs.
If I instead use this line of code...
Mail::to($demoDownloader->Email)->send(new DemoRequestFollowUp($demoDownloader));
...then the email appears in the Mailgun logs and subsequently arrives in the destination mailbox successfully (minus the time delay of course).
No error messages are written to storage/logs/laravel.log so I'm at a bit of a loss as to why this isn't working. I'm pretty sure I've used the syntax specified in the manual.
By the way, my mailable looks like this...
<?php
namespace App\Mail;
use \App\DemoDownloader;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Queue\ShouldQueue;
class DemoRequestFollowUp extends Mailable
{
use Queueable, SerializesModels;
public $requestee;
public function __construct(DemoDownloader $requestee)
{
$this->requestee = $requestee;
}
public function build()
{
return $this->subject('Overview')
->view('email-demo-request-follow-up');
}
}
I'd be most grateful for any input.
I'd neglected to look in the failed_jobs table which gave me the clue I needed...
Illuminate\Database\Eloquent\ModelNotFoundException: No query results for model [App\DemoDownloader]
As the DemoDownloader instance being passed into the DemoRequestFollowUp constructor wasn't actually being used, I removed the argument and also removed the $requestee public property from the class and its assignment in the constructor. After making these changes emails were reliably arriving after the specified delay interval had passed.

Laravel - Pusher - Detect when a user is no longer in the website or leaves the page

I'm facing a problem with a real time app that i'm developing. My problem is about user's status using Pusher. I would like to get the correct way to detect when a user leaves the page or keep unactive for a while to set it's status to 'offline', for example. How could I achieve that? I'm almost sure that is not recommended develop this feature at client-side, it should be at server-side, but how? How can I ask to clients if they are still there? Should I create a command and run it wit cron? Are there any mechanism to let the server 'detect' the socket disconnection? Any help will be appreciated, Thx!
Update
With NoseJS and SocketIO it's really simple, you just have to write:
io.on('connection', function (socket) { // When client connects
socket.on('disconnect', function() { // Listen to disconnections from SERVER-SIDE
// Logic when a user disconnects. This is what I want!
});
});
But in Laravel, I only have this:
// A Laravel Event Class that implements the shouldBroadcast interface...
public function broadcastOn()
{
// I think here is where connections happen, but I don't know how to detect 'disconnections' :(
return new PresenceChannel('someString');
}
PD: I'm using Laravel Echo and Pusher :)
You can use presence channels to achieve this. You can then use presence webhooks to notify your server whenever a user enters or leaves the channel.
Simplest way is to subscribe to the the ConnectionClosed event
Providers/EventServiceProvider.php
<?php
namespace App\Providers;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
use BeyondCode\LaravelWebSockets\Events\ConnectionClosed;
use App\Listeners\OnConnectionClosed;
class EventServiceProvider extends ServiceProvider
{
protected $listen = [
ConnectionClosed::class => [
OnConnectionClosed::class
]
];
public function boot()
{
parent::boot();
}
}
Listeners/OnConnectionClosed.php
<?php
namespace App\Listeners;
use BeyondCode\LaravelWebSockets\Events\ConnectionClosed;
class OnConnectionClosed
{
public function handle(ConnectionClosed $connection)
{
if( !is_null($connection->appId) && !is_null($connection->socketId) ){
error_log($connection->appId);
error_log($connection->socketId);
}
}
}

Queueable entity App\Setting not found for ID error in Laravel

I am trying to send emails in laravel 5.1 by using queues. When running queue listen command on terminal,
php artisan queue:listen
Displays below error on terminal,
[Illuminate\Contracts\Queue\EntityNotFoundException]
Queueable entity [App\Setting] not found for ID [].
Values of jobs table is not process. Any idea ?
How can I process my queue ?
I know this question is a few months old, but I'd like to add an observation of mine while encountering this very same error message. It is due to the EventListener (interface of ShouldQueue in this example for asynchronous) not being able to resolve a dependant variable correctly (out of scope or not included in scope of Event object passed through the handle(Event $event) method of EventListener).
For me, this error was fired when I put my code within the __construct block within the EventListener:
public function __construct(Event $event)
{
$localProperty = $event->property
Mail::queue(etc...);
}
public function handle()
{
// Yeah I left this blank... whoops
}
Instead, the handle() method of the EventListener takes an Event interface and when called processes the job in the queue:
In the Event:
public function __construct(Object $ticket, AnotherObject $user)
{
$this->ticket = $ticket;
$this->user = $user;
}
And in Event Listener
class SomeEventListener implements ShouldQueue
{
use InteractsWithQueue;
use SerializesModels;
public function __construct()
{
// Leave me blank!
}
public function handle(Event $event)
{
$someArray = [
'ticket' = $event->ticket,
'user' = $event->user,
];
Mail::queue('some.view', $someArray, function($email) use ($someArray) {
// Do your code here
});
}
}
Although a tad late, I hope this helps someone. Queues are similar to Events (with the exception of Jobs being the main driving force behind Queues), so most of this should be relevant.
Turned out that it was because a model was added to the queue, that has since been deleted.

Resources