Magento 2 – Email Template Not Defined When Sending Custom Email

emailemail-templatesmagento2send mail

I created a module to send a custom email, but when i send the email i always got an error like this:

Email template '' is not defined.

app/code/Blob/Withdrawal/etc/adminhtml/system.xml

<?xml version="1.0" ?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Config:etc/system_file.xsd">
    <system>
        <section id="my_mobile_app">
            <tab>blob</tab>
            <resource>Blob_Withdrawal::config_blob_withdrawal</resource>
            <group id="withdrawal" showInDefault="1" showInStore="1" showInWebsite="1" sortOrder="10" translate="label">
                <label>Withdrawal</label>
                <field id="request_mail" translate="label comment" type="select" sortOrder="1" showInDefault="1" showInWebsite="1" showInStore="1">
            <label>Request E-mail Template</label>
            <comment>Email template chosen based on theme fallback when "Default" option is selected.</comment>
            <source_model>Magento\Config\Model\Config\Source\Email\Template</source_model>
        </field>
                <field id="approve_mail" translate="label comment" type="select" sortOrder="2" showInDefault="1" showInWebsite="1" showInStore="1">
            <label>Approve E-mail Template</label>
            <comment>Email template chosen based on theme fallback when "Default" option is selected.</comment>
            <source_model>Magento\Config\Model\Config\Source\Email\Template</source_model>
        </field>
                <field id="reject_mail" translate="label comment" type="select" sortOrder="3" showInDefault="1" showInWebsite="1" showInStore="1">
            <label>Reject E-mail Template</label>
            <comment>Email template chosen based on theme fallback when "Default" option is selected.</comment>
            <source_model>Magento\Config\Model\Config\Source\Email\Template</source_model>
        </field>
            </group>
        </section>
    </system>
</config>

app/code/Blob/Withdrawal/etc/config.xml

<?xml version="1.0" ?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Store:etc/config.xsd">
    <default>
        <my_mobile_app>
            <withdrawal>
                <request_mail/>
                <approve_mail/>
                <reject_mail/>
            </withdrawal>
        </my_mobile_app>
    </default>
</config>

app/code/Blob/Withdrawal/etc/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="my_mobile_app_withdrawal_request_mail" label="Request E-mail Template" file="request_email.html" type="html" module="Blob_Withdrawal" area="adminhtml"/>
    <template id="my_mobile_app_withdrawal_approve_mail" label="Approve E-mail Template" file="approve_email.html" type="html" module="Blob_Withdrawal" area="adminhtml"/>
    <template id="my_mobile_app_withdrawal_reject_mail" label="Reject E-mail Template" file="reject_email.html" type="html" module="Blob_Withdrawal" area="adminhtml"/>
</config>

app/code/Blob/Withdrawal/Helper/Email.php

     const XML_PATH_EMAIL_TEMPLATE_FIELD_REQUEST  = 'my_mobile_app/withdrawal/request_mail';
     const XML_PATH_EMAIL_TEMPLATE_FIELD_APPROVE  = 'my_mobile_app/withdrawal/approve_mail';
     const XML_PATH_EMAIL_TEMPLATE_FIELD_REJECT  = 'my_mobile_app/withdrawal/reject_mail';

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

    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)
    {
        $template =  $this->_transportBuilder->setTemplateIdentifier($this->temp_id)
                ->setTemplateOptions(
                    [
                        'area' => \Magento\Framework\App\Area::AREA_ADMINHTML, /* 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;
    }

    public function sendMail($emailTemplateVariables,$senderInfo,$receiverInfo,$type)
    {
        if ($type == 'request') {
          $typeId = self::XML_PATH_EMAIL_TEMPLATE_FIELD_REQUEST;
        } elseif ($type == 'approve') {
          $typeId = self::XML_PATH_EMAIL_TEMPLATE_FIELD_APPROVE;
        } else{
          $typeId = self::XML_PATH_EMAIL_TEMPLATE_FIELD_REJECT;
        }
        $this->temp_id = $this->getTemplateId($typeId);
        $this->inlineTranslation->suspend();
        $this->generateTemplate($emailTemplateVariables,$senderInfo,$receiverInfo);
        $transport = $this->_transportBuilder->getTransport();
        $transport->sendMessage();
        $this->inlineTranslation->resume();
    }

app/code/Blob/Withdrawal/view/adminhtml/email/approve_email.html
app/code/Blob/Withdrawal/view/adminhtml/email/reject_email.html
app/code/Blob/Withdrawal/view/adminhtml/email/request_email.html

<!--@subject Credit Withdrawal @-->


<!--@styles
body,td { background:#FFFFFF; margin:0; padding:0; color:#2f2f2f; font:13px/1.35em Verdana, Arial, Helvetica, sans-serif; }
pre{ white-space: pre-wrap; white-space: -moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; word-wrap: break-word;}
@-->
{{template config_path="design/email/header_template"}}
<div style="font:13px/1.35em Verdana, Arial, Helvetica, sans-serif;">
    <table cellspacing="0" cellpadding="0" border="0" width="98%"
           style="margin-top:10px; font:11px/1.35em Verdana, Arial, Helvetica, sans-serif; margin-bottom:10px;">
        <tr>
            <td align="center" valign="top">
                <!-- [ middle starts here] -->
                <table cellspacing="0" cellpadding="0" border="0" width="660">
                    <tr>
                        <td valign="top">
                            <p>
                                hello
                            </p>
                        </td>
                    </tr>
                </table>
            </td>
        </tr>
    </table>
</div>

Best Answer

Fill your email template default config value in etc/config.xml file with email template id which has been defined in etc/email_templates.xml file. in your case:

app/code/Blob/Withdrawal/etc/email_templates.xml

<?xml version="1.0" ?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Store:etc/config.xsd">
    <default>
        <my_mobile_app>
            <withdrawal>
                <request_mail>my_mobile_app_withdrawal_request_mail</request_mail>
                <approve_mail>my_mobile_app_withdrawal_approve_mail</approve_mail>
                <reject_mail>my_mobile_app_withdrawal_reject_mail</reject_mail>
            </withdrawal>
        </my_mobile_app>
    </default>
</config>