Skip to content

Commit 64f5464

Browse files
authored
Mail Script: Redact PII from outbound email body (#2465)
1 parent fb24a39 commit 64f5464

File tree

2 files changed

+76
-0
lines changed

2 files changed

+76
-0
lines changed
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# Redact PII from outbound email body
2+
3+
## What this solves
4+
Notifications sometimes leak personal data into emails. This mail script replaces common identifiers in the email body with redacted tokens before send.
5+
6+
## Where to use
7+
Notification or Email Script record, Advanced view, "Mail script" field. Invoke the function to get a safe body string and print it.
8+
9+
## How it works
10+
- Applies regex patterns to the email text for emails, phone numbers, IP addresses, NI number style patterns, and 16-digit card-like numbers
11+
- Replaces matches with descriptive placeholders
12+
- Leaves HTML tags intact by operating on the plain text portion you pass in
13+
14+
## Configure
15+
- Extend or tighten patterns for your organisation
16+
- Toggle specific scrubs on or off in the config block
17+
18+
## References
19+
- Email Scripts
20+
https://www.servicenow.com/docs/bundle/zurich-platform-administration/page/administer/notification/reference/email-scripts.html
21+
- Notifications
22+
https://www.servicenow.com/docs/bundle/zurich-platform-administration/page/administer/notification/concept/c_EmailNotifications.html
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
// Mail Script: Redact PII from outbound email body
2+
// Usage inside a Notification (Advanced view):
3+
// var safe = redactPii(current.short_description + '\n\n' + current.description);
4+
// template.print(safe);
5+
6+
(function() {
7+
function redactPii(text) {
8+
if (!text) return '';
9+
10+
// Config: toggle specific redactions
11+
var cfg = {
12+
email: true,
13+
phone: true,
14+
ip: true,
15+
niNumber: true,
16+
card16: true
17+
};
18+
19+
var out = String(text);
20+
21+
// Email addresses
22+
if (cfg.email) {
23+
out = out.replace(/\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b/gi, '[redacted email]');
24+
}
25+
26+
// Phone numbers (UK leaning, permissive, 7+ digits ignoring separators)
27+
if (cfg.phone) {
28+
out = out.replace(/\b(?:\+?\d{1,3}[\s-]?)?(?:\(?\d{3,5}\)?[\s-]?)?\d{3,4}[\s-]?\d{3,4}\b/g, '[redacted phone]');
29+
}
30+
31+
// IPv4 addresses
32+
if (cfg.ip) {
33+
out = out.replace(/\b(?:(?:25[0-5]|2[0-4]\d|1?\d?\d)\.){3}(?:25[0-5]|2[0-4]\d|1?\d?\d)\b/g, '[redacted ip]');
34+
}
35+
36+
// National Insurance number style (AA 00 00 00 A) simplified - UK Specific
37+
if (cfg.niNumber) {
38+
out = out.replace(/\b([A-CEGHJ-PR-TW-Z]{2}\s*\d{2}\s*\d{2}\s*\d{2}\s*[A-D])\b/gi, '[redacted ni]');
39+
}
40+
41+
// 16 consecutive digits that look like a card (permit separators)
42+
if (cfg.card16) {
43+
out = out.replace(/\b(?:\d[ -]?){13,19}\b/g, function(match) {
44+
var digits = match.replace(/[ -]/g, '');
45+
return digits.length >= 13 && digits.length <= 19 ? '[redacted card]' : match;
46+
});
47+
}
48+
49+
return out;
50+
}
51+
52+
// Expose function to the mail template scope
53+
this.redactPii = redactPii;
54+
}).call(this);

0 commit comments

Comments
 (0)