Inbound Email Action processing Attachment

punisher
Tera Contributor

Hello everyone,
I have one requirement to create an inbound email action  to process the file using email action whenever an email with attachment comes into ServiceNow and insert the records into incident table.
As for the requirement I create one simple action with below script.

<code>

(function runAction( /*GlideRecord*/ current, /*GlideRecord*/ event, /*EmailWrapper*/ email, /*ScopedEmailLogger*/ logger, /*EmailClassifier*/ classifier) {

    var email_log = new GlideRecord('sys_email');
    email_log.addQuery('uid', email.uid);
    email_log.query();

    if (!email_log.next()) {
        gs.info("Email log not found for UID: " + email.uid);
        return;
    }

    var attachLog = new GlideRecord('sys_attachment');
    attachLog.addQuery('table_sys_id', email_log.sys_id);
    attachLog.addQuery('table', 'sys_email');
    attachLog.query();

    if (!attachLog.hasNext()) {
        gs.info("No attachment found for email: " + email.subject);
        return;
    }

    while (attachLog.next()) {
        var stream = new GlideSysAttachment().getContentStream(attachLog.sys_id.toString());
        var reader = new GlideTextReader(stream);

        var line;
        var data = {};
        while ((line = reader.readLine()) !== null) {
            line = line.trim();

            if (line.toLowerCase().startsWith("short description")) {
                data.short_description = line.split(':')[1]?.trim();
            }
            if (line.toLowerCase().startsWith("description")) {
                data.description = line.split(':')[1]?.trim();
            }
            if (line.toLowerCase().startsWith("priority")) {
                data.priority = line.split(':')[1]?.trim();
            }
            if (line.toLowerCase().startsWith("assigned to")) {
                data.assigned_to = line.split(':')[1]?.trim();
            }
            if (line.toLowerCase().startsWith("assignment group")) {
                data.assignment_group = line.split(':')[1]?.trim();
            }
        }
        reader.close();
    }

    if (Object.keys(data).length > 0) {
        current.short_description = data.short_description;
        current.description = data.description;

        var priority = (data.priority || '').toLowerCase();
        if (priority === 'high') {
            inc.urgency = 1; inc.impact = 2;
        } else if (priority === 'medium') {
            inc.urgency = 2; inc.impact = 2;
        } else if (priority === 'low') {
            inc.urgency = 3; inc.impact = 3;
        } else {
            inc.urgency = 3; inc.impact = 3;
        }

        if (data.assigned_to) {
            var user = new GlideRecord('sys_user');
            user.addQuery('name', data.assigned_to);
            user.query();
            if (user.next()) {
                current.assigned_to = user.sys_id;
                gs.info("Assigned to :"+current.assigned_to);
            }
        }

        if (data.assignment_group) {
            var group = new GlideRecord('sys_user_group');
            group.addQuery('name', data.assignment_group);
            group.query();
            if (group.next()) {
                current.assignment_group = group.sys_id;
                gs.info("Assignment Group " + current.assignment_group);
            }
        }

    }

    gs.info("SD " + data.short_description + " Description " + data.description + " Priority " + data.priority + " Assigned To " + data.assigned_to + " Assignment Group " + data.assignment_group);

    if (current.canCreate()) {
        current.insert();
    }

})(current, event, email, logger, classifier);
</code>


For the reference of the attachment I used:
Short Description: Test Incident from Email
Description: This is a test description from email attachment.
Priority: High
Assigned To: Abel Tuter
Assignment Group: Software
 
The assigned to and assignment group values are not reflecting on the incident record but when I check on the log message it giving correct sys_id. I would be grateful if someone provide any assistance.

Thank you
1 ACCEPTED SOLUTION

Hi @punisher ,

 

please refer the below script

 

 

