In this page
Editing notification email templates
Velocity objects available for the notification emails
Data types
Limited collection types
DTO types
Object instances
Data limits
Customizing the notification emails
When you want to include custom content (like explanations) in the Better Content Archiving notification emails, or to remove some parts, or to translate the mails to your users' natural language, it is possible to customize the templates from which these emails are rendered.
The templates themselves are plain text documents, containing HTML markup augmented with Velocity directives (that implement if-then, iteration- and other type of logic).
Generally speaking, the templates are simple. HTML is easy to understand, plus the web is full of HTML tutorials, writing HTML will not be a problem. Velocity is also easy, and as it is the template language widely used in Confluence, you are probably already familiar with it. (If not, the Velocity User Guide is the best resource to learn more.)
Editing notification email templates
The web based email editor was introduced in Better Content Archiving 4.5.0. If you are using a prior version, read here.
Steps:
- Login to Confluence as administrator.
- Go to Administration → Archiving → Notification Emails (in the left-side bar under Archiving).
- You can edit the subject and the content of all notification email types via a simple web-based, syntax highlighting editor. (You can also reset the original templates easily.)
Velocity objects available for the notification emails
If you just want to add some custom instructions to email, or remove or rephrase some text, you can skip this part. If you want to make significant changes to the logic, numbers and lists, please read on.
The context (the set of objects available) was significantly changed in Better Content Archiving 6.0.0. If you are using a prior version, read here.
Data types
For performance and usability reasons, the email notification templates cannot access "large" amounts of data (10000 spaces, for example). Instead, they will receive size-limited views of the data as instances of the following collection types:
Limited collection types
Type name | Description |
---|---|
LimitedList |
A size limited decorator for the Java List type. Think about it as a list that maximizes the number of items it actually holds, but also knows the total number of items it would contain if it were non-limited. Example: when the list receives 135 items, 100 as max size, then it will return 100 items and 35 as remaining count. It extends the java.util.List interface with:
|
LimitedMap |
A size limited decorator for the Java Map type. It has the semantics with map entries, as LimitedList has with the list items. It extends the java.util.Map interface with:
|
DTO types
The items in the above collections are lightweight DTO objects of the following types:
Type name | Description |
---|---|
LightPage |
A lightweight replacement for a Confluence Page object. Available fields: |
LightSpace |
A lightweight replacement for a Confluence Space object. Available fields:
|
LightPageArchiving |
Describes an archiving operation. Available fields:
|
ContentView |
Describes a page view event. Available fields: |
ContentUpdate |
Describes a page update event. Available fields:
|
Object instances
You can access the following objects in the Velocity context. These are built up from the aforementioned collection and DTO types, or from standard Java types:
Domain Object | Description |
---|---|
$user |
User instance representing the user this email will be sent to. (This also means that the template will be rendered separately for each addressee.) |
$replyToUsers |
List of all User instances whom this email will be sent to. It is available only in the "Discussed Pages" notification email template. It is essentially the list of the users who participate in the conversation, and who will receive the reply if someone uses "Reply All" in the email client. Obviously, this list also contains the user represented by $user. (since 9.1.0) |
$subject |
Subject of the notification email. You can use the ${pages.size()} expression to refer to the length of the $pages collection. |
$reason | Identifies the reason why this notification is sent. It can also be interpreted as the "role" of the addressee. Possible values (with obvious meaning):
|
$spacesToPages |
Lists of pages grouped by their corresponding spaces.
Contains only the pages relevant to the notification email. Type: LimitedMap<LightSpace, LimitedList<LightPage>> ## traverse through the spaces #foreach($space in $spacesToPages.keySet()) ## get the list of pages in the current space #set($pagesInSpace = $spacesToPages.get($space)) ## get the total number of pages in the current space #set($pageCount = $pagesInSpace.nonLimitedSize) ... ## do whatever you want, e.g. traverse pages and render them #end |
$spacesToNotViewedPages |
For "Not-viewed pages" emails only. Type: LimitedMap<LightSpace, LimitedMap<LightPage, ContentView>> #set($lastView = $spacesToNotViewedPages.get($space).get($page)) $lastView.pageId ## page ID $lastView.viewerName ## name of viewer $lastView.viewDate ## date of view |
$spacesToExpiredPages |
For "Expired pages" emails only. Type: LimitedMap<LightSpace, LimitedMap<LightPage, ContentUpdate>> #set($lastUpdate = $spacesToExpiredPages.get($space).get($page)) $lastUpdate.pageId ## page ID $lastUpdate.updaterName ## name of updater $lastUpdate.updateDate ## date of update $lastUpdate.type ## type of update $lastUpdate.updateAction ## human readable type of update |
$pagesArchived |
For "Archived pages" emails only. Type: LimitedMap<LightSpace, LimitedMap<LightPage, LightPageArchiving>> #set($pageArchiving = $pagesArchived.get($space).get($page)) $pageArchiving.freshPage ## fresh page that was archived $pageArchiving.archivingAction ## textual description $pageArchiving.archiverName ## name of archiver $pageArchiving.reason ## textual reason |
$pagesSkipped |
For "Skipped pages" emails only. Type: LimitedMap<LightSpace, LimitedMap<LightPage, LightPageArchiving>> #set($pageArchiving = $pagesArchived.get($space).get($page)) $pageArchiving.archivingAction ## textual description $pageArchiving.archiverName ## name of archiver |
$pageStatsTool |
Velocity tool to work with page statistics. It has various use cases depending on the email type: ## in "Not-viewed pages" emails #set($config = $pageStatsTool.getArchivingConfiguration($space)) $config.pageViewAlertAge ## page view tracking alert age (in days) #set($lastViewedPageAgeInDays = $pageStatsTool.getLastViewedPageAgeInDays($space, $spacesToNotViewedPages)) $lastViewedPageAgeInDays ## days passed since the last page view ## in "Expired pages" emails #set($config = $pageStatsTool.getArchivingConfiguration($space)) $config.pageExpirationTrackingByAgeEnabled ## whether page expiration tracking by age is enabled $config.pageExpirationAlertAge ## page expiration tracking alert age (in days) #set($lastUpdatedPageAgeInDays = $pageStatsTool.getLastUpdatedPageAgeInDays($space, $spacesToExpiredPages)) $lastUpdatedPageAgeInDays ## days passed since the last page update ## in "Expired pages" emails ## get the number of days until the oldest page gets archived, ## or -1 if archiving is not enabled in that space, ## or -2 if there are only explicitly expired pages in the space: #set($firstPageAutoArchivingInDays = $pageStatsTool.getFirstPageAutoArchivingInDays($space, $spacesToExpiredPages)) #if($firstPageAutoArchivingInDays == -1) Auto-archiving is disabled: these pages will not be auto-archived. #elseif($firstPageAutoArchivingInDays == -2) All these pages are expired due to a label added: these pages will not be auto-archived. #else ## get the days until the oldest page gets archived ## (i.e. the days until the first upcoming archival) $firstPageAutoArchivingInDays #end ## in all email types ## get the archiving configuration for a space ## (you will unlikely need this object, ## but please contact Midori for details in case you do) #set($config = $pageStatsTool.getArchivingConfiguration($space)) |
Data limits
As explained above, notification emails receive size-limited views on the data for performance reasons. If you are happy with the default limits, then you don't need to understand the details. Otherwise, please see the Performance Tuning page to learn more about how it works and how it can be configured.
Questions?
Ask us any time.