In this tutorial, you’ll learn how to send emails in Shopware 6 using templates stored in the database. We’ll walk through creating a custom service, fetching a mail template by its technical name, and sending it with dynamic customer data.
Introduction
Shopware 6 comes with a powerful mailing system that allows you to create and manage templates directly in the administration panel. But what if you need to trigger an email programmatically — for example, when a custom event happens in your plugin?
In this guide, we’ll build a service class that loads a mail template from the database and uses Shopware’s AbstractMailService
to send it to the customer.
Step 1: Inject Dependencies
To interact with Shopware’s mail system, we need two things:
-
AbstractMailService
– responsible for sending emails. -
Mail template repositories – to fetch templates by their type and technical name.
Here’s the constructor of our service:
public function __construct( private readonly AbstractMailService $mailService, private readonly EntityRepository $mailTemplateRepository, private readonly EntityRepository $mailTemplateTypeRepository ) {}
Both repositories will be injected automatically by Shopware’s DI container.
Step 2: Fetching the Template
Every mail template in Shopware is connected to a mail template type. To locate the correct template, we first search the type by its technicalName
. Then, we fetch the default system template for that type.
private function getMailTemplate(string $id, Context $context): ?MailTemplateEntity { $criteria = new Criteria(); $criteria->addFilter(new EqualsFilter('technicalName', $id)); $mailTemplateType = $this->mailTemplateTypeRepository->search($criteria, $context)->first(); $criteria = new Criteria(); $criteria->addFilter( new MultiFilter( MultiFilter::CONNECTION_AND, [ new EqualsFilter('mailTemplateTypeId', $mailTemplateType->getId()), new EqualsFilter('systemDefault', true), ] ) ); return $this->mailTemplateRepository->search($criteria, $context)->first(); }
Here we pass in the technical name (test-plugin.template-name
) when calling this method.
Step 3: Preparing the Email Data
With the template loaded, we can extract subject, content, and sender details. We also provide the recipient list (in this case, the current customer).
public function sendTemplateMail(Context $context, CustomerEntity $customer): void { $mailTemplate = $this->getMailTemplate('flex-test-plugin.ticket.created', $context); $data = [ 'recipients' => [ $customer->getEmail() => $customer->getFirstName() . ' ' . $customer->getLastName(), ], 'contentHtml' => $mailTemplate->getContentHtml(), 'contentPlain' => $mailTemplate->getContentPlain(), 'subject' => $mailTemplate->getSubject(), 'senderName' => $mailTemplate->getSenderName(), ]; $this->mailService->send($data, $context, ['customer' => $customer]); }
Notice the third parameter in send()
:
We pass a data array (['customer' => $customer]
) that can be used inside the email template placeholders (Twig variables).
Step 4: Creating a Template in the Admin
To make this work, you must create a mail template type and a mail template in the administration:
-
Go to Settings → Email Templates.
-
Create a new template type with technical name
test-plugin.template-name
. -
Add a new template for that type, including subject, HTML, and plain text content.
-
Use Twig variables like
{{ customer.firstName }}
inside the template.
Step 5: Triggering the Email
Now you can use your service from anywhere in your plugin:
$this->mailSender->sendTemplateMail($context, $customer);
For example, you might trigger it when a support ticket is created or a custom entity is updated.
Conclusion
You now have a reusable service for sending templated emails in Shopware 6. By separating logic into a service class, you gain full control over when and how your templates are used, while still leveraging the administration for template content management.