Overview

The Email service enables you to create and upload email templates so that you can send repetitive emails by making a simple REST call. It provides flexible template management using Velocity-based templates.

Use the Email service to:

  • Send transactional emails such as welcome emails, shipping notices, order confirmations, password reminders, purchase receipts, and so on. These types of emails are sent to one person as a result of an action triggered by the user.
  • Create and manage email templates for any use case.
  • Customize emails for each recipient using the Velocity Template Language.
  • Create localized email templates for different languages and locations.
Do not use the Email service for bulk, marketing, or commercial emails. These types of emails need to be processed in bulk, which the Email service does not support. Mass mailing will be detected and all further requests will be automatically blocked (response code 429)

Examples

  • Send an order confirmation email to a customer that lists their order details.
  • Send an invitation email to an employee to create a new employee account.
  • Send a password reset email to customers to reset their password.


API Reference

/{tenant}/send-async

Adds an email to the email sending queue, causing it to be eventually sent to the specified recipient.

/{tenant}/send-async

post

Queues an email for sending and returns immediately. Uses the specified template to render the subject and body of the email and then passes the given attribute values to that template. All of these inputs are passed in the request body. See its JSON schema for details. The caller must have the hybris.email_send or hybris.email_admin scope assigned.

/{tenant}/send-sync

Sends an email to the specified recipient.

/{tenant}/send-sync

post

Sends an email to a specified recipient. Uses the specified template to render the subject and body of the email and then passes the given attribute values to that template. All of these inputs are passed in the request body. See its JSON schema for details. The caller must have the hybris.email_send or hybris.email_admin scope assigned.

/{tenant}/send

DEPRECATED
Sends an email to a specified recipient. Sending emails from the "yaas.io" domain is disallowed. Emails which have a "fromAddress" which belong to the "yaas.io" domain will be automatically adjusted to the default project sender domain: tenant.mail.yaas.io. Deprecated: Please use /{tenant}/send-async instead, which is functionally equivalent to this resource. This resource is only available for backward compatibility. It will be removed from this path in the next major version of the Email service.

/{tenant}/send

post

Sends an email to a specified recipient. Uses the specified template to render the subject and body of the email and then passes the given attribute values to that template. All of these inputs are passed in the request body. See its JSON schema for details. The caller must have the hybris.email_send or hybris.email_admin scope assigned.

/{tenant}/templates

Manages email templates for the rendering of emails to be sent by the /{tenant}/send resource.

/{tenant}/templates

get

Returns a list with all of the email templates and their metadata for a given project. The caller must have the hybris.email_view, hybris.email_manage or hybris.email_admin scope assigned. This method uses a paging mechanism. If no paging parameters are provided, the default values are used.

post

Creates a new email template by specifying its code and owner, an optional description, and an attribute list. All of these inputs are passed in the request body. See its JSON schema for details. The caller must have the hybris.email_manage or hybris.email_admin scope assigned.

/{tenant}/templates/{client}

Manages email templates for rendering of emails to be sent by the /{tenant}/send resource.

/{tenant}/templates/{client}

get

Returns a list with all of the email templates and their metadata for a given project and client. The caller must have the hybris.email_view, hybris.email_manage or hybris.email_admin scope assigned. This method uses a paging mechanism. If no paging parameters are provided, the default values are used.

/{tenant}/templates/{client}/{code}

Manages a single email template for rendering of emails to be posted by the /{tenant}/send resource.

get

Retrieves an email template and its attributes. The caller must have the hybris.email_view, hybris.email_manage or hybris.email_admin scope assigned.

put

Updates an email template and its attributes. Inputs are passed in the request body. See its JSON schema for details. The caller must have the hybris.email_manage or hybris.email_admin scope assigned. In case the template contains any files, they will not be removed.

delete

Deletes a template. The caller must be the template owner and have the hybris.email_manage or hybris.email_admin scope assigned.

/{tenant}/templates/{client}/{code}/{fileType}

Manages Velocity template files that represent the subject or body of an email template. These may be available in several localized variants.

put

Creates or updates the body/subject file of this email template for a specific locale. The caller must have the hybris.email_manage or hybris.email_admin scope assigned. Files over 50MB cannot be uploaded.

get

Retrieves the body/subject file of this email template for a specific locale. The caller must have the hybris.email_view, hybris.email_manage or hybris.email_admin scope assigned.

delete

Deletes a template file, and unassigns it from the parent template. The caller must be the template owner and have the hybris.email_manage or hybris.email_admin scope assigned.

/{tenant}/domains

Allows you to request a verification token which you can place in your DNS record in order to be able to send emails from custom domain.

/{tenant}/domains

get

Returns a list with all of the domains registered for the project with their verification token. The caller must have the hybris.email_view, hybris.email_manage or hybris.email_admin scope assigned. This method uses a paging mechanism. If no paging parameters are provided, the default values are used.

post

Registering a new domain for tenant. See its JSON schema for details. The caller must have the hybris.email_manage or hybris.email_admin scope assigned.

/{tenant}/domains/{domain}

Manages a single domain.

get

Retrieves a domain. The caller must have the hybris.email_view, hybris.email_manage or hybris.email_admin scope assigned.

delete

Deletes a domain. The caller must be the domain owner and have the hybris.email_manage or hybris.email_admin scope assigned.


Limitations

  • Due to current restrictions, you can only use the Email service to send emails with a fromAddress that belongs to the domain {project}.mail.yaas.io, where {project} is the id of your project, e.g. john.doe@{project}.mail.yaas.io. If you want to avoid this restriction and use your own domain in the fromAddress, please refer to the documentation on Sending from your own Domain. If you want to use your own Mail SMTP Server, please refer to the documentation on Custom SMTP Server Integration.

  • Do not use the Email service for bulk, marketing, or commercial emails. These types of emails need to be processed in bulk, which the Email service does not support. Mass mailing will be detected and all further requests will be automatically blocked (response code 429).


Using Projects and Clients

Most methods in the Email service API make use of the name of the project or the client.

The project is used as the value of the tenant URI parameters. It must match the project that has been assigned to the caller.

