I would like to send a telegram message to a specific user at 17:00 using laravel's Telegram notification channel, I however can't seem to get it going. I currently use a cmd command for testing, but keep getting errors and don't know what to do.
Here are my files for the command and notification:
SendNotification.php
<?php
namespace Rogier\Lab\Console;
use Illuminate\Console\Command;
use Rogier\Lab\Notifications\DailyTelegram;
class SendNotifications extends Command
{
protected $name = 'lab:notifications:send';
protected $description = 'Send notifications';
protected $userid = 919871501;
/**
* Execute the console command.
* #return void
*/
public function handle()
{
$this->output->writeln('Sending notifications');
$notification = new DailyTelegram($this->userid);
$notification->via()->toTelegram();
$this->output->writeln('Done');
}
}
and DailyTelegram.php
<?php
namespace Rogier\Lab\Notifications;
use NotificationChannels\Telegram\TelegramChannel;
use NotificationChannels\Telegram\TelegramMessage;
use Illuminate\Notifications\Notification;
use Illuminate\Notifications\Notifiable;
class DailyTelegram extends Notification
{
protected $userid = 919871501;
public function via()
{
return [TelegramChannel::class];
}
public function toTelegram()
{
return TelegramMessage::create()
// Optional recipient user id.
->to($this->userid)
// Markdown supported.
->content("Hello there!\nYour invoice has been *PAID*");
}
}
I currently get the error "Call to a member function toTelegram() on array", but I feel like I tried everything, maybe I'm doing it completely wrong. Does anyone know how I should do it?
thanks in advance
Yes, you are doing it wrong. Notifiables have notify() method, you should use it:
$user->notify(new DailyTelegram);
In this example $user is App\User instance (which is notifiable out of the box).
You should check out both Laravel's sending notifications and laravel-notification-channels/telegram docs.
Related
Problem
I can confirm that Pusher API is receiving the message. I saw in Debug console of Pusher website. But listen callback is not working at all.
I am following this tutorial to implement Pusher in Laravel 5.4
Below were the step by step things done.
composer require pusher/pusher-php-server
npm install --save laravel-echo pusher-js
instantiated the Echo instance in your resources/assets/js/bootstrap.js
Initialized the pusher key in env and in bootstrap.js file.
Finally, I wrote below code in blade.
<script>
window.Echo.channel('SendMessageChannel.1')
.listen('App.Events.SendMessageEvent', (e) => {
console.log(e);
});
</script>
Controller Code
broadcast(new SendMessageEvent("Hi"))->toOthers();
Event Code
class SendMessageEvent implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $Message;
public function __construct($message)
{
$this->Message = $message;
}
public function broadcastOn()
{
return new PrivateChannel('SendMessageChannel.2');
}
}
Am I missing anything?
You have to listen to: SendMessageEvent without the namespace.
when you listen to a private channel, you need to to listen to private-SendmessageChannel or you use Echo.private('SendmessageChannel')
Because we fixxed the issue via teamspeak at some parts it's difficult to explain it in this answer in full detail.
One problem was also that the event was fired before the client started to listen to it. The best way is to debug with the pusher console and to fire custom events.
I have been using Laravel 5.4 events quite efficiently since 6 months with a project. I had same trouble when I was doing initial setup. Let me guide you with whatever I have done to get it working.
I can see you have controller to initiate an Event, SendMessageEvent to send message content to pusherjs. You need to check following stuff to get it going.
Check 1:
But you have not mentioned if you have an Eventhandler defined. Event handler works as a bridge between the SendMessageEvent and its actual broadcaster.
So define an Eventhandler create one folders like app / Handlers / Events /. (here Handlers and Events are folders. where Events is inside Handlers)
create one file inside this Events folder with a name e.g.
HandleMyMessage.php
And put this code in it:
<?php
namespace App\Handlers\Events;
use App\Events\SendMessageEvent; // This should be your event class..
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
class HandleMyMessage{
protected $name;
public function __construct() {
//
}
public function handle(Message $event) {
// No need to write anything here
}
}
Check 2:
There should be one provider at app / Providers / EventServiceProvider.php location, and put following code in EventServiceProvider.php
<?php
namespace App\Providers;
use Illuminate\Support\Facades\Event;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
class EventServiceProvider extends ServiceProvider
{
/**
* The event listener mappings for the application.
*
* #var array
*/
protected $listen = [
'App\Events\SendMessageEvent' => [
'App\Handlers\Events\EventServiceProvider',
],
];
/**
* Register any events for your application.
*
* #return void
*/
public function boot()
{
parent::boot();
}
}
Check 3:
And you should change syntax of sending event message in your controller like this:
$broadcast_data['first_name'] = 'John';
$broadcast_data['last_name'] = 'Doe';
$return_socket['data'] = $broadcast_data;
Event::fire(new Message($return_socket)); // Sending message to pusherjs via Laravel Event.
More on this, you also need Redis installed on your system and run it.
Hope this helps. If you need more information for any of above, just comment. I am posting a reference link for the same.
Happy coding!!! :-)
I got it working. Below is the correct code. I hope this will be useful to others for sending real time messaging.
Js Work
<script>
window.Echo.channel('private-SendMessageChannel.{!! \Auth::user()->UserID !!}')
.listen('SendMessageEvent', (e) => {
console.log(e);
});
</script>
Controller Code
broadcast(new SendMessageEvent("Hi", 1))->toOthers();
//Here 1 is recepient ID
Event Code
class SendMessageEvent implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $Message;
private $UserID;
public function __construct($message, $RecepientID)
{
$this->Message = $message;
$this->UserID = $RecepientID;
}
public function broadcastOn()
{
return new PrivateChannel('SendMessageChannel.' . $UserID);
}
}
In my case, I had used:
public function broadcastAs()
{
return 'message';
}
If you've set the broadcast name, you must use that name in the listener differently.
For those who have done the same mistake as I did:
If you customize the broadcast name using the broadcastAs method, you should make sure to register your listener with a leading . character. This will instruct Echo to not prepend the application's namespace to the event:
https://laravel.com/docs/9.x/broadcasting#broadcast-name
i can't send email with user address as FROM and Reply To
In the FormRequest :
public function persist()
{
$reservation = Resa::create(
$this->only(['nom', 'email', 'phone', 'formule', 'date_arr', 'date_ret', 'nb_adu', 'nb_enf', 'lemessage'])
);
Mail::to('contact#cotiga.fr')
->from($reservation->email, $reservation->nom)
->replyTo($reservation->email, $reservation->nom)
->send(new Reservation($reservation));
}
I have the error :
FatalThrowableError in ReservationForm.php line 48:
Call to undefined method Illuminate\Mail\PendingMail::from()
I tried full of possibility, but I can not change the field FROM and REPLYTO
Can you help me ?
Thank's
The Mail Facade does not implement the replyTo() method anymore. Instead this method has moved to the Mailable class itself. Official documentation proposes to use the build() method to setup the Mailable, however this is not always convenient (eg the replyTo field might be different each time)
However if you still want to use a similar syntax you can use:
$mailable = new myMailableClass;
$mailable->replyTo('reply#to.com');
Mail::to('email#tocom')
->send($mailable);
For a complete list of available methods on the Mailable class see the Mailable Documentation
In Laravel 5.4 Mailables, the replyTo, subject, cc, bcc and others can be set inside the mailable in the build method. This is also true for the to which can also be set on the Mail facade.
Here is a simple example of a contact form mailable using an array of attributes:
You may use the to static method directly on the Mail facade, but as an example, we're going to set it inside the mailable:
Mail::send(new ContactCompany($attributes));
Then set the replyTo inside the build method:
class ContactCompany extends Mailable
{
use Queueable, SerializesModels;
public $attributes;
/**
* Create a new message instance.
*
* #param $attributes
*/
public function __construct($attributes)
{
$this->attributes = $attributes;
}
/**
* Build the message.
*
* #return $this
*/
public function build()
{
$this->to($this->attributes['departmentEmail'], config('app.name'));
$this->replyTo($this->attributes['email'], $this->attributes['name']);
$this->subject(sprintf("New contact message from %s", $this->attributes['name']));
return $this->markdown('emails.contact.company');
}
}
Please, note that Mail::alwaysFrom() and Mail::alwaysReplyTo() can be used before Mail::send() to set the from and replyTo of all emails, so make sure to use them with care.
The preferred method of sending emails are now mailables and you can set from and reply to using from() or replyTo() methods.
However using plain Mail facades you should try to use alwaysFrom and alwaysReplyTo methods. However after sending such e-mail you should set again previous values to be sure no other emails will be impacted by this change.
But looking at method names it might be not the best solution so better is to look at mailables and use them to send e-mails in latest Laravel releases.
Problem resolved.
I edit app>Mail>Reservation.php
public function build()
{
// return $this->markdown('emails.reservation-email');
return $this->from($this->reservation->email)->markdown('emails.reservation-email');
}
app>Http>Request>ReservationForm.php
public function persist()
{
$reservation = Resa::create(
$this->only(['nom', 'email', 'phone', 'formule', 'date_arr', 'date_ret', 'nb_adu', 'nb_enf', 'lemessage'])
);
Mail::to('contact#cotiga.fr')->send(new Reservation($reservation));
}
I am using an inbuilt code in Laravel to send Email Notification. Code is below. I am using smtp to send email
class RegisterNotification extends Notification
{
use Queueable;
public function __construct($token)
{
$this->token = $token;
}
public function via($notifiable)
{
return ['mail'];
}
public function toMail($notifiable)
{
return (new MailMessage)
->line('hi');
}
public function toArray($notifiable)
{
return [
//
];
}
}
Here the problem is, it takes around 5 seconds to complete the process and control does not come back. I am assuming that if it come back and do the email sending work in background...it would save a lot of time.
Is there any inbuilt work to do the same? I meant, control should come back and should say email sent...and then it should do the work in background.
Email Sending code in Controller
class apiRegisterController extends Controller
{
public function Register(RegisterRequest $request) {
$RegisterNotification = new RegisterNotification($Token);
$User->notify($RegisterNotification);
}
}
Code for Queue
Controller Code
$job = (new SendForgotPasswordEmail($Data))->onConnection('database');
dispatch($job);
Job
class SendForgotPasswordEmail implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
protected $Data;
public $tries = 5;
public function __construct($Data)
{
$this->Data = $Data;
}
public function handle()
{
$Token = $this->Data["Token"];
$User = $this->Data["User"];
$RegisterNotification = new RegisterNotification($Token);
$User->notify($RegisterNotification);
}
}
Step 1: Change class RegisterNotification extends Notification to class RegisterNotification extends Notification implements ShouldQueue
Step 2: Implement a queue driver. In your config/queue.php make sure your driver is not set to sync like so: 'default' => env('QUEUE_DRIVER', 'sync'), and make sure your .env doesnt have QUEUE_DRIVER=sync. You can look at the Laravel documentation for queues to choose an appropriate queue driver
You can use the build-in API.
$user = User::findOrFail($id);
Mail::queue('emails.welcome', $data, function ($message) use ($user){
$message->from('hello#app.com', 'Your Application');
$message->to($user->email, $user->name)->subject('Your Reminder!');
});
But first you have to configure the queues.
Add in your .env file the line QUEUE_DRIVER=sync and then write on the terminal php artisan queue:listen.
If you want the queue to run forever on the server use Supervisor. Queues documentation explains how you can use it.
you can use laravel job queue https://laravel.com/docs/5.4/queues
Mail::queue(
I have a command in my code that is run daily by cron that sends emails to all new users. It used to work ok, but after I have swithched the queue driver to SQS and upgraded Laravel 5.2 to 5.3 it started throwing an error.
InvalidArgumentExceptionvendor/laravel/framework/src/Illuminate/Mail/Mailer.php:379
Invalid view.
I don't know what might cause the error, because I have not deleted the view. Also when I run the command manually it does not throw any errors.
Here is the command code:
public function handle()
{
$subscriptions = Purchase::where('created_at', '>=', Carbon::now()->subDay())
->groupBy('user_id')
->get();
$bar = $this->output->createProgressBar(count($subscriptions));
foreach ($subscriptions as $subscription) {
$user = $subscription->user;
// if ($user->is_active_customer) {
Mail::to($user)->bcc(env('BCC_RECEIPTS_EMAIL'))->send(new NeedHelp());
// }
$bar->advance();
}
$bar->finish();
$this->info("\nSuccess! " . number_format(count($subscriptions)) . ' emails were sent.');
}
Here is the NeedHelp class code (I have changed the email and sender name for this thread):
<?php
namespace App\Mail;
use App\User;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Queue\ShouldQueue;
class NeedHelp extends Mailable
{
use Queueable, SerializesModels;
/**
* Create a new message instance.
*
*/
public function __construct(){
}
/**
* Build the message.
*
* #return $this
*/
public function build()
{
return $this->subject('Need help?')
->from('default#mail.com', 'Sender')
->view('emails.need-help');
}
}
I have found the error. The reason was that I have accidentally connected two applications to the same queue, which caused them to process jobs and emails of each other which resulted in this error.
I am new to laravel and I am currently building a multilingual app. I am implementing password reset using laravels shipped methods. After looking at this method in ResetsPasswords trait:
protected function getEmailSubject()
{
return isset($this->subject) ? $this->subject : 'Your Password Reset Link';
}
I noticed that I can specify a variable for my subject in the PasswordController like so:
protected $subject = 'Password Reset';
How do I get this value from a language file and assign to the variable?
Use the trans() helper function in the contructor
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\ResetsPasswords;
class PasswordController extends Controller
{
use ResetsPasswords;
/**
* Create a new password controller instance.
*
* #return void
*/
public function __construct()
{
$this->subject = trans('passwords.subject');
$this->middleware($this->guestMiddleware());
}
}
After doing some digging I found the answer as shown below.
protected function getEmailSubject(){
return Lang::has('passwords.password_reset')
? Lang::get('passwords.password_reset')
: 'Your Password Reset Link.';
}
Using method overriding, I overrode the getEmailSubject method in the ResetsPasswords trait and provided the necessary implementation as shown in the body of the email. passwords.password_reset is a key for a text in my language file.