[英]Laravel email with queue 550 error (too many emails per second)
我們的電子郵件無法使用帶有 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 談過,電子郵件從未觸及他們的服務器,當我的錯誤發生時,他們的服務完全處於活動狀態。 所以,錯誤似乎就在我的身邊。
有什么想法嗎?
似乎只有Mailtrap 會發送此錯誤,因此要么開設另一個帳戶,要么升級到付費計划。
我終於想出了如何設置整個 Laravel 應用程序以根據配置限制郵件。
在AppServiceProvider
的boot()
函數中,
$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
唯一的問題是,如果QUEUE_DRIVER=sync
,它似乎不會影響通過later()
函數發送的郵件。
僅供調試!
如果您不希望收到超過 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()是一種非常糟糕的做法。 理論上,這段代碼應該只在測試環境或調試模式下執行。
也許您應該確保它確實是通過 Sendgrid 而不是 mailtrap 發送的。 他們的硬速率限制目前似乎是每秒 3k 個請求,而免費計划中的 mailtrap 則是每秒 3 個請求:)
我通過手動設置身份驗證路由在 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
(這兩個數字代表最大重試次數和這些最大重試次數的時間(以分鍾為單位)) 我還在__construct
函數中刪除了文件app\\Http\\Controllers\\Auth\\VerificationController.php
中的一行代碼。
我刪除了這個:
$this->middleware('throttle:6,1')->only('verify', 'resend');
我使用sleep(5)
在再次使用 mailtrap 之前等待五秒鍾。
foreach ($this->suscriptores as $suscriptor) {
\Mail::to($suscriptor->email)
->send(new BoletinMail($suscriptor, $sermones, $entradas));
sleep(5);
}
我在foreach
使用了sleep(5)
。 foreach 遍歷存儲在數據庫中的所有電子郵件, sleep(5)
在繼續下一封電子郵件之前停止循環五秒鍾。
您需要對emails
隊列進行速率限制。
“官方”方法是設置Redis 隊列驅動程序。 但這既困難又費時。
因此,我編寫了自定義隊列工作器mxl/laravel-queue-rate-limit ,它使用Illuminate\\Cache\\RateLimiter
來限制作業執行的速率(與 Laravel 內部用於限制 HTTP 請求速率的相同)。
在config/queue.php
指定emails
隊列的速率限制(例如每秒 2 封電子郵件):
'rateLimit' => [
'emails' => [
'allows' => 2,
'every' => 1
]
]
並為此隊列運行工作程序:
$ php artisan queue:work --queue emails
我在使用郵件陷阱時遇到了這個問題。 我在一秒鍾內發送了 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));
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.