The client occurs both as the value of the client URI parameter, as well as the owner property in JSON schemas. The client is the creator and the owner of a given email template within a given project. For template creation or removal or for sending emails, this parameter must match the application's/service's "YaaS Client" identifier that has been assigned to the caller.


Email Sending

The Email service focuses on sending email messages based on reusable email templates, which define most of the textual contents of the email. In order to send a message using the Email service, you have the option to use no template code, which will send an email with a YaaS-styled template. You can specify the template code _blank to send an email with no styling, or the styling you pass with the definable attribute body, or you can create your own templates with the APIs template endpoint and refer to one of these. You also have to specify some additional information, most notably the recipient to send the specific message to. Optionally, you can customize the contents of the message by passing data into the template itself.

The Email service provides two functionally equivalent alternatives to trigger the sending of an email message. One does most of the involved processing asynchronously and responds to the caller as quickly as possible. The other does most of the processing synchronously and only responds to the caller afterwards.

The following sections describe the information that has to be provided while sending an email, as well as the two alternatives and the trade-offs between them in more detail.

Payload attributes for sending an email

The following information can be provided while sending an email.

  • fromAddress and fromName:
    • The email address and name to be used in the From header of the email.
    • Note that the domain part of the fromAddress is currently limited to {yourProjectId}.mail.yaas.io: e.g. john.doe@{yourProjectId}.mail.yaas.io.
    • If you want to avoid this restriction and use your own domain in the fromAddress, please refer to the documentation on Sending from your own Domain.
  • replyToAddress and replyToName:
    • The email address and name to be used in the Reply-To header of the email.
    • If replyToAddress and replyToName are not provided Reply-To header is set to fromAddress and fromName. replyToName can not be provided without replyToAddress.
  • toAddress and toName:
    • The email address and name to be used in the To header of the email.
    • Use your own valid email address here for testing. This allows you to verify successful transmission of the email and review its contents.
    • If you don't need to check the contents of the email, you can use any email belonging to the test domain @yaastest.com - in such case the
    • email will not be sent.
  • to:
    • Alternatively/additionally to providing the toAddress and toName you can specify your multiple primary recipients here. Each element
    • of the list should contain "address" attribute for the email address, and "name" attribute for the full name of the recipient. If present, this
    • list will be used in the To header of the email, prepended with the toAddress and toName (if specified).
    • In case the first address of the resulting To email header belongs to the test domain @yaastest.com, the email will not be sent.
  • cc:
    • Specify your carbon copy (CC) recipients here. Each element of the list should contain "address" attribute for the email address, and "name"
    • attribute for the full name of the recipient. If present, this list will be used in the Cc header of the email.
  • bcc:
    • Specify your blind carbon copy (BCC) recipients here. Each element of the list should contain "address" attribute for the email address, and "name"
    • attribute for the full name of the recipient. If present, this list will be used in the Bcc header of the email.
  • templateOwner and templateCode:
    • Together, these properties identify the email template to use for the contents of the email. They reference the owner and code of the email template created in the "Upload Your Template" tutorial. If the owner attribute is not specified, the {client} is used as the owner value.
    • When you specify _blank as code, you'll get a template with no styles or text, that you can fill with setting definable attributes ${body} and ${subject}.
    • Specifying no templateCode will send an email with a predefined YaaS-styling.
  • locale:
  • attributes:
    • A list of attribute names and values to be passed into the subject and body template files. The values passed here replace the placeholders that have been defined in the Velocity templates.
    • For this example, include the attributes from the Velocity template file introduced in the "Create Your Template" tutorial: customerName, couponValue, and couponCode.

The required attributes are the following:

  • fromAddress
  • at least one toAddress, or a non empty list of to

Asynchronous email sending

Use a POST request to the /{project}/send-async resource of the Email service to trigger asynchronous sending of a message.

Asynchronous sending means that the Email service will queue the outgoing email and process it after the request. Thus, a request made to the async resource will always return immediately. Because of the queuing of the emails, however, it might take up to several minutes until the email is actually sent, depending on the service load.

Be aware that a successful response from the async resource only means that the email has been successfully queued. It does not mean that the email template has been successfully rendered or that the message has been handed over to the outgoing mail server.

For example, if the referenced template does not exist, the Email service will still return a successful response, even though email processing will later fail at the rendering time. Similarly, if a recipient's email address is incorrect, there will be no notification of the problem. For that reason, if you use asynchronous email sending, you should always verify beforehand that the template you are referencing works and that the data that you include in the send request is correct.

Synchronous email sending

Synchronous email sending is triggered through a POST request to the /{project}/send-sync resource of the Email service.

This approach will give you instant feedback in case something went wrong when sending the email, and thus will facilitate troubleshooting. When you apply your knowledge in a production scenario, you may prefer using asynchronous email sending instead.

A request to the sync resource will only respond after the email template has been rendered and the message has been handed over to the outgoing mail server. In case of any error during those processing steps, the sync resource will always respond with an error status. Therefore, if you receive a successful response you can always assume that the email was rendered and processed successfully.

However, subsequent errors may arise after the mail arrives at the outgoing mail server but before it is actually delivered to its intended recipient. In that case, the Email server will not notify the caller of the error. This is a limitation of the nature of email sending itself.

Synchronous email sending requests may take noticeably longer then asynchronous ones. A response time of several seconds is not unusual.

If you wish to test using the Email service but you do not need to send actual emails (such as performance tests or business logic testing), you should use the test domain @yaastest.com in the destination email address:

e.g. john.doe.will.not.get.this.email@yaastest.com

The email service will detect the test domain from the destination address and, although it will process the request, it will skip sending the email to the SMTP server.


Using Velocity Templates

The Email service makes use of the Velocity Template Language (VTL, or simply Velocity for short) for customizing emails. This allows for simple variable replacement as well as more advanced templating techniques like string operations, numeric operations, conditionals, and loops.

For more information about the Velocity Template Language, see the Velocity User Guide.

We will use the term Velocity template or template file in order to refer to a Velocity template file, and email template to refer to an email template.

How the Email service uses Velocity

The contents of all the template files that are managed by the Email service are written in the Velocity Template Language. When you use the email template management functionality of the Email service, the template files are merely stored and not evaluated. A single email template is comprised of several Velocity template files, including:

  • body – The template file used for the content of the body of the email.
  • subject – The template file used for the subject of the email.
  • Both the body and the subject can have several language variants. For more information, see Template Localization.

