Describe an email once -- get the process XML, EmailContext class, Spring beans, subject/body Velocity templates, the ImpEx that wires up the CMS EmailPage, and the event/listener that triggers it.
🔒 Your code never leaves your browser — everything is generated locally from templates, no AI, no server round-trip.
trainingcore/resources/processes/orderConfirmationEmail-process.xml<?xml version="1.0" encoding="UTF-8"?>
<process-definition xmlns="http://www.hybris.de/xsd/processdefinition"
name="orderConfirmationEmailProcess" start="start">
<start name="start">
<transition name="OK" to="generateEmail"/>
</start>
<action id="generateEmail" bean="generateOrderConfirmationEmailAction">
<transition name="OK" to="sendEmail"/>
</action>
<action id="sendEmail" bean="sendOrderConfirmationEmailAction">
<transition name="OK" to="removeSentEmail"/>
</action>
<action id="removeSentEmail" bean="removeSentOrderConfirmationEmailAction">
<transition name="OK" to="success"/>
</action>
<end name="success" state="SUCCEEDED"/>
</process-definition>
A transactional email in SAP Commerce (Hybris) -- order confirmations, registration emails, password resets -- is driven by a small business process (extending StoreFrontCustomerProcess) whose actions generate the email content from a Velocity template, send it, and clean up afterwards. The content side is a CMS EmailPage: a RendererTemplate per Velocity file, wired together by an EmailPageTemplate and EmailPage, with the page's content slots scoped to a content catalog.
An EmailContext class (extending AbstractEmailContext, or CustomerEmailContext for order-related emails) populates the Velocity model from the running process instance, so the templates can reference e.g. $context.get("orderCode") without any Java-side string building.
Use this generator for any customer-facing transactional email that needs to be triggered by a domain event -- order confirmation, shipment notification, account registration, password reset, and similar one-shot notifications tied to a business process.
If the email doesn't need its own process (e.g. a one-off marketing blast sent from a campaign tool), most of the scaffolding here -- the process XML, the event, the listener -- isn't needed; just the EmailContext/Velocity/ImpEx pieces apply.
StoreFrontCustomerProcess (via CustomerProcess) already carries a reference to the customer and base site, which almost every transactional email needs (to know who to send to and which storefront's branding/content to use) -- extending it means the Email generator doesn't have to redeclare those attributes.
AbstractEmailContext is the generic base that any process type can extend to populate a Velocity model. CustomerEmailContext adds order/customer-specific convenience accessors and is the usual choice when the triggering process is order-related; this generator defaults to AbstractEmailContext and flags that choice as something to verify against your project's acceleratorservices version.
Yes in the OOTB pattern -- Backoffice's process monitoring and the generateEmail/sendEmail/removeSentEmail actions all operate on a concrete process instance, so each distinct email needs its own process type (even if, like here, it's a thin one with just a couple of extra attributes).
Inject EventService and call publishEvent(new <Name>RequestedEvent(...)) with the context attribute values. The generated listener catches that event, creates and starts the process, and the process's actions take care of generating and sending the email.
SAP Commerce resolves localized properties by file suffix (-locales_en.properties, -locales_de.properties, etc.), so each language needs its own file -- this mirrors exactly how a real multi-language storefront extension is laid out.