How to Send Emails With Attachment in Magento2?

2

Hi Friends!

Sending email is the important functionality of every framework and in this today’s blog, we will learn about “How to send email programmatically with attachment” in your Magento 2 custom module.

Here, we will create one field in system file that will load all transactional emails which admin has created from admin.

Sometimes attachment is an optional part of the email system but to do that attachment functionality you need to call your controller while submitting the form so you can easily get the data from the request method.

Please check the below steps, we will take the example of a sample module.

Step 1: Add transactional email template field in “system.xml”

First open or create system.xml in following path: app/code/Yournamespace/Brand/etc/adminhtml and add the below code in specific group.

<field id="email_templates" translate="label comment" type="select" sortOrder="50" showInDefault="1" showInWebsite="1" showInStore="1">
	<label>Email Template</label>
	<source_model>Magento\Config\Model\Config\Source\Email\Template</source_model>
	<!-- This model return all transactional email template list of magento -->
</field>

Step 2: Declare custom email template using “email_templates.xml” file

Now create the email_templates.xml file in following path: app/code/Yournamespace/Brand/etc/

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 	xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Email:etc/email_templates.xsd">
	<template id="brand_date_options_email_templates" label="Email Template" file="email_templates.html" type="html" module="Yournamespace_Brand" area="frontend"/>
</config>

Step 3: Now create custom “email_templates.html” file

Now create “email_templates.html” file in following path: app/code/Yournamespace/Brand/view/frontend/email

Here we will use “email_templates.html” name for email template

<!--@subject {{trans "%subject1" subject1=$subject}} @-->
{{template config_path="design/email/header_template"}} 
<table>
	<tr class="email-intro">
		<td>
			<p class="greeting">Thankyou for contacting us!</p>            
		</td>
	</tr>
	<tr class="email-summary">
		<td>
			<h1>Contact Form</h1>            
		</td>
	</tr>
	<tr class="email-information">
		{{layout handle="data_of_formdetail" formdetail=$formdetail area="frontend"}}
	</tr>
</table>    
{{template config_path="design/email/footer_template"}} <!--footer of template-->

Step 4: Now, create the action controller to execute method

Now create “Index.php” file in following path: app/code/Yournamespace/Brand/Controller/Index

<?php
namespace Yournamespace\Brand\Controller\Index;
use Magento\Framework\Controller\ResultFactory; 
class Index extends \Magento\Framework\App\Action\Action
{
	protected $_cacheTypeList;
	protected $_cacheState;
	protected $_cacheFrontendPool;
	protected $resultPageFactory;
	protected $_messageManager;	
	private $_transportBuilder;

	public function __construct(
		\Magento\Framework\App\Action\Context $context,		
		\Magento\Framework\Message\ManagerInterface $messageManager,
		\Magento\Framework\Mail\Template\TransportBuilder $transportBuilder    
	) {		
		$this->_messageManager = $messageManager;
		$this->_transportBuilder = $transportBuilder;
		parent::__construct($context);            
	}

	public function execute()
	{
		$resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT);		    
		$data = $this->getRequest()->getPost();	
		$attachmentData = array();
		if($_FILES){
			$attachmentData = $_FILES['fields'];
		}		
		$emailTempVariables = array();		

		foreach($data['fields'] as $key => $value){
			$emailTempVariables[$key] = $value;
		}

		$emailTemplateVariables['formdetail'] = $emailTempVariables;
		$emailTemplateVariables['subject'] = $data['subject'];
		
		$receiverInfo = array(
			'name' => $data['fields']['name'],
			'email' => $data['sender']
		);    

		$senderInfo = array(
			'name' => 'Owner',
			'email' => $data['fromemail']
		);
		$this->_objectManager->get('Yournamespace\Brand\Helper\Email')->yourCustomMailSendMethod($emailTemplateVariables,$senderInfo,$receiverInfo,$attachmentData);		
	
		$this->_messageManager->addSuccess(__("Success Message"));
		$resultRedirect->setUrl($this->_redirect->getRefererUrl());
		return $resultRedirect;
	}
}

Step 5: Now, create “Email.php” helper file

Now create helper file “Email.php” in following path: app/code/Yournamespace/Brand/Helper

<?php
namespace Yournamespace\Brand\Helper;
class Email extends \Magento\Framework\App\Helper\AbstractHelper
{
	const XML_PATH_EMAIL_TEMPLATE_FIELD  = 'brand/date_options/email_templates';
	
	protected $_storeManager;
	protected $inlineTranslation;
	protected $_transportBuilder;
	protected $temp_id;
	protected $scopeConfig;
	
	public function __construct(
		\Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
		\Magento\Framework\App\Helper\Context $context,
		\Magento\Store\Model\StoreManagerInterface $storeManager,
		\Magento\Framework\Translate\Inline\StateInterface $inlineTranslation,
		\Yournamespace\Brand\Model\Mail\TransportBuilder $transportBuilder
	) {		
		parent::__construct($context);
		$this->_storeManager = $storeManager;
		$this->scopeConfig = $scopeConfig;
		$this->inlineTranslation = $inlineTranslation;
		$this->_transportBuilder = $transportBuilder; 
	}

