Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
Purpose
This scheduled job automatically identifies inactive users in the ServiceNow instance and deactivates their accounts if they have not logged in for a specified period (default: 3 months).
It ensures compliance, reduces clutter, and maintains security by removing stale user accounts.

Key Features
Runs automatically once per month.
Identifies users who have been inactive for a defined number of months.
Supports dry-run testing to safely validate before applying changes.
Deactivates inactive users automatically.
Sends email notifications to both users and their managers upon deactivation.
Logs all activities in the system log for auditing purposes.

Script Workflow

1. Calculate Cutoff Date
The script calculates a cutoff date by subtracting the configured number of months (default: 3) from the current date.
Any user created before this date and who has not logged in since is considered inactive.

2. Query Eligible Users
The script searches the sys_user table for records meeting these conditions:
active = true
sys_created_on <= cutoffDate
last_login_time <= cutoffDate

3. Process Each User
For every matching user, the script:
Logs user details (name, email, last login, manager).
Deactivates the account (if DRY_RUN is false).
Sends notification emails.

4. Send Notification to User
Sends a plain-text email to the user informing them that their account was deactivated due to inactivity.
Includes instructions on how to request reactivation.

5. Send Notification to Manager
If the user has a manager assigned, an additional email is sent to the manager.
The email contains the user’s details and the date of last login for awareness.

6. Log Summary
At the end of execution, the script logs:
Total users found
Total users deactivated
Status of the run (Dry Run or Actual)
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
(function executeAutoUserCleanup() {

/***************************************************************
* AUTO CLEANUP INACTIVE USERS - MONTHLY JOB
* ------------------------------------------------------------
* This script automatically deactivates users who have not
* logged in for a defined number of months. It can also send
* notifications to both the user and their manager.
*
* SAFETY: Use DRY_RUN = true first to test (no updates).
***************************************************************/

// === CONFIGURATION ===
var MONTHS_THRESHOLD = 3; // Inactive period threshold (in months)
var DRY_RUN = true; // true = test mode, no database updates
var BATCH_LIMIT = 1000; // Max records per execution
var FROM_EMAIL = 'no-reply@yourcompany.com'; // sender email address

// === STEP 1: Calculate cutoff date ===
var cutoffDate = new GlideDateTime();
cutoffDate.addMonths(-MONTHS_THRESHOLD);

gs.info('[UserCleanup] Job started. Cutoff date: ' + cutoffDate.getDisplayValue() +
' | DRY_RUN: ' + DRY_RUN + ' | Threshold: ' + MONTHS_THRESHOLD + ' months');

// === STEP 2: Query eligible users ===
var userGr = new GlideRecord('sys_user');
userGr.addQuery('active', true); // only active users
userGr.addQuery('sys_created_on', '<=', cutoffDate); // created before cutoff
userGr.addQuery('last_login_time', '<=', cutoffDate); // no recent login
userGr.setLimit(BATCH_LIMIT); // safety limit
userGr.query();

var totalFound = 0;
var totalDeactivated = 0;

// === STEP 3: Loop through each user ===
while (userGr.next()) {
totalFound++;

var userName = userGr.name.toString();
var userEmail = userGr.email.toString();
var lastLogin = userGr.last_login_time ? userGr.last_login_time.getDisplayValue() : 'Never';
var managerEmail = (userGr.manager && userGr.manager.email) ? userGr.manager.email.toString() : null;

gs.info('[UserCleanup] Found user: ' + userName +
' | Email: ' + userEmail +
' | Last Login: ' + lastLogin +
' | Manager: ' + (managerEmail || 'None'));

if (!DRY_RUN) {

// === STEP 4: Deactivate the user ===
userGr.active = false;
userGr.update();
totalDeactivated++;

// === STEP 5: Send notification to user ===
if (userEmail) {
var subjectUser = 'Your ServiceNow account has been deactivated due to inactivity';
var bodyUser =
'Hello ' + userName + ',\n\n' +
'Your ServiceNow account has been automatically deactivated because there has been no login activity ' +
'for over ' + MONTHS_THRESHOLD + ' months.\n\n' +
'If you believe this is a mistake or require access, please contact the IT Service Desk.\n\n' +
'Regards,\nIT Service Management Team';

gs.email(FROM_EMAIL, userEmail, subjectUser, bodyUser);
gs.info('[UserCleanup] Email sent to user: ' + userEmail);
}

// === STEP 6: Send notification to manager ===
if (managerEmail) {
var subjectMgr = 'User under your management has been deactivated';
var bodyMgr =
'Hello,\n\n' +
'The following user under your management has been deactivated due to inactivity:\n\n' +
'User: ' + userName + '\n' +
'Last Login: ' + lastLogin + '\n\n' +
'If this account is still required, please raise a ServiceNow access request.\n\n' +
'Regards,\nIT Service Management Team';

gs.email(FROM_EMAIL, managerEmail, subjectMgr, bodyMgr);
gs.info('[UserCleanup] Email sent to manager: ' + managerEmail);
}
}
}

// === STEP 7: Log summary ===
gs.info('[UserCleanup] Total users found: ' + totalFound);
gs.info('[UserCleanup] Total users deactivated: ' + totalDeactivated +
(DRY_RUN ? ' (Dry Run - no records updated)' : ''));

})();

Loading