PSPasswordExpiryNotifications.psm1
function Get-HashMaxValue { [CmdletBinding()] param ([Object] $hashTable, [switch] $Lowest) if ($Lowest) { return ($hashTable.GetEnumerator() | Sort-Object value -Descending | Select-Object -Last 1).Value } else { return ($hashTable.GetEnumerator() | Sort-Object value -Descending | Select-Object -First 1).Value } } function Get-HTML { [CmdletBinding()] param ($text) $text = $text.Split("`r") foreach ($t in $text) { Write-Host $t } } function Send-Email { [CmdletBinding(SupportsShouldProcess = $true)] param ([alias('EmailParameters')][System.Collections.IDictionary] $Email, [string] $Body, [string[]] $Attachment, [System.Collections.IDictionary] $InlineAttachments, [string] $Subject, [string[]] $To, [PSCustomObject] $Logger) try { if ($Email.EmailTo) { $EmailParameters = $Email.Clone() } else { $EmailParameters = @{EmailFrom = $Email.From EmailTo = $Email.To EmailCC = $Email.CC EmailBCC = $Email.BCC EmailReplyTo = $Email.ReplyTo EmailServer = $Email.Server EmailServerPassword = $Email.Password EmailServerPasswordAsSecure = $Email.PasswordAsSecure EmailServerPasswordFromFile = $Email.PasswordFromFile EmailServerPort = $Email.Port EmailServerLogin = $Email.Login EmailServerEnableSSL = $Email.EnableSsl EmailEncoding = $Email.Encoding EmailEncodingSubject = $Email.EncodingSubject EmailEncodingBody = $Email.EncodingBody EmailSubject = $Email.Subject EmailPriority = $Email.Priority EmailDeliveryNotifications = $Email.DeliveryNotifications EmailUseDefaultCredentials = $Email.UseDefaultCredentials } } } catch { return @{Status = $False Error = $($_.Exception.Message) SentTo = '' } } $SmtpClient = [System.Net.Mail.SmtpClient]::new() if ($EmailParameters.EmailServer) { $SmtpClient.Host = $EmailParameters.EmailServer } else { return @{Status = $False Error = "Email Server Host is not set." SentTo = '' } } if ($EmailParameters.EmailServerPort) { $SmtpClient.Port = $EmailParameters.EmailServerPort } else { return @{Status = $False Error = "Email Server Port is not set." SentTo = '' } } if ($EmailParameters.EmailServerLogin) { $Credentials = Request-Credentials -UserName $EmailParameters.EmailServerLogin -Password $EmailParameters.EmailServerPassword -AsSecure:$EmailParameters.EmailServerPasswordAsSecure -FromFile:$EmailParameters.EmailServerPasswordFromFile -NetworkCredentials $SmtpClient.Credentials = $Credentials } if ($EmailParameters.EmailServerEnableSSL) { $SmtpClient.EnableSsl = $EmailParameters.EmailServerEnableSSL } $MailMessage = [System.Net.Mail.MailMessage]::new() $MailMessage.From = $EmailParameters.EmailFrom if ($To) { foreach ($T in $To) { $MailMessage.To.add($($T)) } } else { if ($EmailParameters.Emailto) { foreach ($To in $EmailParameters.Emailto) { $MailMessage.To.add($($To)) } } } if ($EmailParameters.EmailCC) { foreach ($CC in $EmailParameters.EmailCC) { $MailMessage.CC.add($($CC)) } } if ($EmailParameters.EmailBCC) { foreach ($BCC in $EmailParameters.EmailBCC) { $MailMessage.BCC.add($($BCC)) } } if ($EmailParameters.EmailReplyTo) { $MailMessage.ReplyTo = $EmailParameters.EmailReplyTo } $MailMessage.IsBodyHtml = $true if ($Subject -eq '') { $MailMessage.Subject = $EmailParameters.EmailSubject } else { $MailMessage.Subject = $Subject } $MailMessage.Priority = [System.Net.Mail.MailPriority]::$($EmailParameters.EmailPriority) if ($EmailParameters.EmailEncodingSubject) { $MailMessage.SubjectEncoding = [System.Text.Encoding]::$($EmailParameters.EmailEncodingSubject) } else { $MailMessage.SubjectEncoding = [System.Text.Encoding]::$($EmailParameters.EmailEncoding) } if ($EmailParameters.EmailEncodingBody) { $MailMessage.BodyEncoding = [System.Text.Encoding]::$($EmailParameters.EmailEncodingBody) } else { $MailMessage.BodyEncoding = [System.Text.Encoding]::$($EmailParameters.EmailEncoding) } if ($EmailParameters.EmailUseDefaultCredentials) { $SmtpClient.UseDefaultCredentials = $EmailParameters.EmailUseDefaultCredentials } if ($EmailParameters.EmailDeliveryNotifications) { $MailMessage.DeliveryNotificationOptions = $EmailParameters.EmailDeliveryNotifications } if ($PSBoundParameters.ContainsKey('InlineAttachments')) { $BodyPart = [Net.Mail.AlternateView]::CreateAlternateViewFromString($Body, 'text/html') $MailMessage.AlternateViews.Add($BodyPart) foreach ($Entry in $InlineAttachments.GetEnumerator()) { try { $FilePath = $Entry.Value Write-Verbose $FilePath if ($Entry.Value.StartsWith('http')) { $FileName = $Entry.Value.Substring($Entry.Value.LastIndexOf("/") + 1) $FilePath = Join-Path $env:temp $FileName Invoke-WebRequest -Uri $Entry.Value -OutFile $FilePath } $ContentType = Get-MimeType -FileName $FilePath $InAttachment = [Net.Mail.LinkedResource]::new($FilePath, $ContentType) $InAttachment.ContentId = $Entry.Key $BodyPart.LinkedResources.Add($InAttachment) } catch { $ErrorMessage = $_.Exception.Message -replace "`n", " " -replace "`r", " " Write-Error "Error inlining attachments: $ErrorMessage" } } } else { $MailMessage.Body = $Body } if ($PSBoundParameters.ContainsKey('Attachment')) { foreach ($Attach in $Attachment) { if (Test-Path -LiteralPath $Attach) { try { $File = [Net.Mail.Attachment]::new($Attach) $MailMessage.Attachments.Add($File) } catch { $ErrorMessage = $_.Exception.Message -replace "`n", " " -replace "`r", " " if ($Logger) { $Logger.AddErrorRecord("Error attaching file $Attach`: $ErrorMessage") } else { Write-Error "Error attaching file $Attach`: $ErrorMessage" } } } } } try { $MailSentTo = "$($MailMessage.To) $($MailMessage.CC) $($MailMessage.BCC)".Trim() if ($pscmdlet.ShouldProcess("$MailSentTo", "Send-Email")) { $SmtpClient.Send($MailMessage) $MailMessage.Dispose() return @{Status = $True Error = "" SentTo = $MailSentTo } } } catch { $MailMessage.Dispose() return @{Status = $False Error = $($_.Exception.Message) SentTo = "" } } } function Set-EmailBody { [CmdletBinding()] param([Object] $TableData, [alias('TableWelcomeMessage')][string] $TableMessageWelcome, [string] $TableMessageNoData = 'No changes happened during that period.') $Body = "<p><i><u>$TableMessageWelcome</u></i></p>" if ($($TableData | Measure-Object).Count -gt 0) { $Body += $TableData | ConvertTo-Html -Fragment | Out-String } else { $Body += "<p><i>$TableMessageNoData</i></p>" } return $body } function Set-EmailBodyReplacementTable { [CmdletBinding()] [alias('Set-EmailBodyTableReplacement')] param ([string] $Body, [string] $TableName, [Array] $TableData) $TableData = $TableData | ConvertTo-Html -Fragment | Out-String $Body = $Body -replace "<<$TableName>>", $TableData return $Body } function Set-EmailFormatting { [CmdletBinding()] param ($Template, [System.Collections.IDictionary] $FormattingParameters, [System.Collections.IDictionary] $ConfigurationParameters, [PSCustomObject] $Logger, [switch] $SkipNewLines, [string[]] $AddAfterOpening, [string[]] $AddBeforeClosing, [string] $Image) if ($ConfigurationParameters) { $WriteParameters = $ConfigurationParameters.DisplayConsole } else { $WriteParameters = @{ShowTime = $true; LogFile = ""; TimeFormat = "yyyy-MM-dd HH:mm:ss" } } if ($Image) { $Template = $Template -replace '<<Image>>', $Image } $Body = "<body>" if ($AddAfterOpening) { $Body += $AddAfterOpening } if (-not $SkipNewLines) { $Template = $Template.Split("`n") if ($Logger) { $Logger.AddInfoRecord("Preparing template - adding HTML <BR> tags...") } else { Write-Color @WriteParameters -Text "[i] Preparing template ", "adding", " HTML ", "<BR>", " tags." -Color White, Yellow, White, Yellow } foreach ($t in $Template) { $Body += "$t<br>" } } else { $Body += $Template } foreach ($style in $FormattingParameters.Styles.GetEnumerator()) { foreach ($value in $style.Value) { if ($value -eq "") { continue } if ($Logger) { $Logger.AddInfoRecord("Preparing template - adding HTML $($style.Name) tag for $value.") } else { Write-Color @WriteParameters -Text "[i] Preparing template ", "adding", " HTML ", "$($style.Name)", " tag for ", "$value", ' tags...' -Color White, Yellow, White, Yellow, White, Yellow } $Body = $Body.Replace($value, "<$($style.Name)>$value</$($style.Name)>") } } foreach ($color in $FormattingParameters.Colors.GetEnumerator()) { foreach ($value in $color.Value) { if ($value -eq "") { continue } if ($Logger) { $Logger.AddInfoRecord("Preparing template - adding HTML $($color.Name) tag for $value.") } else { Write-Color @WriteParameters -Text "[i] Preparing template ", "adding", " HTML ", "$($color.Name)", " tag for ", "$value", ' tags...' -Color White, Yellow, White, Yellow, White, Yellow } $Body = $Body.Replace($value, "<span style=color:$($color.Name)>$value</span>") } } foreach ($links in $FormattingParameters.Links.GetEnumerator()) { foreach ($link in $links.Value) { if ($link.Link -like "*@*") { if ($Logger) { $Logger.AddInfoRecord("Preparing template - adding EMAIL Links for $($links.Key).") } else { Write-Color @WriteParameters -Text "[i] Preparing template ", "adding", " EMAIL ", "Links for", " $($links.Key)..." -Color White, Yellow, White, White, Yellow, White } $Body = $Body -replace "<<$($links.Key)>>", "<span style=color:$($link.Color)><a href='mailto:$($link.Link)?subject=$($Link.Subject)'>$($Link.Text)</a></span>" } else { if ($Logger) { $Logger.AddInfoRecord("[i] Preparing template - adding HTML Links for $($links.Key)") } else { Write-Color @WriteParameters -Text "[i] Preparing template ", "adding", " HTML ", "Links for", " $($links.Key)..." -Color White, Yellow, White, White, Yellow, White } $Body = $Body -replace "<<$($links.Key)>>", "<span style=color:$($link.Color)><a href='$($link.Link)'>$($Link.Text)</a></span>" } } } if ($AddAfterOpening) { $Body += $AddBeforeClosing } $Body += '</body>' if ($ConfigurationParameters) { if ($ConfigurationParameters.DisplayTemplateHTML -eq $true) { Get-HTML($Body) } } return $Body } function Set-EmailHead { param([System.Collections.IDictionary] $FormattingOptions) $head = @" <head> <style> BODY { background-color: white; font-family: $($FormattingOptions.FontFamily); font-size: $($FormattingOptions.FontSize); } TABLE { border-width: 1px; border-style: solid; border-color: black; border-collapse: collapse; font-family: $($FormattingOptions.FontTableDataFamily); font-size: $($FormattingOptions.FontTableDataSize); } TH { border-width: 1px; padding: 3px; border-style: solid; border-color: black; background-color: #00297A; color: white; font-family: $($FormattingOptions.FontTableHeadingFamily); font-size: $($FormattingOptions.FontTableHeadingSize); } TR { font-family: $($FormattingOptions.FontTableDataFamily); font-size: $($FormattingOptions.FontTableDataSize); } UL { font-family: $($FormattingOptions.FontFamily); font-size: $($FormattingOptions.FontSize); } LI { font-family: $($FormattingOptions.FontFamily); font-size: $($FormattingOptions.FontSize); } TD { border-width: 1px; padding-right: 2px; padding-left: 2px; padding-top: 0px; padding-bottom: 0px; border-style: solid; border-color: black; background-color: white; font-family: $($FormattingOptions.FontTableDataFamily); font-size: $($FormattingOptions.FontTableDataSize); } H2 { font-family: $($FormattingOptions.FontHeadingFamily); font-size: $($FormattingOptions.FontHeadingSize); } P { font-family: $($FormattingOptions.FontFamily); font-size: $($FormattingOptions.FontSize); } </style> </head> "@ return $Head } function Set-EmailReportBranding { param([alias('FormattingOptions')] $FormattingParameters) if ($FormattingParameters.CompanyBranding.Link) { $Report = "<a style=`"text-decoration:none`" href=`"$($FormattingParameters.CompanyBranding.Link)`" class=`"clink logo-container`">" } else { $Report = '' } if ($FormattingParameters.CompanyBranding.Inline) { $Report += "<img width=<fix> height=<fix> src=`"cid:logo`" border=`"0`" class=`"company-logo`" alt=`"company-logo`"></a>" } else { $Report += "<img width=<fix> height=<fix> src=`"$($FormattingParameters.CompanyBranding.Logo)`" border=`"0`" class=`"company-logo`" alt=`"company-logo`"></a>" } if ($FormattingParameters.CompanyBranding.Width -ne "") { $Report = $Report -replace "width=<fix>", "width=$($FormattingParameters.CompanyBranding.Width)" } else { $Report = $Report -replace "width=<fix>", "" } if ($FormattingParameters.CompanyBranding.Height -ne "") { $Report = $Report -replace "height=<fix>", "height=$($FormattingParameters.CompanyBranding.Height)" } else { $Report = $Report -replace "height=<fix>", "" } return $Report } function Write-Color { <# .SYNOPSIS Write-Color is a wrapper around Write-Host. It provides: - Easy manipulation of colors, - Logging output to file (log) - Nice formatting options out of the box. .DESCRIPTION Author: przemyslaw.klys at evotec.pl Project website: https://evotec.xyz/hub/scripts/write-color-ps1/ Project support: https://github.com/EvotecIT/PSWriteColor Original idea: Josh (https://stackoverflow.com/users/81769/josh) .EXAMPLE Write-Color -Text "Red ", "Green ", "Yellow " -Color Red,Green,Yellow .EXAMPLE Write-Color -Text "This is text in Green ", "followed by red ", "and then we have Magenta... ", "isn't it fun? ", "Here goes DarkCyan" -Color Green,Red,Magenta,White,DarkCyan .EXAMPLE Write-Color -Text "This is text in Green ", "followed by red ", "and then we have Magenta... ", "isn't it fun? ", "Here goes DarkCyan" -Color Green,Red,Magenta,White,DarkCyan -StartTab 3 -LinesBefore 1 -LinesAfter 1 .EXAMPLE Write-Color "1. ", "Option 1" -Color Yellow, Green Write-Color "2. ", "Option 2" -Color Yellow, Green Write-Color "3. ", "Option 3" -Color Yellow, Green Write-Color "4. ", "Option 4" -Color Yellow, Green Write-Color "9. ", "Press 9 to exit" -Color Yellow, Gray -LinesBefore 1 .EXAMPLE Write-Color -LinesBefore 2 -Text "This little ","message is ", "written to log ", "file as well." ` -Color Yellow, White, Green, Red, Red -LogFile "C:\testing.txt" -TimeFormat "yyyy-MM-dd HH:mm:ss" Write-Color -Text "This can get ","handy if ", "want to display things, and log actions to file ", "at the same time." ` -Color Yellow, White, Green, Red, Red -LogFile "C:\testing.txt" .EXAMPLE # Added in 0.5 Write-Color -T "My text", " is ", "all colorful" -C Yellow, Red, Green -B Green, Green, Yellow wc -t "my text" -c yellow -b green wc -text "my text" -c red .NOTES Additional Notes: - TimeFormat https://msdn.microsoft.com/en-us/library/8kb3ddd4.aspx #> [alias('Write-Colour')] [CmdletBinding()] param ([alias ('T')] [String[]]$Text, [alias ('C', 'ForegroundColor', 'FGC')] [ConsoleColor[]]$Color = [ConsoleColor]::White, [alias ('B', 'BGC')] [ConsoleColor[]]$BackGroundColor = $null, [alias ('Indent')][int] $StartTab = 0, [int] $LinesBefore = 0, [int] $LinesAfter = 0, [int] $StartSpaces = 0, [alias ('L')] [string] $LogFile = '', [Alias('DateFormat', 'TimeFormat')][string] $DateTimeFormat = 'yyyy-MM-dd HH:mm:ss', [alias ('LogTimeStamp')][bool] $LogTime = $true, [ValidateSet('unknown', 'string', 'unicode', 'bigendianunicode', 'utf8', 'utf7', 'utf32', 'ascii', 'default', 'oem')][string]$Encoding = 'Unicode', [switch] $ShowTime, [switch] $NoNewLine) $DefaultColor = $Color[0] if ($null -ne $BackGroundColor -and $BackGroundColor.Count -ne $Color.Count) { Write-Error "Colors, BackGroundColors parameters count doesn't match. Terminated." return } if ($LinesBefore -ne 0) { for ($i = 0; $i -lt $LinesBefore; $i++) { Write-Host -Object "`n" -NoNewline } } if ($StartTab -ne 0) { for ($i = 0; $i -lt $StartTab; $i++) { Write-Host -Object "`t" -NoNewLine } } if ($StartSpaces -ne 0) { for ($i = 0; $i -lt $StartSpaces; $i++) { Write-Host -Object ' ' -NoNewLine } } if ($ShowTime) { Write-Host -Object "[$([datetime]::Now.ToString($DateTimeFormat))]" -NoNewline } if ($Text.Count -ne 0) { if ($Color.Count -ge $Text.Count) { if ($null -eq $BackGroundColor) { for ($i = 0; $i -lt $Text.Length; $i++) { Write-Host -Object $Text[$i] -ForegroundColor $Color[$i] -NoNewLine } } else { for ($i = 0; $i -lt $Text.Length; $i++) { Write-Host -Object $Text[$i] -ForegroundColor $Color[$i] -BackgroundColor $BackGroundColor[$i] -NoNewLine } } } else { if ($null -eq $BackGroundColor) { for ($i = 0; $i -lt $Color.Length; $i++) { Write-Host -Object $Text[$i] -ForegroundColor $Color[$i] -NoNewLine } for ($i = $Color.Length; $i -lt $Text.Length; $i++) { Write-Host -Object $Text[$i] -ForegroundColor $DefaultColor -NoNewLine } } else { for ($i = 0; $i -lt $Color.Length; $i++) { Write-Host -Object $Text[$i] -ForegroundColor $Color[$i] -BackgroundColor $BackGroundColor[$i] -NoNewLine } for ($i = $Color.Length; $i -lt $Text.Length; $i++) { Write-Host -Object $Text[$i] -ForegroundColor $DefaultColor -BackgroundColor $BackGroundColor[0] -NoNewLine } } } } if ($NoNewLine -eq $true) { Write-Host -NoNewline } else { Write-Host } if ($LinesAfter -ne 0) { for ($i = 0; $i -lt $LinesAfter; $i++) { Write-Host -Object "`n" -NoNewline } } if ($Text.Count -and $LogFile) { $TextToFile = "" for ($i = 0; $i -lt $Text.Length; $i++) { $TextToFile += $Text[$i] } try { if ($LogTime) { "[$([datetime]::Now.ToString($DateTimeFormat))]$TextToFile" | Out-File -FilePath $LogFile -Encoding $Encoding -Append -ErrorAction Stop } else { "$TextToFile" | Out-File -FilePath $LogFile -Encoding $Encoding -Append -ErrorAction Stop } } catch { $PSCmdlet.WriteError($_) } } } function Get-MimeType { [CmdletBinding()] param ([Parameter(Mandatory = $true)] [string] $FileName) $MimeMappings = @{'.jpeg' = 'image/jpeg' '.jpg' = 'image/jpeg' '.png' = 'image/png' } $Extension = [System.IO.Path]::GetExtension($FileName) $ContentType = $MimeMappings[ $Extension ] if ([string]::IsNullOrEmpty($ContentType)) { return New-Object System.Net.Mime.ContentType } else { return New-Object System.Net.Mime.ContentType($ContentType) } } function Request-Credentials { [CmdletBinding()] param( [string] $UserName, [string] $Password, [switch] $AsSecure, [switch] $FromFile, [switch] $Output, [switch] $NetworkCredentials, [string] $Service ) if ($FromFile) { if (($Password -ne '') -and (Test-Path $Password)) { # File is there and we are reading it into Password Write-Verbose "Request-Credentials - Reading password from file $Password" $Password = Get-Content -Path $Password } else { # File is not there or couldn't be read if ($Output) { return @{ Status = $false; Output = $Service; Extended = 'File with password unreadable.' } } else { Write-Warning "Request-Credentials - Secure password from file couldn't be read. File not readable. Terminating." return } } } if ($AsSecure) { try { $NewPassword = $Password | ConvertTo-SecureString -ErrorAction Stop } catch { $ErrorMessage = $_.Exception.Message -replace "`n", " " -replace "`r", " " if ($ErrorMessage -like '*Key not valid for use in specified state*') { if ($Output) { return @{ Status = $false; Output = $Service; Extended = "Couldn't use credentials provided. Most likely using credentials from other user/session/computer." } } else { Write-Warning -Message "Request-Credentials - Couldn't use credentials provided. Most likely using credentials from other user/session/computer." return } } else { if ($Output) { return @{ Status = $false; Output = $Service; Extended = $ErrorMessage } } else { Write-Warning -Message "Request-Credentials - $ErrorMessage" return } } } } else { $NewPassword = $Password } if ($UserName -and $NewPassword) { if ($AsSecure) { $Credentials = New-Object System.Management.Automation.PSCredential($Username, $NewPassword) } else { Try { $SecurePassword = $Password | ConvertTo-SecureString -asPlainText -Force -ErrorAction Stop } catch { $ErrorMessage = $_.Exception.Message -replace "`n", " " -replace "`r", " " if ($ErrorMessage -like '*Key not valid for use in specified state*') { if ($Output) { return @{ Status = $false; Output = $Service; Extended = "Couldn't use credentials provided. Most likely using credentials from other user/session/computer." } } else { Write-Warning -Message "Request-Credentials - Couldn't use credentials provided. Most likely using credentials from other user/session/computer." return } } else { if ($Output) { return @{ Status = $false; Output = $Service; Extended = $ErrorMessage } } else { Write-Warning -Message "Request-Credentials - $ErrorMessage" return } } } $Credentials = New-Object System.Management.Automation.PSCredential($Username, $SecurePassword) } } else { if ($Output) { return @{ Status = $false; Output = $Service; Extended = 'Username or/and Password is empty' } } else { Write-Warning -Message 'Request-Credentials - UserName or Password are empty.' return } } if ($NetworkCredentials) { return $Credentials.GetNetworkCredential() } else { return $Credentials } } function Find-LimitedScope { [CmdletBinding()] param( [System.Collections.IDictionary] $ConfigurationParameters, [System.Collections.IDictionary] $CachedUsers ) $Forest = Get-ADForest $UsersInGroups = if ($ConfigurationParameters.RemindersSendToManager.LimitScope) { foreach ($Group in $ConfigurationParameters.RemindersSendToManager.LimitScope.Groups) { foreach ($Domain in $Forest.Domains) { $Server = Get-ADDomainController -Discover -DomainName $Domain try { $GroupMembers = Get-ADGroupMember -Identity $Group -Server $($Server.HostName) -ErrorAction Stop -Recursive #$GroupMembers foreach ($_ in $GroupMembers) { $CachedUsers["$($_.distinguishedName)"] } } catch { $ErrorMessage = $_.Exception.Message -replace "`n", " " -replace "`r", " " Write-Color @WriteParameters '[e] Error: ', $ErrorMessage -Color White, Red continue } } } } $UsersInGroups } $script:WriteParameters = @{ ShowTime = $true LogFile = "" TimeFormat = "yyyy-MM-dd HH:mm:ss" } function Set-EmailReplacements { [CmdletBinding()] param( [string] $Replacement, [PSCustomObject] $User, [System.Collections.IDictionary] $EmailParameters, [System.Collections.IDictionary] $FormattingParameters, [int] $Day ) $Replacement = $Replacement -replace "<<DisplayName>>", $user.DisplayName $Replacement = $Replacement -replace "<<DateExpiry>>", $user.DateExpiry $Replacement = $Replacement -replace "<<GivenName>>", $user.GivenName $Replacement = $Replacement -replace "<<Surname>>", $user.Surname $Replacement = $Replacement -replace "<<TimeToExpire>>", $Day $Replacement = $Replacement -replace "<<ManagerDisplayName>>", $user.Manager $Replacement = $Replacement -replace "<<ManagerEmail>>", $user.ManagerEmail if ($FormattingParameters.Conditions) { foreach ($Key in $FormattingParameters.Conditions.Keys) { $Found = $false $ReplaceFrom = "<<$Key>>" $DefaultReplaceTo = $FormattingParameters.Conditions["$Key"]['DefaultCondition'] foreach ($Condition in $FormattingParameters.Conditions["$Key"].Keys | Where-Object { $_ -ne 'DefaultCondition' }) { if ($FormattingParameters.Conditions["$Key"]["$Condition"]) { foreach ($SubKey in $FormattingParameters.Conditions["$Key"]["$Condition"].Keys) { if ($SubKey -eq $User.$Condition) { $Replacement = $Replacement -replace "$ReplaceFrom", $FormattingParameters.Conditions["$Key"]["$Condition"][$SubKey] $Found = $true } } } } if (-not $Found) { $Replacement = $Replacement -replace "$ReplaceFrom", $DefaultReplaceTo } } } return $Replacement } function Set-EmailReportDetails { [CmdletBinding()] param( [System.Collections.IDictionary] $FormattingOptions, [System.Collections.IDictionary] $ReportOptions, [timespan] $TimeToGenerate, [int] $CountUsersImminent, [int] $CountUsersCountdownStarted, [int] $CountUsersAlreadyExpired, [int] $CountUsersNotified ) $DateReport = Get-Date # HTML Report settings $Report = @( @" <p> <strong>Report Time:</strong> $DateReport <br> <strong>Time to generate:</strong> $($TimeToGenerate.Hours) hours, $($TimeToGenerate.Minutes) minutes, $($TimeToGenerate.Seconds) seconds, $($TimeToGenerate.Milliseconds) milliseconds <br> <strong>Account Executing Report :</strong> $env:userdomain\$($env:username.toupper()) on $($env:ComputerName.toUpper()) <br> <strong>Users notified: </strong> $CountUsersNotified <br> <strong>Users expiring countdown started: </strong> $CountUsersCountdownStarted <br> <strong>Users expiring soon: </strong> $CountUsersImminent <br> <strong>Users already expired count: </strong> $CountUsersAlreadyExpired <br> </p> "@ foreach ($ip in $ReportOptions.MonitoredIps.Values) { "<li>ip:</strong> $ip</li>" } '</ul>' '</p>' ) return $Report } function Test-Prerequisits { [CmdletBinding()] param() try { $null = Get-ADForest } catch { if ($_.Exception -match "Unable to find a default server with Active Directory Web Services running.") { Write-Color @script:WriteParameters "[-] ", "Active Directory", " not found. Please run this script with access to ", "Domain Controllers." -Color White, Red, White, Red } Write-Color @script:WriteParameters "[-] ", "Error: $($_.Exception.Message)" -Color White, Red Exit } } function Find-PasswordExpiryCheck { [CmdletBinding()] param( [string] $AdditionalProperties, [Array] $ConditionProperties, [System.Collections.IDictionary] $WriteParameters, [System.Collections.IDictionary] $CachedUsers, [System.Collections.IDictionary] $CachedUsersPrepared, [System.Collections.IDictionary] $CachedManagers ) if ($null -eq $WriteParameters) { $WriteParameters = @{ ShowTime = $true LogFile = "" TimeFormat = "yyyy-MM-dd HH:mm:ss" } } $Properties = @( 'Manager', 'DisplayName', 'GivenName', 'Surname', 'SamAccountName', 'EmailAddress', 'msDS-UserPasswordExpiryTimeComputed', 'PasswordExpired', 'PasswordLastSet', 'PasswordNotRequired', 'Enabled', 'PasswordNeverExpires', 'Mail' if ($AdditionalProperties) { $AdditionalProperties } if ($ConditionProperties) { $ConditionProperties } ) # We're caching all users to make sure it's speedy gonzales when querying for Managers if (-not $CachedUsers) { $CachedUsers = [ordered] @{ } } if (-not $CachedUsersPrepared) { $CachedUsersPrepared = [ordered] @{ } } if (-not $CachedManagers) { $CachedManagers = [ordered] @{ } } Write-Color @WriteParameters -Text "[i] Discovering forest information" -Color White, Yellow, White, Yellow, White, Yellow, White $Forest = Get-ADForest $Users = @( foreach ($Domain in $Forest.Domains) { try { Write-Color @WriteParameters -Text "[i] Discovering DC for domain ", "$($Domain)", " in forest ", $Forest.Name -Color White, Yellow, White, Yellow, White, Yellow, White $Server = Get-ADDomainController -Discover -DomainName $Domain -ErrorAction Stop #$Users = Get-ADUser -Server $Server -Filter { Enabled -eq $True -and PasswordNeverExpires -eq $False -and PasswordLastSet -gt 0 -and PasswordNotRequired -ne $True } -Properties $Properties -ErrorAction Stop Write-Color @WriteParameters -Text "[i] Getting users from ", "$($Domain)", " using ", $Server.Hostname -Color White, Yellow, White, Yellow, White, Yellow, White # We query all users instead of using filter. Since we need manager field and manager data this way it should be faster (query once - get it all) $DomainUsers = Get-ADUser -Server $($Server.HostName) -Filter '*' -Properties $Properties -ErrorAction Stop foreach ($_ in $DomainUsers) { Add-Member -InputObject $_ -Value $Domain -Name 'Domain' -Force -Type NoteProperty $CachedUsers["$($_.DistinguishedName)"] = $_ # We reuse filtering if ($_.Enabled -eq $true -and $_.PasswordNeverExpires -eq $false -and $_.PasswordLastSet -gt 0 -and $_.PasswordNotRequired -ne $true) { $_ } } } catch { $ErrorMessage = $_.Exception.Message -replace "`n", " " -replace "`r", " " Write-Color @WriteParameters '[e] Error: ', $ErrorMessage -Color White, Red } } ) Write-Color @WriteParameters -Text "[i] Preparing all users for password expirations in forest ", $Forest.Name -Color White, Yellow, White, Yellow, White, Yellow, White $ProcessedUsers = foreach ($_ in $Users) { $UserManager = $CachedUsers["$($_.Manager)"] if ($AdditionalProperties) { # fix this for a user $EmailTemp = $_.$AdditionalProperties if ($EmailTemp -like '*@*') { $EmailAddress = $EmailTemp } else { $EmailAddress = $_.EmailAddress } # Fix this for manager as well if ($UserManager) { if ($UserManager.$AdditionalProperties -like '*@*') { $UserManager.Mail = $UserManager.$AdditionalProperties } } } else { $EmailAddress = $_.EmailAddress } if ($_."msDS-UserPasswordExpiryTimeComputed" -ne 9223372036854775807) { # This is standard situation where users password is expiring as needed try { $DateExpiry = ([datetime]::FromFileTime($_."msDS-UserPasswordExpiryTimeComputed")) } catch { $DateExpiry = $_."msDS-UserPasswordExpiryTimeComputed" } try { $DaysToExpire = (New-TimeSpan -Start (Get-Date) -End ([datetime]::FromFileTime($_."msDS-UserPasswordExpiryTimeComputed"))).Days } catch { $DaysToExpire = $null } $PasswordNeverExpires = $_.PasswordNeverExpires } else { # This is non-standard situation. This basically means most likely Fine Grained Group Policy is in action where it makes PasswordNeverExpires $true # Since FGP policies are a bit special they do not tick the PasswordNeverExpires box, but at the same time value for "msDS-UserPasswordExpiryTimeComputed" is set to 9223372036854775807 $DateExpiry = $null $DaysToExpire = $null $PasswordNeverExpires = $true } $MyUser = [ordered] @{ UserPrincipalName = $_.UserPrincipalName Domain = $_.Domain SamAccountName = $_.SamAccountName DisplayName = $_.DisplayName GivenName = $_.GivenName Surname = $_.Surname EmailAddress = $EmailAddress PasswordExpired = $_.PasswordExpired PasswordLastSet = $_.PasswordLastSet PasswordNotRequired = $_.PasswordNotRequired PasswordNeverExpires = $PasswordNeverExpires Manager = $UserManager.Name ManagerEmail = $UserManager.Mail ManagerDN = $_.Manager DateExpiry = $DateExpiry DaysToExpire = $DaysToExpire } foreach ($Property in $ConditionProperties) { $MyUser["$Property"] = $_.$Property } [PSCustomObject] $MyUser $CachedUsersPrepared["$($_.DistinguishedName)"] = $MyUser } foreach ($_ in $CachedUsersPrepared.Keys) { $ManagerDN = $CachedUsersPrepared[$_]['ManagerDN'] if ($ManagerDN) { $Manager = $CachedUsers[$ManagerDN] $MyUser = [ordered] @{ UserPrincipalName = $Manager.UserPrincipalName Domain = $Manager.Domain SamAccountName = $Manager.SamAccountName DisplayName = $Manager.DisplayName GivenName = $Manager.GivenName Surname = $Manager.Surname DistinguishedName = $ManagerDN } foreach ($Property in $ConditionProperties) { $MyUser["$Property"] = $_.$Property } $CachedManagers[$ManagerDN] = $MyUser } } $ProcessedUsers } #$Test = Find-PasswordExpiryCheck -AdditionalProperties 'extensionAttribute13' #$Test | Format-Table -AutoSize * Function Start-PasswordExpiryCheck { [CmdletBinding()] param ( [System.Collections.IDictionary] $EmailParameters, [System.Collections.IDictionary] $FormattingParameters, [System.Collections.IDictionary] $ConfigurationParameters ) $time = [System.Diagnostics.Stopwatch]::StartNew() # Timer Start Test-Prerequisits $WriteParameters = $ConfigurationParameters.DisplayConsole $FieldName = $ConfigurationParameters.RemindersSendToUsers.UseAdditionalField $Today = Get-Date $CachedUsers = [ordered] @{ } $CachedUsersPrepared = [ordered] @{ } $CachedManagers = [ordered] @{ } [Array] $ConditionProperties = if ($FormattingParameters.Conditions) { foreach ($Key in $FormattingParameters.Conditions.Keys) { foreach ($Condition in $FormattingParameters.Conditions["$Key"].Keys | Where-Object { $_ -ne 'DefaultCondition' }) { $Condition } } } $Users = Find-PasswordExpiryCheck -AdditionalProperties $FieldName -ConditionProperties $ConditionProperties -WriteParameters $WriteParameters -CachedUsers $CachedUsers -CachedUsersPrepared $CachedUsersPrepared -CachedManagers $CachedManagers | Sort-Object DateExpiry #$UsersWithEmail = @( # $Users | Where-Object { $_.EmailAddress -like '*@*' } #) $UsersExpired = $Users | Where-Object { $null -ne $_.DateExpiry -and $_.DateExpiry -lt $Today } $EmailBody = Set-EmailHead -FormattingOptions $FormattingParameters $Image = Set-EmailReportBranding -FormattingOptions $FormattingParameters $EmailBody += Set-EmailFormatting -Template $FormattingParameters.Template -FormattingParameters $FormattingParameters ` -ConfigurationParameters $ConfigurationParameters -Image $Image $UsersNotified = @( [bool] $TestingLimitReached = $false #region Send Emails to Users if ($ConfigurationParameters.RemindersSendToUsers.Enable -eq $true) { Write-Color @WriteParameters '[i] Starting processing ', 'Users', ' section' -Color White, Yellow, White if ($ConfigurationParameters.RemindersSendToUsers.Reminders -is [System.Collections.IDictionary]) { [Array] $DaysToExpire = ($ConfigurationParameters.RemindersSendToUsers.Reminders).Values | Sort-Object -Unique } else { [Array] $DaysToExpire = $ConfigurationParameters.RemindersSendToUsers.Reminders | Sort-Object -Unique } #foreach ($Day in $ConfigurationParameters.RemindersSendToUsers.Reminders.GetEnumerator()) { #$Date = (Get-Date).AddDays($Day.Value).Date $Count = 0 foreach ($u in $Users) { if ($TestingLimitReached -eq $true) { break } if ($u.DaysToExpire -in $DaysToExpire) { if ($u.EmailAddress -like '*@*') { $Count++ Write-Color @WriteParameters -Text "[i] User ", "$($u.DisplayName)", " expires in ", "$($u.DaysToExpire)", " days (", "$($u.DateExpiry)", ")." -Color White, Yellow, White, Red, White, Red, White $TemporaryBody = Set-EmailReplacements -Replacement $EmailBody -User $u -FormattingParameters $FormattingParameters -EmailParameters $EmailParameters -Day $u.DaysToExpire $EmailSubject = Set-EmailReplacements -Replacement $EmailParameters.EmailSubject -User $u -FormattingParameters $FormattingParameters -EmailParameters $EmailParameters -Day $u.DaysToExpire #$u.DaysToExpire = $Day.Value if ($ConfigurationParameters.RemindersSendToUsers.RemindersDisplayOnly -eq $true) { Write-Color @WriteParameters -Text "[i] Pretending to send email to ", "$($u.EmailAddress)", " ...", "Success" -Color White, Green, White, Green $EmailSent = [ordered] @{ } $EmailSent.Status = $false $EmailSent.SentTo = 'N/A' } else { $EmailSplat = @{ EmailParameters = $EmailParameters Body = $TemporaryBody Subject = $EmailSubject } if ($FormattingParameters.CompanyBranding.Inline) { $EmailSplat.InlineAttachments = @{ logo = $FormattingParameters.CompanyBranding.Logo } } if ($ConfigurationParameters.RemindersSendToUsers.SendToDefaultEmail -eq $false) { Write-Color @WriteParameters -Text "[i] Sending email to ", "$($u.EmailAddress)", " ..." -Color White, Green -NoNewLine $EmailSplat.To = $u.EmailAddress } else { Write-Color @WriteParameters -Text "[i] Sending email to users is disabled. Sending email to default value: ", "$($EmailParameters.EmailTo) ", "..." -Color White, Yellow, White -NoNewLine } $EmailSent = Send-Email @EmailSplat if ($EmailSent.Status -eq $true) { Write-Color -Text "Done" -Color "Green" } else { Write-Color -Text "Failed!" -Color "Red" } } Add-Member -InputObject $u -NotePropertyName "EmailSent" -NotePropertyValue $EmailSent.Status Add-Member -InputObject $u -NotePropertyName "EmailSentTo" -NotePropertyValue $EmailSent.SentTo } else { Add-Member -InputObject $u -NotePropertyName "EmailSent" -NotePropertyValue $false Add-Member -InputObject $u -NotePropertyName "EmailSentTo" -NotePropertyValue 'Not available' Write-Color @WriteParameters -Text "[i] User ", "$($u.DisplayName)", " expires in ", "$($u.DaysToExpire)", " days (", "$($u.DateExpiry)", "). However user has no email address and will be skipped." -Color White, Yellow, White, Red, White, Red, White } $u if ($ConfigurationParameters.RemindersSendToUsers.SendCountMaximum -eq $Count) { Write-Color @WriteParameters -Text "[i] Sending email to maximum number of users ", "$($ConfigurationParameters.RemindersSendToUsers.SendCountMaximum) ", "has been reached. Skipping..." -Color White, Yellow, White $TestingLimitReached = $true break } } } #} Write-Color @WriteParameters '[i] Ending processing ', 'Users', ' section' -Color White, Yellow, White } else { Write-Color @WriteParameters '[i] Skipping processing ', 'Users', ' section' -Color White, Yellow, White } ) #endregion #region Send Emails to Managers $ManagersReceived = if ($ConfigurationParameters.RemindersSendToManager.Enable -eq $true) { Write-Color @WriteParameters '[i] Starting processing ', 'Managers', ' section' -Color White, Yellow, White # preparing email $EmailSubject = $ConfigurationParameters.RemindersSendToManager.ManagersEmailSubject $EmailBody = Set-EmailHead -FormattingOptions $FormattingParameters $EmailReportBranding = Set-EmailReportBranding -FormattingOptions $FormattingParameters $EmailBody += Set-EmailFormatting -Template $FormattingParameters.TemplateForManagers ` -FormattingParameters $FormattingParameters ` -ConfigurationParameters $ConfigurationParameters ` -AddAfter $EmailReportBranding # preparing manager lists if ($ConfigurationParameters.RemindersSendToManager.LimitScope.Groups) { # send emails to managers only if those people are in limited scope groups [Array] $LimitedScopeMembers = Find-LimitedScope -ConfigurationParameters $ConfigurationParameters -CachedUsers $CachedUsersPrepared [Array] $UsersWithManagers = foreach ($_ in $UsersNotified) { if ($LimitedScopeMembers.UserPrincipalName -contains $_.UserPrincipalName) { if ($null -ne $_.ManagerEmail) { $_ } } } } else { [Array] $UsersWithManagers = foreach ($_ in $UsersNotified) { if ($null -ne $_.ManagerEmail) { $_ } } # $UsersWithManagers = $UsersNotified | Where-Object { $null -ne $_.ManagerEmail } } # Find managers with emails. Make sure only unique is added to the list $ManagersEmails = [System.Collections.Generic.List[string]]::new() foreach ($u in $UsersWithManagers) { if ($ManagersEmails -notcontains $u.ManagerEmail) { $ManagersEmails.Add($u.ManagerEmail) } } Write-Color @WriteParameters '[i] Preparing package for managers with emails ', "$($UsersWithManagers.Count) ", 'users to process with', ' manager filled in', ' where unique managers ', "$($ManagersEmails.Count)" -Color White, Yellow, White, Yellow, White, Yellow # processing one manager at time $Count = 0 foreach ($m in $ManagersEmails) { $Count++ # preparing users belonging to manager $ColumnNames = 'UserPrincipalName', 'DisplayName', 'DateExpiry', 'PasswordExpired', 'SamAccountName', 'Manager', 'ManagerEmail', 'PasswordLastSet' [Array] $UsersNotifiedManagers = $UsersWithManagers | Where-Object { $_.ManagerEmail -eq $m } [string] $ManagerDN = $UsersNotifiedManagers[0].ManagerDN $ManagerFull = $CachedManagers[$ManagerDN] if ($ConfigurationParameters.RemindersSendToManager.Reports.IncludePasswordNotificationsSent.IncludeNames -ne '') { $UsersNotifiedManagers = $UsersNotifiedManagers | Select-Object $ConfigurationParameters.RemindersSendToManager.Reports.IncludePasswordNotificationsSent.IncludeNames } else { $UsersNotifiedManagers = $UsersNotifiedManagers | Select-Object 'UserPrincipalName', 'DisplayName', 'DateExpiry', 'DaysToExpire', 'SamAccountName', 'Manager', 'ManagerEmail', 'PasswordLastSet', 'EmailSent', 'EmailSentTo' } if ($ConfigurationParameters.RemindersSendToManager.Reports.IncludePasswordNotificationsSent.Enabled -eq $true) { foreach ($u in $UsersNotifiedManagers) { Write-Color @WriteParameters -Text '[-] User ', "$($u.DisplayName) ", " Managers Email (", "$($m)", ')' -Color White, Yellow, White, Yellow, White } } #$ManagerFull['EmailsSent'] = $UserPrincipalNames -join '; ' if ($ConfigurationParameters.RemindersSendToManager.RemindersDisplayOnly -eq $true) { Write-Color @WriteParameters -Text "[i] Pretending to send email to manager email ", "$($m)", " ...", "Success" -Color White, Green, White, Green $EmailSent = @{ } $EmailSent.Status = $false $EmailSent.SentTo = 'N/A' } else { $TemporaryBody = $EmailBody $TemporaryBody = Set-EmailBodyReplacementTable -Body $TemporaryBody -TableName 'ManagerUsersTable' -TableData $UsersNotifiedManagers $TemporaryBody = Set-EmailReplacements -Replacement $TemporaryBody -User $u -FormattingParameters $FormattingParameters -EmailParameters $EmailParameters #-Day '' if ($ConfigurationParameters.Debug.DisplayTemplateHTML -eq $true) { Get-HTML -text $TemporaryBody } $EmailSplat = @{ EmailParameters = $EmailParameters Body = $TemporaryBody Subject = $EmailSubject } if ($FormattingParameters.CompanyBranding.Inline) { $EmailSplat.InlineAttachments = @{ logo = $FormattingParameters.CompanyBranding.Logo } } if ($ConfigurationParameters.RemindersSendToManager.SendToDefaultEmail -eq $false) { Write-Color @WriteParameters -Text "[i] Sending email to managers email ", "$($m)", " ..." -Color White, Green -NoNewLine $EmailSplat.To = $m } else { Write-Color @WriteParameters -Text "[i] Sending email to managers is disabled. Sending email to default value: ", "$($EmailParameters.EmailTo) ", "..." -Color White, Yellow, White -NoNewLine } $EmailSent = Send-Email @EmailSplat if ($EmailSent.Status -eq $true) { Write-Color -Text "Done" -Color "Green" } else { Write-Color -Text "Failed!" -Color "Red" } } $ManagerFull['EmailSent'] = $EmailSent.Status $ManagerFull['EmailSentTo'] = $EmailSent.SentTo if ($ConfigurationParameters.RemindersSendToManager.Reports.IncludeManagersPasswordNotificationsSent.IncludeNames.Count -gt 0) { ([PSCustomObject] $ManagerFull) | Select-Object -Property $ConfigurationParameters.RemindersSendToManager.Reports.IncludeManagersPasswordNotificationsSent.IncludeNames } else { ([PSCustomObject] $ManagerFull) | Select-Object -Property 'UserPrincipalName', 'Domain', 'DisplayName', 'SamAccountName', 'EmailSent', 'EmailSentTo' } if ($ConfigurationParameters.RemindersSendToManager.SendCountMaximum -eq $Count) { Write-Color @WriteParameters -Text "[i] Sending email to maximum number of managers ", "$($ConfigurationParameters.RemindersSendToManager.SendCountMaximum) ", " has been reached. Skipping..." -Color White, Yellow, White -NoNewLine break } } Write-Color @WriteParameters '[i] Ending processing ', 'Managers', ' section' -Color White, Yellow, White } else { Write-Color @WriteParameters '[i] Skipping processing ', 'Managers', ' section' -Color White, Yellow, White } #endregion Send Emails to Managers if ($ConfigurationParameters.DisableExpiredUsers.Enable -eq $true) { Write-Color @WriteParameters '[i] Starting processing ', 'Disable Expired Users', ' section' -Color White, Yellow, White foreach ($U in $UsersExpired) { if ($ConfigurationParameters.DisableExpiredUsers.DisplayOnly) { Write-Color @WriteParameters -Text "[i] User ", "$($u.DisplayName)", " expired on (", "$($u.DateExpiry)", "). Pretending to disable acoount..." -Color White, Yellow, White, Red, White, Red, White } else { Write-Color @WriteParameters -Text "[i] User ", "$($u.DisplayName)", " expired on (", "$($u.DateExpiry)", "). Disabling..." -Color White, Yellow, White, Red, White, Red, White Disable-ADAccount -Identity $u.SamAccountName -Confirm:$false } } Write-Color @WriteParameters '[i] Ending processing ', 'Disable Expired Users', ' section' -Color White, Yellow, White } #region Send Emails to Admins if ($ConfigurationParameters.RemindersSendToAdmins.Enable -eq $true) { Write-Color @WriteParameters '[i] Starting processing ', 'Administrators', ' section' -Color White, Yellow, White if ($ConfigurationParameters.RemindersSendToUsers.Reminders -is [System.Collections.IDictionary]) { $DayHighest = Get-HashMaxValue $ConfigurationParameters.RemindersSendToUsers.Reminders $DayLowest = Get-HashMaxValue $ConfigurationParameters.RemindersSendToUsers.Reminders -Lowest } else { [Array] $OrderedDays = $ConfigurationParameters.RemindersSendToUsers.Reminders | Sort-Object -Unique $DayHighest = $OrderedDays[-1] $DayLowest = $OrderedDays[0] } $DateCountdownStart = (Get-Date).AddDays($DayHighest).Date $DateIminnent = (Get-Date).AddDays($DayLowest).Date #Write-Color 'Day Highest ', $DayHighest, ' Day Lowest ', $DayLowest, ' Day Countdown Start ', $DateCountdownStart, ' Day Iminnet ', $DateIminnent -Color White, Yellow, White, Yellow, White, Yellow, White, Yellow $ColumnNames = 'UserPrincipalName', 'DisplayName', 'DateExpiry', 'PasswordExpired', 'SamAccountName', 'Manager', 'ManagerEmail', 'PasswordLastSet' if ($ConfigurationParameters.RemindersSendToAdmins.Reports.IncludePasswordNotificationsSent.IncludeNames -gt 0) { $UsersNotified = $UsersNotified | Select-Object $ConfigurationParameters.RemindersSendToAdmins.Reports.IncludePasswordNotificationsSent.IncludeNames } else { $UsersNotified = $UsersNotified | Select-Object $ColumnNames, 'EmailSent', 'EmailSentTo' } if ($ConfigurationParameters.RemindersSendToAdmins.Reports.IncludeExpiringImminent.IncludeNames.Count -gt 0) { $ExpiringIminent = $Users | Where-Object { $null -ne $_.DateExpiry -and $_.DateExpiry -lt $DateIminnent -and $_.PasswordExpired -eq $false } | Select-Object $ConfigurationParameters.RemindersSendToAdmins.Reports.IncludeExpiringImminent.IncludeNames } else { $ExpiringIminent = $Users | Where-Object { $null -ne $_.DateExpiry -and $_.DateExpiry -lt $DateIminnent -and $_.PasswordExpired -eq $false } | Select-Object $ColumnNames } if ($ConfigurationParameters.RemindersSendToAdmins.Reports.IncludeExpiringCountdownStarted.IncludeNames -gt 0) { $ExpiringCountdownStarted = $Users | Where-Object { $null -ne $_.DateExpiry -and $_.DateExpiry -lt $DateCountdownStart -and $_.PasswordExpired -eq $false } | Select-Object $ConfigurationParameters.RemindersSendToAdmins.Reports.IncludeExpiringCountdownStarted.IncludeNames } else { $ExpiringCountdownStarted = $Users | Where-Object { $null -ne $_.DateExpiry -and $_.DateExpiry -lt $DateCountdownStart -and $_.PasswordExpired -eq $false } | Select-Object $ColumnNames } if ($ConfigurationParameters.RemindersSendToAdmins.Reports.IncludeExpired.IncludeNames -gt 0) { $UsersExpired = $UsersExpired | Select-Object $ConfigurationParameters.RemindersSendToAdmins.Reports.IncludeExpired.IncludeNames } else { $UsersExpired = $UsersExpired | Select-Object $ColumnNames } $EmailBody = Set-EmailHead -FormattingOptions $FormattingParameters $EmailBody += "<body>" $EmailBody += Set-EmailReportBranding -FormattingOptions $FormattingParameters $EmailBody += Set-EmailReportDetails -FormattingOptions $FormattingParameters ` -ReportOptions $ReportOptions ` -TimeToGenerate $Time.Elapsed ` -CountUsersCountdownStarted $($ExpiringCountdownStarted.Count) ` -CountUsersImminent $($ExpiringIminent.Count) ` -CountUsersAlreadyExpired $($UsersExpired.Count) -CountUsersNotified $($UsersNotified.Count) $time.Stop() if ($ConfigurationParameters.RemindersSendToAdmins.Reports.IncludeSummary.Enabled -eq $true) { $SummaryOfUsers = $Users | Group-Object DaysToExpire ` | Select-Object @{Name = 'Days to Expire'; Expression = { [int] $($_.Name) } }, @{Name = 'Users with Days to Expire'; Expression = { [int] $($_.Count) } } $SummaryOfUsers = $SummaryOfUsers | Sort-Object -Property 'Days to Expire' Write-Color @WriteParameters -Text '[i] Preparing data for report ', 'Summary of Expiring Users' -Color White, Yellow $EmailBody += Set-EmailBody -TableData $SummaryOfUsers ` -TableMessageWelcome "Summary of days to expire and it's count" ` -TableMessageNoData 'There were no users that have days of expiring.' } if ($ConfigurationParameters.RemindersSendToAdmins.Reports.IncludePasswordNotificationsSent.Enabled -eq $true) { Write-Color @WriteParameters -Text '[i] Preparing data for report ', 'Password Notifcations Sent' -Color White, Yellow $EmailBody += Set-EmailBody -TableData $UsersNotified ` -TableMessageWelcome "Following users had their password notifications sent" ` -TableMessageNoData 'No users required nofifications.' } if ($ConfigurationParameters.RemindersSendToAdmins.Reports.IncludeManagersPasswordNotificationsSent.Enabled -eq $true) { Write-Color @WriteParameters -Text '[i] Preparing data for report ', 'Password Notifcations Sent to Managers' -Color White, Yellow $EmailBody += Set-EmailBody -TableData $ManagersReceived ` -TableMessageWelcome "Following managers had their password bundle notifications sent" ` -TableMessageNoData 'No managers required nofifications.' } if ( $ConfigurationParameters.RemindersSendToAdmins.Reports.IncludeExpiringImminent.Enabled -eq $true) { Write-Color @WriteParameters -Text '[i] Preparing data for report ', 'Users expiring imminent' -Color White, Yellow $EmailBody += Set-EmailBody -TableData $ExpiringIminent ` -TableMessageWelcome "Following users expiring imminent (Less than $DayLowest day(s)" ` -TableMessageNoData 'No users expiring.' } if ( $ConfigurationParameters.RemindersSendToAdmins.Reports.IncludeExpiringCountdownStarted.Enabled -eq $true) { Write-Color @WriteParameters -Text '[i] Preparing data for report ', 'Expiring Couintdown Started' -Color White, Yellow $EmailBody += Set-EmailBody -TableData $ExpiringCountdownStarted ` -TableMessageWelcome "Following users expiring countdown started (Less than $DayHighest day(s))" ` -TableMessageNoData 'There were no users that had their coundown started.' } if ($ConfigurationParameters.RemindersSendToAdmins.Reports.IncludeExpired.Enabled -eq $true) { Write-Color @WriteParameters -Text '[i] Preparing data for report ', 'Users are already expired' -Color White, Yellow if ($ConfigurationParameters.DisableExpiredUsers.Enable -eq $true -and -not $ConfigurationParameters.DisableExpiredUsers.DisplayOnly -eq $true) { $EmailBody += Set-EmailBody -TableData $UsersExpired -TableMessageWelcome "Following users are already expired (and were disabled...)" -TableMessageNoData "No users that are expired." } else { $EmailBody += Set-EmailBody -TableData $UsersExpired -TableMessageWelcome "Following users are already expired (and still enabled...)" -TableMessageNoData "No users that are expired and enabled." } } $EmailBody += "</body>" if ($ConfigurationParameters.Debug.DisplayTemplateHTML -eq $true) { Get-HTML -text $EmailBody } if ($ConfigurationParameters.RemindersSendToAdmins.RemindersDisplayOnly -eq $true) { Write-Color @WriteParameters -Text "[i] Pretending to send email to admins email ", "$($ConfigurationParameters.RemindersSendToAdmins.AdminsEmail) ", "...", 'Success' -Color White, Yellow, White, Green } else { Write-Color @WriteParameters -Text "[i] Sending email to administrators on email address ", "$($ConfigurationParameters.RemindersSendToAdmins.AdminsEmail) ", "..." -Color White, Yellow, White -NoNewLine $EmailSplat = @{ EmailParameters = $EmailParameters Body = $EmailBody Subject = $ConfigurationParameters.RemindersSendToAdmins.AdminsEmailSubject To = $ConfigurationParameters.RemindersSendToAdmins.AdminsEmail } if ($FormattingParameters.CompanyBranding.Inline) { $EmailSplat.InlineAttachments = @{ logo = $FormattingParameters.CompanyBranding.Logo } } $EmailSent = Send-Email @EmailSplat if ($EmailSent.Status -eq $true) { Write-Color -Text "Done" -Color "Green" } else { Write-Color -Text "Failed! Error: $($EmailSent.Error)" -Color "Red" } } Write-Color @WriteParameters '[i] Ending processing ', 'Administrators', ' section' -Color White, Yellow, White } else { Write-Color @WriteParameters '[i] Skipping processing ', 'Administrators', ' section' -Color White, Yellow, White } #endregion Send Emails to Admins } Export-ModuleMember -Function @('Find-PasswordExpiryCheck', 'Start-PasswordExpiryCheck') -Alias @() |