#Template reference
Signatures are written in HTML with Liquid placeholders. Liquid is a simple, safe templating language: it can print values, test conditions and loop over lists, but it cannot run code or access the server.
#Printing values
Wrap a variable in double braces:
<b>{{ user.displayName }}</b>
Every printed value is HTML-encoded automatically, so a name containing < or & can never break or inject markup. You do not need (and should not use) an escape filter.
A variable without a value is empty (nil): it prints nothing and counts as false in conditions.
#User data — user.*
Read from Microsoft Entra ID.
| Variable | Entra attribute | Example |
|---|---|---|
user.displayName |
Display name | Jane Doe |
user.givenName |
First name | Jane |
user.surname |
Last name | Doe |
user.jobTitle |
Job title | Head of Sales |
user.department |
Department | Sales |
user.companyName |
Company name | Example Ltd. |
user.officeLocation |
Office | Ljubljana |
user.mail |
E-mail address | jane.doe@example.com |
user.upn |
User principal name | jane.doe@example.com |
user.mobilePhone |
Mobile phone | +386 41 123 456 |
user.businessPhone |
Business phone | +386 1 234 5678 |
user.ext.ext1 … user.ext.ext15 |
Extension attributes 1–15 | any text |
Extension attributes are the place for data that has no standard field — for example a second language title, a licence number or a direct-dial extension. Fill them in Entra ID / Active Directory (extensionAttribute1…15) and use {{ user.ext.ext3 }}.
Leading and trailing spaces are trimmed; empty strings become empty values.
#Organization data — org.*
Set in the portal under Organizations and inherited down the tree.
| Variable | Meaning |
|---|---|
org.name |
Company name |
org.address |
Address |
org.website |
Website (display text) |
org.websiteUrl |
Website (link) |
org.logoUrl |
Logo address (https://…) |
org.accentColor |
Accent colour, for example #0f766e |
org.<yourField> |
Any custom field you added |
#Conditions
Hide lines that would otherwise be empty:
{% if user.mobilePhone %}
M {{ user.mobilePhone }}<br>
{% endif %}
Other forms:
{% if user.department == "Sales" %} … {% elsif user.department == "Support" %} … {% else %} … {% endif %}
{% unless user.jobTitle %} (no title) {% endunless %}
{% if user.jobTitle and user.department %} … {% endif %}
{% if user.mail contains "@example.com" %} … {% endif %}
#Assigning variables and defaults
{% assign accent = org.accentColor | default: "#0f766e" %}
{% assign company = user.companyName | default: org.name %}
<span style="color:{{ accent }}">{{ company }}</span>
#Filters
Filters transform a value: {{ value | filter: argument }}. Commonly useful ones:
| Filter | Example | Result |
|---|---|---|
default |
{{ user.jobTitle | default: "Employee" }} |
fallback when empty |
remove |
{{ user.mobilePhone | remove: " " }} |
+38641123456 (for tel: links) |
replace |
{{ user.department | replace: "&", "and" }} |
substitute text |
upcase, downcase, capitalize |
{{ user.surname | upcase }} |
DOE |
truncate |
{{ user.jobTitle | truncate: 40 }} |
shortened text |
append, prepend |
{{ user.mail | prepend: "mailto:" }} |
add text |
strip, size |
{{ user.displayName | size }} |
trim, length |
The standard Liquid filter set is available.
#What is not allowed
For security and stability SignetMail restricts templates:
- No ranges such as
(1..100); they are rejected when the template is saved. Loops over data ({% for … %}) are allowed, but total work is capped (step limit and nesting depth). - No access to .NET objects or server data beyond
user.*andorg.*. - No scripts in the output:
<script>, event attributes (onclick…) andjavascript:links are rejected on save/publish. - Output is always HTML-encoded; there is no "raw" output.
- Templates that are too complex fail with a clear error instead of hanging the server.
#HTML for e-mail
Mail clients are not browsers. The most reliable rules:
- Tables for layout, no
divgrids, noflex/grid. - Inline styles on every element (the CSS tab inlines for you).
- Images with absolute
https://URLs,width,height,altandstyle="display:block;border:0". - Safe fonts: Arial, Helvetica, Calibri, Verdana, Georgia, Times New Roman.
- Links with
https://,mailto:ortel:(use| remove: " "for phone numbers). - Keep the HTML small (under 60 KB).
#A complete example
{%- assign accent = org.accentColor | default: "#0f766e" -%}
<table cellpadding="0" cellspacing="0" border="0" role="presentation"
style="border-collapse:collapse;font-family:Arial,Helvetica,sans-serif;font-size:13px;line-height:18px;color:#1f2937;">
<tr>
{%- if org.logoUrl %}
<td valign="top" style="padding:0 16px 0 0;">
<img src="{{ org.logoUrl }}" width="80" height="80" alt="{{ org.name }}" style="display:block;border:0;">
</td>
{%- endif %}
<td valign="top" style="padding-left:14px;border-left:3px solid {{ accent }};">
<div style="font-size:15px;font-weight:bold;">{{ user.displayName }}</div>
{%- if user.jobTitle %}<div>{{ user.jobTitle }}</div>{% endif %}
{%- if user.businessPhone %}<div>T {{ user.businessPhone }}</div>{% endif %}
{%- if user.mail %}<div><a href="mailto:{{ user.mail }}">{{ user.mail }}</a></div>{% endif %}
</td>
</tr>
</table>
#Plain-text parts
The text parts use the same variables and conditions but no HTML:
{{ user.displayName }}
{%- if user.jobTitle %}
{{ user.jobTitle }}{% endif %}
{{ org.name }}
#Campaign banners
When a campaign applies to a person, SignetMail appends the banner to the end of the rendered signature automatically (and its alternative text to the plain-text version). You do not add anything to the template for that.