What It Is
Email Templates are reusable message containers that define the subject line and body content for ServiceNow Notifications. They solve the fundamental problem of maintaining consistent, professional email communication across your platform without duplicating HTML markup and content logic in every notification rule. Rather than embedding message content directly into notification records, you reference a template that can be shared across multiple notifications and updated centrally.
Architecturally, Email Templates live in the System Notification application as part of the notification framework layer, sitting between your business logic and the actual email delivery mechanism. They're stored in the sysevent_email_template table and get processed by the notification engine during email generation. The template acts as a formatting layer that receives context data from the triggering record and transforms it into human-readable email content through variable substitution.
The underlying execution model processes templates through ServiceNow's email rendering engine, which parses substitution variables like ${number} and ${short_description} against the record that triggered the notification. Templates support both simple field references and complex expressions using dot-walking syntax for related records. The engine also handles HTML sanitization, encoding, and attachment processing during the rendering phase before handing the final message to the email queue.
You cannot function without Email Templates in any environment that requires professional, branded, or legally compliant email communication. The moment you need consistent formatting across incident notifications, approval requests, and user communications, individual notification configuration becomes unmaintainable. Templates become absolutely essential when you're supporting multiple business units with different branding requirements, managing multilingual communications, or maintaining audit trails for compliance where message content must be centrally controlled and version-tracked.
ServiceNow administrators typically manage Email Templates as part of notification configuration, though developers often create the initial templates with complex variable logic and HTML structure. Platform owners control template governance, especially in scoped applications where templates can be application-specific. The relationship is collaborative: developers build the technical framework and variable structure, admins configure the business content and maintain ongoing updates, while platform owners ensure templates follow enterprise standards and don't create performance issues.
Recent ServiceNow releases enhanced Email Templates with improved HTML editor capabilities and better variable validation in Vancouver, while Xanadu introduced enhanced template preview functionality and stricter security controls around script execution within templates. The platform also added better support for responsive email design and improved template inheritance patterns for scoped applications, making it easier to maintain brand consistency across custom applications.
Where to Find and Configure It
Navigate to System Notification > Email > Email Templates for the primary configuration interface where you create, modify, and test email templates. Access System Definition > Tables and search for sysevent_email_template to manage templates at the data level or perform bulk operations. Use Studio > Email Templates when developing scoped application templates that need to be packaged and deployed with your application.
See templates in action by going to System Notification > Email > Notifications where the Email Template field references your templates, or check System Logs > Email to see rendered template output in sent messages. For scoped applications, templates created in Studio are application-scoped and only available to notifications within that scope, while global templates can be used across all applications but require admin access to modify.
How It Works Step by Step
Email Templates operate as dynamic content generators within ServiceNow's notification pipeline, processing substitution variables against record data to produce formatted email messages. When a notification fires, the system loads the referenced template and passes it the context of the triggering record, along with any additional variables defined in the notification itself. The template engine parses the HTML and text content, identifies variable placeholders using the ${variable_name} syntax, and replaces them with actual values from the record or calculated expressions.
The rendering process handles both simple field substitution and complex dot-walking operations like ${assigned_to.manager.email} by following reference relationships in the database. Variable resolution respects field access controls and returns empty strings for fields the recipient cannot access, while the HTML processing engine handles encoding to prevent injection attacks. Templates can include conditional logic through advanced variable expressions and support both plain text and HTML versions for different email client capabilities.
Enjoying this? Get one deep-dive per week.
Join 1,000+ ServiceNow pros — scripts, GlideRecord patterns, Flow Designer techniques, and career moves. Free.
The Execution Order
- Notification rule evaluates conditions and determines an Email Template should be used
- System loads template record from
sysevent_email_templatetable using template reference - Template engine receives current record context and notification variables as input data
- Variable parser scans subject line and body content for
${...}placeholders - Each variable gets resolved against record data, following reference chains if dot-walking is used
- HTML content gets processed for encoding and sanitization while preserving markup structure
- Final rendered content gets passed to email queue with recipient list and attachments
<h2>Incident ${number} Assigned</h2>
<p><strong>Priority:</strong> ${priority}</p>
<p><strong>Short Description:</strong> ${short_description}</p>
<p><strong>Assigned to:</strong> ${assigned_to.name}</p>
<p><strong>Assignment Group:</strong> ${assignment_group.name}</p>
<div style="background-color: #f5f5f5; padding: 10px; margin: 10px 0;">
<h3>Current Work Notes:</h3>
<p>${work_notes}</p>
</div>
<p><a href="${instance_url}/${table}/${sys_id}">View Incident</a></p>
<hr>
<p><small>This notification was sent because you are ${notification_reason}</small></p>Real-World Scenarios
Multi-Language Incident Assignment Template
Your global support team needs incident assignment notifications in multiple languages based on the assigned user's preferred language setting. Rather than maintaining separate notification rules for each language, you need a single template that adapts content dynamically.
Create the template with name Multi-Language Incident Assignment and set the subject to ${gs.getMessage('incident.assigned.subject', [number])}. In the HTML body, use ${gs.getMessage('incident.assigned.greeting', [assigned_to.first_name])} for personalized greetings and wrap all static text in getMessage calls that reference your message catalog entries. Configure the notification to use Language field from the recipient's user record.
Watch for message catalog completeness across all supported languages and test with users who have different language preferences set. The template will fall back to English if getMessage can't find translations, but empty message keys will render as literal key names in the email. You'll also need to ensure your ServiceNow instance has the appropriate language packs installed for proper date and time formatting within the template variables.
Branded Approval Request with Company Logo
Executive leadership requires professional-looking approval request emails that include the company logo, proper branding, and clear approval action buttons. The template must work for all approval types while maintaining corporate visual standards and ensuring approvers can act directly from their email client.
Upload your company logo to System UI > Images and note the image URL. Create an Email Template named Corporate Approval Request with HTML body including <img src="/your_logo.png" alt="Company Logo"> in the header. Add approval action links using <a href="${instance_url}/approve.do?sys_id=${sysapproval_approver}&state=approved">Approve</a> and similar for rejection. Include CSS styling for consistent button appearance and responsive design.
Test image accessibility from external email clients since some block external images by default, and consider embedding base64-encoded images for critical branding elements. The approval links work best when combined with email security settings that whitelist your ServiceNow instance domain. Monitor that your CSS doesn't break in Outlook clients, which have limited HTML rendering capabilities compared to modern email clients.
Change Advisory Board Meeting Digest with Risk Assessment
Your Change Advisory Board needs weekly digest emails summarizing upcoming changes with risk assessments, impact analysis, and implementation schedules. The template must aggregate data from multiple change records and present it in a scannable format that highlights high-risk changes requiring board attention.
<h1>Change Advisory Board Weekly Digest</h1>
<h2>High Risk Changes - Immediate Attention Required</h2>
<div class="high-risk">
<g:evaluate>
var gr = new GlideRecord('change_request');
gr.addQuery('risk', 'high');
gr.addQuery('state', 'IN', 'scheduled_for_review,scheduled_for_approval');
gr.query();
while(gr.next()) {
template.print('<div style="border-left: 4px solid red; padding-left: 10px; margin: 10px 0;">');
template.print('<h3>CHG' + gr.number + ' - ' + gr.short_description + '</h3>');
template.print('<p><strong>Risk:</strong> ' + gr.risk.getDisplayValue() + '</p>');
template.print('<p><strong>Implementation:</strong> ' + gr.start_date.getDisplayValue() + '</p>');
template.print('<p><strong>Business Impact:</strong> ' + gr.business_impact + '</p>');
template.print('</div>');
}
</g:evaluate>
</div>Watch for performance issues when the digest includes many change records, and consider adding query limits or date ranges to prevent email timeouts. The g:evaluate tags execute server-side during template rendering, so complex queries can delay email delivery. Ensure your scheduled notification that triggers this template runs during off-peak hours, and test with realistic data volumes to verify the email renders properly in different email clients with the generated HTML structure.
The Classic Mistake
Putting complex business logic and database queries directly in the Email Template's HTML body instead of using Mail Scripts to populate variables.
<h2>Incident ${number} Update</h2>
<p>Assigned to:
${if (assigned_to) {
var gr = new GlideRecord('sys_user');
gr.get(assigned_to);
var manager = new GlideRecord('sys_user');
if (gr.manager && manager.get(gr.manager)) {
return gr.getDisplayValue() + ' (Manager: ' + manager.getDisplayValue() + ')';
}
return gr.getDisplayValue();
} else {
return 'Unassigned';
}}
</p>
<p>Total incidents for this user:
${var count = new GlideAggregate('incident');
count.addQuery('assigned_to', assigned_to);
count.addAggregate('COUNT');
count.query();
if (count.next()) count.getAggregate('COUNT'); else '0'}
</p>This approach fails because Email Templates execute in a limited context where complex GlideRecord operations often timeout or throw security exceptions. Users see emails with literal JavaScript code instead of processed data, or emails fail to send entirely with cryptic errors in the System Log > Email. ServiceNow processes the template synchronously during notification generation, causing performance bottlenecks when multiple notifications trigger simultaneously. The template parser has strict execution limits that aren't clearly documented, making complex logic unpredictable.
<h2>Incident ${number} Update</h2>
<p>Assigned to: ${mail_script.assignee_with_manager}</p>
<p>Total incidents for this user: ${mail_script.user_incident_count}</p>
<p>Priority: ${priority}</p>
<p>State: ${state}</p>
<div style="margin-top: 20px;">
<h3>Recent Comments</h3>
${mail_script.formatted_comments}
</div>
<p style="font-size: 12px; color: #666;">
This incident was last updated on ${sys_updated_on} by ${sys_updated_by}
</p>If your email template substitution requires more than a simple field reference or basic conditional, create a Mail Script instead and reference it as ${mail_script.script_name}.
When to Use This vs Alternatives
Use Email Templates when you need consistent, reusable email formatting across multiple notifications with dynamic content substitution. This is the standard approach for any email that needs to reference record data, support multiple languages, or maintain corporate branding standards.
When Email Templates Are Correct
Choose Email Templates for any notification that needs HTML formatting, record field substitution, or will be reused across multiple notification records. Hardcoding email content directly in the Message HTML field of notifications creates maintenance nightmares and prevents translation support. Email Templates provide version control through update sets and support the translation framework automatically.
When to Use Direct Message Content
Skip Email Templates for simple, one-off notifications that only need plain text and basic field substitution. System-generated notifications like password resets or simple approval confirmations work fine with direct message content in the notification record. The overhead of creating a template isn't justified when the message is static and won't be reused.
When You Need Both Templates and Scripts
Complex notifications require Email Templates paired with Mail Scripts for optimal performance and maintainability. Use Mail Scripts to handle database queries, complex calculations, and formatting logic, then reference the script results in your Email Template using ${mail_script.script_name}. This separation keeps templates focused on presentation while scripts handle business logic, making both easier to debug and modify.
Platform Interactions & Side Effects
- Notification Engine processes templates synchronously, blocking the transaction until all substitutions complete - can cause timeout errors on complex database queries within templates
- Template processing respects ACL restrictions based on the notification sender's user context, potentially hiding field values that should appear in emails
- Update Sets capture Email Template changes but don't automatically update dependent notification records - requires manual verification after deployment
- Translation framework creates duplicate template records in
sys_email_templatetable with language-specific suffixes, not visible in standard template lists - Template substitution variables execute with elevated privileges when referenced from system notifications, bypassing normal script security restrictions
- Business Rules on
sys_emailtable can modify template content after substitution but before sending, creating hard-to-trace email discrepancies - Template processing writes debug information to
syslogtable whenglide.email.log.levelis set to info or debug, consuming significant database space in high-volume environments - Email client rendering variations cause template HTML to display differently across Outlook, Gmail, and mobile clients - no server-side validation catches these issues
- Template caching in application nodes can serve stale content for up to 5 minutes after updates, causing inconsistent email formatting in clustered environments
- Failed template substitutions write error records to
syseventtable withemail.failedevent name, but don't automatically retry or alert administrators
Debugging and Troubleshooting
Template failures typically manifest as emails containing literal JavaScript code instead of processed values, emails with missing content sections, or notifications that simply don't send. Users report receiving emails with text like ${incident.number} instead of actual incident numbers, or administrators notice email queues backing up without error messages. The most common symptom is partial template processing where some substitutions work but others display as raw variable names.
Start debugging by checking System Log > Email for template processing errors, then examine the sys_email table to see exactly what content was generated before sending. Enable detailed email logging by setting glide.email.log.level to debug and reproduce the notification to capture detailed substitution logs. The Application Navigator's Preview Email Template feature under System Notification shows real-time processing but requires a specific record context to test variable substitution.
Look for specific error patterns in logs: "Template variable not found" indicates incorrect field references, "Script execution timeout" suggests complex database queries in templates, and "Access denied" errors point to ACL restrictions blocking field access during template processing. Failed substitutions often log as "Invalid script in email template" with the specific line number and variable name that caused the failure.
- Verify the notification record references the correct template in the
Message HTMLfield using${template:template_name} - Test template substitution using a known record by navigating to the template and clicking
Previewwith a valid sys_id - Check if referenced Mail Scripts exist and are active in
System Definition > Mail Scripts - Verify field names match the table schema exactly - case sensitivity matters for all substitution variables
- Enable
glide.email.log.level=debugand reproduce the notification to capture detailed processing logs - Query
sys_emailtable filtering by recipient and recent dates to see the actual generated content - Check ACL permissions for the notification sender user on fields referenced in template substitutions
Quick Reference
- Template names must be unique across all applications - duplicates cause random template selection based on sys_id sort order
- Maximum template size is 4MB in the
body_htmlfield - larger templates silently truncate without error messages - Template caching refreshes every 300 seconds (5 minutes) by default - modify
glide.email.template.cache_expirysystem property to change - Substitution variable processing timeout is 30 seconds per template - complex queries cause email generation failure
- Reference fields in templates use
${field_name.display_value}syntax - omitting.display_valueshows sys_id values instead - Template translation creates separate records with language suffixes like
_esfor Spanish - these don't appear in standard template lists - HTML email clients strip
<script>tags and most CSS - use inline styles and avoid JavaScript entirely - Template variables execute with the notification sender's user permissions - system notifications bypass normal ACL restrictions
- Failed template processing falls back to plain text from the
Messagefield in notifications - always populate both fields - Templates process once per recipient - high recipient count notifications with complex templates cause significant database load