4

https://extait.com/blog/how-to-send-email-with-attachment-in-magento-2-3/

I have tried above link, and below is the code: Now I am receiving emails without attachment. Full code as below: Custom\Module\Mail\Template\TransportBuilder.php


<?php
namespace Custom\Module\Mail\Template;

class TransportBuilder extends \Magento\Framework\Mail\Template\TransportBuilder
{
   /**
     * @var \Extait\Attachment\Mail\Message
     */
    protected $message;
    /**
     * Add an attachment to the message.
     *
     * @param string $content
     * @param string $fileName
     * @param string $fileType
     * @return $this
     */
    public function addAttachment($fileName, $fileType)
    {
        $this->message->setBodyAttachment($fileName, $fileType);
        return $this;
    }
    /**
     * After all parts are set, add them to message body.
     *
     * @return $this
     * @throws \Magento\Framework\Exception\LocalizedException
     */
    protected function prepareMessage()
    {
        parent::prepareMessage();
        $this->message->setPartsToBody();
        return $this;
    }
}



File: Vendor\Module\Mail\Message.php

namespace Vendor\Module\Mail;
use Zend\Mime\Mime;
use Zend\Mime\PartFactory;
use Zend\Mail\MessageFactory as MailMessageFactory;
use Zend\Mime\MessageFactory as MimeMessageFactory;
class Message implements \Magento\Framework\Mail\MailMessageInterface
{
    /**
     * @var \Zend\Mime\PartFactory
     */
    protected $partFactory;
    /**
     * @var \Zend\Mime\MessageFactory
     */
    protected $mimeMessageFactory;
    /**
     * @var \Zend\Mail\Message
     */
    private $zendMessage;
    /**
     * @var \Zend\Mime\Part[]
     */
    protected $parts = [];
    /**
     * Message constructor.
     *
     * @param \Zend\Mime\PartFactory $partFactory
     * @param \Zend\Mime\MessageFactory $mimeMessageFactory
     * @param string $charset
     */
    public function __construct(PartFactory $partFactory, MimeMessageFactory $mimeMessageFactory, $charset = 'utf-8')
    {
        $this->partFactory = $partFactory;
        $this->mimeMessageFactory = $mimeMessageFactory;
        $this->zendMessage = MailMessageFactory::getInstance();
        $this->zendMessage->setEncoding($charset);
    }
    /**
     * Add the HTML mime part to the message.
     *
     * @param string $content
     * @return $this
     */
    public function setBodyText($content)
    {
        $textPart = $this->partFactory->create();
        $textPart->setContent($content)
            ->setType(Mime::TYPE_TEXT)
            ->setCharset($this->zendMessage->getEncoding());
        $this->parts[] = $textPart;
        return $this;
    }


   /**
     * Add the text mime part to the message.
     *
     * @param string $content
     * @return $this
     */
    public function setBodyHtml($content)
    {
        $htmlPart = $this->partFactory->create();
        $htmlPart->setContent($content)
            ->setType(Mime::TYPE_HTML)
            ->setCharset($this->zendMessage->getEncoding());
        $this->parts[] = $htmlPart;
        return $this;
    }

    /**
     * Add the attachment mime part to the message.
     *
     * @param string $content
     * @param string $fileName
     * @param string $fileType
     * @return $this
     */


    public function setBodyAttachment($file, $name)
    {
        $attachmentPart = $this->partFactory->create();
        $attachmentPart->setType($file)
            ->setFileName($name);
        $this->parts[] = $attachmentPart;

        return $this;
    }


    /**
     * Set parts to Zend message body.
     *
     * @return $this
     */
    public function setPartsToBody()
    {
        $mimeMessage = $this->mimeMessageFactory->create();
        $mimeMessage->setParts($this->parts);
        $this->zendMessage->setBody($mimeMessage);
        return $this;
    }


