Goodnight
Porblem 1.-
I need to send more than 1000 emails for each event created, and for this I use queue (as Laravel's documentation says), but when sending the emails I have to wait until all the emails are sent to return to the view of control Panel
this is my "store" function in NewsEvents.php controller that sends the emails
public function store(Request $request)
{
$attributes = request()->validate(News::$rules, News::$messages);
$news = $this->createEntry(News::class, $attributes);
//queue for sending emails
$this->dispatch(new Nevent($news));
return redirect_to_resource();
}
the "handle" function of job "Nevent.php"
public function handle()
{
//
$users=User::where('tipo_user','user')->get();
foreach($users as $user)
{
$user->notify(new EventCreated($this->news));
echo 'enviado correo';
Informe::create([
'event_id' => $this->news->id,
'total' => '1',
'tipo' => 'invitacion',
'dst_id' => $user->id,
'estado' => 'correcto',
]);
}
}
What could be the problem?
problem 2.-
How could I send an email for every minute?
since when sending all emails my server responded with this message:
Domain mu.edu.fi has exceeded the max emails per hour (100/100 (100%)) allowed. Message will be reattempted later
If u are using Redis server for managing jobs, Laravel provides a simple
API for Rate Limiting API's
Redis::throttle('your job id')->allow(10)->every(60)->then(function () {
// Job logic...
}, function () {
return $this->release(10);
});
Hope this helps.
Related
I run a cronjob every minute and data returne, i save on db in a table notification. But here i need to save also user_id. I mean i know we can not find Auth::user()->id on cronjob but how can we get this user id?
public function handle(ReminderEventServices $reminderServices)
{
// return 0;
// $getLastReminders = $reminderServices->ReminderEvent();
$getLastReminders = Reminder::orderBy('id', 'DESC')->get();
return app('App\Http\Controllers\NotificationController')->store($getLastReminders);
}
I have send request to Notification controller , hoping there i can use there Auth but i was wrong.
public function store($getLastReminders)
{
$user_id = Auth::user()->id;
foreach($getLastReminders as $reminder) {
if (!Notification::where('title', $reminder->title)->exists()) {
$notification = Notification::create([
'title' => $reminder->title,
'user_id' => $user_id,
'description' => $reminder->description,
'remindTime' => $reminder->remindTime
]);
}
event(new ReminderEvent($reminder));
}
}
You should try another approach - the cron job is not supposed to handle users in that way. Consider trying an event listener or an observer instead. I've included the link to Laravels documentation on events for your convienience.
I'm trying to get Postmark's new Message Streams working with Laravel.
Is there a way of adding the property + value '"MessageStream": "notifications" to the JSON body of an email sent using Laravel mail? I'm guessing I will need to extend the Mailable class in some way to do this.
Ideally, i'd like to be able to do something like the following in my Mailable class:
DiscountMailable.php
public function build()
{
return $this->from('hello#example.com')
->markdown('emails.coupons.created')
->subject('🎟 Your Discount')
->with([
'coupon' => $this->coupon,
])
->messageStream(
'notifications',
);
}
Just to make sure this question has an answer, this is what was necessary to make it work (and it worked for my issue in Laravel 7 today as well, where I wanted to use different Postmark Streams for different mail notification types).
public function build()
{
return $this->from('hello#example.com')
->markdown('emails.coupons.created')
->subject('🎟 Your Discount')
->with([
'coupon' => $this->coupon,
])
->withSwiftMessage(function ($message) {
$message->getHeaders()
->addTextHeader('X-PM-Message-Stream', 'notifications')
});
}
I am using SwiftMailer in my Symfony 5 project to send emails.
I was using it in a controller to send a reset password e-mail, and everything was working.
I am now trying to use it in a MessageHandler, here is the code I am now using :
final class SendEmailMessageHandler implements MessageHandlerInterface
{
private $mailer;
public function __construct(\Swift_Mailer $mailer)
{
$this->mailer = $mailer;
}
public function __invoke(SendEmailMessage $message)
{
$mail = (new \Swift_Message())
->setFrom($message->getFrom())
->setTo($message->getTo())
->setBody($message->getBody(), $message->getContentType())
->setSubject($message->getSubject());
$response = $this->mailer->send($mail);
}
}
The response is ok, but the mail never reach my mailbox.
Here is how I am dispatching my SendEmailMessage :
class AskResetPassword extends AbstractController
{
use ResetPasswordControllerTrait;
private $resetPasswordHelper;
private $validator;
private $bus;
public function __construct(ResetPasswordHelperInterface $resetPasswordHelper, ValidatorInterface $validator, MessageBusInterface $bus)
{
$this->resetPasswordHelper = $resetPasswordHelper;
$this->validator = $validator;
$this->bus = $bus;
}
public function __invoke($data)
{
$emailConstraints = new Assert\Email();
$email = $data->getEmail();
if ($email) {
$errors = $this->validator->validate($email, $emailConstraints);
if (count($errors) === 0) {
return $this->processPasswordReset($email);
} else {
return new JsonResponse(['success' => false, 'error' => 'Invalid E-Mail format'], 404);
}
}
}
private function processPasswordReset($email)
{
$user = $this->getDoctrine()->getRepository(User::class)->findOneBy([
'email' => $email,
]);
$this->setCanCheckEmailInSession();
if (!$user) {
// Do not reveal whether a user account was found or not.
return new JsonResponse(['success' => true], 200);
}
try {
$resetToken = $this->resetPasswordHelper->generateResetToken($user);
} catch (ResetPasswordExceptionInterface $e) {
return new JsonResponse(['success' => false, 'error' => 'There was a problem handling your password reset request - ' . $e->getReason()]);
}
$message = new SendEmailMessage($email);
$message->setFrom('from.from#from.from');
$message->setBody(
$this->renderView('reset_password/email.html.twig', [
'resetToken' => $resetToken,
'tokenLifetime' => $this->resetPasswordHelper->getTokenLifetime()
])
);
$message->setSubject('Votre demande de changement de mot de passe');
$this->bus->dispatch($message);
return new JsonResponse(['success' => true], 200);
}
}
Here is my swiftmailer.yaml :
swiftmailer:
url: '%env(MAILER_URL)%'
spool: { type: 'memory' }
Can you help me ?
The answer is "DO NOT spool emails unless you want to process them later".
Check docs Spool Emails
A spooler is a queue mechanism which will process your message queue one by one. This was introduced when swift-mailer was rewritten and added back to symfony. In combination with Messenger Component which provides abstract interface MessageBusInterface, it would delegate to right backend service which can be smtp relay, push notification or any other type of RPC which may trigger actions on separate web services.
As symfony adds new capabilities to the message bus, this feature was added to utilize it for message queues & other services where transactional emails and notifications are processed separately.
To process your spool simply run :
APP_ENV=prod php bin/console swiftmailer:spool:send
In typical installation spooling is disabled, when you enable spooling in memory, it will wait till request is finished and kernel is about to exit. If you are using anything else to debug that terminates kernel halfway or there are other components & parts of application that keeps kernel in memory, events will not be triggered and mail will not be sent.
You can check whole documentation here : Sending Emails
I cant remember the exact reason why and at the time of posting this I'm struggling to find the answer but the swiftmailer type must be file instead of memory. This GitHub issue references this. You can also see how to change the type here.
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();
}