Skip to content
intermediate Phase 50 · Order Operations

Order Emails

Order confirmation, shipment notification, invoice notification, and email templates

45m
0 problems
Topic Progress 0%

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?

Question 1 options

2. What information is included in shipment notification?

Question 2 options

3. How do you customize email content?

Question 3 options

Flashcards

Question

Order email template ID?

Answer

sales_email_order_template

Question

Shipment email template ID?

Answer

sales_email_order_shipment_template

Question

Invoice email template ID?

Answer

sales_email_order_invoice_template

Question

Template variable syntax?

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())}}