Password expiry notification!

Experts out there !

I am running the below script to send out email notification to all AD users whose password is going expire (mainly for the remote users who do not login to domain), below script does not throw any errors. powerGUI shows script execution is successfull and we do receive an email.

The issue with the below script is we receive an empty email with the subject "Password change log for",  the body of the message "Password change log for" and the attachment with txt file is empty. no information is written to the logs.

Appreciate if anyone can coorect the script.

========================================================================

#Add the Quest PowerShell snapin
Add-PsSnapIn Quest.ActiveRoles.ADManagement -ErrorAction SilentlyContinue
Get-QADUser -SearchRoot "OU=Test Accounts,OU=Accounts,OU=Cityname,OU=Xyz,DC=Mydomain"
Where-Object {$_.PasswordStatus -ne "Password never expires" -and $_.PasswordStatus -ne "Expired" -and $_.PasswordStatus -ne "User must change password at next logon." -and $_.mail -ne $null} | 
ForEach-Object {
  $today = Get-Date
  $logdate = Get-Date -format yyyyMMdd
  $samaccountname = $_.samAccountName
  $mail = $_.mail 
  $passwordstatus = $_.PasswordStatus
  $passwordexpiry = $passwordstatus.Replace("Expires at: ","")
  $passwordexpirydate = $passwordexpiry
  $daystoexpiry = ($passwordexpirydate - $today).Days
  $attachment = "C:\passwordexpiry.txt"
  $emailFrom = "adadmin@mydomain.com"
  $body = "Please change your password to prevent loss of access to your *my domain* systems`n`n"
  $body += "If you are unable to change your password, please contact the help desk at ext 000 or 000.000.0000"
  if ($daystoexpiry -lt 9 )
  {
    $emailTo = "$mail"
    $subject = "Your Network password will expire in $daystoexpiry day(s) please change your password."    
    Send-MailMessage -To $emailTo -From $emailFrom -Subject $subject -Body $body -Attachments $attachment -SmtpServer "mail.mydomain.com"
    Write-Host "Email was sent to $mail on $today"
    Add-Content C:\maillog$logdate.txt  "Email was sent to $mail on $today"
  }
}
Send-MailMessage -To "adadmin@mydomain.com" -From "adadmin@mydomain.com" -Subject "Password change log for $today" -Body "This is the log from $today" -Attachments "C:\maillog$logdate.txt" -SmtpServer "mail.mydomain.com"

==========================================================

Thanks in Advance

Naveen Rao

May 28th, 2013 5:14pm

Look closely at the and tell us where 'attachment' is ever created.

$searchRoot='OU=Test Accounts,OU=Accounts,OU=Cityname,OU=Xyz,DC=Mydomain'
Add-PSSnapin Quest.ActiveRoles.ADManagement
$today=Get-Date -f MM-dd-yyy
$logdate="c:\maillog_$(Get-Date -format yyyy-MM-dd).log" 
 
# global mail server
$PSEmailServer='mail.mydomain.com'
 
# admin email parameters
$adminMail=@{
    To='adadmin@mydomain.com'
    From='adadmin@mydomain.com'
    Subject="Password change log for $today"
    Body="This is the log from $today"
    Attachments='C:\maillog$logdate.txt'
}
 
$attachment='C:\passwordexpiry.txt'
$maxpasswordage=60
$pwdnotification=10
$pwdAge=($maxpasswordage - $pwdnotification)
 
# get all passwords exceeding the age before notification
get-qaduser * -PasswordNeverExpires:$false -Enabled -PasswordNotChangedFor $pwdAge -SearchRoot $searchRoot | 
    ForEach-Object {
        
        $passwordExpiresAt = [datetime]($_.PasswordStatus.Replace('Expires at:',''))
        $passWordExpiresInDays=($passwordExpiresAt - (Get-Date)).Days
        $mailProps=@{
            To=$_.mail
            From='adadmin@mydomain.com'
            Subject="Your Network password will expire in $passWordExpiresInDays day(s) please change your password."
            Body='Please change your password to prevent loss of access to your *my domain* systems'
        }
        Send-MailMessage @mailProps -Attachments $attachment 
            
        Write-Host "Email was sent to $($_.mail) on $today" 
        Add-Content $logfile  "Email was sent to $($_.mail) on $today" 
  }
  
