Confused about Laravel 5 Queue for Sending Mail (L

2019-07-09 02:05发布

问题:

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('person@gmail.com')->send(new ForgotPassword($user->first_name));

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

Mail::to('person@gmail.com')->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?).

回答1:

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.



回答2:

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.



回答3:

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