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

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.

Related

Laravel 5.6 testing Notification::assertSentTo() not found

Struggling since multiple days to get Notification::assertSentTo() method working in my feature test of reset password emails in a Laravel 5.6 app, yet receiving ongoing failures with following code:
namespace Tests\Feature;
use Tests\TestCase;
use Illuminate\Auth\Notifications\ResetPassword;
use Illuminate\Support\Facades\Notification;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Foundation\Testing\RefreshDatabase;
class UserPasswordResetTest extends TestCase
{
public function test_submit_password_reset_request()
{
$user = factory("App\User")->create();
$this->followingRedirects()
->from(route('password.request'))
->post(route('password.email'), [ "email" => $user->email ]);
Notification::assertSentTo($user, ResetPassword::class);
}
}
I have tried several ideas including to use Illuminate\Support\Testing\Fakes\NotificationFake directly in the use list.
In any attempt the tests keep failing with
Error: Call to undefined method Illuminate\Notifications\Channels\MailChannel::assertSentTo()
Looking forward to any hints helping towards a succesful test.
Regards & take care!
It seems like you are missing a Notification::fake(); For the correct fake notification driver to be used.
Notification::fake();
$this->followingRedirects()
...

Laravel 5.4: Notification delay, only execute upon condition

It is a chat function, I would like to have the notification delay by 5 seconds, within (or after) these 5seconds the notification will only be sent if the specific message is being read during the time. I have researched for delay() or using sleep() in php lib but they can't seem to do the trick for the conditioning. Is it possible to do such thing?
use https://laravel.com/docs/5.4/notifications#queueing-notifications
class InvoicePaid extends Notification implements ShouldQueue
{
use Queueable;
// ...
}
$when = Carbon::now()->addMinutes(10);
$user->notify((new InvoicePaid($invoice))->delay($when));
You can check condition inside Notification

How to Write a unit test with laravel queue mail?

I already finish the code to sending the mail by queue, and it`s working fine,
and I want to write a test for it (just want to test the mail that it should be send out normally without failing by queue, and to the right person), but how?
Mail::to($user->email)->queue(new Welcome($user));
You would do something like this (depending on your setup):
<?php
namespace Tests\Feature;
use App\User;
use App\Mail\Welcome;
use Illuminate\Support\Facades\Mail;
class SendInvitationEmailTest extends TestCase
{
/** #test */
function mails_get_queued()
{
Mail::fake();
$user = factory(User::class)->create();
$this->post('/route/to/send/the/welcome/mail');
Mail::assertQueued(Welcome::class, 1);
Mail::assertQueued(Welcome::class, function ($mail) use ($user) {
return $mail->user->id === $user->id;
});
}
}
I would recommend grabbing the queued emails from Mail::queued. It's a simple array that then gives you all the power you want.
Like this:
$queuedEmails = Mail::queued(CustomerEmail::class);
$this->assertCount(1, $queuedEmails);
$email = $queuedEmails[0];
$this->assertEquals('status_complete', $email->handle);
You can run asserts as you're used to, which provide more meaningful messages in the case of failure. Unfortunately, Mail::assertQueued's failure report isn't very specific or helpful:
The expected [App\Mail\MyEmail] mailable was not queued.
Failed asserting that false is true.
That's if you simply return true or false in the callback version. Note that you can use asserts in the callback, which is great, it's just more awkward if you need to check more than one email.
Now I'm using the MailTracking to test the mail
https://gist.github.com/anonymous/6e802e56af1f19d53464d667b3e6aa48

Accessing Model in utility in laravel

I'm trying to access the User model in a utility I built that will eventually send emails out, this is being triggered with by cron, and I'm using php artisan schedule:run to test it. Below is the utility I'm starting to build out, and currently when test it I am getting 'I was triggered'. This is being triggered by a registered console command. Thats all working.
<?php
namespace App\Utility;
use Log;
use Mail;
use App\User;
class ReferralProgramUtility
{
static public function test()
{
LOG::info("I was triggered");
}
}
However, when I change this to pull in the User model....
<?php
namespace App\Utility;
use Log;
use Mail;
use App\User;
class ReferralProgramUtility
{
static public function test()
{
$user = User::all();
LOG::info($user);
}
}
I get the following error....
Trying to get property of non-object in /var/www/html/appname/app/User.php:32
I'm using another utility that has a similar configuration and uses the User model and this work fine, the only difference is that this is on is being triggered by task scheduler. Not sure what is causing this, and I'm fairly new to Laravel so any tips or recommendation would be hugely appreciated. Thanks, in advance.

Send email from queued event handler

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. :)

Resources