Send-MailMessage @adminMail
                 

Note that we can use the QAD CmdLet to filter the accounts in question.  Your method will return every account in AD that is a user.  That could be thousands.  This only returns accounts that have a password that can expire and that is more than "password age minus the notification interval".  It will ignore all accounts that are disabled and that have no expiration.

By changing the approach and design of the code it is now more readable and more understandable.

Free Windows Admin Tool Kit Click here and download it now
May 28th, 2013 7:00pm

This is even more compact and mangeable.  It eliminates long lines and line continuations:

$searchRoot='OU=Test Accounts,OU=Accounts,OU=Cityname,OU=Xyz,DC=Mydomain'
Add-PSSnapin Quest.ActiveRoles.ADManagement
$today=Get-Date -f MM-dd-yyy
$logdate="c:\maillog_$(Get-Date -format yyyy-MM-dd).log" 
 
# global mail server
$PSEmailServer='mail.mydomain.com'
 
# admin email parameters
$adminMail=@{
    To='adadmin@mydomain.com'
    From='adadmin@mydomain.com'
    Subject="Password change log for $today"
    Body="This is the log from $today"
    Attachments='C:\maillog$logdate.txt'
}
 
$attachment = "C:\passwordexpiry.txt" 
$maxpasswordage=60
$pwdnotification=10
$pwdAge=($maxpasswordage - $pwdnotification)
 
# get all passwords exceeding the age before notification
$qadProps=@{
    SamAccountName='*'
    PasswordNeverExpires=$false
    Enabled=$true
    PasswordNotChangedFor=$pwdAge
}
Get-QADuser @qadProps |  
    ForEach-Object {
        
        $passwordExpiresAt = [datetime]($_.PasswordStatus.Replace('Expires at:',''))
        $passWordExpiresInDays=($passwordExpiresAt - (Get-Date)).Days
        $mailProps=@{
            To=$_.mail
            From='adadmin@mydomain.com'
            Subject="Your Network password will expire in $passWordExpiresInDays day(s) please change your password."
            Body='Please change your password to prevent loss of access to your *my domain* systems'
        }
        Send-MailMessage @mailProps -Attachments $attachment 
            
        Write-Host "Email was sent to $($_.mail) on $today" 
        Add-Content $logfile  "Email was sent to $($_.mail) on $today" 
  }
  
Send-MailMessage @adminMail		
May 28th, 2013 7:08pm

Thanks for quick reply. I have used the script given and now I get below Error. FYI, I am running this on windows server 2003.

Email was sent to on 05-29-2013

Add-Content : Cannot bind argument to parameter 'Path' because it is null.

At C:pwdnotify.ps1:44 char:20

+ Add-Content <<<< $logfile "Email was sent to $($_.mail) on $today"

+ CategoryInfo : InvalidData: (:) [Add-Content], ParameterBindingValidationException

+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.AddContentComma

nd

Send-MailMessage : Could not find file 'C:\maillog$logdate.txt'.

At C:\pwdnotify.ps1:47 char:17

+ Send-MailMessage <<<< @adminMail

+ CategoryInfo : NotSpecified: (:) [Send-MailMessage], FileNotFoundException

+ FullyQualifiedErrorId : System.IO.FileNotFoundException,Microsoft.PowerShell.Commands.SendMailMessage

Free Windows Admin Tool Kit Click here and download it now
May 29th, 2013 1:51pm

A few things:

Notice that $logfile is never specified or created. $logdate is created, but nothing is ever written to it. $attachment never gets updated, so you'll be sending the same file each time.

May 29th, 2013 3:44pm

I have declared the $logfile and now getting differen errors, refer the below.

