Magento 2: gửi email kèm theo


Câu trả lời:


19

M2 không đi kèm với hộp tuy nhiên nó là một tính năng được tích hợp trong khung zend. Dưới đây là một tài liệu tham khảo tốt về cách thêm chức năng này vào magento: https://blog.bitexpert.de/blog/seinating-mails-with-attachments-in-magento-2/

Trong trường hợp liên kết bị chết, hãy tạo như sau

<?php
namespace Your\CustomModule\Magento\Mail\Template;

class TransportBuilder 
    extends \Magento\Framework\Mail\Template\TransportBuilder
{
    public function addAttachment(
        $body,
        $mimeType    = Zend_Mime::TYPE_OCTETSTREAM,
        $disposition = Zend_Mime::DISPOSITION_ATTACHMENT,
        $encoding    = Zend_Mime::ENCODING_BASE64,
        $filename    = null
    ) {
        $this->message->createAttachment($body, $mimeType, $disposition, $encoding, $filename);
        return $this;
    }
}

sau đó thêm vào etc / di.xml

<?xml version="1.0"?>

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <preference for="\Magento\Framework\Mail\Template\TransportBuilder"
                type="\Your\CustomModule\Magento\Mail\Template\TransportBuilder" />
</config>

Bây giờ bạn có thể sử dụng addAttachment()trên toàn bộ trang web của bạn.


8
Tôi vẫn tự hỏi tại sao magento TransportBuilder không có phương pháp này
Murtuza Zabuawala

4
Làm thế nào chúng ta có thể đính kèm tập tin trong email magento tùy chỉnh 2.3? bởi vì nó sử dụng zendframework 2 và câu trả lời này không hoạt động nữa
Manish Maheshwari

3
Làm thế nào để gửi email với tệp đính kèm trong Magento 2.3?
Dhaduk Mitesh

@M BiếnMaheshwari & Mitesh Bạn đã có giải pháp chưa?
Sameer Bhayani

1
Giải pháp này không hoạt động trong Magento2.3 nữa. Có ai có sự thay thế cho tập tin đính kèm.?
nishu

8

Kể từ Magento 2.2.7, các giải pháp được mô tả ở trên không hoạt động nữa kể từ khi \Magento\Framework\Mail\Messagemở rộng \Zend_Mail.
Để tránh việc thiếu một cách dễ dàng để thêm tệp đính kèm thông qua trình xây dựng giao thông (hiện tại có vẻ là vị trí chính xác cho chức năng đó), người ta cần tạo một thay thế cho TransportBuilder và sử dụng \Zend\Mime\Part:

<?php
namespace Your\CustomModule\Magento\Mail\Template;

use Magento\Framework\Mail\MessageInterface;
use Magento\Framework\Mail\MessageInterfaceFactory;
use Magento\Framework\Mail\Template\FactoryInterface;
use Magento\Framework\Mail\Template\SenderResolverInterface;
use Magento\Framework\Mail\TransportInterfaceFactory;
use Magento\Framework\ObjectManagerInterface;
use Zend\Mime\Mime;
use Zend\Mime\Part as MimePart;
use Zend\Mime\PartFactory as MimePartFactory;
use Zend\Mime\Message as MimeMessage;
use Zend\Mime\MessageFactory as MimeMessageFactory;

class TransportBuilder extends \Magento\Framework\Mail\Template\TransportBuilder
{
    /** @var MimePart[] */
    private $parts = [];

    /** @var MimeMessageFactory */
    private $mimeMessageFactory;

    /** @var MimePartFactory */
    private $mimePartFactory;

    public function __construct(
        FactoryInterface $templateFactory,
        MessageInterface $message,
        SenderResolverInterface $senderResolver,
        ObjectManagerInterface $objectManager,
        TransportInterfaceFactory $mailTransportFactory,
        MimePartFactory $mimePartFactory,
        MimeMessageFactory $mimeMessageFactory,
        MessageInterfaceFactory $messageFactory = null
    ) {
        parent::__construct(
            $templateFactory,
            $message,
            $senderResolver,
            $objectManager,
            $mailTransportFactory,
            $messageFactory
        );

        $this->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;
    }
}

Đừng quên thay thế bản gốc \Magento\Framework\Mail\Template\TransportBuilderbằng cách triển khai của bạn thông qua di.xml.

