我们的电子邮件无法使用带有Redis队列的Laravel发送。
触发错误的代码是:->onQueue('emails')
$job = (new SendNewEmail($sender, $recipients))->onQueue('emails');
$job_result = $this->dispatch($job);
在工作中与此相结合:
use InteractsWithQueue;
我们的错误讯息是:
Feb 09 17:15:57 laravel: message repeated 7947 times: [ production.ERROR: exception 'Swift_TransportException' with message 'Expected response code 354 but got code "550", with message "550 5.7.0 Requested action not taken: too many emails per second "' in /home/laravel/app/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/AbstractSmtpTransport.php:383 Stack trace: #0 /home/laravel/app/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/AbstractSmtpTransport.php(281):
我们的错误只发生在使用Sendgrid而不是Mailtrap,这会欺骗电子邮件发送。我和Sendgrid谈过,电子邮件从未触及他们的服务器,当我的错误发生时,他们的服务完全处于活动状态。所以,错误似乎在我的最后。
有什么想法吗?
答案 0 :(得分:13)
似乎只有Mailtrap发送此错误,因此要么打开另一个帐户或升级到付费计划。
答案 1 :(得分:3)
也许你应该确保它真的是通过Sendgrid而不是mailtrap发送的。他们的硬率限制目前似乎是每秒3k次请求,对于免费计划的邮件捕获每秒3次请求:)
答案 2 :(得分:2)
仅用于调试!
如果您不希望有超过5封电子邮件而且无法更改 mailtrap ,请尝试:
foreach ($emails as $email) {
...
Mail::send(... $email);
if(env('MAIL_HOST', false) == 'smtp.mailtrap.io'){
sleep(1); //use usleep(500000) for half a second or less
}
}
使用sleep()是一种非常糟糕的做法。理论上,此代码应仅在测试环境或调试模式下执行。
答案 3 :(得分:2)
我终于弄清楚了如何设置整个Laravel应用程序以基于配置来限制邮件。
在boot()
的{{1}}函数中,
AppServiceProvider
在$throttleRate = config('mail.throttleToMessagesPerMin');
if ($throttleRate) {
$throttlerPlugin = new \Swift_Plugins_ThrottlerPlugin($throttleRate, \Swift_Plugins_ThrottlerPlugin::MESSAGES_PER_MINUTE);
Mail::getSwiftMailer()->registerPlugin($throttlerPlugin);
}
中,添加以下行:
config/mail.php
在您的'throttleToMessagesPerMin' => env('MAIL_THROTTLE_TO_MESSAGES_PER_MIN', null), //https://mailtrap.io has a rate limit of 2 emails/sec per inbox, but consider being even more conservative.
文件中,添加如下一行:
.env
唯一的问题是,如果使用MAIL_THROTTLE_TO_MESSAGES_PER_MIN=50
,它似乎不会影响通过later()
函数发送的邮件。
答案 4 :(得分:0)
我在Laravel v5.8上通过手动设置身份验证路由来实现。路由位于文件routes\web.php
上。以下是需要添加到该文件的路由:
Auth::routes();
Route::get('email/verify', 'Auth\VerificationController@show')->name('verification.notice');
Route::get('email/verify/{id}', 'Auth\VerificationController@verify')->name('verification.verify');
Route::group(['middleware' => 'throttle:1,1'], function(){
Route::get('email/resend', 'Auth\VerificationController@resend')->name('verification.resend');
});
说明:
Auth::routes();
,以手动配置身份验证路由。email/resend
将Route::group
内的路由throttle:1,1
包裹起来(两个数字代表最大重试次数和这些最大重试的时间,以分钟为单位)我还通过app\Http\Controllers\Auth\VerificationController.php
函数在文件__construct
中删除了一行代码。
我删除了此内容:
$this->middleware('throttle:6,1')->only('verify', 'resend');
答案 5 :(得分:0)
您需要限制emails
队列的速率。
“官方”方式是设置Redis queue driver。但这既困难又耗时。
所以我写了一个自定义队列工作器mxl/laravel-queue-rate-limit,它使用Illuminate\Cache\RateLimiter
来对作业的执行进行速率限制(与Laravel在rate limit HTTP requests内部使用的相同)。
在config/queue.php
中为emails
队列指定速率限制(例如每秒2封电子邮件):
'rateLimit' => [
'emails' => [
'allows' => 2,
'every' => 1
]
]
并为此队列运行worker:
$ php artisan queue:work --queue emails
答案 6 :(得分:0)
我用sleep(5)
等待了五秒钟,然后再次使用了邮件陷阱。
foreach ($this->suscriptores as $suscriptor) {
\Mail::to($suscriptor->email)
->send(new BoletinMail($suscriptor, $sermones, $entradas));
sleep(5);
}
我在sleep(5)
中使用了foreach
。 foreach遍历数据库中存储的所有电子邮件,sleep(5)
将循环暂停五秒钟,然后继续下一封电子邮件。
答案 7 :(得分:0)
在使用邮件陷阱时,我遇到了这个问题。我在一秒钟内发送了10封邮件,它被视为垃圾邮件。我不得不在每项工作之间延迟。看一下解决方案(它的Laravel-我有system_jobs
表并使用queue=database
)
制作一个静态函数来检查上次作业时间,然后将其添加到self::DELAY_IN_SECONDS
-两次作业之间需要多少秒:
public static function addSecondsToQueue() {
$job = SystemJobs::orderBy('available_at', 'desc')->first();
if($job) {
$now = Carbon::now()->timestamp;
$jobTimestamp = $job->available_at + self::DELAY_IN_SECONDS;
$result = $jobTimestamp - $now;
return $result;
} else {
return 0;
}
}
然后使用它来延迟发送消息(考虑队列中的最后一个作业)
Mail::to($mail)->later(SystemJobs::addSecondsToQueue(), new SendMailable($params));