Sending Emails in SAP Hybris
1. Overview
In this article, I will show how to create, configure and send emails in SAP Hybris.
An email in Hybris consists of at least 3 different components :
- Email Template and Email Page.
- Email Process.
- Email Context.
In order to explore all of them we are going to create a simple example, a Hello World Email.
This is a simplified version of how we are going to setup our Hello World Email.
2. Implementation
2.1. Business Process
1. Create an Item type that extends StoreFrontCustomerProcess
or StoreFrontProcess
, call it HelloWorldEmailProcess
.
<itemtype code="HelloWorldEmailProcess" extends="StoreFrontCustomerProcess"
jaloclass="com.stackextend.training.core.jalo.process.HelloWorldEmailProcess">
<attributes>
<attribute qualifier="firstName" type="java.lang.String">
<persistence type="property" />
</attribute>
</attributes>
</itemtype>
2. Create a new xml file, call it helloWorldEmailProcess.xml
, it’s where we are going to define the steps to be executed by the Process Engine.
<!-- .../trainingcore/processes/helloWorldEmailProcess.xml -->
<?xml version="1.0" encoding="utf-8"?>
<process xmlns="http://www.hybris.de/xsd/processdefinition"
start="generateHelloWorldEmail"
name="helloWorldEmailProcess"
processClass="com.stackextend.core.model.process.HelloWorldEmailProcessModel"
onError="error">
<action id="generateHelloWorldEmail" bean="generateHelloWorldEmail">
<transition name="OK" to="sendEmail"/>
<transition name="NOK" to="error"/>
</action>
<action id="sendEmail" bean="sendEmail">
<transition name="OK" to="removeSentEmail"/>
<transition name="NOK" to="failed"/>
</action>
<action id="removeSentEmail" bean="removeSentEmail">
<transition name="OK" to="success"/>
<transition name="NOK" to="error"/>
</action>
<end id="error" state="ERROR">Something went wrong.</end>
<end id="failed" state="FAILED">Could not send HelloWorld email.</end>
<end id="success" state="SUCCEEDED">Sent HelloWorld email.</end>
</process>
3. Register the generateHelloWorldEmail
as a bean in Spring :
<bean id="generateHelloWorldEmail" parent="abstractGenerateEmailAction">
<property name="frontendTemplateName" value="HelloWorldEmailTemplate"/>
</bean>
Note that
sendEmail
andremoveSentEmail
beans are already registered in Spring.
4. Register your process as a ProcessDefinitionResource
into Spring, to be recognized by Hybris Process Engine.
<bean id="helloWorldEmailProcessDefinitionResource"
class="de.hybris.platform.processengine.definition.ProcessDefinitionResource" >
<property name="resource" value="classpath:/traingingcore/processes/helloWorldEmailProcess.xml"/>
</bean>
5. Create a new Java class that extends CustomerEmailContext
or AbstractEmailContext
, call it HelloWorldEmailContext
.
An EmailContext is the one that holds the data to be passed to the email template, in our case we will passe to the template a single attribute called firstName.
public class HelloWorldEmailContext extends CustomerEmailContext
{
private String firstName;
@Override
public void init(final StoreFrontCustomerProcessModel processModel, final EmailPageModel emailPageModel)
{
super.init(processModel, emailPageModel);
if (processModel instanceof HelloWorldEmailProcessModel)
{
setFirstName(((HelloWorldEmailProcessModel) processModel).getFirstName());
}
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
}
6. Register the HelloWorldEmailContext
as a bean in Spring.
<bean id="helloWorldEmailContext"
class="com.stackextend.training.facades.process.email.context.HelloWorldEmailContext"
parent="customerEmailContext"
scope="prototype" >
</bean>
2.2. Email Template
The concept of Emails Template in Hybris is similar to Pages Template of the WCMS module, refer to this article for more details.
1. Create 2 Velocity templates, one for the email Subject and the other for the Body.
<%-- .../trainingcore/import/emails/email-helloworld-subject.vm --%>
${ctx.messages.emailSubject}
<%-- .../trainingcore/import/emails/email-helloworld-body.vm --%>
<html>
<head>
</head>
<body bgcolor="#ffffff">
<h1>Hello ${ctx.firstName}</h1>
<p>This is a Hello World Email from Hybris</p>
</body>
</html>
2. The following impex allows you to create RendererTemplates
for the Subject and the Body, and attach them to an EmailPageTemplate
.
# Content Catalog Version
$contentCV=...
# Path to the Velocity Templates
$emailResource=...
# Package of the Context class
$emailPackageName=...
# Create Template Renderers
INSERT_UPDATE RendererTemplate ;code[unique=true] ;contextClass ;templateScript[lang=en,translator=de.hybris.platform.commerceservices.impex.impl.FileLoaderValueTranslator];rendererType(code)[default='velocity']
;email-helloworld-body ;$emailPackageName.HelloWorldEmailContext ;$emailResource/email-helloworld-body.vm
;email-helloworld-subject ;$emailPackageName.HelloWorldEmailContext ;$emailResource/email-helloworld-subject.vm
# Create Email page Template
INSERT_UPDATE EmailPageTemplate ;$contentCV[unique=true];uid[unique=true] ;active ;frontendTemplateName ;subject(code) ;htmlTemplate(code) ;restrictedPageTypes(code)
; ;HelloWorldEmailTemplate;true ;helloWorldEmail ;email-helloworld-subject ;email-helloworld-body ;EmailPage
# Create Email Page
INSERT_UPDATE EmailPage ;$contentCV[unique=true];uid[unique=true] ;masterTemplate(uid,$contentCV);approvalStatus(code)[default='approved']
; ;HelloWorldEmail ;HelloWorldEmailTemplate;
2.3. Email Config
Before sending the email make sure to add these properties to your local.properties
.
emailservice.send.enabled = true
mail.from = [email protected]
mail.replyto = [email protected]
mail.smtp.server = smtp.gmail.com
mail.smtp.port = 465
mail.smtp.user = [email protected]
mail.smtp.password = password
2.4. Sending Email
Sending a Hello World Email means starting a new instance of the Hello World Process.
// Create a new instance of the process
HelloWorldProcessModel helloWorldProcessModel = (HelloWorldProcessModel) getBusinessProcessService()
.createProcess("helloWorld-" + System.currentTimeMillis(), "helloWorldEmailProcess");
// Fill the process with the appropriate data
helloWorldProcessModel.setSite(...);
helloWorldProcessModel.setCustomer(...);
helloWorldProcessModel.setLanguage(...);
helloWorldProcessModel.setCurrency(...);
helloWorldProcessModel.setStore(...);
helloWorldProcessModel.setFirstName("Mouad");
// Save the process
getModelService().save(helloWorldProcessModel);
// Then start the process = send the Email
getBusinessProcessService().startProcess(helloWorldProcessModel);
The code snippet above requires
modelService
andemailService
to be injected (Autowired).
3. Conclusion
Creating emails in Hybris is quite tricky because you have to go for a bunch of components, however this separation of responsibilities (process, context, template,…) comes with many more benefits especially for debugging and maintaining.
Software Craftsmanship, Stackextend author and Full Stack developer with 6+ years of experience in Java/Kotlin, Java EE, Angular and Hybris…
I’m Passionate about Microservice architectures, Hexagonal architecture, Event Driven architecture, Event Sourcing and Domain Driven design (DDD)…
Huge fan of Clean Code school, SOLID, GRASP principles, Design Patterns, TDD and BDD.
Hi,
In the above explanation, Sending email code should be enclosed in an EventListener class and that class should be registered as a bean in spring xml file.
Thanks.
Hi Himanshu,
Actually I didn’t add an EventListener for the sake of simplicity, I think it’s not mandatory however it is the right way to do it indeed (y)
Thanks,
Hi,
Can you please provide code to send email using EventListener.Because I am not able to understand that if we will enclose the sending email code in EventListener then what will be event in that case?
Thanks
Hi,
Can you please provide code to send email using EventListener because I am not able to understand that if we will enclose the sending email code in eventListener then what will be the event?
Thanks
Hi,
how to send an attachement csv file in email ?
Hi Charafi,
Unfortunately, there is no short answer for that because you have to go for a bunch of customization to make it work.
I have created a new post for that (link bellow) feel free to check it.
Good luck,
Link : https://www.stackextend.com/hybris/sending-emails-with-attachments-in-sap-hybris/
Hi,
How To inject emailService to be injected (Autowired) can you expline please..
I am getting Exception.
Ex: private EmailService emailservice;
in my class . is there any extension i need to add to my Custom Extension to get EmailService.
Hi,
EmailService is defined in the acceleratorservices extension which I asume you already have (To be checked).
There are two ways to inject EmailService into your class (bean).
1. Using annotation @Autowired :
@Autowired
private EmailService emailservice;
2. Via XML :
<bean id="yourClass" class="foo.bar.YourClass" >
<property name="emailservice" ref="emailservice"></property>
</bean>
Refer to the officiel documentation of Spring.
I am Adding acceleratorservices extension in two places.
1) in localextensions as
extension name=”acceleratorservices”
2) and also adding into inside my custom extension in file extensioninfo.xml as
requires-extension name=”acceleratorservices”
is it correct way or issue with me?.
requires-extension name=”acceleratorservices”
Is enough.
it could be also dependency issue between your custom extension and acceleratorservices extension.
Make sure your custom extension is required acceleratorservices extension by adding in its extensioninfo.xml
Hi Mouad.
I have no idea what values put in the following macros.
$contentCV=…
$emailResource=…
$emailPackageName=…
Follow the link bellow for more details about all the possible values for
$emailResource
.https://www.stackextend.com/hybris/import-media-using-impex-in-hybris/
It’s Hybris , the is not such easy, it’s a bunch of configurations. I need to send a simply email, using spring-boot, it’s just some injections and services, that all. Hybris make me unhappy.
I can’t say otherwise!
wow, really nice explanation
Thanks!
Hi Mouad EL Fakir,
when I get the email the URL link should be expired after 30 minutes after that If the link has already expired, please request a new activation email here: Request a new activation email.
Could you please suggest how to work on it.
Thanks & Regards,
Upendar
Hi,
we are already having an Email setup configured and everything works fine until now.But Now I made some changes to the email body (i mean in the respective .vm file) ,did a build of the project and then performed server restart.
The problem here is the new changes done in the .vm file are not getting reflected in the email generated.I am still getting the old email .could you please let me know if I am missing any other steps apart from build and server restart.
Thanks a lot.
Changes will not be affected on the email by only updating the .vm, you should also re-import the new .vm using an impex script like :
UPDATE RendererTemplate;code[unique=true];description[lang=$lang];templateScript[lang=$lang,translator=de.hybris.platform.commerceservices.impex.impl.FileLoaderValueTranslator]
Or by importing the vm’s content into your
RendererTemplateModel.templateScript
from the HMC or the Backoffice.Good luck,
Thanks a lot for your quick reply.I will check and will update.
Hi Mouad EL Fakir, updating the Renderer template through impex script resolved the issue.now I am able to see the changes made in the .vm file of the email.Thanks once again.
Hi,
Can you please provide code to send email using EventListener. Because I am not able to understand that if we will enclose the sendingEmail code in EventListener then what will be the Event in that case?
Thanks
Hi,
You can update the example here to match your needs.
Thanks for reference..
HI Mouad,
Can you please tell me how do we get email id of the user to whom we want to send the email. Ofcourse we can’t specify it in properties file right?
what is the use of frontendtemplatename here, which value it is referring to?
it’s the uid of the
EmailPageTemplate
.How to embed logo or image in html email,i used cid but it is not working properly
Hi @Mouad EL Fakir
How to set BCC to this email process.
Hi,
I am a new bee in SAP Hybris. I have followed your tutorial, struck in the process of going forward. Need your support !
2.4 section (sending email snippet) where to place ( which class, Extention ) is not aware. Can you help me out there?
this should be HelloWorldProcessModel replaced with HelloWorldEmailProcess. There is no model HelloWorldProcessModel .plse check sir, i am getting the build issues
Hi, I am getting null pointer exception at HelloWorldProcessModel helloWorldProcessModel = (HelloWorldProcessModel) getBusinessProcessService()
.createProcess(“helloWorld-” + System.currentTimeMillis(), “helloWorldEmailProcess”); this line can anyone solve
Check the bean for your business process service is loaded
I am facing the same can somone help me
Hi!
Mouad,It seems like you have not added firstName to email context.
In Section 2.4 :
Create a new instance of the process, it should be typeCast to “HelloWorldEmailProcessModel” ,
and not “HelloWorldProcessModel”.
Hi Mouad,
Thanks for the detailed explanation.Could you please let me know if we can make a switch like enable/disable simply using properties file to stop the mail trigger for certain business process..without actually configuring from. Backoffice.
Please share the process how we can achieve the same.
TIA
Hi! So, my collegue created cronjob to send particular emails for our customers every 6 months. When I try to run cronjob manually sometimes the templates of the emails are broken – sometimes they work ok. How can I find what causes those broken cases? .vm looks fine and it doesn’t depend on teh user, but for some reason sometimes it is broken. Any ideas? Thanks in advance
HI,
Where did you specified sender(to address) email address?