The Email service also manages a list of defined attributes that may be passed to the email template when its template files are evaluated.

An email template that has been defined in that manner can be used later while sending an email. The caller of the send operation must specify the email template to use in terms of its templateOwner and templateCode. It can also pass values for each of the attributes that are defined for that email template. The Email service then evaluates the respective template files to create the body and subject of the actual email message using Velocity, and it passes all necessary values to the Velocity template.

Variables available in Velocity templates

In Velocity templating, values are passed to the Velocity templates by means of Velocity variables. As Velocity itself is implemented in Java, the available variable types are modeled closely after Java types. Velocity variables can hold any of the following types:

  • Simple types, such as strings and numbers.
  • Collection types, such as lists and maps.
  • Arbitrary Java objects, which can store data and provide additional functionality for templating.

In order to avoid namespace cluttering, the Email service only makes use of a small number of top-level Velocity variables. Currently, these top-level variables are data, mailContext, and tools. Each of these variables is a map that provides access to specific values, as described in the following section.

The 'data' variable

The top-level variable data (aliased to d) holds the values of all defined attributes that the caller passes when invoking the Velocity template. Assuming the email template defines attributes foo and bar, their respective values can be accessed by these VTL expressions:

  ${data.foo}
  ${d.foo}
  ${data.bar}
  ${d.bar}

Each defined attribute can be used to pass arbitrary JSON values to the Velocity template. This is not limited to strings or numbers. It also includes more complex JSON objects and JSON arrays. All these JSON types map to Velocity types, which makes it easy to access structured data in your Velocity template. The following table includes example data that is passed in a defined attribute called val. It summarizes the mapping from JSON to Velocity:

JSON typeJSON exampleJava / Velocity typeVelocity access example
string"YaaS we can!"String${d.val}
${d.val.length}
number-3.14Double${d.val}
${d.val.isInfinite()}
true, falsetrueBoolean${d.val}
nullnullnull${d.val}
object{
"sku" : "1337",
"name" : "Leet"
}
Map${d.val}
${d.val.sku}
${d.val.name}
${d.val["name"]}
${d.val.keys}
array[1, "two", 3.0]List${d.val}
{$d.val[0]}
${d.val[2]}
${d.val.size()}

JSON objects and JSON arrays may be nested within each other. You can access their contents in your Velocity template the same way. For more detailed examples, see the advanced templating tutorial on Leveraging Structured Data.

The legacy top-level variable body is still available as an alias for data and d, and it provides the same data. However, body exists for historical reasons only, and its use is deprecated.

The 'mailContext' variable

The top-level variable mailContext (aliased to mc) holds data taken from the email sending request itself. The following data is available:

  • ${mailContext.toAddress}:
    The email address of the first recipient to whom the email is sent, such as tom.jones@hybris.com.
  • ${mailContext.toName}:
    The full name of the first recipient to whom the email is sent, such as Tom Jones.
  • ${mailContext.to}:
    The list of all primary recipients to whom the email is sent. Each list item is a map, that has a field "address" for storing the recipient's email address and field "name" for storing the recipient's full name.
  • ${mailContext.cc}:
    The list of all carbon copy (CC) recipients to whom the email is sent. Each list item is a map, that has a field "address" for storing the recipient's email address and field "name" for storing the recipient's full name.
  • ${mailContext.bcc}:
    The list of all blind carbon copy (BCC) recipients to whom the email is sent. Each list item is a map, that has a field "address" for storing the recipient's email address and field "name" for storing the recipient's full name.
  • ${mailContext.fromAddress}:
    The email address from which the email is sent, such as noreply@hybris.com.
  • ${mailContext.fromName}:
    The full name of the sender of the email, such as Thomas Jones.
  • ${mailContext.replyToAddress}:
    The email address that should be used to reply to the email such as support@hybris.com.
  • ${mailContext.replyToName}:
    The full name that should be used to reply to the email, such as Support.
  • ${mailContext.templateOwner}:
    The client that is the owner of the email template being used, such as order.
  • ${mailContext.templateCode}:
    The email template code to use for sending the email, such as invite.
  • ${mailContext.locale}:
    The locale to use for templating the email, such as DE_de.

The 'tools' variable

The top-level variable tools (aliased to t) exposes useful Velocity Tools. The following Velocity Tools are available:

  • ${tools.number}:
    The NumberTool, which provides number formatting facilities with internationalization support.
    The exposed NumberTool uses ${mailContext.locale} as its default Locale.
  • ${tools.date}:
    The DateTool, which provides date and time formatting facilities with internationalization support.
    The exposed DateTool uses ${mailContext.locale} as its default locale,
    it uses Java's short date format as its default format,
    and it uses GMT as its default timezone.
  • ${tools.convert}:
    The ConversionTool, which provides explicit data-type conversion facilities.
    The exposed ConversionTool uses ${mailContext.locale} as its default locale,
    and it uses yyyy-MM-dd'T'HH:mm:ss.SSSXXX as its default dateFormat.
    While this date format, yyyy-MM-dd'T'HH:mm:ss.SSSXXX, may seem a little bulky, it provides good compatibility with ISO 8601 and RFC 3339. Also, it is less ambiguous than most natural-language date formats and is well suited for data transfer and programmatic processing. For more information, see Date and Time Attributes.
  • ${tools.esc}:
    The EscapeTool, which provides escaping facilities like HTML and URL escaping.

For examples of how to make use of these tools in the context of the Email service, see the advanced templating tutorials on leveraging structured data and securing your templates.

Velocity template restrictions

In addition to plain access to Velocity variables, the Email service supports most other features of the Velocity Template Language. Therefore, you can utilize Velocity directives such as #set, #if, #foreach, #evaluate, and #define to structure your Velocity template code.

However, there are some Velocity features that the Email service disregards for security reasons. These are:

  • Inclusion Directives:
    The Email service ignores the Velocity directives #include and #parse. When found in a Velocity template, they will always evaluate to an empty string.
  • Java Reflection API:
    A Velocity template can call arbitrary Java methods on all Velocity variables. However, methods that provide access to the Java Reflection API are explicitly blocked. In particular, you cannot use the getClass() method and related functionality. Attempts to do so will evaluate to null.


