Order Confirmation Email
Email Sender Service
namespace Magento\Sales\Model\Order\Email;
class Sender
{
public function __construct(
private \Magento\Email\Model\Template\Factory $emailTemplateFactory,
private \Magento\Store\Model\StoreManagerInterface $storeManager
) {}
public function send(
\Magento\Sales\Api\Data\OrderInterface $order,
string $templateId,
array $templateParams = []
): void {
$store = $this->storeManager->getStore($order->getStoreId());
$transport = $this->emailTemplateFactory->create();
$transport->setDesignConfig(['area' => 'frontend', 'store' => $store->getCode()]);
$transport->sendTransactional(
$templateId,
$order->getStore()->getEmail(),
$order->getCustomerEmail(),
$order->getCustomerName(),
$templateParams
);
}
}
Order Confirmation
// Send order confirmation email
$this->sender->send(
$order,
'sales_email_order_template',
[
'order' => $order,
'formattedShippingAddress' => $order->formatAddress($order->getShippingAddress()),
'formattedBillingAddress' => $order->formatAddress($order->getBillingAddress()),
'paymentHtml' => $this->getPaymentInfoHtml($order),
]
);
Shipment Notification
Shipment Email
namespace Magento\Sales\Model\Order\Email;
class ShipmentSender
{
public function send(
\Magento\Sales\Api\Data\OrderInterface $order,
\Magento\Sales\Api\Data\ShipmentInterface $shipment,
bool $forceSyncMode = false
): void {
$templateId = 'sales_email_order_shipment_template';
$transport = $this->emailTemplateFactory->create();
$transport->sendTransactional(
$templateId,
$order->getStore()->getEmail(),
$order->getCustomerEmail(),
$order->getCustomerName(),
[
'order' => $order,
'shipment' => $shipment,
'tracking' => $shipment->getTracksCollection(),
'formattedShippingAddress' => $order->formatAddress($order->getShippingAddress()),
]
);
}
}
Tracking in Email
<!-- Shipment tracking template -->
<div class="tracking-info">
<h3>Shipment Tracking</h3>
{{if shipment.getTracksCollection().count()}}
<table>
<tr><th>Carrier</th><th>Number</th></tr>
{{for track in shipment.getTracksCollection()}}
<tr>
<td>{{var track.getTitle()}}</td>
<td>{{var track.getNumber()}}</td>
</tr>
{{/for}}
</table>
{{/if}}
</div>
Invoice Notification
Invoice Email
namespace Magento\Sales\Model\Order\Email;
class InvoiceSender
{
public function send(
\Magento\Sales\Api\Data\OrderInterface $order,
\Magento\Sales\Api\Data\InvoiceInterface $invoice
): void {
$templateId = 'sales_email_order_invoice_template';
$transport = $this->emailTemplateFactory->create();
$transport->sendTransactional(
$templateId,
$order->getStore()->getEmail(),
$order->getCustomerEmail(),
$order->getCustomerName(),
[
'order' => $order,
'invoice' => $invoice,
'formattedBillingAddress' => $order->formatAddress($order->getBillingAddress()),
]
);
}
}
Email Configuration
<!-- system.xml -->
<group id="email">
<field id="email_sender" translate="label" type="select" sortOrder="10">
<label>Sender Email</label>
<source_model>Magento\Config\Model\Config\Source\Email\Sender</source_model>
</field>
<field id="email_template" translate="label" type="select" sortOrder="20">
<label>Email Template</label>
<source_model>Magento\Config\Model\Config\Source\Email\Template\Options</source_model>
</field>
<field id="email_copy_to" translate="label" type="text" sortOrder="30">
<label>Send Order Email Copy To</label>
</field>
<field id="email_copy_method" translate="label" type="select" sortOrder="40">
<label>Send Order Email Copy Method</label>
<source_model>Magento\Config\Model\Config\Source\Email\Method</source_model>
</field>
</group>
Email Templates
Custom Email Template
// Create custom template
namespace Vendor\Order\Email\Template;
class CustomTemplate
{
public function createTemplate(): \Magento\Email\Model\Template
{
$template = $this->templateFactory->create();
$template->setData([
'template_code' => 'Custom Order Email',
'template_subject' => 'Your order {{var order.getIncrementId()}} has been processed',
'template_content' => $this->getTemplateContent(),
'template_styles' => $this->getTemplateStyles(),
'orig_template_code' => 'custom_order_email',
]);
$template->save();
return $template;
}
private function getTemplateContent(): string
{
return <<<HTML
<html>
<body>
<h1>Thank you for your order!</h1>
<p>Order #{{var order.getIncrementId()}}</p>
<p>Status: {{var order.getStatus()}}</p>
<p>Grand Total: {{var order.formatPrice(order.getGrandTotal())}}</p>
</body>
</html>
HTML;
}
}
Template Variables
// Available template variables for order emails
$variables = [
'order' => $order, // Order object
'store' => $store, // Store object
'formattedShippingAddress' => '...',
'formattedBillingAddress' => '...',
'paymentHtml' => '...',
'created_at_formatted' => '...',
];
// Access in template:
// {{var order.getIncrementId()}}
// {{var order.getGrandTotal()}}
// {{var order.getCustomerName()}}
// {{var formattedShippingAddress}}
Quiz
1. How are order emails sent?
2. What information is included in shipment notification?
3. How do you customize email content?
Flashcards
Question
Order email template ID?
Click to reveal answer
Answer
sales_email_order_template
Question
Shipment email template ID?
Click to reveal answer
Answer
sales_email_order_shipment_template
Question
Invoice email template ID?
Click to reveal answer
Answer
sales_email_order_invoice_template
Question
Template variable syntax?
Click to reveal answer
Answer
{{var object.method()}}
Revision Notes
Key Takeaways
- 1. Order emails use transactional templates with dynamic variables
- 2. Confirmation, shipment, and invoice each have separate templates
- 3. Tracking information is included in shipment notifications
- 4. Templates can be customized with HTML and CSS
- 5. Email copy can be sent to additional recipients
Interview Tips
- • Explain the email template system and variable syntax
- • Describe what information each email type includes
- • Discuss how to customize email templates for different stores
Cheat Sheet
Order Emails:
Confirmation: sales_email_order_template
Shipment: sales_email_order_shipment_template
Invoice: sales_email_order_invoice_template
Sending:
TemplateFactory->sendTransactional(
$templateId, $sender, $recipient, $name, $params
)
Variables:
{{var order.getIncrementId()}}
{{var order.formatPrice(order.getGrandTotal())}}