	protected function getConfigValue($path, $storeId)
	{		    
		return $this->scopeConfig->getValue(
		$path,
		\Magento\Store\Model\ScopeInterface::SCOPE_STORE,
		$storeId
		);	
	}

	public function getStore()
	{
		return $this->_storeManager->getStore();
	}

	 public function getTemplateId($xmlPath)
	{
		return $this->getConfigValue($xmlPath, $this->getStore()->getStoreId());
	}
	
	public function generateTemplate($emailTemplateVariables,$senderInfo,$receiverInfo,$attachmentData)
	{		
		$template =  $this->_transportBuilder->setTemplateIdentifier($this->temp_id)
		->setTemplateOptions(
			[
				'area' => \Magento\Framework\App\Area::AREA_FRONTEND,
				'store' => $this->_storeManager->getStore()->getId(),
			]
		)
		->setTemplateVars($emailTemplateVariables)
		->setFrom($senderInfo)
		->addTo($receiverInfo['email'],$receiverInfo['name'])
		->addAttachment($attachmentData);
		return $this;        
	}
	
	public function yourCustomMailSendMethod($emailTemplateVariables,$senderInfo,$receiverInfo,$attachmentData)
	{		
		$this->temp_id = $this->getTemplateId(self::XML_PATH_EMAIL_TEMPLATE_FIELD);		
		$this->inlineTranslation->suspend();    
		$this->generateTemplate($emailTemplateVariables,$senderInfo,$receiverInfo,$attachmentData);
		$transport = $this->_transportBuilder->getTransport();
		$transport->sendMessage();        
		$this->inlineTranslation->resume();		
	}
}

Step 6: Now create file “TransportBuilder.php”

Create file TransportBuilder.php in following folder app/code/Yournamespace/Brand/Model/Mail

** I make this files for dynamic attachment it can be an image or pdf **

<?php
namespace Yournamespace\Brand\Model\Mail; 
use Zend_Mime;
class TransportBuilder extends \Magento\Framework\Mail\Template\TransportBuilder
{	
	public function addAttachment($attachmentData)
	{		
		foreach($attachmentData as $key => $value){
			if($key == 'name'){
				$name = array_values($value)[0];
			}
			
			if($key == 'type'){
				$type = array_values($value)[0];
			}
			
			if($key == 'tmp_name'){
				$tmp_name = array_values($value)[0];
			}			    
		}		
	
		$this->message->createAttachment(
			file_get_contents($tmp_name),
			$type,
			\Zend_Mime::DISPOSITION_ATTACHMENT,
			\Zend_Mime::ENCODING_BASE64,
			$name
		);
		return $this;
	}
}

Step 7: Create layout handle file for email template

Create data_of_formdetail.xml file in the following path of layout: app/code/Yournamespace/Brand/view/frontend/layout/

In Step 3, We have created a handle on the “email_templates.html” file, as you can see in the below code:

{{layout handle="data_of_formdetail" formdetail=$formdetail area="frontend"}}

*** In this handle we pass the $formdetail variable to phtml file **

<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd" label="Email Of Form Details" design_abstraction="custom">
	<body>
		<block class="Magento\Framework\View\Element\Template" name="formdetail" template="Yournamespace_Brand::email/formdetail.phtml" cacheable="false"> </block>
	</body>
</page>

Step 8: After creating XML file we need to create that template file.

Create the formdetail.phtml file in following path: app/code/Yournamespace/Brand/view/frontend/templates/email/

<?php $getFormdetail = $this->getFormdetail(); ?> 
<?php foreach($getFormdetail as $key => $value): ?>
<tr>
	<td colspan="3" style="text-align:center;font-size:16px;line-height:30px;font-family: 'Roboto', sans-serif;">
		<b><?php echo strtoupper(str_replace('_',' ',$key)); ?></b>
	</td>
	<td colspan="3" style="text-align:center;font-size:16px;line-height:30px;font-family: 'Roboto', sans-serif;">
		<?php if(is_array($value)): ?>
			<p><?php echo implode(',', $value); ?></p>
		<?php else: ?>
			<?php if($value): ?>
				<p><?php echo $value ?></p>
			<?php else: ?>
				<p> --- </p>
			<?php endif; ?>
		<?php endif; ?>
	</td>
</tr>
<?php endforeach; ?> 

Using all the above easy steps you can achieve the email with attachment functionality in your custom module.

Please read the blog carefully and let us know if you have any queries.

Thank you for reading this post.

About the author

I’m Magento Certified Developer having quite 5 years of commercial development expertise in Magento as well as in Shopify. I’ve worked primarily with the Magento and Shopify e-commerce platform, managing the complexities concerned in building e-commerce solutions tailored to a client’s specific desires.

Related Posts

Leave a Reply