Here we learn how to send transactional emails programmatically in Magento 2 custom module.
Transactional emails in Magento 2 play a crucial role in keeping customers informed about important events and actions on the store.
Magento 2 provides a flexible and scalable email system that allows store owners and developers to manage transactional emails using predefined templates, custom email variables, and dynamic content.
1# First, we create a field in the configuration from where we can select which email template will use.
You can create a configuration field according to your section and group in app/code/NameSpace/ModuleName/etc/adminhtml/system.xml file as follows
<field id="your_email_template_field_id" translate="label comment" type="select" sortOrder="2" showInDefault="1" showInWebsite="1" showInStore="1">
<label>Label Of Your Field</label>
<source_model>Magento\Config\Model\Config\Source\Email\Template</source_model>
<!-- This model return all transactional email template list of magento -->
</field>
2# Now create an email template configuration file at app/code/NameSpace/ModuleName/etc location file name should be email_templates.xml
<?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="section_group_your_email_template_field_id" label="Label Of Your Template File" file="your_email_template.html" type="html" module="NameSpace_ModuleName" area="adminhtml"/>
</config>
<!-- here you define your email template and its template location path-->
3# Now create an email template file at app/code/NameSpace/ModuleName/view/adminhtml/email with the same name you gave in email_template.xml file .
Here we will use “your_email_template.html” for the email template
<!--@subject Subject Of your email @-->
<!--@vars {
"var this.getUrl($store, 'admin')":"Warehouse Account URL",
"var customer.email":"Customer Email",
"var customer.name":"Customer Name"
} @-->
{{template config_path="design/email/header_template"}} <!-- pathe of template header-->
<!-- here $myvar1 , $myvar2, $myvar3, $myvar4, $myvar5, $myvar6 are variables in which we
asssign values when we use this template for send mail-->
<!-- you can Modify content of template according to your requirement-->
<table>
<tr class="email-intro">
<td>
<p class="greeting">{{trans "%customer_name," customer_name=$myvar3}}</p>
<p>
{{trans "Your custom message."}}
{{trans 'Your custom message <a href="%account_url">logging into your account</a>.' account_url=$this.getUrl($store,'admin',[_nosid:1]) |raw}}
</p>
</td>
</tr>
<tr class="email-summary">
<td>
<h1>{{trans 'Your Order <span class="no-link">#%increment_id</span>' increment_id=$myvar1 |raw}}</h1>
<p>{{trans 'Placed on <span class="no-link">%created_at</span>' created_at=$myvar2 |raw}}</p>
</td>
</tr>
<tr class="email-information">
<td>
<table class="order-details">
<tr>
<td class="address-details">
<h3>{{trans "Billing Info"}}</h3>
<p>{{var myvar4|raw}}</p>
</td>
</tr>
</table>
<table class="email-items">
<thead>
<tr>
<th class="item-info">{{trans "Item"}}</th>
<th class="item-info">{{trans "Sku"}}</th>
</tr>
</thead>
<tbody>
{{var myvar8|raw}}
</tbody>
</table>
</td>
</tr>
</table>
{{template config_path="design/email/footer_template"}} <!--footer of template-->
4# Now the template is ready, and we will write code to send mail.
Write the send mail code in the action from where you want to send this mail.
/* Here we prepare data for our email */
/* Receiver Detail */
$receiverInfo = [
'name' => 'Reciver Name',
'email' => '[email protected]'
];
/* Sender Detail */
$senderInfo = [
'name' => 'Sender Name',
'email' => '[email protected]',
];
/* Assign values for your template variables */
$emailTemplateVariables = array();
$emailTempVariables['myvar1'] = $variablevalue1;
$emailTempVariables['myvar2'] = $variablevalue2;
...
...
...
/* We write send mail function in helper because if we want to
use same in other action then we can call it directly from helper */
/* call send mail method from helper or where you define it*/
$this->_objectManager->get('NameSpace\ModuleName\Helper\Email')->yourCustomMailSendMethod(
$emailTempVariables,
$senderInfo,
$receiverInfo
);
5# Helper file where we define our custom send mail function
<?php
namespace NameSpace\ModuleName\Helper;
/**
* Custom Module Email helper
*/
class Email extends \Magento\Framework\App\Helper\AbstractHelper
{
const XML_PATH_EMAIL_TEMPLATE_FIELD = 'section/group/your_email_template_field_id';
/* Here section and group refer to name of section and group where you create this field in configuration*/
/**
* @var \Magento\Framework\App\Config\ScopeConfigInterface
*/
protected $_scopeConfig;
/**
* Store manager
*
* @var \Magento\Store\Model\StoreManagerInterface
*/
protected $_storeManager;
/**
* @var \Magento\Framework\Translate\Inline\StateInterface
*/
protected $inlineTranslation;
/**
* @var \Magento\Framework\Mail\Template\TransportBuilder
*/
protected $_transportBuilder;
/**
* @var string
*/
protected $temp_id;
/**
* @param Magento\Framework\App\Helper\Context $context
* @param Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
* @param Magento\Store\Model\StoreManagerInterface $storeManager
* @param Magento\Framework\Translate\Inline\StateInterface $inlineTranslation
* @param Magento\Framework\Mail\Template\TransportBuilder $transportBuilder
*/
public function __construct(
\Magento\Framework\App\Helper\Context $context,
\Magento\Store\Model\StoreManagerInterface $storeManager,
\Magento\Framework\Translate\Inline\StateInterface $inlineTranslation,
\Magento\Framework\Mail\Template\TransportBuilder $transportBuilder
) {
$this->_scopeConfig = $context;
parent::__construct($context);
$this->_storeManager = $storeManager;
$this->inlineTranslation = $inlineTranslation;
$this->_transportBuilder = $transportBuilder;
}
/**
* Return store configuration value of your template field that which id you set for template
*
* @param string $path
* @param int $storeId
* @return mixed
*/
protected function getConfigValue($path, $storeId)
{
return $this->scopeConfig->getValue(
$path,
\Magento\Store\Model\ScopeInterface::SCOPE_STORE,
$storeId
);
}
/**
* Return store
*
* @return Store
*/
public function getStore()
{
return $this->_storeManager->getStore();
}
/**
* Return template id according to store
*
* @return mixed
*/
public function getTemplateId($xmlPath)
{
return $this->getConfigValue($xmlPath, $this->getStore()->getStoreId());
}
/**
* [generateTemplate description] with template file and tempaltes variables values
* @param Mixed $emailTemplateVariables
* @param Mixed $senderInfo
* @param Mixed $receiverInfo
* @return void
*/
public function generateTemplate($emailTemplateVariables,$senderInfo,$receiverInfo)
{
$template = $this->_transportBuilder->setTemplateIdentifier($this->temp_id)
->setTemplateOptions(
[
'area' => \Magento\Framework\App\Area::AREA_FRONTEND, /* here you can defile area and
store of template for which you prepare it */
'store' => $this->_storeManager->getStore()->getId(),
]
)
->setTemplateVars($emailTemplateVariables)
->setFrom($senderInfo)
->addTo($receiverInfo['email'],$receiverInfo['name']);
return $this;
}
/**
* [sendInvoicedOrderEmail description]
* @param Mixed $emailTemplateVariables
* @param Mixed $senderInfo
* @param Mixed $receiverInfo
* @return void
*/
/* your send mail method*/
public function yourCustomMailSendMethod($emailTemplateVariables,$senderInfo,$receiverInfo)
{
$this->temp_id = $this->getTemplateId(self::XML_PATH_EMAIL_TEMPLATE_FIELD);
$this->inlineTranslation->suspend();
$this->generateTemplate($emailTemplateVariables,$senderInfo,$receiverInfo);
$transport = $this->_transportBuilder->getTransport();
$transport->sendMessage();
$this->inlineTranslation->resume();
}
}
With this, you have successfully learn to send transactional emails programmatically in Magento 2.
For technical assistance, please get in touch with us via email at [email protected].
Discover powerful solutions to enhance your Magento 2 store by exploring our Magento 2 plugins page.
Bring your vision to life with custom-built solutions—hire skilled Magento 2 developers today.
Thanks 🙂

But you defined $senderInfo as an Array:
/* Sender Detail */
$senderInfo = [
‘name’ => ‘Sender Name’,
’email’ => ‘[email protected]’,
Shouldn’t that be ->sentFrom($senderInfo[’email’],$senderInfo[‘name’]) ?
If that’s not necessary, why not do the same thing here at line 114:
->addTo($receiverInfo)
instead of ->addTo($receiverInfo[’email’],$receiverInfo[‘name’]) ?