Use an actual mail provider made for the purpose like mailgun, mailpace, postmark etc.
Yandex SMTP limit for outgoing emails
Hi, I had a project that sends lots of notification mails. I'm using the smtp driver with yandex. But yandex has an outgoing mail limit so some of my mails could not be sent. What is the most appropriate solution with lowest cost?
After some research, I decided to write a custom transporter class to use multiple email address. Here you can find the codes:
// app\MailQueue.php
<?php
namespace App;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Config;
class MailQueue
{
protected int $queueMaxSize = 5;
protected int $mailLimitByUser = 100;
protected int $queueSize = 0;
protected int $front = 0;
protected array $users = [];
public function __construct()
{
if(Cache::missing('MailQueue')) {
Cache::put('MailQueue', [
'front' => 0,
'queueSize' => 0
]);
}
$this->front = Cache::get('MailQueue')['front'];
$this->queueSize = Cache::get('MailQueue')['queueSize'];
$this->users = config('mail.mailers.smtp.users');
if (count($this->users) < $this->queueMaxSize) {
$this->queueMaxSize = count($this->users);
}
}
public function advanceQueue(): void
{
// select the user according to queueSize
// 0-99 => 1
// 100-199 => 2
// 200-299 => 3
// 300-399 => 4
// 400-499 => 5
$user = $this->users[(int) ceil($this->queueSize / $this->mailLimitByUser) + 1];
// set the user's credentials
$this->setUser($user);
// increase the queueSize
$this->queueSize++;
// if the queueSize is greater than the queueMaxSize, reset the queueSize
if($this->queueSize >= $this->queueMaxSize * $this->mailLimitByUser) {
$this->queueSize = 0;
}
// update the cache
Cache::put('MailQueue', [
'front' => $this->front,
'queueSize' => $this->queueSize
]);
}
private function setUser(array $user): void
{
Config::set('mail.mailers.smtp.username', $user['username']);
Config::set('mail.from.address', $user['username']);
Config::set('mail.mailers.smtp.password', $user['password']);
}
}
// app\Transports\MultiSmtpTransport.php
<?php
namespace App\Transports;
use App\MailQueue;
use Symfony\Component\Mailer\Transport\Smtp\SmtpTransport;
class MultiSmtpTransport extends SmtpTransport
{
public function __construct(MailQueue $mailQueue)
{
parent::__construct();
$mailQueue->advanceQueue();
}
public function __toString(): string
{
return 'multi_smtp';
}
}
// config/mail.php
'smtp' => [
'transport' => 'multi_smtp',
'host' => env('MAIL_HOST', 'smtp.mailgun.org'),
'port' => /*****/,
'users' => [
1 => [
'username' => env('MAIL_USERNAME1'),
'password' => env('MAIL_PASSWORD1'),
],
2 => [
'username' => env('MAIL_USERNAME2'),
'password' => env('MAIL_PASSWORD2'),
],
3 => [
'username' => env('MAIL_USERNAME3'),
'password' => env('MAIL_PASSWORD3'),
]
]/*...*/
],
// and finally do not forget to extend the `multi_smtp` transporter. In serviceProvider:
Mail::extend('multi_smtp', function (array $config = []) {
return new MultiSmtpTransport(new MailQueue());
});
@aknEvrnky …or you could solve the actual problem and use an actual mail provider instead of trying to work around the problem by using multiple addresses. I’d imagine that’s against the provider’s terms and conditions and a quick way to get your accounts suspended.
They’ll be throttling you for a reason. That reason isn’t to make you create multiple addresses.
Please or to participate in this conversation.