Confused about Laravel 5 Queue for Sending Mail (Laravel 5.4)
Asked Answered
G

3

4

I upgrade from Laravel 4.1 to 5.4. Queue migration is difficult.

Firstly, I commented out iron route from routes:

Route::post('queue/receive', function()
{
    return Queue::marshal();
});

Then, I configured database driver and migrated jobs table:

php artisan queue:table
php artisan migrate

I changed Mail::queue codes to the Mailables like this:

Mail::to('[email protected]')->send(new ForgotPassword($user->first_name));

I succeeded to send mails synchronously (without queue). Then, I switched to queue:

Mail::to('[email protected]')->queue(new ForgotPassword($user->first_name));

And lastly, I run this command from console:

php artisan queue:listen

When a Mail::to line is executed, a row is inserted to the Jobs table but mail isn't sent. How can I solve this problem?

Note: ForgotPassword is a Mailable class (should be a Job class?).

Goeger answered 19/2, 2017 at 18:59 Comment(10)
When you tail your logs tail -f storage/logs/laravel.log, do you see any errors logged?Hodman
Mail::to line doesn't give error. But php artisan queue:listen command results in SQLSTATE[22003]: Numeric value out of range: 1264 Out of range value for column 'attempts'.Goeger
Whats the data type for the column attempts? You may want to change to something bigger, like BIGINTHodman
@DanielVerem It is a standart column of Jobs table.Goeger
Yes. So, here is what I think is happening. For some reason, your job is failing and retrying. Since you don't have a maximum retries attribute set on your job class, the number of retries have grown past the size the attempts column, which is tinyInteger, can carry. One way to solve that would be to add a public $tries = 5; or some other number to your job class. @GoegerHodman
Please find mail driver, from .env it should be smtp not logFlybynight
The default migration created for laravel queue has small limit for attempt column, that's why it throws warningFlybynight
ForgotPassword should be a Mailable. Your queue is attempting to send the mail, but it is failing for some reason. Can you post your ForgotPassword class? Also, are there no other log entries that might explain why the job is failing?Drillstock
Ok. There isn't a log for the job. ForgotPassword is coming..Goeger
@Drillstock I got the problem. I forget to define private variables in the mailable. It works now. Write an answer, 50 rep is yours.Goeger
D
4

The main difference between the synchronous send() and the asynchronous queue(), as far as your ForgotPassword object is concerned, is that when you queue the object for sending, it must be serialized to be sent to the queue, and unserialized when the queue worker processes it.

Since send() works fine, but an error is occurring with queue(), and we can see that the queued job is fired and being attempted to be processed, there is most likely an error in the serialization/unserialization.

Your ForgotPassword class is probably using the SerializesModels trait, since that is how the artisan command generates a new mailable object. This trait defines __sleep() and __wakeup() methods, which modify how serialization and unserialization work.

When the __sleep method is implemented, PHP will only serialize the variables that are returned by the __sleep method. In this case, the implementation provided by the SerializesModels trait uses Reflection to go through the properties defined on the class to provide a special way to serialize Eloquent models and collections.

Because of this, this means that any variables on your ForgotPassword class that are not specifically defined as a property on the class will not get serialized, and it will not be available when the queued job is processed and the class is unserialized. This is the most likely reason for your issue. When your job is being attempted, your unserialized mailable instance doesn't have the data it needs, and is failing.

There are two ways to resolve this. First, if your ForgotPassword does not actually need to serialize any models, you can remove the SerializedModels trait. This will remove the __sleep() definition from the class, and then all variables assigned on the class, not just those actually defined, will be serialized, and will also be available when the class is unserialized.

The second option, which is more appropriate and more explicit, is to actually define the properties you need on your ForgotPassword class.

If you define the properties on your class, you could leave the SerializesModels trait on your class. However, if you aren't actually serializing models, I'd go ahead and remove it. No need for the extra serialization overhead if you don't need it.

Drillstock answered 26/2, 2017 at 7:46 Comment(0)
F
1

You can send Mail using laravel queue, see the example,

Define Job

public function handle()
{
        $mail_meta_data = $this->send_data;
        $require_data = $this->require_data;
        Mail::queue($mail_meta_data['view_name'], ['data'=>$require_data], function($message) use ($mail_meta_data, $require_data) {
            //$message->from($mail_meta_data['to'], $mail_meta_data['name']);

            $message->to($mail_meta_data['to'])->subject($mail_meta_data['subject']);
        });
 }

Call the job

dispatch(new SendEmailNotification($mail_meta_data, $require_data));

.env

 MAIL_DRIVER=smtp
 MAIL_HOST=smtp.sendgrid.net
 MAIL_PORT=587
 MAIL_USERNAME=smtp_username
 MAIL_PASSWORD=smptp_password
 MAIL_ENCRYPTION=tls

 APP_EMAIL=email sent from
 APP_NAME=Name of Email sender

Note

  1. Make sure that you have set above mail configuration in your .env file or in config/mail.php
  2. Also php artisan queue:listen is running
Flybynight answered 23/2, 2017 at 5:16 Comment(2)
Mail::queue or Mail::send in the hande? Isn't Queue running handle? So I think it should be Mail::send.Goeger
yes Mail::queu, you can find more here laravel.com/docs/5.1/mail#queueing-mailFlybynight
A
0

You may have to edit the existing .env file on the project folder on your machine. Look for the .env file, open it through sublime text and edit it.

Edit with the email id and password with which you are going to send the mails.

Alongside answered 22/2, 2017 at 18:50 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.