Sending a mailable with binary data - php

I'm trying to queue a mailable containing a property with a model (Order) that has a binary id.
<?php
namespace App\Mail;
use App\Order;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
class OrderShipped extends Mailable
{
use Queueable, SerializesModels;
/**
* The order instance.
*
* #var Order
*/
public $order;
/**
* Create a new message instance.
*
* #return void
*/
public function __construct(Order $order)
{
$this->order = $order;
}
/**
* Build the message.
*
* #return $this
*/
public function build()
{
return $this->view('emails.orders.shipped');
}
}
The Order implements the Serializable interface. In the serializemethod of the model I'm converting the binary id to a string, so it can be properly encoded to json.
Unfortunately the serializemethod is never called when I want to queue the mail.
Is this a bug in the framework or am I missing something?
Also I noticed in the PHP docs that, when using the Serializableinterface, the __sleepand __wakeupmethods are no longer supported:
Classes that implement this interface no longer support __sleep() and
__wakeup().
But the Illuminate\Queue\SerializesModels trait seems to override them...
EDIT
I'm using this trait for my binary ids.
In my serialize method I simply call $this->toArray().

Related

Laravel 6 - Exception Serialization of 'Closure' is not allowed

Running into an issue when turning my Mailable into a Queue
When the construct is disabled and the variable is injected directly into the build method, the job loads to the job table without issue, yet the job fails when the worker arrives due to the construct being missing with the following error: Illuminate\Contracts\Container\BindingResolutionException: Unable to resolve dependency [Parameter #0...
That said, when I enable the construct and remove the variable from the build method, I get an Exception Serialization of 'Closure' is not allowed.
Goal is to convert this send() to a queue() so that the db update can be performed ahead of an email being triggered.
Controller
public function store(ContactsStoreRequest $request)
{
$request->validated();
$submission = Contact::create(request()->all());
$request->id = $submission->id;
$emails = explode(',', config('mail.mailto'));
$when = now()->addMinutes(1);
Mail::to($emails)
->bcc(['notifications#xxxx.com'])
->later($when, new ContactSubmission($request));
return redirect('/contact/#loc')->with('status', 'success');
}
Mail Class
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
class ContactSubmission extends Mailable implements ShouldQueue
{
use Queueable, SerializesModels;
public $topic;
/**
* Create a new message instance.
*
* #return void
*/
public function __construct($topic)
{
$this->topic = $topic;
}
/**
* Build the message.
*
* #return $this
*/
public function build()
{
return $this->view('emails.contact-submission')
->subject('XXX - Contact Submission #' . $this->topic->id)
->replyTo($this->topic->email_address);
}
}
Any help would be appreciated here!

Handle Method not being called in Laravel Redis Queue

When adding an item to the queue, for some reason the handle method is not being called.
The Log entry in __construct is appearing but when attempting to log in handle(), nothing appears.
The method i'm using to dispatch is ProcessImport::dispatch($path, $task->task_id);
My queue service is configured to use Redis, and redis is storing all the data accordingly.
I am using Laravel 8. What could be wrong?
<?php
namespace App\Jobs;
use App\Models\Tasks;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldBeUnique;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use App\Http\Controllers\Products\Products;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Queue;
use Illuminate\Queue\Events\JobProcessing;
use Illuminate\Queue\Events\JobProcessed;
use Throwable;
class ProcessImport implements ShouldQueue, ShouldBeUnique
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
protected $file_path;
protected $response;
protected $task;
/**
* Create a new job instance.
*
* #return void
*/
public function __construct($path, $task_id)
{
Log::info("Importing products (construct)");
$this->task = Tasks::where('task_id', $task_id)->first();
$this->file_path = $path;
Log::info('Importing ' . $path);
}
private function getFilePath() {
return $this->file_path;
}
/**
* Handle a job failure.
*
* #param \Throwable $exception
* #return void
*/
public function failed(Throwable $exception)
{
$this->task->failed($exception->getMessage());
}
/**
* Get the cache driver for the unique job lock.
*
* #return \Illuminate\Contracts\Cache\Repository
*/
public function uniqueVia()
{
return Cache::driver('redis');
}
/**
* Execute the job.
*
* #return void
*/
public function handle()
{
Log::info("Importing products (handle)");
$this->task->start();
$products = new Products();
$products->importProductsFromCSV($this->getFilePath());
$this->task->success();
Log::info("End of importing products..");
}
}
You've just pushed the jobs onto the queue but haven't started a worker to process them. You can run the worker with:
php artisan queue:work

Emailing in Laravel

