Er zijn momenten waarop u liever sendmail gebruikt in plaats van diensten als Mailgun, gezien de prijzen.
Wanneer u bijvoorbeeld een VPS bestelt bij TransIP, krijgt u op dit moment 1000 gratis mails.
Helaas ondersteunt Laravel's fallback het niet als Postfix down is. Daarom heb ik + GPT deze custom mailer geschreven.
Maak een bestand met de naam App\Mail\ConditionalTransport.php:
php
<?php
namespace App\Mail;
use Illuminate\Mail\MailManager;
use Illuminate\Support\Facades\Cache;
use Symfony\Component\Mailer\SentMessage;
use Symfony\Component\Mailer\Transport\AbstractTransport;
class ConditionalTransport extends AbstractTransport
{
protected $sendmailTransport;
protected $mailgunTransport;
protected $cacheKey;
/**
* Create a new Conditional transport instance.
*/
public function __construct(MailManager $mailManager)
{
parent::__construct();
$this->cacheKey = 'email_sendmail_count_' . date('Y-m-d');
// Create the sendmail transport
$this->sendmailTransport = $mailManager->createSymfonyTransport(['transport' => 'sendmail']);
// Create the mailgun transport
$this->mailgunTransport = $mailManager->createSymfonyTransport(['transport' => 'mailgun']);
}
/**
* Send the given message.
*
* @param \Symfony\Component\Mailer\SentMessage $message
*/
protected function doSend(SentMessage $message): void
{
// Check if Postfix service is running
if ($this->isPostfixRunning()) {
// Get the current count from cache
$count = Cache::get($this->cacheKey, 0);
if ($count < 1000) {
// Send with Sendmail
$this->sendmailTransport->send($message->getOriginalMessage(), $message->getEnvelope());
// Increment the count
Cache::increment($this->cacheKey);
return;
}
}
// If Postfix is not running or count >= 2000, send with Mailgun
$this->mailgunTransport->send($message->getOriginalMessage(), $message->getEnvelope());
}
/**
* Check if Postfix service is running.
*
* @return bool
*/
protected function isPostfixRunning(): bool
{
$isDisabled = in_array('exec', explode(',', ini_get('disable_functions')));
if ($isDisabled) {
// If exec is disabled, we can't check; assume it's not running
return false;
}
try {
$output = [];
$returnVar = null;
exec('systemctl is-active postfix', $output, $returnVar);
if (isset($output[0]) && trim($output[0]) === 'active') {
return true;
}
} catch (\Exception $e) {
// Handle exception or log error if necessary
}
return false;
}
/**
* Get the string representation of the transport.
*/
public function __toString(): string
{
return 'conditional';
}
}
Registreer vervolgens uw aangepaste transport binnen de opstartmethode van uw applicatie App\Providers\AppServiceProvider
dienstverlener:
php gebruik App\Mail\ConditionalTransport; gebruik Illuminate\Mail\MailManager; gebruik Illuminate\Support\Facades\Mail; /** * Bootstrap alle applicatieservices. */ public function boot(): void { Mail::extend('conditional', function (array $config = []) { return new ConditionalTransport(app(MailManager::class)); }); }
Voeg vervolgens een nieuwe mailerdefinitie toe aan de map van uw toepassing. configuratie/mail.php
configuratiebestand dat gebruikmaakt van het nieuwe transport:
php 'mailers' => [ // Andere mailers... 'conditional' => [ 'transport' => 'conditional', ], ],
Met deze instelling gebruikt uw Laravel-applicatie de sendmail-driver om e-mails te versturen als de Postfix-service actief is en de dagelijkse limiet nog niet is bereikt. Zodra de limiet wordt overschreden of als Postfix niet actief is, schakelt deze automatisch over naar de Mailgun-driver.
Opmerkingen:
- De
isPostfixRunning
methode controleert of de Postfix-service actief is met behulp van deuitvoerend
functie om te bellensystemctl is-actief postfix
Pas deze methode aan als uw omgeving een andere manier gebruikt om services te beheren of als exec is uitgeschakeld. - Het aantal e-mails wordt gecached met behulp van Laravel's Cache-facade met een sleutel die de huidige datum bevat (met behulp van de Ymd-indeling).
- Zorg ervoor dat uw sendmail- en mailgun-configuraties correct zijn ingesteld in uw
configuratie/mail.php
bestand.
Deze implementatie is in overeenstemming met de documentatie van Laravel over aangepaste transporten en zou naadloos in uw toepassing moeten passen.
Mailgun wordt als alternatief geselecteerd, maar u kunt ook andere drivers opgeven als u dat wenst.
Momenteel is de limiet 1000 verzendingen per dag, maar u kunt dit naar eigen wens aanpassen.
Getest met Laravel 10. Gebruik op eigen risico, uiteraard :).