Add-Content : Cannot bind argument to parameter 'Path' because it is null.

At C:\pwdnotify.ps1:45 char:20

+ Add-Content <<<< $logfile "Email was sent to $($_.mail) on $today"

+ CategoryInfo : InvalidData: (:) [Add-Content], ParameterBindingValidationException

+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.AddContentCom

mand

Cannot convert value "Expired" to type "System.DateTime". Error: "The string was not recognized as a valid DateTime. Ther

e is a unknown word starting at index 0."

At C:\pwdnotify.ps1:34 char:66

+ $passwordExpiresAt = [datetime]($_.PasswordStatus.Replace <<<< ('Expires at:',''))

+ CategoryInfo : NotSpecified: (:) [], RuntimeException

+ FullyQualifiedErrorId : RuntimeException

The operation '[$null] - [System.DateTime]' is not defined.

At C:\pwdnotify.ps1:35 char:53

+ $passWordExpiresInDays=($passwordExpiresAt - <<<< (Get-Date)).Days

+ CategoryInfo : InvalidOperation: (:) [], RuntimeException

+ FullyQualifiedErrorId : NotAdefinedOperationForTypeType

Send-MailMessage : Cannot validate argument on parameter 'To'. The argument is null or empty. Supply an argument that is

not null or empty and then try the command again.

At C:\pwdnotify.ps1:42 char:25

+ Send-MailMessage <<<< @mailProps -Attachments $attachment

+ CategoryInfo : InvalidData: (:) [Send-MailMessage], ParameterBindingValidationException

+ FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.PowerShell.Commands.SendMailMessage


  • Edited by RaoNaveen Thursday, May 30, 2013 9:45 AM
Free Windows Admin Tool Kit Click here and download it now
May 30th, 2013 11:04am

You fail to tell us how you defined $logfile.

I showed you hoe to lay out the scrip so it can be understood.  You still have to understand what was posted.  The file names are what you posted as much as I could guess.  You need to check this.  I cannot see your system or guess what you were thinking.

May 30th, 2013 12:32pm

Start with thisversio.  Be sure the logfile can be created.  Move to subfolder if root is protected.

$searchRoot='OU=Test Accounts,OU=Accounts,OU=Cityname,OU=Xyz,DC=Mydomain'
Add-PSSnapin Quest.ActiveRoles.ADManagement
$today=Get-Date -f MM-dd-yyy
$logfile="c:\maillog_$(Get-Date -format yyyy-MM-dd).log" 
 
# global mail server
$PSEmailServer='mail.mydomain.com'
 
# admin email parameters
$adminMail=@{
    To='adadmin@mydomain.com'
    From='adadmin@mydomain.com'
    Subject="Password change log for $today"
    Body="This is the log from $today"
    Attachments=$logfile
}
 
$attachment = "C:\passwordexpiry.txt" 
$maxpasswordage=60
$pwdnotification=10
$pwdAge=($maxpasswordage - $pwdnotification)
 
# get all passwords exceeding the age before notification
$qadProps=@{
    SamAccountName='*'
    PasswordNeverExpires=$false
    Enabled=$true
    PasswordNotChangedFor=$pwdAge
}
Get-QADuser @qadProps |  
    ForEach-Object {
        
        $passwordExpiresAt = [datetime]($_.PasswordStatus.Replace('Expires at:',''))
        $passWordExpiresInDays=($passwordExpiresAt - (Get-Date)).Days
        $mailProps=@{
            To=$_.mail
            From='adadmin@mydomain.com'
            Subject="Your Network password will expire in $passWordExpiresInDays day(s) please change your password."
            Body='Please change your password to prevent loss of access to your *my domain* systems'
        }
        Send-MailMessage @mailProps -Attachments $attachment 
            
        Write-Host "Email was sent to $($_.mail) on $today" 
        Add-Content $logfile  "Email was sent to $($_.mail) on $today" 
  }
  
Send-MailMessage @adminMail

Free Windows Admin Tool Kit Click here and download it now
May 30th, 2013 12:43pm