(function runAction(current, event, email, logger, classifier) {
// Get the sys_email record associated with the email
var email_log = new GlideRecord('sys_email');
email_log.addQuery('uid', email.uid);
email_log.query();

if (!email_log.next()) {
gs.info("Email log not found for UID: " + email.uid);
return;
}

// Retrieve the attachments linked to the email
var attachLog = new GlideRecord('sys_attachment');
attachLog.addQuery('table_sys_id', email_log.sys_id);
attachLog.addQuery('table', 'sys_email');
attachLog.query();

if (!attachLog.hasNext()) {
gs.info("No attachment found for email: " + email.subject);
return;
}

var data = {}; // Object to store parsed values

while (attachLog.next()) {
// Read content of each attachment
var stream = new GlideSysAttachment().getContentStream(attachLog.sys_id.toString());
var reader = new GlideTextReader(stream);

var line;
while ((line = reader.readLine()) !== null) {
line = line.trim();
var parts = line.split(':');
if (parts.length < 2) continue;
var field = parts[0].toLowerCase().trim();
var value = parts.slice(1).join(':').trim();

if (field === "short description") {
data.short_description = value;
} else if (field === "description") {
data.description = value;
} else if (field === "priority") {
data.priority = value;
} else if (field === "assigned to") {
data.assigned_to = value;
} else if (field === "assignment group") {
data.assignment_group = value;
}
}
reader.close();
}

// Populate mandatory fields
current.short_description = data.short_description || "No short description";
current.description = data.description || "No description";

// Set priority using urgency & impact
var priority = (data.priority || '').toLowerCase();
if (priority === 'high') {
current.urgency = 1; current.impact = 2;
} else if (priority === 'medium') {
current.urgency = 2; current.impact = 2;
} else if (priority === 'low') {
current.urgency = 3; current.impact = 3;
} else {
current.urgency = 3; current.impact = 3;
}

// Lookup and assign user if found
if (data.assigned_to) {
var user = new GlideRecord('sys_user');
user.addQuery('email', data.assigned_to); // safer than using name
user.query();
if (user.next()) {
current.assigned_to = user.sys_id;
gs.info("Assigned to user: " + user.name);
} else {
gs.info("Assigned to user NOT FOUND: " + data.assigned_to);
}
}

// Lookup and assign group if found
if (data.assignment_group) {
var group = new GlideRecord('sys_user_group');
group.addQuery('name', data.assignment_group); // or use unique code/email
group.query();
if (group.next()) {
current.assignment_group = group.sys_id;
gs.info("Assignment group found: " + group.name);
} else {
gs.info("Assignment group NOT FOUND: " + data.assignment_group);
}
}

// Log extracted info
gs.info("Final values: " +
"Short Description: " + current.short_description +
" | Description: " + current.description +
" | Priority: " + data.priority +
" | Assigned To: " + current.assigned_to +
" | Assignment Group: " + current.assignment_group);

// Insert only if the platform hasn't already done it (use only for Action = None)
if (current.operation() !== 'insert') {
var id = current.insert();
gs.info("Incident created with Sys ID: " + id);
}

})(current, event, email, logger, classifier);

View solution in original post

4 REPLIES 4

Rafael Batistot
Kilo Patron

Hi @punisher,

You're correctly setting the field values on the current object, but you were assigning urgency and impact using a variable named inc, which doesn't exist in your script. This would result in those values not being applied to the record.

Also, the current.insert() is not necessary if your Inbound Email Action is configured to run on the incident table directly — in that case, the platform will create the incident automatically. However, if you're working with a different table or if your action is purely script-based (i.e., no target table defined), then using current.insert() might be appropriate.


Let me know if this correction work for you 

(function runAction( /*GlideRecord*/ current, /*GlideRecord*/ event, /*EmailWrapper*/ email, /*ScopedEmailLogger*/ logger, /*EmailClassifier*/ classifier) {

    // Get the sys_email record associated with the email
    var email_log = new GlideRecord('sys_email');
    email_log.addQuery('uid', email.uid);
    email_log.query();

    if (!email_log.next()) {
        gs.info("Email log not found for UID: " + email.uid);
        return;
    }

    // Retrieve the attachments linked to the email
    var attachLog = new GlideRecord('sys_attachment');
    attachLog.addQuery('table_sys_id', email_log.sys_id);
    attachLog.addQuery('table', 'sys_email');
    attachLog.query();

    if (!attachLog.hasNext()) {
        gs.info("No attachment found for email: " + email.subject);
        return;
    }

    var data = {}; // Object to store parsed values

    while (attachLog.next()) {
        // Read content of each attachment
        var stream = new GlideSysAttachment().getContentStream(attachLog.sys_id.toString());
        var reader = new GlideTextReader(stream);

        var line;
        while ((line = reader.readLine()) !== null) {
            line = line.trim();

            // Extract values based on the expected format in the attachment
            if (line.toLowerCase().startsWith("short description")) {
                data.short_description = line.split(':')[1]?.trim();
            }
            if (line.toLowerCase().startsWith("description")) {
                data.description = line.split(':')[1]?.trim();
            }
            if (line.toLowerCase().startsWith("priority")) {
                data.priority = line.split(':')[1]?.trim();
            }
            if (line.toLowerCase().startsWith("assigned to")) {
                data.assigned_to = line.split(':')[1]?.trim();
            }
            if (line.toLowerCase().startsWith("assignment group")) {
                data.assignment_group = line.split(':')[1]?.trim();
            }
        }
        reader.close();
    }

    // Populate the incident fields if any data was extracted
    if (Object.keys(data).length > 0) {
        current.short_description = data.short_description || "";
        current.description = data.description || "";

        var priority = (data.priority || '').toLowerCase();
        if (priority === 'high') {
            current.urgency = 1; current.impact = 2;
        } else if (priority === 'medium') {
            current.urgency = 2; current.impact = 2;
        } else if (priority === 'low') {
            current.urgency = 3; current.impact = 3;
        } else {
            current.urgency = 3; current.impact = 3;
        }

        // Find user by name and assign
        if (data.assigned_to) {
            var user = new GlideRecord('sys_user');
            user.addQuery('name', data.assigned_to); // Alternatively: use 'user_name' or 'email' for better accuracy
            user.query();
            if (user.next()) {
                current.assigned_to = user.sys_id;
                gs.info("Assigned to: " + current.assigned_to);
            } else {
                gs.info("User not found: " + data.assigned_to);
            }
        }

        // Find group by name and assign
        if (data.assignment_group) {
            var group = new GlideRecord('sys_user_group');
            group.addQuery('name', data.assignment_group);
            group.query();
            if (group.next()) {
                current.assignment_group = group.sys_id;
                gs.info("Assignment Group: " + current.assignment_group);
            } else {
                gs.info("Group not found: " + data.assignment_group);
            }
        }
    }

    // Log the final extracted data
    gs.info("Short Description: " + data.short_description +
            " | Description: " + data.description +
            " | Priority: " + data.priority +
            " | Assigned To: " + data.assigned_to +
            " | Assignment Group: " + data.assignment_group);

    // Insert the record only if not already inserted by the platform
    if (current.canCreate()) {
        current.insert();
    }

})(current, event, email, logger, classifier);




Thanks for providing the solution but there is still an issue. When I assigned the  assigned to and assignment group field, incident record is not creating. It return empty as in the image. But when I comment out the code snippet for the assigning part it's creating and maps the value correctly in the incident record.

Hi @punisher ,

 

please refer the below script

 

 

(function runAction(current, event, email, logger, classifier) {
// Get the sys_email record associated with the email
var email_log = new GlideRecord('sys_email');
email_log.addQuery('uid', email.uid);
email_log.query();

if (!email_log.next()) {
gs.info("Email log not found for UID: " + email.uid);
return;
}

// Retrieve the attachments linked to the email
var attachLog = new GlideRecord('sys_attachment');
attachLog.addQuery('table_sys_id', email_log.sys_id);
attachLog.addQuery('table', 'sys_email');
attachLog.query();

if (!attachLog.hasNext()) {
gs.info("No attachment found for email: " + email.subject);
return;
}

var data = {}; // Object to store parsed values

while (attachLog.next()) {
// Read content of each attachment
var stream = new GlideSysAttachment().getContentStream(attachLog.sys_id.toString());
var reader = new GlideTextReader(stream);

var line;
while ((line = reader.readLine()) !== null) {
line = line.trim();
var parts = line.split(':');
if (parts.length < 2) continue;
var field = parts[0].toLowerCase().trim();
var value = parts.slice(1).join(':').trim();

if (field === "short description") {
data.short_description = value;
} else if (field === "description") {
data.description = value;
} else if (field === "priority") {
data.priority = value;
} else if (field === "assigned to") {
data.assigned_to = value;
} else if (field === "assignment group") {
data.assignment_group = value;
}
}
reader.close();
}

// Populate mandatory fields
current.short_description = data.short_description || "No short description";
current.description = data.description || "No description";

// Set priority using urgency & impact
var priority = (data.priority || '').toLowerCase();
if (priority === 'high') {
current.urgency = 1; current.impact = 2;
} else if (priority === 'medium') {
current.urgency = 2; current.impact = 2;
} else if (priority === 'low') {
current.urgency = 3; current.impact = 3;
} else {
current.urgency = 3; current.impact = 3;
}

// Lookup and assign user if found
if (data.assigned_to) {
var user = new GlideRecord('sys_user');
user.addQuery('email', data.assigned_to); // safer than using name
user.query();
if (user.next()) {
current.assigned_to = user.sys_id;
gs.info("Assigned to user: " + user.name);
} else {
gs.info("Assigned to user NOT FOUND: " + data.assigned_to);
}
}

// Lookup and assign group if found
if (data.assignment_group) {
var group = new GlideRecord('sys_user_group');
group.addQuery('name', data.assignment_group); // or use unique code/email
group.query();
if (group.next()) {
current.assignment_group = group.sys_id;
gs.info("Assignment group found: " + group.name);
} else {
gs.info("Assignment group NOT FOUND: " + data.assignment_group);
}
}

// Log extracted info
gs.info("Final values: " +
"Short Description: " + current.short_description +
" | Description: " + current.description +
" | Priority: " + data.priority +
" | Assigned To: " + current.assigned_to +
" | Assignment Group: " + current.assignment_group);

// Insert only if the platform hasn't already done it (use only for Action = None)
if (current.operation() !== 'insert') {
var id = current.insert();
gs.info("Incident created with Sys ID: " + id);
}

})(current, event, email, logger, classifier);

Thanks for replying.
In my code, I didn't check out whether the assigned to user is a member of the assignment group. That's why I can't create the incident record. After validating it, it works. 
Gracias