Template Localization

The Email service supports localization of your Velocity templates and emails so that you can conveniently manage multiple language variants for your email templates.

Managing localized email templates

The Email service can manage multiple localized variants of the subject and body template files.

To add new localizations, you can issue PUT requests to the following URLs:

https://api.eu.yaas.io/hybris/email/v1/{project}/templates/{client}/{code}/subject_{locale}
https://api.eu.yaas.io/hybris/email/v1/{project}/templates/{client}/{code}/body_{locale}

The {locale} suffix is a locale identifier, which is a formal reference to a natural language, dialect, or similar variant. Examples of valid locale identifiers are pl (Polish), en_US (American English), or de_AT (Austrian German). A PUT to the following URLs uploads a body template file for those locales:

https://api.eu.yaas.io/hybris/email/v1/{project}/templates/{client}/{code}/body_pl
https://api.eu.yaas.io/hybris/email/v1/{project}/templates/{client}/{code}/body_en_US
https://api.eu.yaas.io/hybris/email/v1/{project}/templates/{client}/{code}/body_de_AT

Sending emails with localized email templates

When sending an email based on an email template with multiple localizations, you can specify which locale to use. For example, to use the template file with the name body_de_AT for the body of the email, include the JSON property "templateLocale" : "de_AT" in the send request.

There are fallback mechanisms if no template file can be found for the desired locale. First, the Email service tries to find a file for a more general locale using the same mechanism as the ResourceBundle class in Java. If it cannot find a more general locale that matches, it uses the default subject or body files without a locale suffix. If there is no default template file, the content is left blank.

For example, if you request to send an email with locale de_AT, the Email service performs these checks:

  1. Is there an email template file with locale de_AT? If yes, use it.
  2. Is there an email template file with locale de? If yes, use it.
  3. Is there a default email template file? If yes, use it.
  4. If none of these email templates exist, leave the content blank.
To avoid sending an email with a blank subject line or body, you should upload default body and subject template files.


Send Emails from Your Own Domain

By default, the Email service restricts the domain part of the fromAddress when sending an email message. This domain must comply with {project}.mail.yaas.io, where {project} refers to the project on whose behalf the email is sent.

To circumvent this restriction, you can register your own domain in the YaaS Email service and get it verified later on.

Register the Domain

Send a POST request to the /{project}/domains resource of the Email Service to register your own domain. Provide a name for your domain, for example, domain.com. To register multiple domains for your project, you must perform multiple requests. A successful response contains the name of your registered domain and two verification tokens (TXT records), which you should add to your domain's DNS server, together with your domain. The order of entries does not matter. This example is a DNS configuration for hybrisVerificationToken=daeb852e-b588-11e6-80f5-76304dec7eb7 and verificationToken=fmxqxT/icOYx4aA/bEUrDPMeax9/s3frblS+niixmqk=:

TypeNameValue
TXT@daeb852e-b588-11e6-80f5-76304dec7eb7
TXT@fmxqxT/icOYx4aA/bEUrDPMeax9/s3frblS+niixmqk=
If you do not add the TXT record to your DNS within three days, the verification fails and your domain is removed from the system. To use that domain to send emails after verification failure, you must perform the full process again.


Custom SMTP Server Integration

It is possible to integrate the YaaS Email service with a custom SMTP server. When a custom SMTP server is configured, the Email service will not deliver email messages directly, but instead will use SMTP to submit them to the configured server. This SMTP server acts as a Mail Transfer Agent (MTA), more specifically as a Mail Submission Agent (MSU), and is thus responsible for handling the delivery of the message.

When using a custom SMTP server, your project is not restricted to specific fromAddress domains. However, the SMTP server itself may impose its own restrictions on how it handles email messages.

SMTP server configuration

Integration of a custom SMTP server is configured on a per-project level, and it will affect all email messages that the Email service sends on behalf of the particular project. In order to configure a custom SMTP server, create the following configuration properties in the Configuration service:

Property clientProperty keyDescriptionExample value
hybris.emailsmtp.hostThe host name (or IP-address) of the SMTP server.smtp.example.net
hybris.emailsmtp.portThe port on which the Email service connects to the SMTP server.
If empty, it will be derived from the smtp.security property. (Port 465 for SSL and 587 for STARTTLS.)
465
hybris.emailsmtp.securityThe type of connection security the Email service will use for communication with the SMTP server. Must be one of the following:If empty, it will default to STARTTLS, unless smtp.port is set to port 465, which is the standard port for SMTP over SSL.
(Note that, by design, the Email service does not support plain SMTP communication without connection security.)
SSL
hybris.emailsmtp.usernameThe user name that the Email service will use to authenticate itself against the SMTP server.me@domain.com
hybris.emailsmtp.passwordThe password that the Email service will use to authenticate itself against the SMTP server.
(The password must be provided in plain text, however you can ensure that the Configuration service stores it encrypted by setting the secured flag of this property to true.)
mPa$wrt!

As indicated in the above table, all configurations are stored in client-specific configuration properties that belong to hybris.email. In order to set these configuration properties, you will have to use the hybris.configuration_admin scope when calling the Configuration service.

If you want to disable the custom SMTP server configuration and switch back to the default Email service email sending, you must make sure to remove all of the above configuration properties from the Configuration service.


Securing The Templates

Email templates consists of Velocity template files that define how the visual output of the email would look like. They also enable injecting values specific to the concrete email being sent. For more information about creating Velocity template refer to the Create Your Template tutorial.

Velocity template authors should take an extra step and make sure that all dynamically created HTML outputs of a Velocity template are being sanitized. This helps to prevent Cross-Site Scripting (XSS) attacks and makes sure that attribute values passed into template files will not harm the recipient of the rendered email (or their email client).

Luckily, the Email service and Velocity support this, which helps to protect your reputation.

Use the Velocity EscapeTool to sanitize your outputs

The key to output sanitization in the Email service is Velocity EscapeTool, which is always available in the ${tools.esc} variable of the Velocity context. It provides methods to escape HTML code and URL parts, amongst others.

When templating an HTML email, you should pass all your outputs through the html method of the Escape Tool. For instance, instead of just writing ${data.customerName}, use the following:

${tools.esc.html(${data.customerName})}

Moreover, when you want to construct a URL dynamically in your Velocity template, use the url method of the Escape Tool. For instance, when adding a coupon code to a URL, do not use ${data.couponCode}. Instead, construct your URL like the following:

https://virtually4free.example.net/?couponCode=${tools.esc.url(${data.couponCode})}

When applying these principles to the body template file for win notification emails, you might end up with something like this:

<html>
<body>
  <h1>Win notification!</h1>
  <p>Dear ${tools.esc.html(${data.customerName})},</p>
  <p>
     Thank you for participating in our super-fabulous new customer competition!
     You're one of the lucky winners!
  </p>
  <p>
    We hereby present you with your coupon worth
    <strong>${tools.esc.html(${data.couponValue})}</strong>,
    to make your next purchase at Virtually-4-Free shop even cheaper.
    To redeem your coupon, simply enter the following coupon code during checkout:
    <div class="coupon">${tools.esc.html(${data.couponCode})}<div>
  </p>
  #if( ${data.products} && ${data.products.size()} > 0 )
    <p>
      Or, how about you check out one of our ${data.products.size()} latest products right now?
    </p>
    <ul>
    #foreach( $product in ${data.products} )
      #set( $createdAt = ${tools.convert.toDate(${product.createdAt})} )
      <li>
        <strong>
          <a href="https://virtually4free.example.net/products/${tools.esc.url(${product.sku})}?couponCode=${tools.esc.url(${data.couponCode})}">
            ${tools.esc.html(${product.name})}
          </a>
        </strong>
        <br>
        New since ${tools.date.format("EEEEE MMMMM d, yyyy", ${createdAt})} and recommended by 
        ${tools.number.percent(${product.score})} of our customers :-)
        <br>
        <em>Only ${tools.number.format("¤#.00", ${product.price})}!</em>
      </li>
    #end
    </ul>
  #else
    <p>
      Or, how about starting your shopping spree at 
      <a href="https://virtually4free.example.net/?couponCode=${tools.esc.url(${data.couponCode})}">Virtually-4-Free</a>,
      right now?
    </p>
  #end
</body>
</html>

After uploading this secured template, you can test it by sending an email that contains malicious data. For example, you can pass a customerName attribute value that contains undesirable HTML code. The HTML gets displayed as is and does not break the overall HTML structure of your Velocity template.

When is it OK to omit escaping?

When looking at the above secured template file, you may notice that it does not apply HTML escaping in all situations. Following are some situations and examples.

Predictable outputs of Velocity Tool methods

For instance, the expression ${tools.number.percent(${product.score})} does not strictly require additional escaping in HTML. Its output will always be a percentage, for example 98%, which never contains any HTML special characters.

That said, it is good practice to apply HTTP escaping even in such situations:

${tools.esc.html(${tools.number.percent(${product.score})})}

While that is slightly more verbose, it makes your Velocity template code more robust in case of future changes. Also, there may be locales that use unusual characters as currency symbols, for number formatting, or for date formatting. So try to apply proper output sanitization all the time, even when you think it is not necessary. Better safe than sorry!

Preformatted HTML values

Another situation when you should not apply HTML escaping is when outputting the value of a defined attribute that is intended to contain preformatted HTML code. Here it is the responsibility of the email sender (that is, the YaaS service or client that triggers the send request) to ensure that that the HTML code does not contain any malicious code.

The Email service does not formally distinguish between preformatted HTML and other inputs. Such situations are subject to informal agreement between the email template author and potential email senders. As an email template author, you may want to use the description of your template object to state that your Velocity template expects preformatted HTML in certain defined attributes.

The email subject

Last but not least, you should not utilize any escaping in your subject template files. By design, mail reader software interprets the contents of the subject line as plain text.


Introduction to Tutorials

This tutorial demonstrates how to prepare and send emails.

In this tutorial, you will send notification emails to contest winners using a fictional storefront called Virtually-4-Free as the basis for all examples shown.

The email template in this tutorial uses HTML formatting so that you can use your corporate design in the email. Over time, you will send similar emails to numerous winners. You don't want to do all the repetitive formatting work each time, but you do want to customize each email for the individual contest winners. The email should contain a personalized salutation as well as the prize itself: a coupon that can be redeemed at your example shop.

Basic tutorial

The first three parts of this tutorial focus on getting you started quickly. They cover all the steps that are necessary to send basic win-notification emails:

  1. Create your template files:

    The template file for the email contents is an HTML file that includes a few snippets of Velocity template code.

  2. Upload your email template:

    An email template is created in the Email service, so the two Velocity template files created in the previous step need to be uploaded to the Email service.

  3. Send an email:

    When sending an email, you specify which email template to use, add email addresses for the sender and recipient, and personalize the email contents by passing data into the template.

Advanced templating tutorial

The subsequent parts build on that and introduce several more advanced topics:

  1. Leverage Structured Data:

    Pass JSON data when sending emails, and process the data using Velocity directives and tools.

  2. Secure your templates:

    Make use of the Velocity Template Tool to sanitize your outputs and prevent cross-site scripting.

Preparations

You can execute all the steps in this tutorial using the API Console of the Email service. In particular, you need to know how to:

  1. Set up a Project within the organization.
  2. Obtain an access token for an authenticated client of your project.
  3. Make API calls using that access token.

The following placeholders are used in this tutorial. You can replace these placeholders with values from your own project.

DetailPlaceholderExample Value
Project ID{project}virtually4free
Application's/Service's "YaaS Client" Identifier{client}hybris.order


Create Your Template

This section of the tutorial shows you how to write the contents of the subject and body template files that will comprise your email template.

Step 1: Prepare the template file for the email subject

In this use case you are sending notification emails to the winners of the Virtually-4-Free storefront contest. The subject of the emails should be customizable for the individual winners. This customization is done using simple Velocity code in the template.

To create the template file for the subject of the email, paste the following text into a text editor:

Hello ${data.customerName}! You have won a coupon for the Virtually-4-Free shop

The variable expression that serves as a placeholder for the customerName attribute is replaced with a value when the email is sent using the email template.

All attribute names must be prepended with data, which is a hash array that the Email service uses to make the attributes available to Velocity. For details on how to work with attributes, see the Velocity Templates for the Email service section.

Save your file as subject.vm. (.vm is the standard file extension for Velocity files.) You can save the file to refer to it later, although you will only upload the contents of the file and not the file itself.

Step 2: Prepare the template file for the email body

As indicated in the use case, you are using HTML formatting for your notification emails. Therefore, you must use a template file that includes both HTML code and Velocity code.

To create the template file for the body of the email, paste the following text into a text editor:

<html>
<body>
  <h1>Win notification!</h1>
  <p>Dear ${data.customerName},</p>
  <p>
     Thank you for participating in our super-fabulous new-customer competition!
     You're one of the lucky winners!
  </p>
  <p>
    We hereby present you with your coupon worth
    <strong>${data.couponValue}</strong>,
    to make your next purchase at Virtually-4-Free shop even cheaper.
    To redeem your coupon, simply enter the following coupon code during checkout:
    <div class="coupon">${data.couponCode}<div>
  </p>
  <p>
    Or, start your next shopping spree from 
    <a href="https://virtually4free.example.net/coupon?code=${data.couponCode}">this link</a>,
    and have the coupon code conveniently pre-filled!
  </p>
</body>
</html>

In this template file, you use the same customerName placeholder that you used in the subject template file. In addition, there are two new placeholders named couponValue and couponCode, which are also prepended by data.

Note how the template file makes use of the couponCode attribute in both the visible contents of the HTML and in a hyperlink URL. You can refer to attributes anywhere in the HTML code of your template file. This gives you a great deal of flexibility and control when authoring your own template files for the Email service.

The great flexibility of templating can introduce security concerns. While the above body template file is suitable for your first experiments with the Email service, production template files must take more care to ensure proper HTML formatting and prevent code-injection attacks. For more information on this subject, see the advanced templating tutorial on securing your templates.

When you are done adjusting the template, save the file as body.vm. The next step is to upload your template to the Email service.


Upload Your Template

In the "Create Your Template" tutorial you have prepared your subject and body template files. Now it's time to upload them to the Email service. To do this, you must create an email template with some metadata in the Email service that will serve as a container for the subject and body template files.

You need to provide the following information when creating a new email template:

  • owner and code:
    • Together, these properties identify the email template. You need them to refer to your email template later.
    • In this tutorial, the owner must be the {client}, as described in the introduction. If owner is not specified the {client} is used as the owner value by default.
    • The code of the email template is a short identifier that reflects the purpose of the email template. This example uses win-notification as the code.
  • name and description:
    • These are part of the user documentation of the email template and are displayed in any email template management GUI.
  • definableAttributes:
    • This is the list of attributes that can be passed to the email template when sending an email. You must declare all the attributes that appear as placeholders in your Velocity template files.
    • For this example, include the attributes from the Velocity template file introduced in the "Create Your Template" tutorial: customerName, couponValue, and couponCode.

Now you can use the API Console to define an email template with the above information in the Email service.

Step 1: Create the email template

Using the API Console, issue the following request to the Email service:

  • Method: POST
  • Request URL: https://api.eu.yaas.io/hybris/email/v1/{project}/templates
  • Content Type: application/json
  • Body:
    {
        "code" : "win-notification",
        "name" : "A notification email for contest winners",
        "description" : "An email template for emails to winners of our new customer contest. Includes a coupon.",
        "definableAttributes" : [
            {
                "key" : "customerName",
                "mandatory" : true
            },
            {
                "key" : "couponValue",
                "mandatory" : true
            },
            {
                "key" : "couponCode",
                "mandatory" : true
            }
        ]
    }
    

This creates an empty email template containing all the required metadata that is associated with it.

You should expect the following response:

  • Status code: 201
  • Content Type: application/json
  • Body: The body content is the same as the request body.

Troubleshooting

If you encounter a 400 response status code, verify that there are no typos in the JSON object that you sent. It must be syntactically correct JSON, and its structure must conform to the example shown above. Look at the error message in the response body, which might help to identify the problem.

If you encounter authorization problems, verify that you are using a suitable access token. Also, verify that you replaced the {client} in your JSON with your actual Application's/Service's "YaaS Client" Identifier.

Step 2: Upload the Velocity template file for the subject

You have now created the email template, but it still does not contain any information about how the subject and body of the email should look. You can upload this information in two separate steps.

In order to upload the subject of the email, issue the following request to the Email service:

  • Method: PUT
  • Request URL: https://api.eu.yaas.io/hybris/email/v1/{project}/templates/{client}/win-notification/subject
  • Content Type: application/octet-stream
  • Body: The body content is the content of the subject.vm file created in the "Create Your Template" tutorial.

You should get a response similar to the following:

  • Status code: 200
  • Content type: application/json
  • Body example:
    {
        "sizeInBytes": 85,
        "type": "body",
        "url": "https://api.eu.yaas.io/hybris/email/v1/{project}/templates/{client}/win-notification/subject"
    }
    
If you append ?validateTemplate=true to the Request URL, the content of the template file will get passed through a validator. In case of a syntactic error in the template, the upload will fail.

Step 3: Upload the Velocity template file for the body

Issue the following request:

  • Method: PUT
  • Request URL: https://api.eu.yaas.io/hybris/email/v1/{project}/templates/{client}/win-notification/body
  • Content Type: application/octet-stream
  • Body: The content of the body.vm file created in the "Create Your Template" tutorial.

You should get a response similar to the following:

  • Status code: 200
  • Content type: application/json
  • Body example:
    {
        "sizeInBytes": 749,
        "type": "body",
        "url": "https://api.eu.yaas.io/hybris/email/v1/{project}/templates/{client}/win-notification/body"
    }
    

Troubleshooting

Make sure that you are using a suitable authorization token.

Be aware that even if a template file is uploaded successfully, no validation of the Velocity code in the template has occurred. Velocity is often lenient when evaluating template files. If a syntactical error is found, the template file evaluation is likely to succeed anyway because Velocity will simply output that part of the template verbatim.

Congratulations! You have created and uploaded your first email template. To check how the uploaded template will render, you must use it to send an email, which is the subject of the "Send an Email" tutorial.


Send an Email

This part of the tutorial shows you how to make use of the email templates that you have written and uploaded in the "Upload Your Template" tutorial, specifically how to send notification emails. It also shows you how to pass custom values to defined attributes in order to personalize the contents of the email for the individual contest winner.

Due to current limitations, you can only use the Email service to send emails with a fromAddress that belongs to the domain {yourProjectId}.mail.yaas.io, where {yourProjectId} is the ID of your project:

e.g. john.doe@{yourProjectId}.mail.yaas.io

If you want to avoid this restriction and use your own domain in the fromAddress, please refer to the documentation on Sending from your own Domain.

When sending an email, you must provide additional inputs to the Email service. They are explained in detail here.

You can use the API Console to send emails using these inputs.

Sending an email

In order to send an email, issue the following request to the Email service:

  • Method: POST
  • Request URL: https://api.eu.yaas.io/hybris/email/v1/{project}/send-sync
  • Content Type: application/json
  • Body:
    {
        "fromAddress" : "virtually4free@yaas.io",
        "fromName" : "Virtually 4 Free",
        "replyToAddress" : "virtually4freeSupport@yaas.io",
        "replyToName" : "Virtual Support",
        "toAddress" : "{the recipient's email address, such as your own}",
        "toName" : "John Doe",
        "templateCode" : "win-notification",
        "locale" : "en_us",
        "attributes": [
            {
              "key" : "customerName",
              "value": "John Doe"
            },
            {
              "key": "couponValue",
              "value": "1000 EUR"
            },
            {
              "key": "couponCode",
              "value": "ACA114Hk"
            }
        ]
    }
    

You can also add more recipients to your email:

  • Method: POST
  • Request URL: https://api.eu.yaas.io/hybris/email/v1/{project}/send-sync
  • Content Type: application/json
  • Body:
    {
        "fromAddress" : "virtually4free@yaas.io",
        "fromName" : "Virtually 4 Free",
        "replyToAddress" : "virtually4freeSupport@yaas.io",
        "replyToName" : "Virtual Support",
        "toAddress" : "{the valid recipient's email address, such as your own}",
        "toName" : "John Doe",
        "to" : [{
            "address" : "{second valid recipient's email address}",
            "name" : "John Doe"
        }],
        "cc" : [{
            "address" : "{the valid email of the notification center}",
            "name" : "Win Notification Center"
        }],
        "bcc" : [{
            "address" : "{the valid email of the notification tracking}",
            "name" : "Win Notification Tracking"
        }],
        "templateCode" : "win-notification",
        "locale" : "en_us",
        "attributes": [
            {
              "key" : "customerName",
              "value": "John Doe"
            },
            {
              "key": "couponValue",
              "value": "1000 EUR"
            },
            {
              "key": "couponCode",
              "value": "ACA114Hk"
            }
        ]
    }
    

In both cases, you should receive the following response:

  • Status code: 201
  • Body: None

Troubleshooting

If you encounter a 400 response status code, read the provided error message. Here are some common problems that you might need to fix if your send request yielded an error response:

  • Verify that there are no typos in the JSON object that you sent. It must be syntactically correct JSON, and its structure must conform to the example shown above. Look at the error message in the response body, which might help to identify the problem.

  • If you encounter authorization problems, verify that you are using a suitable access token. Also, verify that you replaced the {client} in your JSON with your actual Client.

  • Due to current limitations, the domain of the fromAddress must be set to {project}.mail.yaas.io, where {project} represents your actual YaaS project.

  • Make sure that the domain(s) of the toAddress, to, cc and bcc addresses exist and are configured to receive emails. It is strongly recommended that you send test emails to your own addresses so that you can verify the results by looking them up in your inbox. Please do not use the Email service to send messages to other recipients without their prior consent – even for testing purposes.

  • Verify that the referenced email template is present and that it has a Velocity template file for both the subject and the body. Note that the owner and code must exactly match an existing email template and that both are case-sensitive. Also make sure that localized template files are present for the specified locale, or at least for the default locale.

  • The Velocity template files for subject and body must be syntactically correct in terms of the Velocity Template Language (VCL). While VCL is very lenient about syntax (usually it will fall back to rendering the source code verbatim), there are some constructs that may cause Velocity template rendering to fail completely. Read the Velocity user guide, or start from the Velocity templates in this guide, and modify them step-by-step in order to get to the root of such problems.


Leverage Structured Data

As described above, the Email service makes use of Velocity to allow you to create flexible and reusable email templates. So far, the example template for win notification emails has been fairly simple.

In the following tutorial, you will learn how to add flexible product recommendations to the above example email template. This will demonstrate more of the advanced templating features provided by the Email service.

Pass structured product data in your send request

When you send an email using the Email service, the defined attribute values that you pass are not constrained to be mere strings. Instead, you can use more complex, structured data – basically anything that can be expressed in JSON. For product recommendations, you might use a defined attribute called products with a value similar to the following:

[
  {
    "sku" : "395879346",
    "name" : "Canned Unicorn Meat",
    "price" : 279.5,
    "score" : 0.98,
    "createdAt" : "2015-07-05T15:32:12.345Z"
  },
  {
    "sku" : "NCC-1701",
    "name" : "Vintage Tricorder",
    "price" : 17.01,
    "score" : 0.86,
    "createdAt" : "2015-02-23T07:45:04.235Z"
  }
]

Step 1: Loop over a list of products

In your Velocity template, you can access the above products through the VTL expression ${data.products}, which results in the following output:

[{sku=395879346, name=Canned Unicorn Meat, price=279.5, score=0.98, createdAt=2015-07-05T15:32:12.345Z},
{sku=NCC-1701, name=Vintage Tricorder, price=17.01, score=0.86, createdAt=2015-07-03T07:45:04.235Z}]

That formatting isn't easy to read, though. In order to obtain more pleasant output, you have to loop over the products and format each of them separately, such as in an HTML list. Use Velocity's #foreach directive, which loops over the contents of ${data.products} and makes each of them available in a new variable ${product}:

<ul>
#foreach( $product in ${data.products} )
  <li>
    ${product}
  </li>
#end
</ul>

This yields the following output:

<ul>
  <li>
    {sku=395879346, name=Canned Unicorn Meat, price=279.5, score=0.98, createdAt=2015-07-05T15:32:12.345Z}
  </li>
  <li>
    {sku=NCC-1701, name=Vintage Tricorder, price=17.01, score=0.86, createdAt=2015-07-03T07:45:04.235Z}
  </li>
</ul>

Each ${product} now appears as a separate list item of an HTML list.

Step 2: Access the fields of a product

To improve formatting further, you can break down the projects themselves. Use Velocity references to access the fields of a product separately and format them in HTML. The following example also constructs a link back to the Virtually-4-Free storefront based upon the product's stock keeping unit (SKU):

<li>
  <strong>
    <a href="https://virtually4free.example.net/products/${product.sku}">
      ${product.name}
    </a>
  </strong>
  <br>
  New since ${product.createdAt} and recommended by ${product.score} of our customers :-)
  <br>
  <em>Only ${product.price}!</em>
</li>

The result will be a formatted representation of a product:

<li>
  <strong>
    <a href="https://virtually4free.example.net/products/395879346">
      Canned Unicorn Meat
    </a>
  </strong>
  <br>
  New since 2015-07-05T15:32:12.345Z and recommended by 0.98 of our customers :-)
  <br>
  <em>Only 279.5!</em>
</li>

Step 3: Format dates and numbers

While overall formatting of the product is under control now, the output of dates, numbers, and prices still requires some work. The Email service provides several Velocity Tools, which are excellent for this purpose.

First, have a look at the calendar date in ${product.createdAt}, which up until now has been rendered in ISO 8601 format, such as 2015-07-05T15:32:12.345Z in the example above. It is a good idea to stick to such a machine-readable date format in your JSON data. However, in an email message, a format that is more pleasant to the human reader is advised. Both can be achieved with the following approach:

  1. Use the Velocity Conversion Tool to convert the ISO 8601 String to a Velocity / Java Date object, and store it in a new Velocity variable:
    #set( $createdAt = ${tools.convert.toDate(${product.createdAt})} )
  2. Use the Velocity Date Tool to format the Date object according to a custom date format pattern:
    ${tools.date.format("EEEEE MMMMM d, yyyy", ${createdAt})}

Next, have a look at the numbers in ${product.score} and ${product.price}. Both can be formatted in a more meaningful way using the Velocity Number Tool:

  • Use it to format the score as a percentage: ${tools.number.percent(${product.score})}
  • Use it to format the price as a currency according to a custom format, taking the passed-in locale into account: ${tools.number.format("¤#.00", ${product.price})}

Altogether, you can use the following Velocity template for your products:

#set( $createdAt = ${tools.convert.toDate(${product.createdAt})} )
<li>
  <strong>
    <a href="https://virtually4free.example.net/products/${product.sku}">
      ${product.name}
    </a>
  </strong>
  <br>
  New since ${tools.date.format("EEEEE MMMMM d, yyyy", ${createdAt})} and recommended by 
  ${tools.number.percent(${product.score})} of our customers :-)
  <br>
  <em>Only ${tools.number.format("¤#.00", ${product.price})}!</em>
</li>

Which results in nicely formatted output like the following:

<li>
  <strong>
    <a href="https://virtually4free.example.net/products/395879346">
      Canned Unicorn Meat
    </a>
  </strong>
  <br>
  New since Sunday July 5, 2015 and recommended by
  98% of our customers :-)
  <br>
  <em>Only $279.50!</em>
</li>

Step 4: Put it all together

Time to integrate the above code snippets into the overall body Velocity template for win notification emails!

Because product recommendations will not always be available, you may want to make that part of the email optional. With Velocity's #if directive, you can render the list of products (plus a short introductory sentence) when recommendations are available. Otherwise, you can render a generic paragraph with a link to to your shop.

Last but not least, you can extend the product links and pass the coupon code along with them, which might be evaluated by the fictional storefront. This is what it all might look like:

<html>
<body>
  <h1>Win notification!</h1>
  <p>Dear ${data.customerName},</p>
  <p>
     Thank you for participating in our super-fabulous new customer competition!
     You're one of the lucky winners!
  </p>
  <p>
    We hereby present you with your coupon worth
    <strong>${data.couponValue}</strong>,
    to make your next purchase at Virtually-4-Free shop even cheaper.
    To redeem your coupon, simply enter the following coupon code during checkout:
    <div class="coupon">${data.couponCode}<div>
  </p>
  #if( ${data.products} && ${data.products.size()} > 0 )
    <p>
      Or, how about you check out one of our ${data.products.size()} latest products right now?
    </p>
    <ul>
    #foreach( $product in ${data.products} )
      #set( $createdAt = ${tools.convert.toDate(${product.createdAt})} )
      <li>
        <strong>
          <a href="https://virtually4free.example.net/products/${product.sku}?couponCode=${data.couponCode}">
            ${product.name}
          </a>
        </strong>
        <br>
        New since ${tools.date.format("EEEEE MMMMM d, yyyy", ${createdAt})} and recommended by 
        ${tools.number.percent(${product.score})} of our customers :-)
        <br>
        <em>Only ${tools.number.format("¤#.00", ${product.price})}!</em>
      </li>
    #end
    </ul>
  #else
    <p>
      Or, how about starting your shopping spree at 
      <a href="https://virtually4free.example.net/?couponCode=${data.couponCode}">Virtually-4-Free</a>,
      right now?
    </p>
  #end
</body>
</html>

Now try to upload this template and use it to send an email! Don't forget to pass an additional attribute value that holds the recommended products.

Feel free to experiment a little! For instance, see what happens when you don't pass any products. Or, try to pass a different locale in your send request, such as de-DE. Watch how dates and numbers automatically get adjusted to local customs. (Hint: Germans use a comma as a decimal separator rather than a period.) For more information about fully localizing your email template, see template localization.

And now, for something completely different...


  • Send feedback

    If you find any information that is unclear or incorrect, please let us know so that we can improve the Dev Portal content.

  • Get Help

    Use our private help channel. Receive updates over email and contact our specialists directly.

  • hybris Experts

    If you need more information about this topic, visit hybris Experts to post your own question and interact with our community and experts.