- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
3 weeks ago - last edited 3 weeks ago
Hi,
I have this inbound action script below:
(function runAction( /*GlideRecord*/ current, /*GlideRecord*/ event, /*EmailWrapper*/ email, /*ScopedEmailLogger*/ logger, /*EmailClassifier*/ classifier) {
// Prep fields
var groupSysID = '12345678910'; // User Group Sys ID
var subject = email.subject;
var bodyHtml = email.body_html;
var bodyText = email.body_text;
var sender = email.sys_updated_by;
var mailType = "send-ready";
// Create a new email record in the Outbox
var mail = new GlideRecord("sys_email");
mail.initialize();
mail.mailbox.setDisplayValue("Outbox"); // Place the new email in the Outbox
mail.subject = subject;
mail.type = mailType;
var t = new GlideTemplate.get('1a2b3c4d5e6f7g'); // Email Template Sys ID
gs.info('t is ' + t);
gs.info('name is ' + t.name);
gs.info('sys_id is ' + t.sys_id);
gs.info('layout is ' + t.email_layout);
t.apply('mail');
mail.applyTemplate('Our Company Notification Template'); // NAME of Email Template
// Get list of group members
var groupMembers = getGroupMembers(groupSysID);
mail.recipients = sender;
mail.blind_copied = groupMembers.join(',');
// Include HTML body if available and set content type
if (bodyHtml) {
mail.body_html = bodyHtml;
mail.body = bodyHtml; // Fallback for plain text clients
mail.content_type = "text/html";
} else {
mail.body = bodyText;
mail.content_type = "text/plain";
}
// Insert email record
mail.insert();
// Function to retrieve list of users from group
function getGroupMembers(groupId) {
var members = [];
var grMem = new GlideRecord('sys_user_grmember');
grMem.addQuery('group', groupSysID);
grMem.addActiveQuery();
grMem.query();
while (grMem.next()) {
members.push(grMem.user.email.toString());
}
return members;
}
})(current, event, email, logger, classifier);
I have tried to debug but this is what I get:
I'm not able to use our company configured template on the outgoing notification and it's also not blind copying the users in the group. Any ideas?
Solved! Go to Solution.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
3 weeks ago
Hi Neil,
That is an excellent catch. Since we are moving away from the manual sys_email insert, we need a mechanism to "transport" that dynamic content (Subject and Body) from the Inbound Action to the Notification.
You are absolutely correct: Email Scripts are the key here.
Since gs.eventQueue only accepts string parameters, the best practice is to package your Subject and Body into a JSON Object and pass it via Parm2.
Here is the updated implementation:
1. Update Inbound Action (The Packer) We will package your data into a JSON string and pass it in the 4th argument (Parameter 2).
(function runAction(/*GlideRecord*/ current, /*GlideRecord*/ event, /*EmailWrapper*/ email, /*ScopedEmailLogger*/ logger, /*EmailClassifier*/ classifier) { var groupSysID = '12345678910'; // 1. Build a Payload Object with the data you want to transfer var payload = { subject: email.subject + '', // ensure string body: email.body_html ? email.body_html + '' : email.body_text + '' }; // 2. Fire Event: Pass GroupID in Parm1, and JSON Payload in Parm2 gs.eventQueue('inbound.group.notification', current, groupSysID, JSON.stringify(payload)); })(current, event, email, logger, classifier);
2. Update the Email Script (The Unpacker) Modify the add_group_bcc script we created earlier. It will now handle both the BCC logic and the content injection.
Script Name: add_group_bcc
(function runMailScript(/* GlideRecord */ current, /* TemplatePrinter */ template, /* Optional EmailOutbound */ email, /* Optional GlideRecord */ email_action, /* Optional GlideRecord */ event) { // --- PART A: Handle Content (Subject & Body) --- if (event.parm2) { var data = JSON.parse(event.parm2); // Unpack the JSON // 1. Set the Subject dynamically if (data.subject) { email.setSubject(data.subject); } // 2. Print the original HTML body if (data.body) { template.print(data.body); } } // --- PART B: Handle BCC (Group Members) --- var groupId = event.parm1; if (groupId) { var grMem = new GlideRecord('sys_user_grmember'); grMem.addQuery('group', groupId); grMem.addActiveQuery(); grMem.query(); while (grMem.next()) { email.addBCC(grMem.user.email.toString()); } } })(current, template, email, email_action, event);
3. Final Notification Config
Subject: Leave it empty (or put a placeholder), as the script will overwrite it.
Message HTML: Only strictly needs the script call: ${mail_script:add_group_bcc}
How this works: The Inbound Action bundles the original email's content into a text package -> The Event carries it -> The Email Script opens the package and paints the new email with the original subject and HTML body, while preserving your Company Template wrapper.
If this response helps you solve the issue, please mark it as Accepted Solution.
This helps the community grow and assists others in finding valid answers faster.
Best regards,
Brandão.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
3 weeks ago
Hi Neil,
You are very close! The screenshots perfectly explain what is happening.
The Issue: The "Phantom" Record In your screenshot image_c50aa0.png, the URI leads to a "Record not found". This happens because you are passing current as the second argument in gs.eventQueue.
In an Inbound Action, current is typically a New Record (like an Incident) that exists only in memory until you call current.insert().
Since your script does not assume a ticket creation (you removed the insert), current is never saved to the database.
The Event fires pointing to this temporary ID, but when the Notification System tries to load it from the DB to process the email, it finds nothing.
The Fix: Anchor to the Incoming Email Since your Event Registration (image_c50a7f.png) is set to the Email [sys_email] table, you should pass the Incoming Email Record itself as the instance, not the target current.
In Inbound Actions, the variable sys_email gives you direct access to the stored incoming email record.
Updated Code Line:
Change this line:
// OLD (Wrong because current might not be saved) gs.eventQueue('inbound.group.notification', current, groupSysID, JSON.stringify(payload));
To this:
// NEW (Correct - uses the existing Incoming Email record) gs.eventQueue('inbound.group.notification', sys_email, groupSysID, JSON.stringify(payload));
Why this works:
The sys_email variable refers to the email that just arrived (which is definitely saved in the database).
It matches your Event Registration table (sys_email).
The URI in the event will now link correctly to the incoming email, and the Notification will process successfully.
If this response helps you solve the issue, please mark it as Accepted Solution.
This helps the community grow and assists others in finding valid answers faster.
Best regards,
Brandão.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
3 weeks ago - last edited 3 weeks ago
Hi @Itallo Brandão I appreciate the quick response! That seems to have worked, the event was triggered and the notification was sent out. The last remaining piece would be the recipient and blind copy list. Both appear to be blank on the email record.
Here is the inbound action script. Now, in a previous comment/revision, Parm2 was the email.sys_updated_by but we have since changed it to the payload so that we could grab the subject and body of the incoming email to be used in the outgoing email notification.
// 1. Build a Payload Object with the data you want to transfer
var payload = {
subject: email.subject + '', // ensure string
body: email.body_html ? email.body_html + '' : email.body_text + ''
};
// 2. Fire Event: Pass GroupID in Parm1, and JSON Payload in Parm2
gs.eventQueue('sn_lg_ops.tech_tuesday', sys_email, groupSysID, JSON.stringify(payload));Here is the mail script:
(function runMailScript(/* GlideRecord */ current, /* TemplatePrinter */ template,
/* Optional EmailOutbound */ email, /* Optional GlideRecord */ email_action,
/* Optional GlideRecord */ event) {
// --- PART A: Handle Content (Subject & Body) ---
if (event.parm2) {
var data = JSON.parse(event.parm2); // Unpack the JSON
// 1. Set the Subject dynamically
if (data.subject) {
email.setSubject(data.subject);
}
// 2. Print the original HTML body
if (data.body) {
template.print(data.body);
}
}
// --- PART B: Handle BCC (Group Members) ---
var groupId = event.parm1;
if (groupId) {
var grMem = new GlideRecord('sys_user_grmember');
grMem.addEncodedQuery('group='+groupId);
grMem.addActiveQuery();
grMem.query();
while (grMem.next()) {
email.addBCC(grMem.user.email.toString());
}
}
})(current, template, email, email_action, event);Correct me if I am wrong but I think ServiceNow might have a limitation where I cannot set the recipient through a mail script as I believe those only handle cc and bcc. I figured perhaps I can configure the Notification > Who will receive > Event parm 2 contains recipient, but parm 2 is the payload and parm 1 is the group sys_id. I have also thought considered adding the email.sys_updated_by to the payload but then we're stuck at the mail script where we cannot assign a recipient. Since we aren't able to use Parm2, how do you suggest we set the recipient and get the bcc populated?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
3 weeks ago
Hi @neil_b ,
You are doing great, we are almost there!
To answer your specific question: No, that is not a limitation. You absolutely can set the main "To" recipient via an Email Script. The function is email.addAddress("to", ...).
The reason your fields are empty is simply data flow:
To: We haven't told the script who to send it to (the original sender isn't in the payload yet).
BCC: The code looks logically correct, so we likely have a data type issue (String conversion) or the query is returning 0 results.
Here is the final piece of the puzzle to fix both:
Step 1: Update Inbound Action (Add Sender to Payload) We need to capture the sender's email address (email.origemail) and bundle it into your JSON payload.
// 1. Build a Payload Object var payload = { subject: email.subject + '', body: email.body_html ? email.body_html + '' : email.body_text + '', sender: email.origemail + '' // <--- ADD THIS (The person who sent the email) }; // 2. Fire Event gs.eventQueue('sn_lg_ops.tech_tuesday', sys_email, groupSysID, JSON.stringify(payload));
Step 2: Update Email Script (Set "To" & Fix BCC) I have added the logic to read the sender from the payload and gs.info logs so you can verify if the BCC loop is actually finding members.
(function runMailScript(/* GlideRecord */ current, /* TemplatePrinter */ template, /* Optional EmailOutbound */ email, /* Optional GlideRecord */ email_action, /* Optional GlideRecord */ event) { // --- PART A: Handle Content & Primary Recipient --- if (event.parm2) { var data = JSON.parse(event.parm2); // 1. Set Subject if (data.subject) email.setSubject(data.subject); // 2. Print Body if (data.body) template.print(data.body); // 3. Set the "To" Recipient (The Sender) if (data.sender) { // This method allows setting the Target recipient dynamically email.addAddress("to", data.sender, ""); } } // --- PART B: Handle BCC --- // Force string conversion to be safe var groupId = event.parm1 + ''; // Debug Log (Check System Logs > All) gs.info("MAIL SCRIPT DEBUG: Group ID is " + groupId); if (groupId) { var grMem = new GlideRecord('sys_user_grmember'); grMem.addQuery('group', groupId); grMem.addActiveQuery(); grMem.query(); while (grMem.next()) { var memberEmail = grMem.user.email.toString(); if (memberEmail) { email.addBCC(memberEmail); gs.info("MAIL SCRIPT DEBUG: Added BCC for " + memberEmail); } } } })(current, template, email, email_action, event);
Note: After testing, check System Logs > All and search for "MAIL SCRIPT DEBUG".
If you see "Added BCC...", it worked.
If you see "Group ID is..." but no "Added BCC", then that Group has no members or the members have no email addresses.
If this response helps you solve the issue,
please mark it as Accepted Solution.
This helps the community grow and assists others in finding valid answers faster.
Best regards,
Brandão.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
3 weeks ago - last edited 3 weeks ago
Hi @Itallo Brandão thank you for the clarification! That was incredibly helpful.
I did as you suggested and the debugging certainly helped. I was able to capture the recipient but it's still not sending it to the recipient, I ran into an issue with the blind copy list.
Here is the log info:
com.glide.script.RhinoEcmaError: Cannot find function addBCC in object com.glide.notification.outbound.ScopedEmailOutbound@e2fbe8.
Email Script: 'inbound_info' : Line(43) column(0)
40: while (grMem.next()) {
41: var memberEmail = grMem.user.email.toString();
42: if (memberEmail) {
43: email.addBCC(grMem.user.email.toString());
44: gs.info("MAIL SCRIPT DEBUG: Added BCC for " + memberEmail);
Stack trace:
at sys_script_email.63114e3587223a9002147626cebb3554:43 (runMailScript)
at sys_script_email.63114e3587223a9002147626cebb3554:48
I was able to get around this though! I updated the script as follows:
while (grMem.next()) {
var memberEmail = grMem.user.email.toString();
var memberName = grMem.user.name.toString();
if (memberEmail) {
email.addAddress('bcc', memberEmail, memberName);This ended up fixing it and I am able to confirm that it does get the users from the group.
The only remaining piece is that I cannot get the recipient populated and so the email won't send.
Here is the script for the recipient:
// 3. Set the "To" Recipient (The Sender)
if (data.sender) {
// This method allows setting the Target recipient dynamically
email.addAddress('to', data.sender, '');
gs.info('sender is ' + data.sender);
}I see it in the log, and it shows 'sender is [my email address]' but it's still not sending the notification. I tested configuring the notification > who will receive > user > my own user, and the notification does get sent. For some reason, assigning 'to' via addAddress in the mail script still isn't working for me.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
3 weeks ago
ServiceNow shows that addAddress only handles cc and bcc, this is probably why it's still not adding the email address to the "to" field.
