email-notifications
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseEmail Notifications for ServiceNow
ServiceNow邮件通知
ServiceNow notifications are triggered by events and send emails, SMS, or other alerts to users.
ServiceNow通知由事件触发,可向用户发送邮件、短信或其他告警信息。
Notification Components
通知组件
| Component | Table | Purpose |
|---|---|---|
| Notification | sysevent_email_action | Main notification record |
| Email Template | sysevent_email_template | Reusable email layouts |
| Event | sysevent | Triggers notifications |
| Event Registration | sysevent_register | Defines custom events |
| Email Script | sys_script_email | Dynamic content scripts |
| 组件 | 表名 | 用途 |
|---|---|---|
| Notification | sysevent_email_action | 主要通知记录 |
| Email Template | sysevent_email_template | 可复用邮件布局 |
| Event | sysevent | 触发通知 |
| Event Registration | sysevent_register | 定义自定义事件 |
| Email Script | sys_script_email | 动态内容脚本 |
Creating Notifications
创建通知
Basic Notification Structure
基础通知结构
Notification: Incident Assigned
├── When to send
│ ├── Table: incident
│ ├── When: Record inserted or updated
│ └── Conditions: assigned_to changes AND is not empty
├── Who will receive
│ ├── Users: ${assigned_to}
│ └── Groups: (optional)
├── What it will contain
│ ├── Subject: Incident ${number} assigned to you
│ ├── Message: HTML body with ${field} references
│ └── Email Template: (optional)
└── Advanced
├── Weight: 0 (priority)
└── Send to event creator: falseNotification: Incident Assigned
├── 发送时机
│ ├── 表:incident
│ ├── 触发条件:记录插入或更新
│ └── 筛选条件:assigned_to字段变更且不为空
├── 收件人
│ ├── 用户:${assigned_to}
│ └── 用户组:(可选)
├── 通知内容
│ ├── 主题:事件${number}已分配给您
│ ├── 消息:包含${field}引用的HTML正文
│ └── 邮件模板:(可选)
└── 高级设置
├── 权重:0(优先级)
└── 是否发送给事件创建者:falseNotification Conditions
通知条件
javascript
// Simple field conditions
assigned_to CHANGES
priority = 1
state = 6 // Resolved
// Script condition (ES5 only!)
// Returns true to send, false to skip
(function() {
// Only notify for VIP callers
var caller = current.caller_id.getRefRecord();
return caller.vip == true;
})()
// Advanced condition with multiple checks
(function() {
// Don't notify on bulk updates
if (current.sys_mod_count > 100) return false;
// Only for production CIs
var ci = current.cmdb_ci.getRefRecord();
return ci.used_for == 'Production';
})()javascript
// 简单字段条件
assigned_to CHANGES
priority = 1
state = 6 // 已解决
// 脚本条件(仅支持ES5!)
// 返回true则发送,false则跳过
(function() {
// 仅通知VIP呼叫者
var caller = current.caller_id.getRefRecord();
return caller.vip == true;
})()
// 多条件高级判断
(function() {
// 批量更新时不发送通知
if (current.sys_mod_count > 100) return false;
// 仅针对生产环境配置项
var ci = current.cmdb_ci.getRefRecord();
return ci.used_for == 'Production';
})()Email Templates
邮件模板
Template Variables
模板变量
html
<!-- Field references -->
${number} <!-- Direct field value -->
${caller_id.name} <!-- Dot-walked reference -->
${opened_at.display_value} <!-- Display value -->
<!-- Special variables -->
${URI} <!-- Link to record -->
${URI_REF} <!-- Reference link -->
${mail_script:script_name} <!-- Include email script -->
<!-- Conditional content -->
${mailto:assigned_to} <!-- Mailto link -->html
<!-- 字段引用 -->
${number} <!-- 直接字段值 -->
${caller_id.name} <!-- 关联字段取值 -->
${opened_at.display_value} <!-- 显示值 -->
<!-- 特殊变量 -->
${URI} <!-- 记录链接 -->
${URI_REF} <!-- 引用链接 -->
${mail_script:script_name} <!-- 引入邮件脚本 -->
<!-- 条件内容 -->
${mailto:assigned_to} <!-- 邮件链接 -->Template Example
模板示例
html
<html>
<body style="font-family: Arial, sans-serif;">
<h2>Incident ${number} - ${short_description}</h2>
<table border="0" cellpadding="5">
<tr>
<td><strong>Priority:</strong></td>
<td>${priority}</td>
</tr>
<tr>
<td><strong>Caller:</strong></td>
<td>${caller_id.name}</td>
</tr>
<tr>
<td><strong>Assigned to:</strong></td>
<td>${assigned_to.name}</td>
</tr>
<tr>
<td><strong>Description:</strong></td>
<td>${description}</td>
</tr>
</table>
<p>
<a href="${URI}">View Incident</a>
</p>
${mail_script:incident_history}
</body>
</html>html
<html>
<body style="font-family: Arial, sans-serif;">
<h2>事件${number} - ${short_description}</h2>
<table border="0" cellpadding="5">
<tr>
<td><strong>优先级:</strong></td>
<td>${priority}</td>
</tr>
<tr>
<td><strong>呼叫者:</strong></td>
<td>${caller_id.name}</td>
</tr>
<tr>
<td><strong>负责人:</strong></td>
<td>${assigned_to.name}</td>
</tr>
<tr>
<td><strong>描述:</strong></td>
<td>${description}</td>
</tr>
</table>
<p>
<a href="${URI}">查看事件</a>
</p>
${mail_script:incident_history}
</body>
</html>Email Scripts
邮件脚本
Basic Email Script
基础邮件脚本
javascript
// Email Script: incident_history
// Table: incident
// Script (ES5 only!):
(function runMailScript(current, template, email, email_action, event) {
// Build activity history
var html = '<h3>Recent Activity</h3><ul>';
var history = new GlideRecord('sys_journal_field');
history.addQuery('element_id', current.sys_id);
history.addQuery('name', 'incident');
history.orderByDesc('sys_created_on');
history.setLimit(5);
history.query();
while (history.next()) {
html += '<li><strong>' + history.sys_created_on.getDisplayValue() + '</strong>: ';
html += history.value.substring(0, 200) + '</li>';
}
html += '</ul>';
template.print(html);
})(current, template, email, email_action, event);javascript
// 邮件脚本:incident_history
// 表:incident
// 脚本(仅支持ES5!):
(function runMailScript(current, template, email, email_action, event) {
// 构建活动历史
var html = '<h3>近期活动</h3><ul>';
var history = new GlideRecord('sys_journal_field');
history.addQuery('element_id', current.sys_id);
history.addQuery('name', 'incident');
history.orderByDesc('sys_created_on');
history.setLimit(5);
history.query();
while (history.next()) {
html += '<li><strong>' + history.sys_created_on.getDisplayValue() + '</strong>: ';
html += history.value.substring(0, 200) + '</li>';
}
html += '</ul>';
template.print(html);
})(current, template, email, email_action, event);Email Script with Attachments
带附件的邮件脚本
javascript
// Add attachments from the record to the email
(function runMailScript(current, template, email, email_action, event) {
var gr = new GlideRecord('sys_attachment');
gr.addQuery('table_sys_id', current.sys_id);
gr.addQuery('table_name', 'incident');
gr.query();
while (gr.next()) {
email.addAttachment(gr);
}
})(current, template, email, email_action, event);javascript
// 将记录中的附件添加到邮件
(function runMailScript(current, template, email, email_action, event) {
var gr = new GlideRecord('sys_attachment');
gr.addQuery('table_sys_id', current.sys_id);
gr.addQuery('table_name', 'incident');
gr.query();
while (gr.next()) {
email.addAttachment(gr);
}
})(current, template, email, email_action, event);Dynamic Recipients
动态收件人
javascript
// Email Script to add CC recipients dynamically
(function runMailScript(current, template, email, email_action, event) {
// Add all group members as CC
var group = current.assignment_group;
if (!group.nil()) {
var members = new GlideRecord('sys_user_grmember');
members.addQuery('group', group);
members.query();
while (members.next()) {
var user = members.user.getRefRecord();
if (user.email) {
email.addAddress('cc', user.email, user.name);
}
}
}
})(current, template, email, email_action, event);javascript
// 动态添加抄送人邮件脚本
(function runMailScript(current, template, email, email_action, event) {
// 将所有组成员添加为抄送人
var group = current.assignment_group;
if (!group.nil()) {
var members = new GlideRecord('sys_user_grmember');
members.addQuery('group', group);
members.query();
while (members.next()) {
var user = members.user.getRefRecord();
if (user.email) {
email.addAddress('cc', user.email, user.name);
}
}
}
})(current, template, email, email_action, event);Custom Events
自定义事件
Registering a Custom Event
注册自定义事件
javascript
// Event Registration
// Name: x_myapp.incident.escalated
// Table: incident
// Description: Fired when incident is escalated to management
// Fired by: Business Rule
// In Business Rule (ES5 only!)
(function executeRule(current, previous) {
// Check if escalation occurred
if (current.escalation > previous.escalation) {
// Fire custom event
gs.eventQueue('x_myapp.incident.escalated', current,
current.escalation.getDisplayValue(), // parm1
current.assigned_to.name // parm2
);
}
})(current, previous);javascript
// 事件注册
// 名称:x_myapp.incident.escalated
// 表:incident
// 描述:事件升级到管理层时触发
// 触发方式:业务规则
// 业务规则中(仅支持ES5!)
(function executeRule(current, previous) {
// 检查是否发生升级
if (current.escalation > previous.escalation) {
// 触发自定义事件
gs.eventQueue('x_myapp.incident.escalated', current,
current.escalation.getDisplayValue(), // 参数1
current.assigned_to.name // 参数2
);
}
})(current, previous);Notification on Custom Event
基于自定义事件的通知
Notification: Escalation Alert
├── When to send
│ ├── Send when: Event is fired
│ └── Event name: x_myapp.incident.escalated
├── Who will receive
│ └── Users/Groups: Escalation Managers
└── What it will contain
├── Subject: Escalation: ${number} - ${event.parm1}
└── Message: Incident escalated. Assigned to: ${event.parm2}Notification: 升级告警
├── 发送时机
│ ├── 触发条件:事件触发时
│ └── 事件名称:x_myapp.incident.escalated
├── 收件人
│ └── 用户/用户组:升级管理人员
└── 通知内容
├── 主题:升级通知:${number} - ${event.parm1}
└── 消息:事件已升级,负责人:${event.parm2}Recipient Types
收件人类型
Who Will Receive
收件人范围
| Type | Description | Example |
|---|---|---|
| Users | Specific users | ${assigned_to}, ${caller_id} |
| Groups | User groups | Service Desk, CAB |
| Group Managers | Group manager field | ${assignment_group.manager} |
| Event Parm 1/2 | From event parameters | ${event.parm1} |
| Additional Recipients | Email addresses | External emails |
| 类型 | 描述 | 示例 |
|---|---|---|
| Users | 指定用户 | ${assigned_to}, ${caller_id} |
| Groups | 用户组 | Service Desk, CAB |
| Group Managers | 组管理员字段 | ${assignment_group.manager} |
| Event Parm 1/2 | 事件参数取值 | ${event.parm1} |
| Additional Recipients | 外部邮箱地址 | 外部联系人邮箱 |
Recipient Script
收件人脚本
javascript
// Recipient Script (ES5 only!)
// Returns comma-separated list of emails or sys_ids
(function getRecipients(current, event) {
var recipients = [];
// Add the caller
if (!current.caller_id.nil()) {
recipients.push(current.caller_id.email.toString());
}
// Add VIP's manager
var caller = current.caller_id.getRefRecord();
if (caller.vip == true && !caller.manager.nil()) {
recipients.push(caller.manager.email.toString());
}
return recipients.join(',');
})(current, event);javascript
// 收件人脚本(仅支持ES5!)
// 返回逗号分隔的邮箱地址或用户sys_id列表
(function getRecipients(current, event) {
var recipients = [];
// 添加呼叫者
if (!current.caller_id.nil()) {
recipients.push(current.caller_id.email.toString());
}
// 添加VIP用户的经理
var caller = current.caller_id.getRefRecord();
if (caller.vip == true && !caller.manager.nil()) {
recipients.push(caller.manager.email.toString());
}
return recipients.join(',');
})(current, event);Notification Weight
通知权重
Priority system for multiple matching notifications:
| Weight | Use Case |
|---|---|
| 0 | Default priority |
| 1-99 | Higher priority (lower weight = higher priority) |
| -1 to -99 | Lower priority |
| 100+ | Rarely used |
javascript
// Only highest weight notification sends if "Exclude subscribers" checked
// Weight 0 notification beats Weight 10 notification多通知匹配时的优先级机制:
| 权重 | 使用场景 |
|---|---|
| 0 | 默认优先级 |
| 1-99 | 高优先级(权重值越小,优先级越高) |
| -1至-99 | 低优先级 |
| 100+ | 极少使用 |
javascript
// 若勾选“排除订阅者”,仅最高优先级通知会发送
// 权重0的通知优先级高于权重10的通知Digest Notifications
摘要通知
Configuring Digest
配置摘要通知
Notification: Daily Incident Summary
├── Digest: Checked
├── Digest Interval: Daily
├── Digest Time: 08:00
└── Content: Summary of all incidentsNotification: 每日事件汇总
├── 摘要:已勾选
├── 摘要间隔:每日
├── 发送时间:08:00
└── 内容:所有事件汇总Digest Email Script
摘要邮件脚本
javascript
// Summarize digest records
(function runMailScript(current, template, email, email_action, event) {
var count = 0;
var html = '<table border="1" cellpadding="5">';
html += '<tr><th>Number</th><th>Description</th><th>Priority</th></tr>';
// 'current' is a GlideRecord with all digest records
while (current.next()) {
count++;
html += '<tr>';
html += '<td>' + current.number + '</td>';
html += '<td>' + current.short_description + '</td>';
html += '<td>' + current.priority.getDisplayValue() + '</td>';
html += '</tr>';
}
html += '</table>';
html += '<p>Total: ' + count + ' incidents</p>';
template.print(html);
})(current, template, email, email_action, event);javascript
// 汇总摘要记录
(function runMailScript(current, template, email, email_action, event) {
var count = 0;
var html = '<table border="1" cellpadding="5">';
html += '<tr><th>编号</th><th>描述</th><th>优先级</th></tr>';
// 'current' 为包含所有摘要记录的GlideRecord对象
while (current.next()) {
count++;
html += '<tr>';
html += '<td>' + current.number + '</td>';
html += '<td>' + current.short_description + '</td>';
html += '<td>' + current.priority.getDisplayValue() + '</td>';
html += '</tr>';
}
html += '</table>';
html += '<p>总计:' + count + ' 个事件</p>';
template.print(html);
})(current, template, email, email_action, event);Outbound Email Configuration
outbound邮件配置
Email Properties
邮件属性
javascript
// System Properties for email
glide.email.smtp.active // Enable/disable outbound email
glide.email.smtp.host // SMTP server
glide.email.smtp.port // SMTP port (usually 25 or 587)
glide.email.default.sender // Default from address
glide.email.test.user // Test recipient (all emails go here)javascript
// 系统邮件属性
glide.email.smtp.active // 启用/禁用 outbound邮件
glide.email.smtp.host // SMTP服务器
glide.email.smtp.port // SMTP端口(通常为25或587)
glide.email.default.sender // 默认发件人地址
glide.email.test.user // 测试收件人(所有邮件将发送至此)Testing Notifications
测试通知
javascript
// Background Script to test notification (ES5 only!)
var gr = new GlideRecord('incident');
gr.get('sys_id_here');
// Fire event to trigger notification
gs.eventQueue('incident.assigned', gr,
gr.assigned_to.getDisplayValue(),
gs.getUserDisplayName());
gs.info('Event queued for incident: ' + gr.number);javascript
// 测试通知的后台脚本(仅支持ES5!)
var gr = new GlideRecord('incident');
gr.get('sys_id_here');
// 触发事件以启动通知
gs.eventQueue('incident.assigned', gr,
gr.assigned_to.getDisplayValue(),
gs.getUserDisplayName());
gs.info('已为事件触发队列:' + gr.number);Best Practices
最佳实践
- Use Templates - Reuse layouts across notifications
- Test Thoroughly - Use test user property during development
- Consider Digests - For high-volume notifications
- Weight Carefully - Prevent duplicate emails
- ES5 Only - All scripts must be ES5 compliant
- Limit Recipients - Don't spam large groups
- Include Context - Provide enough info to act without login
- Mobile-Friendly - Keep HTML simple for mobile clients
- 使用模板 - 在多个通知中复用布局
- 充分测试 - 开发期间使用测试用户属性
- 考虑摘要通知 - 针对高频率通知场景
- 合理设置权重 - 避免重复邮件
- 仅用ES5 - 所有脚本必须兼容ES5标准
- 限制收件人范围 - 不要向大型用户组发送垃圾邮件
- 包含上下文信息 - 提供足够信息,无需登录即可操作
- 适配移动端 - 简化HTML以适配移动客户端
Common Issues
常见问题
| Issue | Cause | Solution |
|---|---|---|
| Email not sent | Event not fired | Check business rule fires event |
| Wrong recipients | Script error | Debug recipient script |
| Missing content | Template variable wrong | Check field names |
| Duplicate emails | Multiple notifications | Check weights and conditions |
| Delayed emails | Email job schedule | Check sysauto_script |
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 邮件未发送 | 事件未触发 | 检查业务规则是否触发事件 |
| 收件人错误 | 脚本错误 | 调试收件人脚本 |
| 内容缺失 | 模板变量错误 | 检查字段名称 |
| 重复邮件 | 多个通知匹配 | 检查权重和条件 |
| 邮件延迟 | 邮件任务调度问题 | 检查sysauto_script |