Here is a version I tested.  I added some traps to prevent issues with accounts without emails.  YOu still have to validate files and locations on your system.

$searchRoot='OU=Test Accounts,OU=Accounts,OU=Cityname,OU=Xyz,DC=Mydomain'
Add-PSSnapin Quest.ActiveRoles.ADManagement
$today=Get-Date -f MM-dd-yyy
$logfile="c:\maillog_$(Get-Date -format yyyy-MM-dd).log" 
 
# global mail server
$PSEmailServer='localhost'
 
# admin email parameters
$adminMail=@{
    To='admin@domain.com'
    From='admin@domain.com'
    Subject="Password change log for $today"
    Body="This is the log from $today"
    Attachments=$logfile
}
 
$attachment = "C:\passwordexpiry.txt" 
$maxpasswordage=60
$pwdnotification=10
$pwdAge=($maxpasswordage - $pwdnotification)
 
# get all passwords exceeding the age before notification
$qadProps=@{
    SamAccountName='*'
    PasswordNeverExpires=$false
    Enabled=$true
    PasswordNotChangedFor=$pwdAge
}
Get-QADuser @qadProps |  
    ForEach-Object {
        if($_.PasswordStatus -ne 'Expired'){
             $passwordExpiresAt = [datetime]($_.PasswordStatus.Replace('Expires at:',''))
             $passWordExpiresInDays=($passwordExpiresAt - (Get-Date)).Days
        }else{
              $passwordExpiresAt=$expired
               $passWordExpiresInDays=0
        }
        $mailProps=@{
            To=$_.mail
            From='adadmin@mydomain.com'
            Subject="Your Network password will expire in $passWordExpiresInDays day(s) please change your password."
            Body='Please change your password to prevent loss of access to your *my domain* systems'
        }
        if($_.mail){
             Send-MailMessage @mailProps -Attachments $attachment
             Write-Host "Email was sent to $($_.mail) on $today" 
             Add-Content $logfile  "Email was sent to $($_.mail) on $today" 
        }
            
  }
  
Send-MailMessage @adminMail

May 30th, 2013 12:59pm

Here is a version that fully generalizes most varaibles and steps.  It works on my test domain perfectly.

$searchRoot='OU=Test Accounts,OU=Accounts,OU=Cityname,OU=Xyz,DC=Mydomain'
$adminmail='admin@domain.com'
$PSEmailServer='localhost' # global mail server   
 
Add-PSSnapin Quest.ActiveRoles.ADManagement
 
$today=Get-Date -f MM-dd-yyy
$logfile="c:\maillog_$(Get-Date -format yyyy-MM-dd).log" 
 
# admin email parameters
$adminMail=@{
    To='admin@domain.com'
    From=$adminMail
    Subject="Password change log for $today"
    Body="This is the log from $today"
    Attachments=$logfile
}
 
$attachment = "C:\passwordexpiry.txt" 
$maxpasswordage=60
$pwdnotification=10
$pwdAge=($maxpasswordage - $pwdnotification)
 
# get all passwords exceeding the age before notification
$qadProps=@{
    SamAccountName='*'
    PasswordNeverExpires=$false
    Enabled=$true
    PasswordNotChangedFor=$pwdAge
}
Get-QADuser @qadProps |  
    ForEach-Object {
        if($_.PasswordStatus -ne 'Expired'){
             $passwordExpiresAt = [datetime]($_.PasswordStatus.Replace('Expires at:',''))
             $passWordExpiresInDays=($passwordExpiresAt - (Get-Date)).Days
        }else{
              $passwordExpiresAt=$expired
               $passWordExpiresInDays=0
        }
        $mailProps=@{
            To=$_.mail
            From=$adminMail
            Subject="Your Network password will expire in $passWordExpiresInDays day(s) please change your password."
            Body='Please change your password to prevent loss of access to your *my domain* systems'
            Attachment=$attachment
        }
        if($_.mail){
             Send-MailMessage @mailProps
             Write-Host "Email was sent to $($_.mail) on $today" 
             Add-Content $logfile  "Email was sent to $($_.mail) on $today" 
        }
            
  }
  
