Fotografía de enfoque superficial de un buzón gris

Laravel usa Sendmail con Postfix y un Fallback: un correo personalizado

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 de ejecutivo función a llamar systemctl 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 :).

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

es_ESEspañol
Ir arriba