Want to add some text/content in order email which is dependent on order data.

For this I want to call a template file, where I can get the order data and based on that I want to perform my calculation.

How can I call this template in order email ?


3 Answers 3


You can achieve this from just a block calling from email and pass the order variable in that block and do you calculation like : in email template just use this to call block

{{block class="Magento\Framework\View\Element\Template" order=$order name="order_sms" template="[vendor]_[module]::[filename].phtml" area="frontend"}}

And in your [vendor]/[module]/[frontend]/[templates]/[filename].phtml

$order = $this->getData('order');

After this you can perform your calculation and write your html here.

  • In {{.. order=$order ..}} do we access/get the $order-variable from [filename].phtml ? Or do we set the $order-variable for [fielname].phtml ? Dec 24, 2016 at 16:42
  • report.DEBUG: NULL [] [], I can't get order details this way. Jul 31, 2020 at 20:41
  • 1
    @MagentoAaron, since Magento 2.3.4+ you can't get order data like this anymore unforunately. You will additionaly need to go to email_templates and for the desired email template put "1" in the field "is_legacy". Then this answer works, but this might change in v. 2.4+
    – Lez
    Aug 3, 2020 at 14:31
  • 1
    @MagentoAaron I'm not sure what RMA auth email is, so I can't help there. But if the template doesn't have order data in general, you would first have to bring that data to the template before you can use it in an inserted block. My suggestion would be to analyze how Magento core does this and go from there.
    – Lez
    Aug 4, 2020 at 7:55
  • 1
    As people mentioned above, since Magento 2.3.4 templates are in "strict mode" so you will not be able to pass the order object, BUT you can still pass scalar values, like the order_id !!! so, pass order_id=$order_id and then just instantiate the original \Magento\Sales\Model\Order class using the object manager in your phtml file and continue from there (tested in Magento 2.4).
    – Mitxel
    Jan 12, 2022 at 9:27

This was my method for getting product attributes into my email template. I utilize the productRepositoryInterface to pull custom attributes that we store as JSON strings.

Our business uses core charges (like when you buy a battery at an auto parts store). So we needed to display what the total core charge would be for items in the cart. We also needed to show Important notes that are stored in a particular section of a JSON string that we store in a custom product attribute.

I call the block and phtml file in my email template:

{{block class="[VENDOR]\[MODULE]\Block\CoresEmail" order=$order name="custom_attribute_stuff" template="[vendor]_[module]::emailcores.phtml" area="frontend"}}

And this in the emailcores.phtml file

$order = $this->getData('order')->getItems();

$items = [];
$corebank = 0;
$notes = [];

foreach ($order as $items){
    $items = $items->getData();

    $id = $items['product_id'];

    if ($id){
        $core = $block->getCoreTotal($id);
        array_push($notes, $block->getProductImportantNotes($id)) ;
        $corebank = $core + $corebank;

<table width="100%" style="padding-right: 10px;">
        <td style="padding: 10px;">
            <?php if($notes): ?>
                <p style="font-weight: bold;">Important Notes:</p>
               <?php foreach ($notes as $note): ?>
                   <?php foreach ($note as $detail): ?>
                        <li><?= $detail ?></li>
                   <?php endforeach; ?>
                <?php endforeach; ?>
            <?php endif; ?>
        <td style="padding: 10px;">
            <p style="text-align: right; font-weight: bold;">Core Deposit:     $<?= $corebank ?>.00</p>
            <p style="text-align: right;"><i>* Core deposit not reflected in order total.</i></p>

And then my CoresEmail.php block file contains this:


namespace [VENDOR]\[MODULE]\Block;

use Magento\Framework\View\Element\Template;
use Magento\Framework\View\Element\Template\Context;

class CoresEmail extends Template

    protected $productRepository;

     * Constructor
     * @param Context $context
     * @param array   $data
    public function __construct(
        Context $context,
        \Magento\Catalog\Api\ProductRepositoryInterface $productRepository,
        array $data = []
    ) {
        parent::__construct($context, $data);
        $this->_product = $productRepository;

    public function getCoreTotal($id)
        $coretotal = 0;

            $coredeposit = json_decode($this->_product->getById($id)->getEteCoreDeposit(), true);
            try {$core = $coredeposit;} catch (\Exception $ex) {$core = [];}
            if ($core){
                $coretotal = $coretotal + $core;

        return $coretotal;

    public function getProductImportantNotes($id)
        $note_array = [];
        $product = json_decode($this->_product->getById($id)->getPiesDescriptions(), true);
        try {$pies = $product;} catch (\Exception $ex) {$pies = [];}
        if ($pies){
            $note_array = str_getcsv($pies['EXT']);
            return $note_array;
        } else {
            return $note_array;

This produces the following result in a new order email: Screenshot of sucessful product attribute pulled into order email template

  • This is the only option that worked for on 2.3.5 Oct 3, 2022 at 23:25

A quick reference:

Take a look:


protected function prepareTemplate(Order $order)
        $transport = [
            'order' => $order,
            'billing' => $order->getBillingAddress(),
            'payment_html' => $this->getPaymentHtml($order),
            'store' => $order->getStore(),
            'formattedShippingAddress' => $this->getFormattedShippingAddress($order),
            'formattedBillingAddress' => $this->getFormattedBillingAddress($order),
        $transport = new \Magento\Framework\DataObject($transport);

            ['sender' => $this, 'transport' => $transport]



As we can see, Magento passes some dynamic transport data to the template email.

We can get the email customer note var order.getEmailCustomerNote() or var order.getShippingDescription().

<!--@subject {{trans "Your %store_name order confirmation" store_name=$store.getFrontendName()}} @-->
<!--@vars {
"var formattedBillingAddress|raw":"Billing Address",
"var order.getEmailCustomerNote()":"Email Order Note",
"var order.increment_id":"Order Id",
"layout handle=\"sales_email_order_items\" order=$order area=\"frontend\"":"Order Items Grid",
"var payment_html|raw":"Payment Details",
"var formattedShippingAddress|raw":"Shipping Address",
"var order.getShippingDescription()":"Shipping Description"
"var shipping_msg":"Shipping message"
} @-->
{{layout handle="sales_email_order_items" order=$order area="frontend"}}

The layout handle will load the layout vendor/magento/module-sales/view/frontend/layout/sales_email_order_items.xml. So, we can override the layout and template of order email items or define our own layouts and templates.

For customization purpose, Magento gives us some Observer events. We can use these events to add more data to our template.


We should see more in vendor/magento/module-sales/Model/Order/Email

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.