.. /*
* This file is part of the SavaPage project .
* Copyright (c) 2026 Datraverse B.V.
* Author: Rijk Ravestein.
*
* SPDX-FileCopyrightText: (c) 2020 Datraverse B.V.
* SPDX-License-Identifier: CC-BY-SA-4.0
*
* For more information, please contact Datraverse B.V. at this
* address: info@datraverse.com
*/
.. _ch-custom-email:
Email Templates
---------------
.. contents:: |RST_TABLE_OF_CONTENTS|
:depth: 1
:local:
.. _ch-custom-email-intro:
Introduction
~~~~~~~~~~~~
Email templates are a powerful instrument to customize layout and
content of email messages. Templates are defined as XML files, and are
located in the ``/opt/savapage/server/custom/template/`` directory by
default. :ref:`Alternative locations ` can
be configured.
Default templates are present in the SavaPage i18n jars. Therefore,
after a first-time installation the custom ``template/`` directory will
be empty. However, when SavaPage finds a suitable i18n XML file in
the custom directory, that belongs to an
:ref:`Email Message Type `, it will use that template.
You can create i18n variants of template XML files by appending the
locale to the base file name. For example: ``template_de.html`` is the
German variant of ``template.xml``.
.. _ch-custom-email-template-syntax:
Email Template Syntax
~~~~~~~~~~~~~~~~~~~~~
.. contents::
:depth: 1
:local:
The base syntax of an Email Template [2]_ is described by example in
the following XML file:
.. callout::
.. code-block:: xml
# <1>
# <2>
# <3>
# <4>
HTML
with $obj.attr$ and other placeholders
]]>
.. annotations::
:1: `DTD `__ of XML persisted ``java.util.Properties`` file.
:2: Placeholder object attributes are dentified by a ``$`` character at the beginning and the end.
Valid objects are defined for each :ref:`Email Message Type `.
The global :ref:`Application Object ` is valid for all types.
:3: Content for plain ``text`` message body.
:4: Content for ``html`` message body.
.. [2]
Email Template syntax is based on `StringTemplate `__.
.. _ch-custom-email-template-syntax-cid:
Embedded Images
^^^^^^^^^^^^^^^
HTML content may contain Embedded (Inline) Images.
Images are first defined in separated template entries with keys that
have “``cid_``” prefix. Those keys can then be used as placeholders for
``cid`` scheme values. SavaPage email processor will embed the image
file and replace ``cid`` placeholders with a unique Content-ID for the
Embedded (Inline) Image.
Custom image files are referred to by their relative path from the
custom ``template/`` directory. Internal stock images can simply be
referred to by their upper-case identifier, as shown in the table below.
.. table:: Stock Image Identifiers
+-----------------------+-----------------------------------------------+
| Object.attribute | Value |
+=======================+===============================================+
| ``SAVAPAGE_ICON`` | SavaPage Icon: 32 x 32 pixels, 705 bytes. |
+-----------------------+-----------------------------------------------+
| ``SAVAPAGE_LOGO`` | SavaPage Logo with "SavaPage" text at the |
| | bottom: 148 x 174 pixels, 5.6 kB. |
+-----------------------+-----------------------------------------------+
The XML snippet below shows how it works:
.. callout::
.. code-block:: xml
SAVAPAGE_ICON # <1>
images/mysite-logo.png # <2>
# <3>
# <4>
]]>
.. annotations::
:1: ``cid_1`` holds a stock image.
:2: ``cid_2`` holds the relative path to a custom image file.
:3: Note that the URL of the image has scheme ``cid``. |PRODUCT_NAME|
email processor will embed the image and replace `$cid_1$`` with
a unique Content-ID for the Embedded (Inline) Image with key ``cid_1``.
:4: The ``cid_2`` image is handled just as its ``cid_1`` sibling.
.. _ch-custom-email-template-stationary:
Email Stationary Template
~~~~~~~~~~~~~~~~~~~~~~~~~
An Email Stationary Template is used by an
:ref:`Email Message Template `
as container to embed its content in. A stationary is typically used
by many :ref:`Email Messages Types `,
and thus gives a common look-and-feel to various email output.
A Stationary Template contains the following placeholder objects:
- :ref:`Stationary `.
- :ref:`Application `.
And this is how it looks like:
.. callout::
.. code-block:: xml
$stationary.content$ and additional app placeholders]]> # <2>
$stationary.header$
$stationary.content$ and additional cid_ and app placeholders
]]> # <3>
.. annotations::
:1: ``$stationary.header$`` is replaced by the ``header`` entry of the embedded template.
:2: ``$stationary.content$`` is replaced by the ``text`` entry of the embedded template.
:3: ``$stationary.content$`` is replaced by the ``html`` entry of the embedded template.
.. note::
SavaPage uses its own stationary types. These types can be
overwritten. See :ref:`Email Stationary Types `.
.. _ch-custom-email-template-message:
Email Message Template
~~~~~~~~~~~~~~~~~~~~~~
Email Message Templates are used by :ref:`Email Message Types `.
*Template and Type are tied by name.*
For example: the
:ref:`JobTicketCompleted `
message type will look for the nearest i18n version of a
``JobTicketCompleted.xml`` template file. In this way,
``JobTicketCompleted_de.xml`` will be the perfect match when a German
email message is requested.
Email Message Template adds the entry key “``subject``” to the syntax.
Optionally, entry keys “``stationary``” and “``header``” can be used to
link to an :ref:`Email Stationary Template `.
The syntax is described by example in the following XML file:
.. callout::
.. code-block:: xml
# <1>
Text with $obj.attr$ placeholders
# <2>
EmailStationary
Stationary header with placeholders
HTML with placeholders.
]]>
.. annotations::
:1: The ``subject`` text of the email.
:2: The ``stationary`` value (just the template file basename, without the ``.xml`` suffix)
refers to ``EmailStationary.xml``, including i18n ``EmailStationary_*.xml`` variants.
If a stationary is linked this way, the ``header`` value is injected into the ``stationary.header``
placeholder of the target stationary, and the ``text`` and ``html``
values are injected into the ``stationary.content`` placeholder of their
counterpart stationary entry.
.. _ch-custom-email-template-placeholders:
Email Placeholders Objects
~~~~~~~~~~~~~~~~~~~~~~~~~~
.. contents::
:depth: 1
:local:
Placeholder Objects are used in :ref:`Email Stationary `,
and in :ref:`Email Message ` Templates tied to
:ref:`Email Messages Types `.
.. _ch-custom-email-template-placeholder-stationary:
Stationary
^^^^^^^^^^
Object uniquely used by :ref:`Email Stationary Template `.
.. table:: Placeholder: Stationary
+------------------------+-----------------------------------------------+
| Object.attribute | Value |
+========================+===============================================+
| ``stationary.header`` | The ``header`` entry of the embedded |
| | template. |
+------------------------+-----------------------------------------------+
| ``stationary.content`` | The ``text`` or ``html`` entry of the |
| | embedded template. |
+------------------------+-----------------------------------------------+
.. _ch-custom-email-template-placeholder-app:
Application
^^^^^^^^^^^
A global object with SavaPage application attributes. This object
can be used in *any* :ref:`Email Message Type `
context.
.. table:: Placeholder: Application
+--------------------------+-----------------------------------------------+
| Object.attribute | Value |
+==========================+===============================================+
| ``app.name`` | Application name: “|PRODUCT_NAME|” |
+--------------------------+-----------------------------------------------+
| ``app.nameVersion`` | Formatted name and version, like: |br| |
| | |br| |
| | “SavaPage Major.Minor.Revision” |
+--------------------------+-----------------------------------------------+
| ``app.nameVersionBuild`` | Formatted name, version and build, like: |br| |
| | |br| |
| | “SavaPage Major.Minor.Revision (Build)” |
+--------------------------+-----------------------------------------------+
| ``app.slogan`` | Short slogan describing the application: |br| |
| | |br| |
| | “Open Print Portal” |
+--------------------------+-----------------------------------------------+
.. _ch-custom-email-template-placeholder-ticket:
Ticket
^^^^^^
A Print Job Ticket. See |RST_LINK_JOBTICKETS_WEBAPP|.
.. table:: Placeholder: Ticket
+--------------------------+-----------------------------------------------+
| Object.attribute | Value |
+==========================+===============================================+
| ``ticket.number`` | Ticket number. |
+--------------------------+-----------------------------------------------+
| ``ticket.name`` | Document name. |
+--------------------------+-----------------------------------------------+
| ``ticket.operator`` | Name of the Job Ticket Operator. |
+--------------------------+-----------------------------------------------+
| ``ticket.returnMessage`` | The return message to :ref:`Job Ticket |
| | Creator ` |
| | (optional). |
+--------------------------+-----------------------------------------------+
.. _ch-custom-email-template-placeholder-user:
User
^^^^
A User as :ref:`Person `.
.. table:: Placeholder: User
+-----------------------+-----------------------------------------------+
| Object.attribute | Value |
+=======================+===============================================+
| ``user.fullName`` | The full name of the user. |
+-----------------------+-----------------------------------------------+
.. _ch-custom-email-template-placeholder-user-registration:
User Registration
^^^^^^^^^^^^^^^^^
.. table:: Placeholder: User Registration
+-----------------------+-----------------------------------------------+
| Object | Value |
+=======================+===============================================+
| ``user_reg.userName`` | User Name. |
+-----------------------+-----------------------------------------------+
| ``user_reg.fullName`` | User Full Name. |
+-----------------------+-----------------------------------------------+
| ``user_reg.link`` | Verification URL. |
+-----------------------+-----------------------------------------------+
.. _ch-custom-email-stationary-types:
Email Stationary Types
~~~~~~~~~~~~~~~~~~~~~~
SavaPage uses its own Email Stationary Types. As the table below
shows, currently there is just one type in use. You can use this type in
your own custom :ref:`Email Message Template ` files.
Or, you can override this type by creating your own ``EmailStationary.xml`` i18n
variants in the custom ``template/`` directory.
.. table:: Email Stationary Types
+-----------------------+-----------------------------------------------+
| Name | Scope |
+=======================+===============================================+
| ``EmailStationary`` | All Email messages |
+-----------------------+-----------------------------------------------+
.. _ch-custom-email-msg-types:
Email Message Types
~~~~~~~~~~~~~~~~~~~
.. contents::
:depth: 1
:local:
The sections below describe email message types that can be customized.
The list is limited for now, but will grow as more messages are
refactored for this purpose.
.. note::
The global :ref:`Application Object `
is valid for each message type.
.. _ch-custom-email-msg-type-ticket-canceled:
JobTicketCanceled Email
^^^^^^^^^^^^^^^^^^^^^^^
Email sent when a Job Ticket is canceled. See
:ref:`Job Ticket Configuration Properties `.
The following placeholder objects apply:
.. table:: Placeholder Objects: JobTicketCanceled
+-----------------+--------------------------------------------------------------+
| Object | Role |
+=================+==============================================================+
| ``ticket`` | Canceled Job Ticket. |
+-----------------+--------------------------------------------------------------+
| ``user`` | :ref:`Job Ticket Creator `. |
+-----------------+--------------------------------------------------------------+
.. _ch-custom-email-msg-type-ticket-completed:
JobTicketCompleted Email
^^^^^^^^^^^^^^^^^^^^^^^^
Email sent when a Job Ticket is completed successfully. See
:ref:`Job Ticket Configuration Properties `.
The following placeholder objects apply:
.. table:: Placeholder Objects: JobTicketCompleted
+-----------------+--------------------------------------------------------------+
| Object | Role |
+=================+==============================================================+
| ``ticket`` | Completed Job Ticket. |
+-----------------+--------------------------------------------------------------+
| ``user`` | :ref:`Job Ticket Creator `. |
+-----------------+--------------------------------------------------------------+
.. _ch-custom-email-msg-type-user-reg-verification:
UserRegVerification
^^^^^^^^^^^^^^^^^^^
Email sent to verify User :ref:`Self Registration `.
The following placeholder objects apply:
.. table:: Placeholder Objects: UserRegVerification
+-----------------+--------------------------------------------------------------------+
| Object | Role |
+=================+====================================================================+
| ``user_reg`` | User |
| | :ref:`Self Registration `. |
+-----------------+--------------------------------------------------------------------+
.. _ch-custom-template-locations:
Custom Template Locations
~~~~~~~~~~~~~~~~~~~~~~~~~
Custom templates are located in the
``/opt/savapage/server/custom/template/`` directory. Sub-locations
can be defined for different template groups. These sub-locations can
then be activated for different applications, with the following
configuration properties:
.. list-table:: Configuration Properties for Custom Template Locations
:width: 100%
:header-rows: 1
* - Configuration property
- Description
* - custom.template.home
- Home location of *all* template files, relative to the default location.
For example: a value of ``group-1``` will resolve to: |br|
``/opt/savapage/server/custom/template/group-1``
* - custom.template.home.mail
- Home location of Email template files, relative to the default location.
For example: a value of ``group-1/mail`` will resolve to: |br|
``/opt/savapage/server/custom/template/group-1/mail``
See |RST_LINK_CONFIG_EDITOR| on how to set these items.