I am trying to send a email in Laravel. It works finicky to say at least. got couple of classes for sending email for different conditions. Only difference would be markup of sent email and blade file which data is sent to before sending. I tried using use Mail; in controller from whom i'm sending it, with \Mail::(... and use Illuminate\Support\Facades\Mail; with Mail::(... and vice-versa. So it ain't it.
Here are the mail files:
ToHR file:
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use App\User;
class toHR extends Mailable
{
use Queueable, SerializesModels;
public $user;
public $job;
public $jobCount;
/**
* Create a new message instance.
*
* #return void
*/
public function __construct($user,$job,$jobCount)
{
$this->user = $user;
$this->job = $job;
$this->jobCount = $jobCount;
}
/**
* Build the message.
*
* #return $this
*/
public function build()
{
return $this->markdown('mail.toHR');
}
}
ToHRFirst file:
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use App\User;
class toHRFirst extends Mailable
{
use Queueable, SerializesModels;
public $user;
public $job;
public $jobCount;
/**
* Create a new message instance.
*
* #return void
*/
public function __construct($user,$job,$jobCount)
{
$this->user = $user;
$this->job = $job;
$this->jobCount = $jobCount;
}
/**
* Build the message.
*
* #return $this
*/
public function build()
{
return $this->markdown('mail.toHRFirst');
}
}
And my test file JobCreated:
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use App\User;
class JobCreated extends Mailable
{
use Queueable, SerializesModels;
public $user;
public $job;
public $jobCount;
/**
* Create a new message instance.
*
* #return void
*/
public function __construct($user,$job,$jobCount)
{
$this->user = $user;
$this->job = $job;
$this->jobCount = $jobCount;
}
/**
* Build the message.
*
* #return $this
*/
public function build()
{
return $this->markdown('mail.job-created');
}
}
They'll all the same, yet error occurs. What gives? Did i miss something? Any help will be appreciated, just point me in the right direction.
Code which i use to send email:
Variables used get values from queries which are rather long, but they are not an issue anyways.
Ver1:
Mail::to($user->email)->send(
new JobCreated($user,$job,$jobCount)
);
Ver2:
Mail::to($user->email)->send(
new toHRFirst($user,$job,$jobCount)
);
Ver3:
Mail::to($user->email)->send(
new toHR($user,$job,$jobCount)
);
Sending works if it's used first version. Other cannot be found and that's the error.
Try renaming your files to follow Laravel convention;
You can see that the file JobCreated has a class JobCreated. You need to respect the uppercases:
Rename the ToHR.php file into ToHr.php, then:
Rename the class class toHRinto class ToHr
Rename the ToHRFirst.php file into ToHrfirst.php, then:
Rename the class class toHRFirst into class ToHrfirst
Or if you want to keep the uppercases, just rename the classes like so:
class toHRinto class ToHR
class toHRFirstinto class ToHRFirst
Finally, don't forget to import your job class at the top of your controller file (or wherever you use the Mail method:
use App\Mail\ToHR;
and
use App\Mail\ToHRFirst;

Attach large files with laravel Mail Facade

When i am trying to attach large files greater than 1MB this error appears
message :fwrite(): send of 5067 bytes failed with errno=11 Resource temporarily unavailable
file: "/var/www/html/test/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/StreamBuffer.php"
and here is my code
in module.php
Mail::to($data[EMAIL])->send(new SigningApplication($data));
in SigningApplication.php
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
class SigningApplication extends Mailable
{
use Queueable, SerializesModels;
/**
* Create a new message instance.
*
* #return void
*/
public $user_data;
public function __construct($user_data)
{
$this->user_data = $user_data;
}
/**
* Build the message.
*
* #return $this
*/
public function build()
{
return $this->from(config('email'), config('mail.from')['name'])
->view('emails.signing_application')
->attach($this->user_data['pdf'],['mime' => 'application/pdf'])
}
}

Using form request data in Laravel 5.3 mailable views

Looking around I cant find much information on how to do this. Plenty of the same examples just explaining the basic implementation of the mailable class but thats it.
I am sending an email from a contact form and have a route set up for testing that my form posts to:
Route::post('/sendmail', function() {
Mail::to("my email.com")->send(new MyTestMail());
});
I then have my mailable class which I have passed a test variable as a test string to:
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Queue\ShouldQueue;
class MyTestMail extends Mailable
{
use Queueable, SerializesModels;
public $test;
/**
* Create a new message instance.
*
* #return void
*/
public function __construct()
{
$this->test = "test";
}
/**
* Build the message.
*
* #return $this
*/
public function build()
{
return $this->view('emails.myTestMail');
}
}
What I wish to do is have access to my post values from the contact from and use them in the email view.
You can try passing the data you need to the constructor of that mailable.
public $postdata;
public function __construct($data)
{
$this->postdata = $data;
}
Now 'postdata' will be available to your view.
Mail::to("my email.com")->send(new MyTestMail($request->all()))

Categories