Magento 2, E-Mail Templates & Transport Builder

I wanted to give our sales people some notifications from customer offers. It seemed a bit more personal to set these as coming from the customer, with the information they sent, while tying it into a Magento 2 template for easy modification. This brought me to the transport builder part of Magento 2’s framework.

What will we need?

We’re going to make use of three key Magento components.

\Psr\Log\LoggerInterface $LoggerInterface,
\Magento\Framework\Mail\Template\TransportBuilder $_transportBuilder,
\Magento\Store\Model\StoreManagerInterface $_storeManager

The logger interface might be the odd ball here. I like putting transactions into a log file. This is why I’m going to include it in this post.

As for the others, the transport builder is the class that will do the email template parsing and send, while the store manager will give us access to a piece of information we’re going to need.

The Magento PHP Code Behind

Let’s assume we have an observer setup.

namespace Danjoseph\Helloworld\Observer;

use Magento\Framework\Event\ObserverInterface;
use Magento\Framework\Event\Observer;

class NewOffers implements ObserverInterface
{
	protected $_logger;
	protected $_storeManager;

	private $_transportBuilder;

	public function __construct(
		\Psr\Log\LoggerInterface $LoggerInterface,
		\Magento\Framework\Mail\Template\TransportBuilder $_transportBuilder,
		\Magento\Store\Model\StoreManagerInterface $_storeManager
	)
	{
		$this->_logger           = $LoggerInterface;
		$this->_transportBuilder = $_transportBuilder;
		$this->_storeManager     = $_storeManager;
	}

	public function execute( Observer $observer )
	{
		$myData = $observer->getData('myEventData');

		$this->notifySales( $myData );
	}

	private function notifySales( $customer )
	{
		$templateVars = [
		    "store"         => $this->_storeManager->getStore(),
		    "customer_name" => $customer['customer_name'],
		    "message"       => $customer['message'],
		    "sku"           => $customer['sku'],
		    "offer"         => $customer['offer_amount']
		];

		$transport = $this->_transportBuilder->setTemplateIdentifier( 1 )
			->setTemplateOptions( [ 'area' => \Magento\Framework\App\Area::AREA_FRONTEND, 'store' => $this->_storeManager->getStore() ] )
			->setTemplateVars( $templateVars )
			->setFrom( [ "name" => $customer['customer_name'], "email" => $customer['customer_email'] ] )
			->addTo('[email protected]')
			->setReplyTo( $customer['customer_email'] )
			->getTransport();
		
		$transport->sendMessage();

		$this->_logger->addDebug( "Message sent" );
	}
}

Now let’s examine our function from that class.

private function notifySales( $customer )
{
	$templateVars = [
	    "store"         => $this->_storeManager->getStore(),
	    "customer_name" => $customer['customer_name'],
	    "message"       => $customer['message'],
	    "sku"           => $customer['sku'],
	    "offer"         => $customer['offer_amount']
	];

	$transport = $this->_transportBuilder->setTemplateIdentifier( 1 )
		->setTemplateOptions( [ 'area' => \Magento\Framework\App\Area::AREA_FRONTEND, 'store' => $this->_storeManager->getStore() ] )
		->setTemplateVars( $templateVars )
		->setFrom( [ "name" => $customer['customer_name'], "email" => $customer['customer_email'] ] )
		->addTo('[email protected]')
		->setReplyTo( $customer['customer_email'] )
		->getTransport();
	
	$transport->sendMessage();

	$this->_logger->addDebug( "Message sent" );
}

Your $templateVars array holds the variable names and values inside your e-mail template.

The $transport object is where we put everything together. Let’s break this down a bit.

setTemplateIdentifier( 1 ) – This is the template ID from the Magento 2 admin area. We’ll get to that in a minute.

setTemplateVars() – This is where your $templateVars array will go.

setFrom() takes an array. Your array elements should be “name” and “email”.

addTo() and setReplyTo() are just email addresses.

Finally, you’ll send the message and then make a log entry in your debug.log.

What does my template look like?

Head to the admin area, and go to Marketing > Email Templates.

From here, you’ll want to create a new email template. You can give it any name you want, and set it up any way you, but here is my template.

Template Name: dan_offers_notification
Template Subject: {{trans “I have an offer for”}} {{var sku}}

Template Code:

<p class="greeting">Hello, Sales:</p>
<p>{{var message}}</p>
<p>Offer Amount: ${{var offer}}</p>

Sincerely, {{var customer_name}}

You’ll notice the {{var something}} lines. The something is where you’ll take those $templateVars array key names and plug put them in the template.

Conclusion

You don’t have to use an observer to use templates and send out e-mails. You can drop this code into any model or controller. Setting variables is as simple as building an array. Use this for notifications, updates, or anything.

-Dan

Written by Dan
I am a Magento Certified Developer Plus and Lead Developer for an online auto parts retailer. My hobbies include anything tech, movies, video games, and hanging out with my wife and daughter. I am a Christian and like sharing things I am studying and reading.