dynamic smtp not working with queueble mail in laravel - laravel

trying to implement dynamic SMTP with laravel it works fine without queue mail but when adding queue to mail it takes default mail SMTP details
dispatch(function () use ($details, $email, $name, $tutorEmail, $brandName, $ownerEmail, $createdBy, $mailSubject) {
Mail::send('mail.mailSchedule', $details, function ($m) use ($email, $name, $tutorEmail, $brandName, $ownerEmail, $createdBy, $mailSubject) {
$m->to($email, $name);
$m->from($ownerEmail, $brandName);
$m->subject($mailSubject);
});
})->delay(now()->addSeconds());

Dynamic configuration in mail is not compatible with queue jobs because the configuration settings, such as the server address and port, may change while the job is in the queue. When the job is pulled from the queue and executed, the configuration settings may no longer be valid, resulting in the job failing to send the email.
The solution of this problem is to pass the email configuration settings as an argument when the job is pushed to the queue, so that the job has access to the correct settings at the time of execution.

Related

laravel swift-mailer exception "Expected response code 250 but got an empty response" using gmail smtp-relay (database queue driver)

the gmail smtp-relay works fine using the sync driver, but if we queue the email we this error. cleared config, cache, & restarted queue workers. tested in prod and dev, same results
[2021-01-24 20:04:22] production.ERROR: Expected response code 250 but got an empty response {"exception":"[object] (Swift_TransportException(code: 0): Expected response code 250 but got an empty response at /home/****/****/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/AbstractSmtpTransport.php:448)
were wondering is this because of serialization and something is not making it through that process???
using latest stable release of laravel >8.0. gmail smtp is authenticating just fine, per why the sync driver sends emails easily. maybe there needs to be a timeout on the queue jobs so they dont barrage gmail so quickly? also our code works fine using sendgrid for example as the smtp relay. thanks.
See https://laracasts.com/discuss/channels/laravel/laravel-swift-mailer-exception-expected-response-code-250-but-got-an-empty-response-using-gmail-smtp-relay-database-queue-driver
Update your AppServiceProvider.php
add this inside boot();
// Fix for SwiftMailer Service;
$_SERVER["SERVER_NAME"] = "your.domain.name";
For users of smtp-relay.gmail.com, if you use localhost/127.0.0.1 as domain during developments, you probably need to change the domain name to use in EHLO command to begin the transaction. I solved this by adding &local_domain=dev.mydomain.tld at the and of my DSN.
smtp://smtp-relay.gmail.com:587?encryption=tls&local_domain=dev.mydomain.tld&...
For SwiftMailer Symfony bundle (since 2.4.0), you can set the local_domain config parameter:
// config/packages/dev/swiftmailer.yaml
swiftmailer:
...
local_domain: dev.mydomain.tld
Explanation for the 2 previous Answers
if $_SERVER["SERVER_NAME"] is the solution:
When you are using cron
The reason is that $_SERVER["SERVER_NAME"] is null when cron is executed. $_SERVER["SERVER_NAME"] is usually only defined for http access.
Example implementation (laravel):
if (!isset($_SERVER['SERVER_NAME'])) {
$url = config('env.APP_URL');
$domain = mb_ereg_replace("http(s)? ://", "", $url);
$domainParts = explode('/', $domain);
ini_set('server_name', count($domainParts) > 0 ? $domainParts[0] : $domain)
}
References :
Cron Job $_SERVER issue
https://github.com/swiftmailer/swiftmailer/issues/992
if 'local_domain' is the solution
When you have a mailhost setting of MAIL_HOST=smtp-relay.gmail.com in your laravel project
The reason is that if local_domain' is not set, the protocol for mail communication with Gmail will be EHLO [127.0.0.1]` and the communication will be disconnected.
By the way, I used gmail->gmail alias and did not need relay in the first place, so I solved the problem by setting MAIL_HOST=smtp.gmail.com.
References:
https://blog.trippyboy.com/2021/laravel/laravel-expected-response-code-250-but-got-an-empty-response/
I had to deal with both of them because of cron messaging and MAIL_HOST=smtp-relay.gmail.com in my environment.
I hope this information will help you.

Laravel Jobs are not processed when triggered by a Redis subscribed message

I've some mistake with a job that I try to dispatch when my Redis subscribe command receive a message.
I launch the Redis subscribe inside an "artisan console" command :
Redis::subscribe(['channel'], function ($message) {
dipatch((new MyJob($message)
->onQueue('default')
->onConnection('redis'));
}
Job is created and I can see it on my Laravel Horizon dashboard. But it's never processed... "handle" function is never called and the job stay in "pending" tab on Horizon.
But when I dispatch it from a tinker session, that's work fine!
Maybe I have to call another artisan command to launch the job outside the redis subscribe function, but hope there is a better solution...
Any ideas?
Solution :
create another connection on the database.php file for your Redis database (same params as the default one, just change the name, eg name it "subscribe"), so after that change, the code must look like this :
$redis = Redis::connection('subscribe');
$redis->subscribe(['channel'], function () {});
I had the same problem, The job will never be dispatched on Redis queue. When I used another queue driver (database or beanstalkd) it worked fine.

What is the right way to send bulk mail with Laravel via AWS SES?

I've SES approved sending rate of 500 emails / second. When I try to send bulk email via Laravel using SES API, the actual mail sending rate is very slow (about ~100 per minute).
Here's an overview of how I do it -
...
Users::latest()->chunk(100, function($users) use($newsletter) {
Notification::send($users, new SendNewsLetter($newsletter)); // queued
})
My guess was that I'd send about 100 mails in one shot, however, Horizon shows that the queue which I'm using will have long wait time (of several seconds).
Can someone inform me what is the right way to send bulk emails using SES and Laravel?
First, i recommand you change the .env file setting for QUEUE_DRIVER=sync to QUEUE_DRIVER=database.
sending Email action
$users = Users::latest()->take(100)->get();
Mail::queue('send', ['users' => $users], function($m) use ($users) {
foreach ($users as $user) {
$m->to($user->email)->subject('YOUR SUBJECT GOES HERE');
}
});
As next step you need to create a Queue table in the database using
the following command before clicking on the route:
PHP artisan queue: table
PHP artisan migrate
Before starting the project you need to run a listener to listen to
the Queue Request. But you're gonna introduce with the new method as
listen is high CPU usage. It's better to use a daemon. So Run the
following command:
PHP artisan queue:work --daemon --tries=3
Source

How to use Laravel IMAP for receive mailbox?

I am using laravel imap package for email setup for receive mailbox.
use this https://github.com/Webklex/laravel-imap#installation package, but i don't understand how it works or test. If anybody for help ?
Assuming you have already installed the package and set your environment variables in .env
Here is an example of how to get all unseen messages from Inbox. (check the API Docs for more available methods or classes)
https://github.com/Webklex/laravel-imap#documentation
$oClient = Client::account('default'); // defined in config/imap.php
$oClient->connect();
// get all unseen messages from folder INBOX
$aMessage = $oClient->getUnseenMessages($oClient->getFolder('INBOX'));
foreach ($aMessage as $oMessage) {
// do something with the message
}

Laravel event not being Broadcast

I am working on a chat/message feature for an app. When a User sends a message, I want a specific Event to be triggered and to be broadcasted. I am then wanting Laravel Echo to listen on the event's broadcast channel to an event via Laravel Echo, using the pusher driver.
I am wanting the Laravel Echo implementation to be in a Vue component and to retrieve the data that was broadcasted via the event. Currently, I can't get an event to broadcast to either a private channel or just a channel.
Here is what I have done:
1) Added the config to .env.
2) Added config to bootstrap.js :
window.Echo = new Echo({
broadcaster: 'pusher',
key: 'mykey',
encypted: false
});
3) Added auth check in App\Providers\BroadcastServiceProvider (just returning true if User is signed in for now):
Broadcast::channel('chat', function ($user) {
// verify that user is recipient of message
return \Auth::check();
});
4) Added App\Providers\BroadcastServiceProvider::class, to App/config/app.php.
5) Created the Event App\Events\UserSentMessage, which broadcasts on a PrivateChannel named chat. I have also tried to broadcast to a Channel. I checked and the event is being fired from a call to the event() helper in a controller, it just seems to not be broadcast. I have also tried using the broadcast method in the controller mentioned.
6) Added the following within the mounted Vue life cycle hook in a valid Vue component (component is rendering data etc as expected, just not working with Laravel Echo atm):
Echo.private('chat').listen('UserSentMessage', (data) => {
console.log(data);
}, (e) => {
console.log(e);
});
Have also tried:
Echo.channel('chat').listen('UserSentMessage', (data) => {
console.log(data);
}, (e) => {
console.log(e);
});
The Vue component is successfully subscribing to the channel specified. The pusher debug console recognized that it is being subscribed to, but the Event, when triggered never gets broadcasted.
Seems to be that there is a problem with broadcasting the event. I have also tried using the broadcast() helper, rather than the event() helper.
Also, when subscribing to the event with Laravel Echo via Echo.private(). It seems to prefix the channel name with private, so I have also tried broadcasting (in the event) to a channel named private-chat.
I can recommend You to check Your .env file and make sure BROADCAST_DRIVER is not log (try pusher) and also don't forget to keep running queue listener:
php artisan queue:listen
UPD.: if You look for more advanced solution, read about laravel horizon
the event will not be broadcasted immediately, it will be send to the queue, only when you listen or work on the queue, the event will be consumed. If you want execute jobs immediately, set QUEUE_DRIVER=sync . see: laravel queue
In my case, my event class file is generated by "make:event", it does have broadcastOn method... But have no implements ShouldBroadcast~
It causes the laravel-echo-server output nothing~
Laravel Framework 8.13.0
I have upvoted Num8er's reply but i also found some other issues so maybe they can help you too.
1) Remove all 'private-' from the beginning of your channel names. These get handled behind the scenes by the various libraries (eg socket.io/laravel-echo). If you look at any debug output you will see 'private-' prepended to the front of the channel names but you DO NOT need to add these.
2) If you're using redis then make sure the REDIS_PREFIX is set to an empty string in your .env file. By default it's set to something like 'laravel_database' and this messes up the channel names.
REDIS_PREFIX=
3) Make sure you've got your laravel-echo server running (and redis/pusher). Also you need to make sure you have the queue worker running:
php artisan queue:work
4) It's worth enabling debugging output on your Echo Server as this will tell you useful info about traffic (eg channel names) so modify the laravel-echo-server.json file (in your project root dir) so that devMode is set to true:
"devMode": true,
#materliu: that was a good hint. In my case i did not create a queue with the working directory set to the project i am working on. Using circus. The event was triggered in code but no job listener was available. As soon as i run "php artisan queue:listen" suddenly all previous broadcasts have been processed.
Usually its difficult to figure out which component of a complex system does not work.

Resources