Servers Automation Scripts

Windows - Password Expiration Warning Sent By Email

posted 19 Jan 2017, 08:49 by Dominique Cressatti   [ updated 29 Jun 2018, 11:14 ]


Purpose: VB script notifying by email Active directory users when their passwords are about to expire.
Useful for: users who aren't using Windows workstations or not directly connected to an AD domain through a VPN, hence not being able to receive the notification that their password is about to expire and could result in locking their AD account.

What you need to have and do:
  • Set the STRFROM variable as the "From" address of the email (usually administrator@yourdomain.com).
  • Set the DAYS_FOR_EMAIL variable as the number of days when to start notifying users that their password is about to expire (usually 7).
  • Set the ExcludedGroup variable as the AD group name (which you'll have to create) which contains the list of users who don't need to be notified (because they either use a Windows workstation or are connected to the AD domain through something like a VPN).
  • Set the  ExchangeServerFQN variable as to your Exchange server FQN
  • You may also want to amend the email body
  • Schedule to run this script every day at midnight using either with Windows AT or better the Windows scheduler

'This program scans all users in the Users container and all organizational units
'beneath the HOSTING_OU organizational unit, for users whose passwords have either
'already expired or will expire within DAYS_FOR_EMAIL days.
'
'An email is sent, using CDO, via the SMTP server specified as SMTP_SERVER to the
'user to tell them to change their password. You should change strFrom to match
'the email address of the administrator responsible for password changes.
'
'You will, at a minimum, need to change the SMTP_SERVER, the HOSTING_OU, and the
'STRFROM constants. If you run this on an Exchange server, then SMTP_SERVER can 
'be "127.0.0.1" - and it may be either an ip address or a resolvable name.
'
'If you don't have an OU containing sub-OU's to scan, then set HOSTING_OU to the
'empty string ("").

Option Explicit

'Per environment constants - you should change these!
Const HOSTING_OU  = ""
Const SMTP_SERVER  = "127.0.0.1"
Const STRFROM   = "<admin@somecompany.com>"
Const DAYS_FOR_EMAIL  = 7
Const ExcludedGroup = "_Excluded"
Const ExchangeServerFQN = "yourexchangeserver@yourdomain.com"

'System Constants - do not change
Const ONE_HUNDRED_NANOSECOND    = .000000100   ' .000000100 is equal to 10^-7
Const SECONDS_IN_DAY            = 86400
Const ADS_UF_DONT_EXPIRE_PASSWD = &h10000
Const E_ADS_PROPERTY_NOT_FOUND  = &h8000500D

'Change to "True" for extensive debugging output
Const bDebug   = true

Dim objRoot
Dim numDays, iResult
Dim strDomainDN
Dim objContainer, objSub
Dim UserName, UserExcluded, EmailAddress
Set objRoot = GetObject ("LDAP://RootDSE")
strDomainDN = objRoot.Get ("defaultNamingContext")
Set objRoot = Nothing
numdays = GetMaximumPasswordAge (strDomainDN)
dp "Maximum Password Age: " & numDays

If numDays > 0 Then
  Set objContainer = GetObject ("LDAP://CN=Users," & strDomainDN)
  Call ProcessFolder (objContainer, numDays)
  Set objContainer = Nothing
  If Len (HOSTING_OU) > 0 Then
    Set objContainer = GetObject ("LDAP://OU=" & HOSTING_OU & "," & strDomainDN)
    For each objSub in objContainer
      Call ProcessFolder (objSub, numDays)
    Next
    Set objContainer = Nothing
  End If
 
 'Add the number of days to the last time he password was set.
 ' whenPasswordExpires = DateAdd ("d", numDays, oUser.PasswordLastChanged)
 ' WScript.Echo "Password Last Changed: " & oUser.PasswordLastChanged
 ' WScript.Echo "Password Expires On: " & whenPasswordExpires
End If
WScript.Echo "Done"

Function GetMaximumPasswordAge (ByVal strDomainDN)
  Dim objDomain, objMaxPwdAge
  Dim dblMaxPwdNano, dblMaxPwdSecs, dblMaxPwdDays
  Set objDomain = GetObject("LDAP://" & strDomainDN)
  Set objMaxPWdAge = objDomain.maxPwdAge

  If objMaxPwdAge.LowPart = 0 And objMaxPwdAge.Highpart = 0 Then
    'Maximum password age is set to 0 in the domain
    'Therefore, passwords do not expire
    GetMaximumPasswordAge = 0
  Else
    dblMaxPwdNano = Abs (objMaxPwdAge.HighPart * 2^32 + objMaxPwdAge.LowPart)
    dblMaxPwdSecs = dblMaxPwdNano * ONE_HUNDRED_NANOSECOND
    dblMaxPwdDays = Int (dblMaxPwdSecs / SECONDS_IN_DAY)
    GetMaximumPasswordAge = dblMaxPwdDays
  End If
End Function

Function UserIsExpired (objUser, iMaxAge, iDaysForEmail, iRes)
  Dim intUserAccountControl, dtmValue, intTimeInterval
  Dim strName
  On Error Resume Next
  Err.Clear
  strName = Mid (objUser.Name, 4)
  intUserAccountControl = objUser.Get ("userAccountControl")

  If intUserAccountControl And ADS_UF_DONT_EXPIRE_PASSWD Then
    dp "The password for " & strName & " does not expire."
    UserIsExpired = False
  Else
    iRes = 0
    dtmValue = objUser.PasswordLastChanged
     If Err.Number = E_ADS_PROPERTY_NOT_FOUND Then
        UserIsExpired = True
        dp "The password for " & strName & " has never been set."
     Else
       intTimeInterval = Int (Now - dtmValue)
       dp "The password for " & strName & " was last set on " & _
       DateValue(dtmValue) & " at " & TimeValue(dtmValue) & _
       " (" & intTimeInterval & " days ago)"
       If intTimeInterval >= iMaxAge Then
         dp "The password for " & strName & " has expired."
         UserIsExpired = True
       Else
         iRes = Int ((dtmValue + iMaxAge) - Now)
         dp "The password for " & strName & " will expire on " & _
         DateValue(dtmValue + iMaxAge) & " (" & _
         iRes & " days from today)."
         If iRes <= iDaysForEmail Then
           dp strName & " needs an email for password change"
           UserIsExpired = True
         Else
           dp strName & " does not need an email for password change"
           UserIsExpired = False
         End If
       End If
     End If
  End If
End Function

Sub ProcessFolder (objContainer, iMaxPwdAge)
  Dim objUser, iResult
  objContainer.Filter = Array ("User")
  Wscript.Echo "Checking company = " & Mid (objContainer.Name, 4)
  For each objUser in objContainer
     UserExcluded = 0
     UserName = ""
     EmailAddress = ""
     UserName = LCase(Mid (objUser.Name, 4))
     EmailAddress = objUser.Mail
     dp "" & vbCRLF
     dp "User name: " & UserName
     dp "Email address: " &  EmailAddress
     'Here we check  if the user account is part of excluded group
     Dim GroupName, Group, IsInExcludedGroup, CheckIfArray
     IsInExcludedGroup = 0
     Group = objUser.memberof
     CheckIfArray = IsArray(Group) 
     'Checking that the group name is not empty, else skip group checking
     If Not IsEmpty(Group) And CheckIfArray = "True" Then 
       For Each GroupName In Group
           'checking if group string contains the excluded group name
           IsInExcludedGroup = InStr (GroupName, ExcludedGroup) 
          If IsInExcludedGroup <> 0 Then
             UserExcluded = 1
            dp "is part of the group: " & ExcludedGroup
          End If
       Next
     End if
     ' Checking that the group name is not empty, else skip group checking
     If Not IsEmpty(Group) And CheckIfArray = "False" Then 
        'checking if group string contains the excluded group name
        IsInExcludedGroup = InStr (Group, ExcludedGroup)
        If IsInExcludedGroup <> 0 Then
          UserExcluded = 1
          dp "is part of the group: " & ExcludedGroup
        End If
     End If
    'checking if user account begin with a $ or has no mailbox
     If (UserExcluded <> 1) And Right (objUser.Name, 1) <> "$" Then
       If IsEmpty (objUser.Mail) or IsNull  (objUser.Mail) Then
         dp "has no mailbox"
         UserExcluded = 1
       End If
     End If
    ' checking if account password is expired or doesnt expire
    If UserExcluded <> 1 Then
       If UserIsExpired (objUser, iMaxPwdAge, DAYS_FOR_EMAIL, iResult) Then
         WScript.Echo "...sending an email for " & objUser.Mail
         dp "Sending email"
         Call SendEmail (objUser, iResult)
       End If
    Else
       dp "...don't send an email"
    End If
  Next
End Sub

Sub SendEmail (objUser, iResult)
  Dim objMail
  Set objMail = CreateObject ("CDO.Message")
  objMail.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/sendusing")      = 2
  objMail.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/smtpserver")     = SMTP_SERVER
  objMail.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/smtpserverport") = 25
  objMail.Configuration.Fields.Update
  objMail.From     = STRFROM
  objMail.To       = objUser.Mail
  objMail.Subject  = "Your Windows password needs to be changed soon"
  objMail.Textbody = "Hi," & vbCRLF & vbCRLF & _
     "Your Windows password will expire soon." & vbCRLF & _
     "The password for the account: " & objUser.userPrincipalName & _
      " (" & objUser.sAMAccountName & ")" & vbCRLF & _
     "will expire in " & iResult & " days. Please change it as soon as possible." & vbCRLF & vbCRLF & _
     "You can change it from the Internet by login on: " & vbCRLF & _
     "https://<ExchangeServerFQN>/owa" & vbCRLF & _
     "(Note: Your Web browser is likely to warn you against using the above Web site, it is because we are using a self-signed certificate and it is safe to continue)" & vbCRLF & vbCRLF & _
     "If you would prefer not to receive this reminder, just send a reply with the subject line: opt out of password reminder" & vbCRLF & vbCRLF & _
     "Thank you," & vbCRLF & _
     "Your email administrator"
      objMail.Send
  Set objMail = Nothing
End Sub

Sub dp (str)
  If bDebug Then
    WScript.Echo str
  End If
End Sub

Gmail - Automatic Cleanup OF Emails From Specific Senders After A Specific Day

posted 19 Jan 2017, 08:36 by Dominique Cressatti   [ updated 29 Jun 2018, 11:16 ]


If like me you have subscribed to receive regular emails from a company, organization,  person, etc... (for example, I get notifications emails from Facebook, which I don't want to keep for more than a week) which you don't want/need to keep after a specific amount of days, the following Google Apps script (thanks to Sergei and Larry for giving us those great JavaScripting functionalities ;) ) will automatically do it for you.

1st go to https://www.google.com/script/start/, click on the Start scripting and past the following code.

Tips:
  1. Manual search in Gmail for the sender's email address to make sure that the script will find the expected emails.
  2. Set the delayDays variable to a fairly high amount of days.
  3. Run the script manually before running it automatically with a trigger.

/* Quick Gmail script to delete emails from a specific sender 
   older than a specified amount of days
   For example, I get Facebook's notification in my inbox
   but I don't want/need to keep them for more than a week.

   Set the the delayDays and sender variables
   Tip: to make sure the script will find the emails you want,
   1st do a manual search in Gmail for the sender's email address.
   If it returns the expected emails, then you're good to go.

   To automatically run it, go into the "Resources" menu -> "All you triggers"
   and set an "Event-Driven" "Day timer"
*/

function DeleteEmailsFromSenderOlderThanNDays() {
  
  var delayDays = 2                    // Specify the number of days before messages are deleted (moved to trash). Ex: 7 
  var Sender = "indoma@earthlink.net"; // specify the sender's email address. Ex: someone@somedomain.com
  
  var maxDate = new Date(); 
  maxDate.setDate(maxDate.getDate()-delayDays);    
  var threads = GmailApp.search(Sender);
  
  for (var i = 0; i < threads.length; i++) {  
    if (threads[i].getLastMessageDate()<maxDate){  
      Utilities.sleep(1000) ;
      threads[i].moveToTrash();
    } 
  } 
}

Windows - Low Disk Space Warning Email Alert

posted 1 Jan 2017, 16:09 by Dominique Cressatti   [ updated 29 Jun 2018, 11:16 ]


Quick Perl script to send you an email alert when your Windows server's system drive free space goes down 100 Meg (or below), so you can take action before the server completely runs out of space and thus stops functioning.

What you need to have and do:
  • Active Perl on your server
  • Win32::DriveInfo and Net::SMTP Perl modules
  • Set the $recipient variable as the recipient who will receive the email alert
  • Set the $from variable as the email address of sender of this email
  • Set the $host variable as the name of the server to be monitored
  • Set the $mailserver variable as the FQN of your local mail server
  • Schedule to run this script using either with Windows AT or better the Windows scheduler

use Win32::DriveInfo; 
use Net::SMTP;

$recipient = 'someone@yourdomain.com'; # The recipient of this email alert
$from = 'administrator@yourdomain.com' # The "from" part this email alert
$host = `hostname`;
$mailserver = 'FQN_of_your_local_mail_server'
$SystemDrive = $ENV{"SYSTEMDRIVE"}, "\n";
$TotalNumberOfFreeBytes = Win32::DriveInfo::DriveSpace($SystemDrive);
$TotalOfFreeMegs = $TotalNumberOfFreeBytes / 1048576;
$TotalOfFreeMegs = &round ($TotalOfFreeMegs);


if ($TotalNumberOfFreeBytes < 104857600) # check to see if free space < 100 Megs
{

    $smtp = Net::SMTP->new($mailserver); 
    $smtp->mail($from); # The "from" part this email alert
    $smtp->to($recipient\); # The recipient of this email alert
    $smtp->data();
    $smtp->datasend("to:$recipient\n"); # What's get written after "To" part in the email
    $smtp->datasend("Subject: Warning: Low space on $host root drive\n"); # subject of the email
    $smtp->datasend("\n");

    # body of the email from now on
    $smtp->datasend("The free space left on $host is: $TotalOfFreeMegs Megs !\n\n");
    $smtp->dataend();
    $smtp->quit;
    

sub round {
    my($number) = shift;
    return int($number + .5);
}

Windows - NTBackup Emailed Backup Report

posted 1 Jan 2017, 16:05 by Dominique Cressatti   [ updated 29 Jun 2018, 11:17 ]


The following Perl script was created to send a daily email of the backup log generated on
a Windows server, saving you from of having to log on each server to check how the backup ran.

What you need to have and do:
  • Active Perl on your server
  • Win32::DriveInfo and Net::SMTP Perl modules
  • Set the $UserName variable to the account under which you will perform the backup
    and under 
    which directory the NTbackup  backup log will end up
  • Set the $recipient variable as the recipient who will receive the email
  • Set the$FromAddress variable as the email address of sender of this email
  • Set the $host variable as the name of the server to be monitored
  • Set the $MailServer variable as the FQN of your local mail server through which this email alter will come from
  • Schedule to run this script after the backup has ended using either with Windows AT or better the Windows scheduler

#!/usr/perl
#
use Net::SMTP;

$UserName = <"UserAccount">
$host = `hostname`;
$LogPath = 'c:/Documents\ and\ Settings/'.$UserName.'/Local\ Settings/Application\ Data/Microsoft/Windows\ NT/NTBackup/data/*.log';
$FoundError = 0;
$recipient = '<admin@snakeoil.com>';
$FromAddress =  '<admin@snakeoil.com>';
$MailServer =  '<mailserver.snakeoil.com>';

 print "###$LogPath\n";

foreach (glob($LogPath)) {
       $age = -M ;
       $age = int($age);

       if ($age == 0) 
       {
$LastLogFile = $_ ;
       }
}
# "backupXX.log" string
$LastLogFile =~ /backup\d*.log/;
# convert from unicode to ASCCI
system "type \"c:\\Documents and Settings\\'.$UserName.'\\Local Settings\\Application Data\\Microsoft\\Windows NT\\NTBackup\\data\\$&\" > \"c:\\Documents and Settings\\zzServiceUser\\Local Settings\\Application Data\\Microsoft\\Windows NT\\NTBackup\\data\\LastestBackupLog.log\"";
# open newly created ASCII file
$LastLogFile ="c:\\Documents and Settings\\'.$UserName.'\\Local Settings\\Application Data\\Microsoft\\Windows NT\\NTBackup\\data\\LastestBackupLog.log";

# print "lastlogfile= $LastLogFile \n";
open (FILE, $LastLogFile) or die "can't open file '$LastLogFile': $! "; 
@lines = <FILE>;

foreach $_ (@lines)
{
$_ =~ s/[\x00-\x1f]//g ;
# print "$_\n";

if ( $_ =~ /error/i || /warning/i|| /failed/i || /aborted/i || /skipped/i)
{
   $FoundError = 1;
   $String = $_;
   last
}
}

# print "FoundError:$FoundError\n";
close (FILE);

#print "@lines\n";
if ($FoundError == 1)
{
print "sending email error with backup\n";
$smtp = Net::SMTP->new('mailgate.lansa.co.uk');
$smtp->mail('administrator@lansa.co.uk');
$smtp->to('postmaster@lansa.co.uk');

$smtp->data();
    $smtp->datasend("to:$recipient\n");
$smtp->datasend("Subject: Backup problem on $host\n");
$smtp->datasend("\n");
$smtp->datasend("There is (are) error(s) or warning(s) in\n");
$smtp->datasend("the backup log of $host\n");
$smtp->datasend("$String\n");
$smtp->dataend();

$smtp->quit;
}

open (FILE, $LastLogFile) or die "can't open file '$LastLogFile': $! "; 
@lines = <FILE>;
#print "@lines\n";
print "sending email backup OK\n";
$smtp = Net::SMTP->new($MailServer);
$smtp->mail($FromAddress);
$smtp->to($recipient);

$smtp->data();
$smtp->datasend("to:$recipient\n");
$smtp->datasend("Subject: Backup on $host\n");
$smtp->datasend("\n");
$smtp->datasend("@lines\n");
$smtp->dataend();

$smtp->quit;

close (FILE);
system "del \"c:\\Documents and Settings\\'.$UserName.'\\Local Settings\\Application Data\\Microsoft\\Windows NT\\NTBackup\\data\\LastestBackupLog.log\""

1-4 of 4