Search code examples
magentomagento2email-attachmentsmagento2.4

How to send email with attachement in Magento 2.4


I am new to Magneto. and i searched and tried different solution online but they didn't work. I have an observer from which I generate CSV file whenever a customer place an order. I'm using <sales_order_place_after> to get it triggered. now i want to add the code to send the email with the generated CSV file in attachment to the customer. What's the way to do this in Magento 2.4. the solution i found online is not working. I want to add the code in the execute(\Magento\Framework\Event\Observer $observer) function of this file.


    public function __construct(
        \Magento\Framework\App\RequestInterface $request,
        \Magento\Sales\Model\Order $order,
        \Magento\Framework\App\Response\Http\FileFactory $fileFactory,
        Filesystem $filesystem,
        \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
        \Magento\Customer\Model\Customer $customer,
        \Magento\Store\Model\StoreManagerInterface $storemanager,

        \Magento\Checkout\Model\Session $checkoutSession,
        \Magento\Sales\Model\OrderFactory $orderFactory,
        \Magento\Framework\ObjectManager\ObjectManager $objectManager,

        
        \Psr\Log\LoggerInterface $logger,
        \Magento\Catalog\Model\ProductFactory $productFactory,

        \Magento\Catalog\Model\ProductRepository $productRepository

    ) { 
        $this->_scopeConfig = $scopeConfig;
        $this->_customer = $customer;
        $this->_storemanager = $storemanager;
        $this->_request = $request;
        $this->_order = $order;
        $this->_fileFactory = $fileFactory;
        $this->directory = $filesystem->getDirectoryWrite(DirectoryList::VAR_DIR);
        $this->_productRepository = $productRepository;

    }
 
    public function execute(\Magento\Framework\Event\Observer $observer) {
        
        
        
        $order = $observer->getEvent()->getOrder();
    

 
        $websiteID = $this->_storemanager->getStore()->getWebsiteId();

        
        $headers = array('Company Name', 'Contact Name', 'Contact Email', 'Contact Phone','Shipping Address' ,'SKU','QTY','Price','Total','Weight');

           
                
            
            $name = strtotime('now');
            $file = 'customorderexport/'.$name.'_detailed_orderexport.csv';
            $this->directory->create('customorderexport');
            $stream = $this->directory->openFile($file, 'w+');
            $stream->lock();
            $stream->writeCsv($headers);
            
            $orderdetail['Company Name'] = "";
            $orderdetail['Contact Name'] = $order->getCustomerName();
            $orderdetail['Contact Email'] = $order->getCustomerEmail();
            $orderdetail['Contact Phone'] = $order->getShippingAddress()->getTelephone();

            $streetadd = $order->getShippingAddress()->getStreet();
            
            $orderdetail['Shipping Address'] = $streetadd[0];



            $items = $order->getAllItems();
            foreach ($items as $item) {
            
                $orderdetail['SKU'] = $item->getSKU();              
                $orderdetail['QTY'] = $item->getQtyOrdered();
                $orderdetail['Price'] = $item->getPrice();
                $orderdetail['Total'] = $item->getRowTotalInclTax();
                $quantity = $item->getQtyOrdered();
                $orderdetail['Weight'] = $item->getWeight() * $quantity ;
                $stream->writeCsv($orderdetail);
            }

            $stream->unlock();
            $stream->close();

        }
    
}

