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?).
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.
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.
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
- Make sure that you have set above mail configuration in your .env file or in config/mail.php
- Also php artisan queue:listen is running