    /**
     * {@inheritdoc}
     */
    public function setBody($body)
    {
        return $this;
    }
    /**
     * {@inheritdoc}
     */
    public function setSubject($subject)
    {
        $this->zendMessage->setSubject($subject);
        return $this;
    }
    /**
     * {@inheritdoc}
     */
    public function getSubject()
    {
        return $this->zendMessage->getSubject();
    }
    /**
     * {@inheritdoc}
     */
    public function getBody()
    {
        return $this->zendMessage->getBody();
    }
    /**
     * {@inheritdoc}
     */
    public function setFrom($fromAddress)
    {
        $this->setFromAddress($fromAddress, null);
        return $this;
    }
    /**
     * {@inheritdoc}
     */
    public function setFromAddress($fromAddress, $fromName = null)
    {
        $this->zendMessage->setFrom($fromAddress, $fromName);
        return $this;
    }
    /**
     * {@inheritdoc}
     */
    public function addTo($toAddress)
    {
        $this->zendMessage->addTo($toAddress);
        return $this;
    }
    /**
     * {@inheritdoc}
     */
    public function addCc($ccAddress)
    {
        $this->zendMessage->addCc($ccAddress);
        return $this;
    }
    /**
     * {@inheritdoc}
     */
    public function addBcc($bccAddress)
    {
        $this->zendMessage->addBcc($bccAddress);
        return $this;
    }
    /**
     * {@inheritdoc}
     */
    public function setReplyTo($replyToAddress)
    {
        $this->zendMessage->setReplyTo($replyToAddress);
        return $this;
    }
    /**
     * {@inheritdoc}
     */
    public function getRawMessage()
    {
        return $this->zendMessage->toString();
    }
    /**
     * @inheritDoc
     */
    public function setMessageType($type)
    {
        return $this;
    }
==========================================
File: Vendor\Module\Controller\Index\Sendemail.php 

$yourFolderName = 'careers-resumes/';

        // "my_custom_file" is the HTML input file name
        $yourInputFileName = 'careers-resume';

