Stack Exchange
access custom customer attribute in email template
I have created a custom attribute for customers.
In the next step I want to access it in email templates. For example in the password forgotten template.
The variable "customer" contains the following information:
            ...
            [email] => doe@example.com
            [firstname] => John
            [lastname] => Doe
            [prefix] => Mr.
            [gender] => 0
            [store_id] => 1
            [website_id] => 1
            [addresses] => Array
                (
                )

            [disable_auto_group_change] => 0
            [custom_attributes] => Array
                (
                    [0] => Array
                        (
                            [attribute_code] => my_custom_attribute
                            [value] => 1234
                        )

                )

            [name] => John Doe
        )

The only way that works is to use {{var customer.custom_attributes.0.value}}. But this doesn't seem to be a reasonable way, because the array key "0" is not reliably the one of my_custom_attribute.
How can I access my_custom_attribute reliable?
side note:
Creating a plugin for the EmailNotification::getFullCustomerData() method doesn't work either, because this method is private.

Did you find a solution for it? I have found a way for it.

To achieve this we need to pass dynamic data through handle.First this is my data which i got in "custom_attributes" - https://prnt.sc/10cvmir
Please follow below steps.Please create any named layout file in any of your module , here i have created "custom_attribute_email.xml"

Step 1: Please create file "custom_attribute_email.xml" under path
PackageName/Vendor/view/frontend/layout

<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd" label="Email Product List" design_abstraction="custom">
    <body>
        <block class="Magento\Framework\View\Element\Template" name="additional.customer.info" template="PackageName_Vendore::customer/email.phtml"/>
    </body>
</page>


Step 2: Please create email.phtml file under path
PackageName/Vendor/view/frontend/templates/customer

<?php $customer = $block->getCustomer(); ?>
<?php foreach ($customer['custom_attributes'] as $key => $data): ?>
    <p><strong><?php echo $data['attribute_code']; ?></strong>:<span><?php echo $data['value']; ?></span></p>
<?php endforeach; ?>

Now please open any of your email template , here i have taken forgot password email template. Then in your email template add the below code like this - https://prnt.sc/10cvqqh
{{layout handle="custom_attribute_email" customer=$customer area="frontend"}}
Note : Your template variable customer should be object
Output will be :- https://prnt.sc/10cvg97
This code will perfectly work for you. Please change code in phtml file according to your need. Please check and let me know on this.
Thanks
Cheers!

Does this work with Version 2.4.2? $block->getCustomer() returns always null. :(
[Trying to access array offset on value of type null]

Yes , it will work.Your template variable customer object should be passed like this {{layout handle="custom_attribute_email" customer=$customer area="frontend"}}

Please follow all steps to make it work. I have practically checked after that i have posted here.

Got it: It only works with template files. If I set up a template via Backend, it won't work. Can you confirm this?

Yes , it won't work. I have shown you just for front end according to your requirement.

My answer will satisfy your requirement.

Can you please approve and upvote this?

getCustomer(); ?> not working please any suggestion.@ZealousWeb
Which magento version you are working ?

Have you added like - https://prnt.sc/15lshsd ?

Yes it doesn't work for me as well, always getting null $customer = $block->getCustomer();

This is a reasonably well answer, but not as comprehensive as I want it to be.
The custom attributes are only accessable with template files, not with templates that are user defined
I created a plugin for Magento\Framework\Reflection\CustomAttributesProcessor which isn't the perfect way I guess, but much more versatile. It replaces the array_keys with the corresponding attribute_code, so you can access it via {{var customer.custom_attributes.my_custom_attribute.value}}
As far as I can tell, it doesn't break anything else either.
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">
    <!-- creates accessable custom attribute keys with attribute code -->
    <type name="Magento\Framework\Reflection\CustomAttributesProcessor">
        <plugin name="Vendor_Module_Reflextion_CustomAttributesProcessorPlugin" type="Vendor\Module\Plugin\Reflection\CustomAttributesProcessorPlugin" sortOrder="10" />
    </type>
</config>

Vendor\Module\Plugin\Reflection\CustomAttributesProcessorPlugin
<?php

namespace Vendor\Module\Plugin\Reflection;

use Magento\Framework\Api\AttributeValue;

/**
 * creates DataOutputArray which is reliable accessible from email templates
 */
class CustomAttributesProcessorPlugin
{
  public function afterBuildOutputDataArray($subject, $result) {
    $customAttributes = [];
    foreach ($result as $attribute) {
        $customAttributes[$attribute[AttributeValue::ATTRIBUTE_CODE]] = 
        [
            AttributeValue::VALUE => $attribute[AttributeValue::VALUE],
            AttributeValue::ATTRIBUTE_CODE => $attribute[AttributeValue::ATTRIBUTE_CODE]
        ];
    }

    return $customAttributes;
  }
}


Can anyone confirm?