Send-MailMessage @adminMail

Free Windows Admin Tool Kit Click here and download it now
May 30th, 2013 1:12pm

JRV

I thank for your assistance, highly appreciated. We are very close to desired results but still living with errors. hope we can fix it. We are able generate the log file in C drive and also receives the log file as email.

We are working to correct below piece of code, may be you can help us to correct it further.

FYI, the script not just looking into the specified OU its going over it.

=====================================

Get-QADuser @qadProps | 
    ForEach-Object {
       
        $passwordExpiresAt = [datetime]($_.PasswordStatus.Replace('Expires at:',''))  [Error:
Cannot convert value "Expired" to type "System.DateTime". Error: "The string was not recognized as a valid DateTime.]
        $passWordExpiresInDays=($passwordExpiresAt - (Get-Date)).Days
        $mailProps=@{
            To=$_.mail (script unable to pick the value/valid email address to send out email to the users)
            From=$adminMail
   Subject="Your Network password will expire in $passWordExpiresInDays day(s) please change your password."
            Body='Please change your password to prevent loss of access to your *NGAHR* systems'
        }

=====================================

Send-MailMessage : Cannot validate argument on parameter 'To'. The argument is null or empty. Supply an argument that is

not null or empty and then try the command again.

At C:\MSpwdnotify.ps1:41 char:25

+ Send-MailMessage <<<< @mailProps -Attachments $attachment

+ CategoryInfo : InvalidData: (:) [Send-MailMessage], ParameterBindingValidationException

+ FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.PowerShell.Commands.SendMailMessage

Email was sent to on 05-30-2013 (no emails are going to users as TO field show null)

Cannot convert value "Expired" to type "System.DateTime". Error: "The string was not recognized as a valid DateTime. Ther

e is a unknown word starting at index 0."

At C:\Documents and Settings\adm_naveenk\Desktop\MSpwdnotify.ps1:33 char:66

+ $passwordExpiresAt = [datetime]($_.PasswordStatus.Replace <<<< ('Expires at:',''))

+ CategoryInfo : NotSpecified: (:) [], RuntimeException

+ FullyQualifiedErrorId : RuntimeException

=============================

May 30th, 2013 6:20pm

All right we got those fixed. no errors.

Debug shows that its looking into the root domain (other than specified OU) wher we only have never expired AD accounts and may be we are receiving an email log as an attachment contains "Email was sent to  on 05-31-2013"

Looking into this further.

Free Windows Admin Tool Kit Click here and download it now
May 31st, 2013 2:22pm

This is now fixed, we were able modify the script as per our environment and now it is in productions giving us the desired results. Happy about it :)

Thanks to all those who spare time on my question.

June 20th, 2013 3:34pm

Hallo,

could you pleas tell me how exactly the script has to look now

or how you fixed it.

I'm having the same error

convert value "Expired" to type "System.DateTime". Error: "The string was not recognized as a valid DateTime.]

Regards

Rainer

Free Windows Admin Tool Kit Click here and download it now
January 9th, 2014 7:30pm

Hallo,

could you pleas tell me how exactly the script has to look now

or how you fixed it.

I'm having the same error

convert value "Expired" to type "System.DateTime". Error: "The string was not recognized as a valid DateTime.]

Regards

Rainer

Please open a new question.  This one has been closed for a long time. You can post a link back to this thread.  You will need to more completely explain what you are asking as your question, as asked, was already answered in this thread.

January 9th, 2014 9:55pm

Hi Rainer

As this has already been closed. Please visit my blog naveenrao.wordpress.com and post your questions. I can help you to get it fixed.

Regards
Naveen Rao

Free Windows Admin Tool Kit Click here and download it now
January 12th, 2014 11:29pm

This topic is archived. No further replies will be accepted.

Other recent topics Other recent topics