        try{
            $postValues = $this->getRequest()->getPost();

            $file = $this->getRequest()->getFiles($yourInputFileName);
            $fileName = ($file && array_key_exists('name', $file)) ? $file['name'] : null;

            if ($file && $fileName) {

                $target = $this->mediaDirectory->getAbsolutePath($yourFolderName);        

                /** @var $uploader \Magento\MediaStorage\Model\File\Uploader */
                $uploader = $this->fileUploader->create(['fileId' => $yourInputFileName]);

                // set allowed file extensions
                $uploader->setAllowedExtensions(['doc', 'docx', 'pdf']);

                // allow folder creation
                $uploader->setAllowCreateFolders(true);

                // rename file name if already exists 
                $uploader->setAllowRenameFiles(true);


                $result = $uploader->save($target);

                $filePath = $result['path'].$result['file'];
                $fileName = $result['name'];


                if ($result['file']) {


                    $storeScope = \Magento\Store\Model\ScopeInterface::SCOPE_STORE;

                     $templateOptions = [
                      'area' => \Magento\Framework\App\Area::AREA_FRONTEND,
                      'store' => 1
                    ];

                    $store = $this->_storeManager->getStore()->getId();
                    $transport = $this->_transportBuilder->setTemplateIdentifier(5)
                    ->setTemplateOptions(['area' => 'frontend', 'store' => $store])
                    ->setTemplateVars(
                        [
                            'store' => $this->_storeManager->getStore(),
                        ]
                    )
                    ->setFrom('general')
                    // you can config general email address in Store -> Configuration -> General -> Store Email Addresses
                    ->addTo('[email protected]', 'Customer Name')
                    ->addAttachment($filePath, $fileName)
                    ->getTransport();
                    $transport->sendMessage();



                    $this->_redirect('careers');
                    $this->messageManager->addSuccess(__('File has been successfully uploaded & mail sent.')); 
                }

            }
        } catch (\Exception $e) {
            $this->messageManager->addError($e->getMessage());
        }

I am receiving email without attachment.

3
  • can you share full both files code? Commented Jun 24, 2019 at 6:17
  • I have edited my question with full code. Commented Jun 24, 2019 at 7:55
  • I have already given answer below. Its working. Commented Aug 2, 2019 at 7:06

3 Answers 3

3

Your overwrite looks good. Problem is where you send email. You maybe missing following part:

$transport->setTemplateVars([])

OR

$template->setVars([]);

[Update]

Replace addAttachment method by following code:

/**
 * @param $body
 * @param $mimeType
 * @param $disposition
 * @param $encoding
 * @param null $filename
 * @return $this
 */
public function addAttachment(
    $body,
    $mimeType    = \Zend_Mime::TYPE_OCTETSTREAM,
    $disposition = \Zend_Mime::DISPOSITION_ATTACHMENT,
    $encoding    = \Zend_Mime::ENCODING_BASE64,
    $filename    = null
) {

    if($disposition == null) {
        $disposition = \Zend_Mime::DISPOSITION_ATTACHMENT;
    }

    if($encoding == null) {
        $encoding = \Zend_Mime::ENCODING_BASE64;
    }

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

And call following way:

$this->transportBuilder->addAttachment(file_get_contents($_FILES['attach']['tmp_name']), $_FILES['attach']['type'], null, null, $_FILES['attach']['name']);
14
  • I have edited my question with full code. Commented Jun 24, 2019 at 8:48
  • check updated answer
    – Sohel Rana
    Commented Jun 24, 2019 at 9:10
  • Hello @Sohel Rana. is that possible to multiple files import in current code? how? can you please share? Commented Jun 24, 2019 at 9:23
  • multiple attachments?
    – Sohel Rana
    Commented Jun 24, 2019 at 9:27
  • Yes multiple attachments Commented Jun 24, 2019 at 9:36
3

Here is my working code as below:

Controller:

Here we've to pass parameter as below line:

$filePath = uploaded attachment file path.

->addAttachment(file_get_contents($filePath), $fileName, $fileType)

public function execute()
    {

        $yourFolderName = 'careers-resumes/';

        // "my_custom_file" is the HTML input file name
        $yourInputFileName = 'careers-resume';

        try{
            $postValues = $this->getRequest()->getPost();
            $file = $this->getRequest()->getFiles($yourInputFileName);
            $fileName = ($file && array_key_exists('name', $file)) ? $file['name'] : null;

            if ($file && $fileName) {
                $target = $this->mediaDirectory->getAbsolutePath($yourFolderName);        

                /** @var $uploader \Magento\MediaStorage\Model\File\Uploader */
                $uploader = $this->fileUploader->create(['fileId' => $yourInputFileName]);

                // set allowed file extensions
                $uploader->setAllowedExtensions(['doc', 'docx', 'pdf']);

                // allow folder creation
                $uploader->setAllowCreateFolders(true);

                // rename file name if already exists 
                $uploader->setAllowRenameFiles(true);

                $fileName = $fileName;
                $fileExt = strtolower(substr(strrchr($fileName, ".") ,1));
                $fileNamewoe = rtrim($fileName, $fileExt);
                $fileName = $fileNamewoe . date("m-d-Y") . '-' .date("h:i:sa") . '.' . $fileExt;
                $fileType = $file['type'];

                $result = $uploader->save($target,$fileName);

                $filePath = $result['path'].$result['file'];

                if ($result['file']) {
                    $applicantName = $postValues['name'];
                    $applicantEmail = $postValues['email'];
                    $applicantTelephone = $postValues['telephone_number'];
                    $applicantPositionAppliedFor = $postValues['position'];

                    $sender = [
                        'name' => $applicantName,
                        'email' => $applicantEmail
                    ];

                    $templateVars = [
                            'store' => $this->_storeManager->getStore(),
                            'applicant_name' => $applicantName,
                            'applicant_email' => $applicantEmail,
                            'applicant_phone' => $applicantTelephone,
                            'applicant_position' => $applicantPositionAppliedFor
                        ];

                    $templateOptions = [
                      'area' => \Magento\Framework\App\Area::AREA_FRONTEND,
                      'store' => $this->_storeManager->getStore()->getId()
                    ];

                    $storeScope = \Magento\Store\Model\ScopeInterface::SCOPE_STORE;
                    $notifyEmail = $this->scopeConfig->getValue(self::XML_NOTIFY_VALUE, $storeScope);

                    $transport = $this->_transportBuilder->setTemplateIdentifier('careerspositions_email_template')
                    ->setTemplateOptions($templateOptions)
                    ->setTemplateVars($templateVars)
                    ->setFrom($sender)
                    // you can config general email address in Store -> Configuration -> General -> Store Email Addresses
                    ->addTo($notifyEmail, 'Receiver Name')

                    ->addAttachment(file_get_contents($filePath), $fileName, $fileType)
                    ->getTransport();

                    try {
                        $transport->sendMessage();
                        $this->getCatalogSession()->setMySession($applicantEmail);

                        $this->_redirect('careers/index/success'); 
                        return;
                    }
                    catch(\Exception $e) {
                        $this->messageManager->addError('Unable to send email. Please check that the details you have entered are correct.');
                        $this->_redirect('careers');
                    }
                }
            }
        } catch (\Exception $e) {
            $this->messageManager->addError('Something went wrong. Please make sure the details you have entered are correct.');
        }

        $this->_redirect('careers');
} 

In Vendor\Module\Mail\Message.php as below same as this github reference link:

https://github.com/extait-com/email-attachment/blob/master/Mail/Message.php Here we've to check setBodyAttachment() function that should be defined in TransportBuilder.php

<?php
/**
 * NOTICE OF LICENSE
 *
 * This source file is subject to the commercial license
 * that is bundled with this package in the file LICENSE.txt.
 *
 * @category Extait
 * @package Extait_Attachment
 * @copyright Copyright (c) 2016-2018 Extait, Inc. (http://www.extait.com)
 */
namespace Vendor\Module\Mail;
use Zend\Mime\Mime;
use Zend\Mime\PartFactory;
use Zend\Mail\MessageFactory as MailMessageFactory;
use Zend\Mime\MessageFactory as MimeMessageFactory;
class Message implements \Magento\Framework\Mail\MailMessageInterface
{
    /**
     * @var \Zend\Mime\PartFactory
     */
    protected $partFactory;
    /**
     * @var \Zend\Mime\MessageFactory
     */
    protected $mimeMessageFactory;
    /**
     * @var \Zend\Mail\Message
     */
    private $zendMessage;
    /**
     * @var \Zend\Mime\Part[]
     */
    protected $parts = [];
    /**
     * Message constructor.
     *
     * @param \Zend\Mime\PartFactory $partFactory
     * @param \Zend\Mime\MessageFactory $mimeMessageFactory
     * @param string $charset
     */
    public function __construct(PartFactory $partFactory, MimeMessageFactory $mimeMessageFactory, $charset = 'utf-8')
    {
        $this->partFactory = $partFactory;
        $this->mimeMessageFactory = $mimeMessageFactory;
        $this->zendMessage = MailMessageFactory::getInstance();
        $this->zendMessage->setEncoding($charset);
    }
    /**
     * Add the HTML mime part to the message.
     *
     * @param string $content
     * @return $this
     */
    public function setBodyText($content)
    {
        $textPart = $this->partFactory->create();
        $textPart->setContent($content)
            ->setType(Mime::TYPE_TEXT)
            ->setCharset($this->zendMessage->getEncoding());
        $this->parts[] = $textPart;
        return $this;
    }


   /**
     * Add the text mime part to the message.
     *
     * @param string $content
     * @return $this
     */
    public function setBodyHtml($content)
    {
        $htmlPart = $this->partFactory->create();
        $htmlPart->setContent($content)
            ->setType(Mime::TYPE_HTML)
            ->setCharset($this->zendMessage->getEncoding());
        $this->parts[] = $htmlPart;
        return $this;
    }

    /**
     * Add the attachment mime part to the message.
     *
     * @param string $content
     * @param string $fileName
     * @param string $fileType
     * @return $this
     */


    public function setBodyAttachment($content, $fileName, $fileType)
    {
        $attachmentPart = $this->partFactory->create();
        $attachmentPart->setContent($content)
            ->setFileName($fileName)
            ->setType($fileType)
            ->setEncoding(Mime::ENCODING_BASE64) /*Add this*/
            ->setDisposition(Mime::DISPOSITION_ATTACHMENT);

        $this->parts[] = $attachmentPart;

        return $this;
    }


    /**
     * Set parts to Zend message body.
     *
     * @return $this
     */
    public function setPartsToBody()
    {
        $mimeMessage = $this->mimeMessageFactory->create();
        $mimeMessage->setParts($this->parts);
        $this->zendMessage->setBody($mimeMessage);
        return $this;
    }


    /**
     * {@inheritdoc}
     */
    public function setBody($body)
    {
        return $this;
    }
    /**
     * {@inheritdoc}
     */
    public function setSubject($subject)
    {
        $this->zendMessage->setSubject($subject);
        return $this;
    }
    /**
     * {@inheritdoc}
     */
    public function getSubject()
    {
        return $this->zendMessage->getSubject();
    }
    /**
     * {@inheritdoc}
     */
    public function getBody()
    {
        return $this->zendMessage->getBody();
    }
    /**
     * {@inheritdoc}
     */
    public function setFrom($fromAddress)
    {
        $this->setFromAddress($fromAddress, null);
        return $this;
    }
    /**
     * {@inheritdoc}
     */
    public function setFromAddress($fromAddress, $fromName = null)
    {
        $this->zendMessage->setFrom($fromAddress, $fromName);
        return $this;
    }
    /**
     * {@inheritdoc}
     */
    public function addTo($toAddress)
    {
        $this->zendMessage->addTo($toAddress);
        return $this;
    }
    /**
     * {@inheritdoc}
     */
    public function addCc($ccAddress)
    {
        $this->zendMessage->addCc($ccAddress);
        return $this;
    }
    /**
     * {@inheritdoc}
     */
    public function addBcc($bccAddress)
    {
        $this->zendMessage->addBcc($bccAddress);
        return $this;
    }
    /**
     * {@inheritdoc}
     */
    public function setReplyTo($replyToAddress)
    {
        $this->zendMessage->setReplyTo($replyToAddress);
        return $this;
    }
    /**
     * {@inheritdoc}
     */
    public function getRawMessage()
    {
        return $this->zendMessage->toString();
    }
    /**
     * @inheritDoc
     */
    public function setMessageType($type)
    {
        return $this;
    }
}

File: Vendor\Module\Mail\Template\TransportBuilder.php

<?php
namespace vendor\Module\Mail\Template;

class TransportBuilder extends \Magento\Framework\Mail\Template\TransportBuilder
{
    /**
     * @var \Extait\Attachment\Mail\Message
     */
    protected $message;
    /**
     * Add an attachment to the message.
     *
     * @param string $content
     * @param string $fileName
     * @param string $fileType
     * @return $this
     */
    public function addAttachment($content, $fileName, $fileType)
    {
        $this->message->setBodyAttachment($content, $fileName, $fileType);
        return $this;
    }
    /**
     * After all parts are set, add them to message body.
     *
     * @return $this
     * @throws \Magento\Framework\Exception\LocalizedException
     */
    protected function prepareMessage()
    {
        parent::prepareMessage();
        $this->message->setPartsToBody();
        return $this;
    }

}
1
  • 2
    doesn't work after update to 2.3.3 ;/ Commented Oct 16, 2019 at 7:37
1

Override \Magento\Framework\Mail\Template\TransportBuilder in 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="TM\ShipmentEmail\Model\Mail\Template\TransportBuilder" />
</config>

Define this constant if you need in overrides file and add following data

const MIME_TYPES = [
        'png' => 'image/png',
        'jpg' => 'image/jpg'
    ];
    
  //check file type  
protected function prepareMessage()
{
$snapshotFileTypes = self::MIME_TYPES[ (string) substr($snapshot, strrpos($snapshot, '.') + 1); ];

 //call for attachment in custom function    
        $this->addAttachment(file_get_contents($fullSnapshotPath), $endSnap, $snapshotFileType );
}
       // finally add attachment in this funtion

        public function addAttachment(?string $content, ?string $fileName, ?string $fileType)
        {
            $attachmentPart = $this->partFactory->create();
            $attachmentPart->setContent($content)
                ->setType($fileType)
                ->setFileName($fileName)
                ->setDisposition(Mime::DISPOSITION_ATTACHMENT)
                ->setEncoding(Mime::ENCODING_BASE64);
            $this->attachments[] = $attachmentPart;
    
            return $this;
        }

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.