Solution

  • You need to use Plugin for this -

    Note - Use you csv generation code before mail send to attach the file

    1. Create di.xml inside etc folder

      <?xml version="1.0"?>
       <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"      xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
            <type name="Magento\Sales\Model\Order\Email\Sender\OrderSender">
                       <plugin name="AttachEmail" type="Vendor\Module_Name\Plugin\Model\Email\Sender\OrderSender"/>
                   </type>
       <type name="Magento\Framework\Mail\TransportInterface">
               <plugin name="AttachEmailTransport" type="Vendor\Module_Name\Plugin\Model\Transport"/>
           </type>
       </config>
      
    2. Inside the OrderSender Model

    Important file to identify if order email

     <?php
        namespace Vendor\Module_Name\Plugin\Model\Email\Sender;
        use Magento\Framework\Registry;
        class OrderSender
        {
           
            public function __construct(
                Registry $registry
            ) {
                $this->registry = $registry;
            }
        
           
            public function beforeSend(
                $subject,
                $order
            ) {
                $this->registry->unregister('email_attachments_type');
                $this->registry->unregister('email_attachments_source');
                $this->registry->register('email_attachments_type', 'order');
                $this->registry->register('email_attachments_source', $order);
            }
        }
    ?>
    
    1. Vendor\Module_Name\Plugin\Model\Transport

    In this file -

    <?php
    
    namespace Vendor\Module_Name\Plugin\Model;
    
    use Magento\Framework\Mail\TransportInterface as Subject;
    use Magento\Framework\Registry;
    use Zend\Mime\Message;
    use Zend\Mime\Part;
    use Zend_Mime;
    use function GuzzleHttp\Psr7\mimetype_from_filename;
    use Magento\Framework\Filesystem;
    use Magento\Framework\App\Filesystem\DirectoryList;
    use Magento\Framework\ObjectManagerInterface;
    
    
    class Transport 
    {
        
        protected $_filterProvider;
        protected $_storeManager;
        protected $_blockFactory;
        
        public function __construct(
            Registry $registry,
            Filesystem $filesystem,
            ObjectManagerInterface $objectManager,
            \Magezon\Core\Helper\Data $coreHelper,
            \Magezon\EmailAttachments\Helper\Data $dataHelper,
            \Magento\Cms\Model\Template\FilterProvider $filterProvider,
            \Magento\Store\Model\StoreManagerInterface $storeManager
        ) {
            $this->objectManager = $objectManager;
            $this->registry = $registry;
            $this->mediaDirectory = $filesystem->getDirectoryWrite(DirectoryList::MEDIA);
            $this->coreHelper = $coreHelper;
            $this->dataHelper = $dataHelper;
            $this->_filterProvider = $filterProvider;
            $this->_storeManager = $storeManager;
        }
    
        public function beforeSendMessage(
            Subject $subject
        ) {
        
            $type = $this->registry->registry('mgz_email_attachments_type');
            $source = $this->registry->registry('mgz_email_attachments_source');
            
            if($source && $type == 'order'){
                
                       try {
                        //pass file name and it will get from media directory
                           $filename = '';
                           $this->prepareMessage(
                            $message,
                            file_get_contents($this->getAbsolutePathFile($filename)),
                            'test.csv',
                            mimetype_from_filename($this->getFileUrl($filename))
                        );
                       } catch (\Exception $e) {
                          
                           
                       }
                
                }
              
                
           }
       }
     
    
       public function prepareMessage($message, $content, $name, $type)
       {
        $this->setParts($message->getBody()->getParts());
        $this->createAttachment(
            $content,
            $type,
            Zend_Mime::DISPOSITION_ATTACHMENT,
            Zend_Mime::ENCODING_BASE64,
            $name
        );
        $parts = $this->getParts();
        $mimeMessage = new Message();
        $mimeMessage->setParts($parts);
        $message->setBody($mimeMessage);
    }
    
    public function createAttachment(
        $body,
        $mimeType,
        $disposition = Zend_Mime::DISPOSITION_ATTACHMENT,
        $encoding = Zend_Mime::ENCODING_BASE64,
        $filename = null
    ) {
        $mp = new Part($body);
        $mp->encoding = $encoding;
        $mp->type = $mimeType;
        $mp->disposition = $disposition;
        $mp->filename = $filename;
        $this->_addAttachment($mp);
        return $mp;
    }
    
        /**
         * Adds an existing attachment to the mail message
         *
         * @param Zend_Mime_Part $attachment
         * @return Zend_Mail Provides fluent interface
         */
        public function _addAttachment($attachment)
        {
            $this->addPart($attachment);
            return $this;
        }
    
        /**
         * @param Zend_Mime_Part $part
         */
        public function addPart($part)
        {
            $this->_parts[] = $part;
        }
    
        /**
         * @return array
         */
        public function getParts()
        {
            return $this->_parts;
        }
    
        /**
         * @param array $parts
         */
        public function setParts($parts)
        {
            $this->_parts = $parts;
            return $this;
        }
    
        /**
         * @return string
         */
        public function getAbsolutePathFile($fileName)
        {
            return $this->mediaDirectory->getAbsolutePath($fileName);
        }
    
        /**
         * @return string
         */
        public function getFileUrl($fileName)
        {
            return $this->coreHelper->getMediaUrl() . $fileName;
        }
    
        protected function generateLog($message){
            $writer = new \Zend_Log_Writer_Stream(BP . '/var/log/ETicket.log');
            $logger = new \Zend_Log();
            $logger->addWriter($writer);
            $logger->info($message);
        }
    
        protected function generateLogCreditMemo($message){
            $writer = new \Zend_Log_Writer_Stream(BP . '/var/log/CreditMemo.log');
            $logger = new \Zend_Log();
            $logger->addWriter($writer);
            $logger->info($message);
        }
    }
    

    Hope this will help