I'm trying to dispatch Welcome Email on Laravel 5.2 but the job is failing and I have no idea how to figure out why.
Here is what I have so far:
public function test(Request $request) {
$email = $request->get('email');
$subject = $this->word('emails.welcome.subject');
// Mail::send # I use this to Send it synchronously
// $this->mailQueue->queue # I use this to Queue
('emails.welcome', ['domain' => 'blablabla', 'name' => 'Marco Aurélio Deleu', 'date' => Carbon::now(),
'total' => 100, 'pretext' => '', 'score' => '', 'surtext' => '', 'password' => 'blabla', 'shop' => ''],
function ($message) use ($email, $subject) {
$message->to($email);
$message->subject($subject);
}, true);
return 'queued';
}
I noticed that Jobs can easily fail when any kind of exception is thrown, so I figured that I could use Mail::send to find out which exception was being thrown / what was the problem and then use the $this->mailQueue->queue() when I had it sorted out.
I managed to use this strategy to find out that I can't use function calls inside the closure, but now I just don't know what else to do in order to find where the problem lies. The synchronous method of sending the email directly works just fine and the email arrives, but the job will fail at a queue.
The last piece of evidence that I have is that the problem is in the $data array, because if I use it without any $data, the job will be processed and the email arrives.
...
// If I use it like this, it will work perfectly.
$this->mailQueue->queue
('emails.welcome', [ /* empty array */ ], function ($message) use ($email, $subject) {
$message->to($email);
$message->subject($subject);
}, true);
Here is the Queue Listener:
// --> This is the job failing with $data array <--
[06:34 PM]-[root#local]-[/project/]-[git sign-up-with-email]
# php artisan queue:listen --timeout=30 --tries=1
[2016-06-28 21:34:29] Failed: mailer#handleQueuedMessage
^C
// --> This is the job working with empty $data array <--
[06:35 PM]-[root#local]-[/project/]-[git sign-up-with-email]
# php artisan queue:listen --timeout=30 --tries=1
[2016-06-28 21:44:31] Processed: mailer#handleQueuedMessage
Related
This is the handle on the job class
public function handle(Request $request)
{
if (strpos($request->status, 'Approved') !== false) {
$client = new Client();
$client->request('POST', 'http://localhost:5000/api/email', [
'headers' => [
'Athentication' => 'ASOIDjhoiqwjheoiwqjeqhowE21323ijosadiweqjeoi',
],
'json' => [
'type' => $request->type
]
]);
}
}
And this is where the job is being called on the controller:
public function update(UpdateRequest $request)
{
$redirect_location = parent::updateCrud($request);
PostEmail::dispatch($request);
return $redirect_location;
}
I'm using Amazon SQS, everything is configured correctly and the job gets called on.
I tried running php artisan queue:work and letting it run, and then I tried php artisan queue:listen, both of them work but I get the same issue..
This is the result for queue:work
[2019-02-08 17:18:21][78272a19-cd7c-4787-8c61-0ab1206ef203]
Processing: App\Jobs\PostEmail
[2019-02-08 17:18:21][78272a19-cd7c-4787-8c61-0ab1206ef203] Processed:
App\Jobs\PostEmail
So, the job gets called upon, but never really executed. I don't know why!
I am working on queue jobs in laravel v5.4. Now I want to send an email to users through email later function. Below is my function that I am using
public static function singleEmailQueueJob(){
for($i=1; $i<=2; $i++){
$time = $i * 10;
$data['email'] = 'abc#gmail.com';
$data['name'] = "Rizwan_$time";
$data['subject'] = 'Queue Job Testing->'.$i;
$data['verification_code'] = base64_encode($i.time());
\Mail::later($time,'emails.password', $data, function ($m) use ($data) {
$m->from(CommonHelper::$email_info['admin_email'],CommonHelper::$email_info['site_title']);
$m->to($data['email'],$data['name']);
$m->subject($data['email']);
});
}
echo "Email send successfully";
}
when I run this function i receive following error in exception
{"success":"false","message":"Only mailables may be queued."}
in .eve file i set
QUEUE_DRIVER=database
and in config/queue.php
'database' => [
'driver' => 'database',
'table' => 'jobs',
'queue' => 'default',
'retry_after' => 90,
],
I don't know where is the problem in code. Please help.
I have found the issue by using the following code
$date = Carbon::now()->addMinutes($time);
Queue::later($date, new EmailSending($data));
Now I am able to send emails in queue
Thanks to help me
In my case I have created job 'SendVerificationEmail' and I call this job after successful registration of user like this.
dispatch(new SendVerificationEmail($user));
Do you also dispatch(your_job) in your code???
I built an API using dingo/api 0.10.0, Laravel 5.1 and lucadegasperi/oauth2-server-laravel": "^5.1".
All my routes work fine in Postman/Paw!
The problem appears when I try to test the API using PHPUnit.
This is part of my route-api.php file
<?php
$api = app('Dingo\Api\Routing\Router');
$api->version(['v1'], function ($api) {
$api->post('oauth/access_token', function () {
return response(
\LucaDegasperi\OAuth2Server\Facades\Authorizer::issueAccessToken()
)->header('Content-Type', 'application/json');
});
$api->group(['middleware' => ['oauth', 'api.auth']], function ($api) {
$api->post('/register', 'YPS\Http\Controllers\Api\UserController#register');
});
And this is my test file UserRegistrationTest.php
class UserRegistrationTest extends ApiTestCase
{
public function setUp()
{
parent::setUp();
parent::afterApplicationCreated();
}
public function testRegisterSuccess()
{
$data = factory(YPS\User::class)->make()->toArray();
$data['password'] = 'password123';
$this->post('api/register', $data, $this->headers)
->seeStatusCode(201)
->seeJson([
'email' => $data['email'],
'first_name' => $data['first_name'],
'last_name' => $data['last_name'],
]);
}
public function testRegisterMissingParams()
{
$this->post('api/register', [], $this->headers, $this->headers, $this->headers)->seeStatusCode(422);
}
}
The ApiTestCase simply retrieves a token and sets the headers.
private function setHeaders()
{
$this->headers = [
'Accept' => 'application/vnd.yps.v1+json',
'Authorization' => 'Bearer ' . $this->OAuthAccessToken,
];
}
Now, the weird part is that the first test testRegisterSuccess runs perfectly and returns the response I expect. But the second one testRegisterMissingParams, even though it's the same route, returns this,
array:2 [
"message" => "The version given was unknown or has no registered routes."
"status_code" => 400
]
I tracked the error and it is in the Laravel adapter here:
public function dispatch(Request $request, $version)
{
// it seems that the second time around can't find any routes with the key 'v1'
if (! isset($this->routes[$version])) {
throw new UnknownVersionException;
}
$routes = $this->mergeExistingRoutes($this->routes[$version]);
$this->router->setRoutes($routes);
return $this->router->dispatch($request);
}
And further more, if i run one test at a time (eg comment one out, run test and then comment the other and run test) i see the result expected in both tests. The problem is when i run multiple tests.
Any thoughts on that?
Thank you!
Run php artisan api:routes to see full path you may have missed something for the URL, also if this working if you request your URL manually?
I had same problem with testing using Dingo & Lumen. This worked for me - remove bootstrap="bootstrap/app.php" from phpunit.xml file and change line processIsolation="false" to processIsolation="true".
This is my code:
$email = "email#gmail.com";
$data = array(
'email' => $email,
'async' => false,
);
Mail::queue('user.mails.welcome', $data, function($message) use ($email) {
$message
->to($email, $email)
->subject('Welcome to the Laravel 4 Auth App!');
});
And this is what shows on my Mandrill account API log:
Full Request {
"key": "x",
"raw_message": "y",
"async": "1"
}
Full Response {
"email": "xy",
"status": "queued",
"_id": "z"
}
As you can see, emails are being queued by default. Why? And how can I change that?
Per the Mandrill docs:
Async: enable a background sending mode that is optimized for bulk sending. In async mode, messages/send will immediately return a status of "queued" for every recipient. To handle rejections when sending in async mode, set up a webhook for the 'reject' event. Defaults to false for messages with no more than 10 recipients; messages with more than 10 recipients are always sent asynchronously, regardless of the value of async.
Basically, it's something that Mandrill is doing on their end is is unrelated to whether you use Mail::send or Mail::queue in Laravel.
All emails sending through Mandrill are queued and sent out in accordance with the parameters defined for your account. In other words: They decide when your emails eventually get sent.
Edit: Laravel's Mandrill Mail Transport is always going to send with async mode enabled. There's no way to configure that without editing the class: MandrillTransport
I am not sure I understand. Your emails are being queued because you are using the queue() method:
Mail::queue('user.mails.welcome', $data, function($message) use ($email) {
If you want to not queue, then use the send() method:
Mail::send('user.mails.welcome', $data, function($message) use ($email) {
I had to set a "from" email to have this work.
The 'async' parameter of the mandrill api isn't exposed to the Laravel mail closure. I just extended the MandrillTransport class and passed a Swift_Mime_Message into it so that I could capture the response, it will be 'sent' or 'rejected' (and reject_reason will be populated with something like "hard/soft bounce") which I can store in my application:
class Mandrill extends MandrillTransport
{
public function send(\Swift_Mime_Message $message, &$failedRecipients = null)
{
$client = $this->getHttpClient();
$response = $client->post('https://mandrillapp.com/api/1.0/messages/send-raw.json', [
'body' => [
'key' => $this->key,
'raw_message' => (string)$message,
'async' => false,
],
]);
return $response->json();
}
}
I have been able to get my Iron.io push queue subscription to work great, but not with mail queues for some reason. In the code below I am pushing a job onto the queue with an email address and username in the $data array. For reasons unknown to me, the email address and username are not getting passed to the Mail function. The job just sits there, failing to send.
FooController.php
<?php
$data = array(
'email_address' => Input::get('email'),
'username' => Input::get('username'),
);
Queue::push('SendEmail#reserve', $data);
routes.php
<?php
// iron.io push queue path
Route::post('queue/push', function()
{
return Queue::marshal();
});
class SendEmail
{
public function reserve($job, $data)
{
Mail::send('emails.reserve', $data, function($message)
{
$message->to($data['email_address'], $data['username'])->subject($data['username'] . ', welcome to RockedIn!');
});
$job->delete();
}
}
?>
You need to pass $data to the closure.
public function reserve($job, $data)
{
Mail::send('emails.reserve', $data, function($message) use ($data)
{
$message->to($data['email_address'], $data['username'])->subject($data['username'] . ', welcome to RockedIn!');
});
$job->delete();
}