Como: Enviar Emails Programaticamente en Magento 2


En esta página

Tarde o temprano todo proyecto necesita enviar un email que Magento no envía por defecto, una notificación a un admin, un recordatorio a un cliente, un reporte al almacén. La buena noticia es que Magento nos da un servicio limpio para hacerlo, el TransportBuilder. Déjame mostrarte la configuración que uso.

Este post asume que existe ya un módulo de Magento con la ruta app/code/Vendor/Module y que ya registraste una plantilla de email. Si necesitas la parte de la plantilla, echa un vistazo a Como: Crear email templates personalizados en Magento 2.

El servicio

Me gusta envolver todo en un pequeño servicio para que el código que lo llama quede limpio y fácil de testear.

php
<?php
/** app/code/Vendor/Module/Model/EmailSender.php */
namespace Vendor\Module\Model;

use Magento\Framework\Mail\Template\TransportBuilder;
use Magento\Framework\Translate\Inline\StateInterface;
use Magento\Store\Model\StoreManagerInterface;
use Magento\Framework\App\Area;

class EmailSender
{
    /**
     * @var TransportBuilder
     */
    private $transportBuilder;

    /**
     * @var StateInterface
     */
    private $inlineTranslation;

    /**
     * @var StoreManagerInterface
     */
    private $storeManager;

    public function __construct(
        TransportBuilder $transportBuilder,
        StateInterface $inlineTranslation,
        StoreManagerInterface $storeManager
    ) {
        $this->transportBuilder = $transportBuilder;
        $this->inlineTranslation = $inlineTranslation;
        $this->storeManager = $storeManager;
    }

    /**
     * @param string $toEmail
     * @param array  $templateVars
     */
    public function send($toEmail, array $templateVars = [])
    {
        $storeId = $this->storeManager->getStore()->getId();

        $this->inlineTranslation->suspend();
        try {
            $transport = $this->transportBuilder
                ->setTemplateIdentifier('vendor_module_email_template')
                ->setTemplateOptions(['area' => Area::AREA_FRONTEND, 'store' => $storeId])
                ->setTemplateVars($templateVars)
                ->setFromByScope('general')
                ->addTo($toEmail)
                ->getTransport();

            $transport->sendMessage();
        } finally {
            $this->inlineTranslation->resume();
        }
    }
}

Algunas cosas que vale la pena señalar:

  1. setTemplateIdentifier es el id que le diste a la plantilla en el email_templates.xml.
  2. Siempre haz suspend() de la traducción inline antes de enviar y resume() después, de lo contrario puedes tener el markup de traducción filtrándose dentro del email. Hacerlo en un bloque finally garantiza que se reanude incluso si el envío lanza una excepción.
  3. setFromByScope('general') usa el contacto general de la tienda, pero puedes pasar el tuyo ['email' => ..., 'name' => ...].

Usándolo

Desde un controlador, un observer u otro servicio, ahora es una sola línea:

php
$this->emailSender->send('customer@example.com', ['customer_name' => 'John', 'order_id' => '000000123']);

Esas variables son las que referencias en la plantilla con {{var customer_name}}.

Espero que esto ayude.

Si tienes alguna pregunta o conoces una mejor manera de lograr esto, siéntete libre de compartir en los comentarios a continuación.

Related links: