DC 5.10 Mail Templates

This guide gives an overview of the functionality in the Mail Template configuration. It is an extension of the already existing mail documentation DC 5.10 Example - Sending emails showing how emails can be triggered by automations.

If you need a template to use for general mail notifications, you can copy-paste the automation and mail template from the example:

Example

 

Mail template

The template for the above mail notification can be found here.

 

{{include 'html-header-start'}} <title>These assets are expiring within the next 14 days.</title> {{include 'html-header-end'}} <span class="preheader">The following assets in the Saether DAM are expiring within the next 14 days</span> {{include 'standard-header'}} <h1>Hi {{receiver.name | html.escape}},</h1> <p>There {{if data.assets.size==1}} is an asset {{ else }} {{if data.assets.size < 100 }} are {{ data.assets.size }} assets {{ else }} are more than 100 assets {{ end }} {{ end }} about to expire within the next 14 days. Please review and take the appropriate action.</p> <br> <br> <!-- Action --> {{ for id in data.assets limit:12}} <a href="{{ digizuite.get_link_to_asset_preview("https://media.saether.dk", id) }}"> <img src="{{ digizuite.get_asset_thumbnail_url(id) }}" alt="{{ digizuite.get_title(id) | html.escape}}" width="80" /> </a> {{ end }} <br> {{ if data.assets.size > 12}} <p> + more. </p> {{ end }} <br> <!-- Sub copy --> <table class="body-sub"> <tr> <td> <p class="sub"> When an asset expires, it will no longer be in the digizuite Media Manager. If you click on the thumbnails you can go to the assets, or you can navigate to the DAM and utilize the filtering. <br> </p> <p class="sub"> This is an automated email, please do not respond. </p> </td> </tr> </table> <br> {{include 'standard-footer'}}

Automation

Input:

action "Send email" {     type = "Send email to member"     needs = "Join Strings"     receiver_is_group = "false"     receiver_id = "23"     template_name = "TestTemplate"     config_version_id = "0"     mail_data = "(assets),(@assets)" } action "Join Strings" {     type = "Join Strings"     needs = "Non Empty search result"     strings = "@AssetIds"     separator = ","     result = "@assets" } trigger "CronScheduleTrigger" {     type = "CronScheduleTrigger"     resolves = "Send email"     schedule = "0 0 8 ? * * *"     misfire_instruction = "fireoncenow"     identity = "ExpiryNotification" } action "Find assets" {     type = "Find assets"     search_request = "[{\"searchKey\":\"27053d69-a523-4ba8-9e58-55f521ed66a1\",\"dateRange\":{\"from\":{\"type\":\"variable\",\"key\":\"@from\"},\"to\":{\"type\":\"variable\",\"key\":\"@to\"}}}]"     max_result_count = "101"     asset_sort_order = "ascending"     asset_ids = "@AssetIds"     asset_item_ids = "@AssetItemIds"     needs = ["Get today", "Get + 14 days"] } action "Get today" {     type = "Get Current Date"     offset = "0"     result = "@from" } action "Get + 14 days" {     type = "Get Current Date"     offset = "1209600"     result = "@to" } filter "Non Empty search result" {     type = "Is Array Empty"     needs = "Find assets"     array = "@AssetIds"     negate = "true" }

 

Prerequisites

As a precondition to following the walkthrough, it is expected that the reader has a basic understanding of the following concepts:

  • HTML

  • Emails

  • Basic programming and control structures

 

The templates are store under the ConfigManager (settings in MM):

Scribans own documentation can be found here: https://github.com/scriban/scriban/blob/master/doc/language.md and can be used for additional examples.

Preparing the mail template

The first thing we will take a look at is the email template. We start out with a pretty simply template that doesn’t do a whole lot, but let us go over how it works either way.

{{include 'html-header-start'}} <title>Here is what happened since last time!</title> {{include 'html-header-end'}} <span class="preheader">Here is what happened since last time!</span> <h1>Hi {{receiver.name | html.escape}},</h1> <p>Here is what was uploaded since yesterday </p>

On line 1 you will notice the double curly braces {{, these denote that some special code should be run, and that it is not just html that to be printed directly into the final mail. In this case we are using a special Scriban structure called an include. Specifically we are including another mail template here. This allows us to standardize somewhat how mails looks, and allows us to avoid having to repeat ourselves. On line 3 we just output a title for the mail client to display. On line 5 we include another template. Next on line 7 we have the pre-header, which is displayed by some email clients as the first part of the body, before you open the email. The pre-header is not displayed in the actual mail. On line 9 we say hello to the receiver of the email. There are certain parts that are always loaded by the mail system. Specifically the receiver and sender. Important to notice is also that we use a pipe operator to call the html.escape function, to prevent html injection. Whenever you output data you don’t control, always remember to run it through html.escape. On line 10 we just output yet more text for the user to see.

Displaying a simple table

Next we need to start outputting out assets. As this is just a simple walkthrough, we will not focus on styling the email, and will just output the assets in a simple table.

First thing to do is setup the basic table structure:

<table> <thread> <tr> <th>AssetId</th> <th>Asset title</th> <th>Thumbnail</th> <th>Status</th> </tr> </thread> <tbody> ... </tbody> </table>

If you have working with html before, there really shouldn’t be anything surprising about this structure. We simply create a table with 4 rows, AssetId, Asset title, Thumbnail and Status. The rest is just basic layout for us to put out main output in.

Looping through our assets

Then we get to the interesting parts, we need to actually output some data. To do this we insert a for loop:

<tbody> {{for assetId in data.assetIds}} <tr> ... </tr> {{end}} </tbody>

This will run once for every assetId in data.assetIds. How does data get into data.assetIds, you ask? This is handled by automations, which we will get to later in this walkthrough. For now, lets continue looking at how we can output data.

Conditioning

You can add conditions on the data to e.g. show alternative text depending on the length of the array.

 

<p>There {{if data.assets.size==1}} is an asset {{ else }} {{if data.assets.size < 100 }} are {{ data.assets.size }} assets {{ else }} are more than 100 assets {{ end }} {{ end }} about to expire within the next 14 days. Please review and take the appropriate action.</p> <br>

Above examples shows three alternative text depending on the number of assets that are about to expire:

  • 1 result:

1 search result

 

  • Between 1 and 99 results

5 search results

 

  • More than 100 results

More than 100 search results

 

Showing the asset id

First thing we wanted to display was the asset id. We already have the asset id available from the loop, so we can output it directly:

<tbody> {{for assetId in data.assetIds}} <tr> <td> {{assetId}} </td> ... </tr> {{end}} </tbody>

As seen on line 5, all we need to do is to write {{assetId}}.

Showing the asset title

Next we want to output the title of the asset. As can be seen in the auto-generated documentation below the mail template editor, there is a function called get_title, that takes an asset id, and returns string. Calling it is as simple as this:

<tbody> {{for assetId in data.assetIds}} <tr> ... <td> {{digizuite.get_title(assetId) | html.escape}} </td> ... </tr> {{end}} </tbody>

All the custom functions Digizuite makes available can be found on the digizuite object in the template. So in this case to call the function and get the title is as simple as {{digizuite.get_title(assetId)}}, and we simply pass the asset id as an argument to the function. As this is user provided input, we have to remember to escape it using html.escape, as mentioned earlier.

Showing a thumbnail of the asset

Next we want to display a thumbnail of the asset. To do this we have a function get_asset_thumbnail_url, which again takes an asset id. So we simply need to do this:

<tbody> {{for assetId in data.assetIds}} <tr> ... <td> <img src="{{digizuite.get_asset_thumbnail_url(assetId)}}" /> </td> ... </tr> {{end}} </tbody>

And we will get a nice small thumbnail. Notice how we don’t need to escape anything here. The function already returns a well formed URL, so it won’t cause any issues being included in the html like this.

Adding a link to the thumbnail

Next we want to thumbnail to actually take us to that asset in the Media Manager. For this we have a convenience function get_link_to_asset_preview, which takes a baseUrl to the Media Manager and an asset id. Because we want to entire image to be clickable, we wrap the entire thumbnail in an a tag with a link to the image:

<tbody> {{for assetId in data.assetIds}} <tr> ... <td> <a href="{{digizuite.get_link_to_asset_preview("https://mm.digizuite.com", assetId)}}"> <img src="{{digizuite.get_asset_thumbnail_url(assetId)}}" /> </a> </td> ... </tr> {{end}} </tbody>

If you have multiple Media Managers installed, you need to enter the link to the correct portal. You can use the config version id of the template to control this. Notice also that we again don’t need extra escaping, since this is again a well formed URL already.

Displaying the asset status

As the last thing in the template we want to include the status of the asset. To do this we need to load the value of a metadata field. During this part we will also see how to do some even more advanced logic to conditionally display output in the template. The Status field is a combo metafield, so we need to use the get_combo_meta_field_value function. And as can be seen from the documentation, this function takes an assetId, which we already have available from the loop, and a metaFieldLabelId. This is the label id of the metafield, which also means it is language specific. On my system the labelId for the status field in English is 51550, so we will use that as an example. On your system it is likely to be different. Last thing we will notice about the function is that it returns a ComboValue, not a string like the other functions we used above. That means we have to extract a specific property from the ComboValue and display that. Additionally we want to handle the asset not having a status at all (Usually you have an automation ensuring the asset always have a status, but for the sake of example, we will take a look at how to check)

<tbody> {{for assetId in data.assetIds}} <tr> ... <td> {{status = digizuite.get_combo_meta_field_value(assetId, 51550)}} {{if status == null}} Asset has no status {{else}} {{status.label | html.escape}} {{end}} </td> </tr> {{end}} </tbody>

On line 6 you can see us calling the get_combo_meta_field_value function, passing in the assetId from the loop, and the labelId of the status metafield, and saving the result in the status variable. Next we wanted to handle the case of the asset not yet having a status at all. We do this by using an if statement, outputting Asset has no status if there is no status, and {{status.label | html.escape}} if there is. If you look in the documentation for the ComboValue type, you can see it has a label property. And again we remember to escape the user input, just to be on the safe side.

This concludes everything we need to do for the mail template. Make sure to save it, and put note down the name you gave the template, since we will need it for configuring the automation.

Sender of email

By default the sender of the email is shown as System Admin <noreply@digizuite.com> with an image of John Burke. The image only shows for internal digizuite mails, however the name (System Admin) is seen by all receivers of the email. It can be adapted by changing the name of the System Admin user. Be careful only to change the First and Last name as changing the System Admin login would potentially break the DAM.

Default sender

 

 

Senders name changed to Digizuite DAM

Using the sender-user

In the mail text you can reference the sender as in the one who triggered the action to send this mail (i.e. if a user send the mail due to a collection share). However, if the mail is triggered by an automation, then this will default to System Admin and is therefore not recommended to use.

{{sender.name | html.escape}} ({{sender.email_address | html.escape}}) has invited you to join a shared collection in Digizuite&#8482; Media Manager called <strong>“{{data.collection_name | html.escape}}”</strong>. Enjoy!

 

Good practices

This section lists some recommendations on good practices with the mail template. It is heavily suggested that you use the below recommendations as it limits toll on the system, makes the templates execute faster and provides a nicer overview for the receiver.

Check that result is not-empty

Users generally don’t want to be notified if nothing happens, so it is a good idea to check that the result returned by the Find Asset in the automation is not-empty before triggering the mail template.

Improving the performance of the mail template

If you run your mail template by loading 10 metadata fields for each assets, and loading 500 assets, it will of course take a bit of time, and put quite a bit of load on your dam center. To optimize your template we provide certain helper functions that will cause data to be bulk preloaded, which is must faster than loading each value as it is necessary.

At the time of writing Digizuite provides 3 functions for this:

  • preload_title

  • queue_meta_field_loads_by_item_guid

  • queue_meta_field_loads_by_label_id

Each of these functions takes the assets to preload. You just need to call them once in the start of the mail, and they are safe to call multiple times.

preload_title is also recommended to use when using the get_link_to_asset_preview function, since it requires the title of the asset to work.

Using these functions properly can make almost any mail template execute instantly, with much less load on the dam center.

Iteration limits

Scriban only allows each loop to run a maximum of 1000 times, after which it will stop execution and throw an error. To get around that you can use a limiting operator like this:

for assetId in data.assetIds limit:200

to only display the first 200 items.

It is also generally recommended that you keep the limit low, to both allow the template to execute faster, and to save the receiver some pain, since their mail client won’t start crying from too much mail.

If you cap the items send in the mail template, you might as well also cap the search result in the automation. You can do this by adding the Mac Result Count to be 1 more than the cap in the mail template

You can always add a clause in the mail template like:

{{ if data.assets.size > 100}} There are more than 100 assets about to expire. {{ end }}

 

Html escaping

It has been mentioned several times in this document, but make sure to escape any user input using | html.escape, otherwise you might introduce security issues. When in doubt, escape the value.

 E.g.

  • {{sender.email_address | html.escape}}

  • {{sender.name | html.escape}}

  • {{receiver.name | html.escape}}

  • {{status.label | html.escape}}

  • {{ digizuite.get_title(id) | html.escape}}