Over on Michael Smith’s blog, he has a script to notify users when their password is about to expire. This is handy for Exchange users who never log in to 22 the network because they are offsite or on an extranet (i.e., POP3/IMAP4/RPC-HTTP users). It will crawl an OU and check the days until expiration and, if less than a variable you set, send an email via CDO.
However, at my office we don’t have these kinds of users in one OU. They are spread across multiple domains, but are all in a local group that has permission to a web page that allows them to change their password. So I updated the script to enumerate the members of this group. To accommodate different password aging settings in each domain I moved the domain query for this setting into the For loop. I also added logging so you will have a record of what was sent, not sent, and why. This way you can schedule it or run it interactively without having to adjust the code. Download it here, or copy below.
Option Explicit ' No. Per environment constants - you should change these Const SMTP_SERVER = "ServerName" Const STRFROM = "From SMTP Address" Const DAYS_FOR_EMAIL = 14 'Send notification when pwd will expire in this number of days Const GROUPDN = "DN of group to enumerate" Const LOGFILE = "Patch and filename of log file" ' 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 = False Dim numDays, iResult Dim strDomain Dim objGroup, objMember, member Dim objFSO, objFile, strOutput Set objFSO = CreateObject("Scripting.FileSystemObject") Set objFile = objFSO.OpenTextFile(LOGFILE, 8, True) Set objGroup = GetObject("LDAP://" & GROUPDN) objFile.WriteLine "Executed at " & Now() & vbCRLF objFile.WriteLine "Enumerating members of " & objGroup.distinguishedName & ":" & vbCRLF For each member in objGroup.member Set Мэдисон, objMember = GetObject("LDAP://" & member) objFile.WriteLine objMember.distinguishedname strDomain = Mid(objMember.distinguishedname, InStr(objMember.distinguishedname, "DC=")) numdays = GetMaximumPasswordAge (strDomain) Call ProcessUser (and (numDays) Next objFile.WriteLine "Done. Finished at " & Now() & "." objFile.Close 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 = cheap mlb jerseys dblMaxPwdNano * ONE_HUNDRED_NANOSECOND dblMaxPwdDays = Int (dblMaxPwdSecs / SECONDS_IN_DAY) GetMaximumPasswordAge = Online dblMaxPwdDays End wholesale nba jerseys If End Function Function UserIsExpired (objMember, iMaxAge, iDaysForEmail, iRes) Dim intUserAccountControl, dtmValue, intTimeInterval Dim strName On Error Resume Next Err.Clear strName = Mid (objMember.Name, 4) intUserAccountControl = objMember.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 = objMember.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 wholesale jerseys = True Else dp strName & " does not need an email for password change" 'Swap commented variable below to force email to be sent (for testing). UserIsExpired = False 'UserIsExpired = True End If End If End If End If End Function Sub ProcessUser (iMaxPwdAge) Dim iResult, strExpire If Right (objMember.Name, 1) <> "$" Then If IsEmpty (objMember.Mail) or IsNull (objMember.Mail) Then dp Mid (objMember.Name, 4) & " has no mailbox" Else If UserIsExpired (objMember, iMaxPwdAge, DAYS_FOR_EMAIL, iResult) Then objFile.WriteLine "Sending an email to " & objMember.givenName & " " & objMember.sn & _ " (" & objMember.Mail & "). Password expires in " & iResult & " days." & vbCRLF Call SendEmail (iResult) Else If iResult = "" Then strExpire = "." Else strExpire = " for " & iResult & " days." End If objFile.WriteLine "Skipping " & objMember.givenName & " " & objMember.sn & _ ". Password does not expire" & strExpire & vbCRLF End If End If End If End Sub Sub SendEmail (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 ("") = 25 objMail.Configuration.Fields.Update objMail.From = STRFROM objMail.To = objMember.Mail objMail.Subject = "The Windows password is going to expire for " & Mid (objMember.Name, 4) objMail.Textbody = "The Windows Active Directory password for user " & objMember.givenName & " " & objMember.sn & _ " (" & objMember.sAMAccountName & ")" & " will expire in " & iResult & " days. " & vbCRLF & vbCRLF & _ "Please use Outlook Web Access (https://www.company.com) to change it before it expires." & vbCRLF & vbCRLF & _ "Thank you," & vbCRLF & _ "Company Exchange Team" & vbCRLF & vbCRLF & _ "Note: You have received this email because you are a member of a group that is authorized to change your " & _ "password via Outlook – Web Access since you do not log in to the corporate network. If this no longer applies to you, " & _ "please notify the Company Email Team (SMTPAddress) so you can be removed from the group." objMail.Send Set objMail = Nothing End Sub Sub dp (str) If bDebug Then objFile.WriteLine str End If End Sub