Saltar al contenido

Magento 2: envíe un correo electrónico con un archivo adjunto

Solución:

M2 no viene listo para usar, sin embargo, es una característica integrada en el marco zend. Aquí hay una buena referencia sobre cómo agregar esta funcionalidad en magento: https://blog.bitexpert.de/blog/sending-mails-with-attachments-in-magento-2/

En caso de que el enlace falle, cree lo siguiente

message->createAttachment($body, $mimeType, $disposition, $encoding, $filename);
        return $this;
    

luego agregue a etc / di.xml




    

Ahora puedes usar addAttachment() en todo su sitio.

A partir de Magento 2.2.7, las soluciones descritas anteriormente ya no funcionan porque MagentoFrameworkMailMessage caído extendiéndose Zend_Mail.
Para evitar la falta de una forma fácil de agregar archivos adjuntos a través del generador de transporte (que actualmente parece ser el lugar correcto para dicha función), es necesario crear un reemplazo para el TransportBuilder y hacer uso ZendMimePart:

mimePartFactory    = $mimePartFactory;
        $this->mimeMessageFactory = $mimeMessageFactory;
    

    protected function prepareMessage()
    
        parent::prepareMessage();

        $mimeMessage = $this->getMimeMessage($this->message);

        foreach ($this->parts as $part) 
            $mimeMessage->addPart($part);
        

        $this->message->setBody($mimeMessage);

        return $this;
    

    public function addAttachment(
        $body,
        $mimeType = Mime::TYPE_OCTETSTREAM,
        $disposition = Mime::DISPOSITION_ATTACHMENT,
        $encoding = Mime::ENCODING_BASE64,
        $filename = null
    ) 
        $this->parts[] = $this->createMimePart($body, $mimeType, $disposition, $encoding, $filename);
        return $this;
    

    private function createMimePart(
        $content,
        $type = Mime::TYPE_OCTETSTREAM,
        $disposition = Mime::DISPOSITION_ATTACHMENT,
        $encoding = Mime::ENCODING_BASE64,
        $filename = null
    ) 
        /** @var MimePart $mimePart */
        $mimePart = $this->mimePartFactory->create(['content' => $content]);
        $mimePart->setType($type);
        $mimePart->setDisposition($disposition);
        $mimePart->setEncoding($encoding);

        if ($filename) 
            $mimePart->setFileName($filename);
        

        return $mimePart;
    

    private function getMimeMessage(MessageInterface $message)
    
        $body = $message->getBody();

        if ($body instanceof MimeMessage) 
            return $body;
        

        /** @var MimeMessage $mimeMessage */
        $mimeMessage = $this->mimeMessageFactory->create();

        if ($body) 
            $mimePart = $this->createMimePart((string)$body, Mime::TYPE_TEXT, Mime::DISPOSITION_INLINE);
            $mimeMessage->setParts([$mimePart]);
        

        return $mimeMessage;
    

No olvides reemplazar el original. MagentoFrameworkMailTemplateTransportBuilder por su implementación a través de di.xml.

Tenga en cuenta que esta implementación probablemente se romperá con una próxima versión de Magento como MagentoFrameworkMailMessageInterface::setBody() está en desuso y puede eliminarse pronto.

HTH

Compatible con Magento 2.3.x:

Esta fue mi respuesta para Magento 2.3, ya que esta era una de las principales preguntas de Google y parece que hay mucha gente en los comentarios buscando.

Parece haber mucho deseo en otras publicaciones sobre sobrescribir el valor predeterminado TransportBuilder clase vía etc/di.xml, sin embargo, el módulo en el que estoy trabajando es tan pequeño que no quiero que sea responsable del valor predeterminado TransportBuilder así que construí una clase Helper (probablemente debería ser un modelo basado en cuán acoplado está a la plantilla de correo electrónico declarada, pero estoy divagando).

los TransportBuilder no tiene acceso público al TransportInterface, pero en su lugar genera un clon cada vez y luego reinicia el constructor. Me resultó más fácil construir mi TransportInterface instancia y luego adjuntar mi archivo adjunto Part Objetos al mensaje del transporte. Si encuentra necesario sobrescribir el valor predeterminado TransportBuilder a través de la preferencia de inyección de dependencia, tenga cuidado con la actualización de métodos públicos. ¡Recuerde practicar la O cuando mantenga su código SÓLIDO!

transportBuilder = $transportBuilder;
        $this->storeManager = $storeManager;
        $this->config = $config;
        $this->file = $file;
    

    /**
     * Send the email for a Help Center submission.
     *
     * @param DataObject $templateParams
     * @param array $attachments
     * @return void
     */
    public function send(DataObject $templateParams, array $attachments = [])
    
        $storeId = $this->storeManager->getStore()->getId();

        // Build transport
        /** @var MagentoFrameworkMailTransportInterface $transport */
        $transport = $this->transportBuilder
            ->setTemplateOptions(['area' => Area::AREA_FRONTEND, 'store' => $storeId])
            ->setTemplateIdentifier($this->config->getEmailTemplate())
            ->setTemplateVars($templateParams->toArray())
            ->setFrom($this->config->getEmailSender())
            ->addTo($this->config->getEmailRecipient(), 'Help Center')
            /**
             * Something important to note is that when the getTransport()
             * function is run, the message is compiled and then the builder 
             * class resets (as of 2.3.1). 
             * 
             * This is note worthy because if you want to send > 1 attachment,
             * your $builder will be reset -- losing all of the ->set* functions
             * you just used above as well as your attachment.
             * 
             * Since we append attachments to the transport, it's easier to:
             * build -> attach -> send. And this way multiple attachments 
             * can be included. :thumbsup:
             */
            ->getTransport();

        // Attach Images to transport
        foreach ($attachments as $a) 
            $transport = $this->addAttachment($transport, $a);
        

        // Send transport
        $transport->sendMessage();
    

    /**
     * Add an attachment to the message inside the transport builder.
     *
     * @param TransportInterface $transportBuilder
     * @param array $file Sanitized index from $_FILES
     * @return TransportInterface
     */
    protected function addAttachment(TransportInterface $transport, array $file): TransportInterface
    
        $part = $this->createAttachment($file);
        $transport->getMessage()->getBody()->addPart($part);

        return $transport;
    

    /**
     * Create an zend mime part that is an attachment to attach to the email.
     * 
     * This was my usecase, you'll need to edit this to your own needs.
     *
     * @param array $file Sanitized index from $_FILES
     * @return Part
     */
    protected function createAttachment(array $file): Part
    
        $ext =  '.' . explode('/', $file['type'])[1];
        $fileName = md5(uniqid(microtime()), true) . $ext;

        $attachment = new Part($this->file->read($file['tmp_name']));
        $attachment->disposition = Zend_Mime::TYPE_OCTETSTREAM;
        $attachment->encoding = Zend_Mime::ENCODING_BASE64;
        $attachment->filename = $fileName;

        return $attachment;
    

Recuerda algo, que tienes la capacidad de valorar esta división si te fue de ayuda.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

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