Lưu ý rằng việc triển khai này có thể sẽ bị phá vỡ với bản phát hành sắp tới của Magento vì \Magento\Framework\Mail\MessageInterface::setBody()không được chấp nhận và có thể bị xóa sớm.

HTH


Chào! Bạn có một phương thức addAttachment trong mã của mình, nhưng bạn đã gọi chúng ở đâu? Tôi không thấy nó.
Nikolai Silin

cảm ơn! Tôi đã thêm vòng lặp vào phương thức Chuẩn bị và công việc vĩnh viễn.
Nikolai Silin

@NikolaiSilin cách gửi png hoặc các tệp khác.
sumeet bajaj

1

Magento 2 Email tùy chỉnh từ Module, Không cung cấp tệp đính kèm hình ảnh.

Nếu bạn muốn sử dụng tệp đính kèm hình ảnh với các mẫu email trong Magento 2, bạn cần ghi đè lớp, Magento \ Framework \ Mail \ Template \ TransportBuilder

Magento Out-of-box không cung cấp tính năng đính kèm cho email. Bạn có thể giới thiệu blog để gửi tệp đính kèm hình ảnh chi tiết,

Bạn cần thêm logic như cách dưới đây,

 public function addAttachment(
        $body,
        $mimeType    = \Zend_Mime::TYPE_OCTETSTREAM,
        $disposition = \Zend_Mime::DISPOSITION_ATTACHMENT,
        $encoding    = \Zend_Mime::ENCODING_BASE64,
        $filename    = null
    ) {
        $this->message->createAttachment($body, $mimeType, $disposition, $encoding, $filename);
        return $this;
    }

1
Bạn có thể giúp để đạt được tương tự trong magento 2.3?
Sameer Bhayani

Tạo tệp đính kèm theo cách này cho đến 2.2.7. 2.2.8 và 2.3+ không hoạt động
Matthias Kleine

Tôi vừa đăng một câu trả lời cho 2.3.x @MatthiasKleine
domdambrogia

xin chào, làm thế nào tôi có thể đính kèm nếu tôi có chuỗi mã hóa base64?
Ketan Borada

1

Đây là câu trả lời hoàn hảo để gửi pdf trong Email trong magetno 2.3

$transport = $_transportBuilder->setTemplateIdentifier(20)
    ->setTemplateOptions($templateOptions)                                                 
    ->setTemplateVars($templateVars)
    ->setFrom($from)
    ->addTo($vendor_email)
    ->getTransport();

$html = $transport->getMessage()>getBody()->generateMessage();            
$bodyMessage = new \Zend\Mime\Part($html);
$bodyMessage->type = 'text/html';
$attachment = $_transportBuilder->addAttachment($pdfData,$fileName);      
$bodyPart = new \Zend\Mime\Message();
$bodyPart->setParts(array($bodyMessage,$attachment));
$transport->getMessage()->setBody($bodyPart);                
$transport->sendMessage();
$inlineTranslation->resume();

Xin chào, Đó là lỗi nghiêm trọng: Uncaught Error: Gọi tới hàm thành viên
createdMessage

Bạn đang tạo một tin nhắn mới không cần thiết khi phương tiện giao thông của bạn đã có tin nhắn. Tại sao không chỉ thêm một phần vào vị trí? Điều này là lộn xộn và khó theo dõi. Chưa kể bạn đang nhân đôi công việc và bộ nhớ cần thiết để giải quyết vấn đề này.
domdambrogia

0

Như đã đề cập trong các câu trả lời trước, magento2 không có chức năng ngoài hộp để gửi thư có tệp đính kèm.

Tôi không biết nếu đó là một cách thực hành tốt nhất, nhưng bạn có thể gọi Zend_Maillớp trực tiếp để thực hiện, mà không cần tạo chức năng tùy chỉnh và ghi đè Magento\Framework\Mail\Template\TransportBuilder, như bên dưới

$mail = new \Zend_Mail('utf-8');
$mail->setFrom($senderEmail);
$mail->addTo($receiverEmail);
$mail->setSubject($subject);
$mail->setBodyHtml($text);

$content = file_get_contents($attachmentAbsolutePath);

