Hay ocasiones en las que desearías utilizar sendmail en lugar de servicios como Mailgun, dados sus precios.
Por ejemplo, al pedir un VPS en TransIP, te darán 1000 envíos de correo gratis al momento de escribir.
Lamentablemente, la alternativa de Laravel no lo admite cuando Postfix no funciona. Por eso, yo y GPT escribimos este correo personalizado.
Crea un archivo llamado 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';
}
}
A continuación, registre su transporte personalizado dentro del método de arranque de su aplicación. Aplicación\Proveedores\Proveedor de servicios de aplicaciones
Proveedor de servicios:
php usa App\Mail\ConditionalTransport; usa Illuminate\Mail\MailManager; usa Illuminate\Support\Facades\Mail; /** * Arrancar cualquier servicio de la aplicación. */ public function boot(): void { Mail::extend('conditional', function (array $config = []) { return new ConditionalTransport(app(MailManager::class)); }); }
Luego, agregue una nueva definición de correo a su aplicación. configuración/mail.php
archivo de configuración que utiliza el nuevo transporte:
php 'mailers' => [ // Otros correos... 'conditional' => [ 'transport' => 'conditional', ], ],
Con esta configuración, su aplicación Laravel utilizará el controlador sendmail para enviar correos electrónicos si el servicio Postfix está en ejecución y no se ha alcanzado el límite diario. Una vez que se supere el límite o si Postfix no está en ejecución, cambiará automáticamente al controlador Mailgun.
Notas:
- En
¿Postfix se está ejecutando?
El método comprueba si el servicio Postfix se está ejecutando mediante el uso deejecutivo
función a llamarsystemctl está activo postfix
. Ajuste este método si su entorno utiliza una forma diferente de administrar los servicios o si la ejecución está deshabilitada. - El recuento de correos electrónicos se almacena en caché utilizando la fachada de caché de Laravel con una clave que incluye la fecha actual (usando el formato Ymd).
- Asegúrese de que sus configuraciones de sendmail y mailgun estén configuradas correctamente en su
configuración/mail.php
archivo.
Esta implementación se adhiere a la documentación de Laravel sobre transportes personalizados y debería encajar perfectamente en su aplicación.
Selecciona Mailgun como alternativa, pero también puedes especificar otros controladores si lo deseas.
Actualmente tiene un límite de 1000 envíos por día, pero cámbialo a tu frecuencia deseada.
Probado con Laravel 10. Úselo bajo su propio riesgo, por supuesto :).