$attachment = new \Zend_Mime_Part($content);
$attachment->type = 'text/xml'; // attachment's mime type
$attachment->disposition = \Zend_Mime::DISPOSITION_ATTACHMENT;
$attachment->encoding = \Zend_Mime::ENCODING_BASE64;
$attachment->filename = $filename;
$mail->addAttachment($attachment);
$mail->send();

trước khi cho -1, bạn nên sử dụng textarea bình luận này, sau đó mọi người có thể hiểu điều gì là sai, thx
LucScu

$ Transport-> getMessage () -> setBody ($ bodyPart);
imtiazau

nhận được lỗi Uncaught này: Gọi tới phương thức không xác định Magento \\ Framework \\ Mail \\ EmailMessage :: setBody ()
imtiazau

Những bình luận này không liên quan đến câu trả lời
LucScu

tôi nhận được lỗi này trong magento 2.3.3
imtiazau

0

Tương thích Magento 2.3.x:

Đây là câu trả lời của tôi cho Magento 2.3 vì đây là câu hỏi hàng đầu trên google và dường như có rất nhiều người trong các bình luận đang tìm kiếm.

Dường như có rất nhiều mong muốn trong các bài đăng khác về việc ghi đè TransportBuilderlớp mặc định thông qua etc/di.xml, tuy nhiên mô-đun tôi đang làm việc quá nhỏ đến mức tôi không muốn nó chịu trách nhiệm về mặc định TransportBuildernên tôi đã xây dựng lớp Trình trợ giúp (nên có thể là một mô hình dựa trên cách kết hợp nó với mẫu email được khai báo - nhưng tôi lạc đề).

Các TransportBuilderkhông có quyền truy cập công cộng đến TransportInterface, nhưng thay vì tạo ra một bản sao mỗi lần và sau đó reset builder. Tôi thấy việc xây dựng TransportInterfacecá thể của mình dễ dàng hơn và sau đó đính kèm Partcác đối tượng đính kèm của tôi vào thông điệp của phương tiện giao thông. Nếu bạn thấy cần phải ghi đè mặc định TransportBuilderthông qua tùy chọn tiêm phụ thuộc, hãy cẩn thận về việc cập nhật các phương thức công khai. Hãy nhớ thực hành O khi giữ mã của bạn RẮN !

namespace Vendor\Module\Helper;

use Magento\Framework\App\Area;
use Magento\Framework\App\Helper\AbstractHelper;
use Magento\Framework\App\Helper\Context;
use Magento\Framework\DataObject;
use Magento\Framework\Filesystem\Io\File;
use Magento\Framework\Mail\Template\TransportBuilder;
use Magento\Framework\Mail\TransportInterface;
use Magento\Store\Model\StoreManagerInterface;
use Zend_Mime;
use Zend\Mime\Part;

/**
 * This was initially built out to send a single email. Abstract this as you 
 * wish.
 *
 * @package Vendor\Module\Helper
 */
class Mail extends AbstractHelper
{
    /**
     * @var Context
     */
    protected $context;

    /**
     * @var TransportBuilder
     */
    protected $transportBuilder;

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

    /**
     * @var Config
     */
    protected $config;

    /**
     * Mail constructor.
     *
     * @param Context $context
     * @param TransportBuilder $transportBuilder
     * @param StoreManagerInterface $storeManager
     * @param Config $config
     * @param File $file
     */
    public function __construct(
        Context $context,
        TransportBuilder $transportBuilder,
        StoreManagerInterface $storeManager,
        Config $config,
        File $file
    ) {
        parent::__construct($context);
        $this->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 \Magento\Framework\Mail\TransportInterface $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()->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;
    }
}

Tôi không thể làm cho nó hoạt động chính xác được : /
hallleron

1
@hallleron Thật kỳ lạ, điều này khác với những gì tôi nhận được, nhưng có vẻ như bạn đã đúng. Các MessageInterface::getBodyphương pháp chữ ký cho thấy một loại chuỗi trở lại. Bạn có thể phải đào xung quanh trong TransportInterfaceđối tượng của mình , nhưng tôi có thể nói với bạn rằng addPartphương thức này tồn tại trên một Zend\Mime\Messageđối tượng. Vì magento có khả năng mở rộng lớp học đó cho lớp học của riêng họ Message, tôi nghĩ sẽ rất thông minh khi thử$transport->getMessage()->addpart($part);
domdambrogia
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.