Sending Emails in Loop

This topic contains 3 replies, has 2 voices, and was last updated by  Steve 5 days, 14 hours ago.

  • Author
    Posts
  • #81119

    Steve
    Participant

    Hello Everyone,

    I have a script that works on some systems but not others, it seems.

    It scans a log file and if it finds the key phrase it will email. This job is run by task scheduler on the hour.
    Now what's happening is that it's sending out this email every hour.

    I thought I created a foolproof plan but perhaps not?

    Let me know your thoughts.

    Dates take this form: [2017-09-28 13:24:59,405]

    function Get-CertErr {
        $reviewer = Get-WmiObject win32_groupuser |
            Where-Object { $_.GroupComponent -match 'user' } |
                ForEach-Object {[wmi]$_.PartComponent } |
                    Where-Object {$_.Name -notmatch '.*test.*|to_be_default|.*User.*|INTERACTIVE'} |
                        ForEach-Object { $_.Name }
    
        $logs = Get-ChildItem -Path "C:\pathtolog\important.log*" | Where-Object { $_.LastWriteTime -ge ((Get-Date).AddDays(-40))}
        $var = Get-Content $logs -EA Ignore | Select-String -SimpleMatch "certificate" -Context 0,10 | Sort-Object Date | Select-Object -Last 1 
    
    foreach ($v in $var){
        $date,$message = $v.Line.Split("]",2)
        $date = $date -replace ('\[','')
            $alert1 = "$([datetime]::ParseExact($date,"yyyy-MM-dd HH:mm:ss,fff",$null))"
            $alert2 = "$message"
            $alert3 = "$v"
            }
    
    if ($v){
        if(!(Test-Path "C:\Users\Administrator\Desktop\Monitoring")){
            New-Item -ItemType directory -Path "C:\Users\Administrator\Desktop\Monitoring"
            }
        if(!(Test-Path "C:\Users\Administrator\Desktop\Monitoring\Cert.txt")){
            New-Item -ItemType file -Path "C:\Users\Administrator\Desktop\Monitoring\Cert.txt"
            }
    
    $oc = Get-ChildItem C:\Users\Administrator\Desktop\Monitoring\Cert.txt
    $oldcerts = Get-Content $oc | Sort-Object Date | Select-Object -Last 1 
     if ($date -gt $oldcerts){
     Send-Email -To "thatonegroup@Contoso.com" -From "$reviewer@$env:COMPUTERNAME" -Subject "Certificate FAILURE on $reviewer@$env:COMPUTERNAME" -Body $MessageBody -Priority Normal -SMTPServer "relay.contoso.com"
        }
      }
    }
    
     Function Send-Email ($To, $Cc, $Bcc, $From, $Subject, $Body, $Priority, $SMTPServer, $Attachments){
     $HTML = @"
    
    
    
    
    body {background-color: lightblue;}
    h1 {background-color: black;color: white;text-align: center;}
    h2 {background-color:lightGrey;}
    p {font-family: verdana;font-size: 12px;}
    p.ridge {border-style: ridge;}
    
    
    
     Certificate Failure 
     Failure Date: $(Get-date $alert1 -Format F)
    $($alert3|Out-String)
    
    
     Reviewer: $reviewer
    
     Workstation: $env:COMPUTERNAME
    
    
    "@
    
            $EmailParams = @{
                 To          = $To
                 Cc          = $Cc
                 Bcc         = $Bcc
                 From        = $From
                 Subject     = $Subject
                 Body        = $HTML
                 BodyAsHtml  = $True
                 Priority    = $Priority
                 SMTPServer  = $SMTPServer
                 Attachments = $Attachments
                 ErrorAction = 'Stop'
            }
    
            $list = New-Object System.Collections.ArrayList
    
            foreach ($h in $EmailParams.Keys) {
                if ($($EmailParams.Item($h)) -eq $null) {
                    $null = $list.Add($h)
                }
            }
    
            foreach ($h in $list) {
                $EmailParams.Remove($h)
            }
    
            Try { 
                Send-MailMessage @EmailParams;
                Write-Verbose "Send-Mail: Sending mail to: $To";
                If ($? -eq $true){
                $date | Out-File -FilePath "C:\Users\Administrator\Desktop\Monitoring\Cert.txt" -Append -NoClobber -Force
                }
            }
            Catch { 
                "Failed to send email to $($To) due to: $_"  
            }
            }
    Get-CertErr
    
  • #81142

    Don Jones
    Keymaster

    I'm not quite following either the intent or what's wrong... can you help me zero in on what you're asking?

    • #81179

      Steve
      Participant

      Sorry if I was unclear Don.

      The structure of this script is that it pulls content from a log scrape.
      If it finds errors it picks the chronologically last occurrence.
      Now it will separate the error into a datetime and the message.

      Next it compares the date against a file on the admin desktop
      If the file contains the date already, the script ends.
      If not, the script will email the results of the log scan.
      On successful email of the new error the script writes the date to the log.

      It's a simple flag file system I put together because we weren't getting notices from non-domain systems and this was the best idea I could come up with to ensure the systems would keep notifying us even if email failures occurred.

      I thought it was foolproof.

      The thing is.. this works without issue on our 64 bit systems but from time to time will go haywire on our 32bit systems.
      It even works reliably on many of our 32bit systems as well..

      When it goes haywire the date of the occurrence may not be the most recent date, the admin desktop file will have multiples of the same date, and they won't be in order. altho they have a general progression towards chronological order.

      Heres's a bad log:

      2017-08-27 11:18:27,601
      2017-09-14 17:24:03,965
      2017-08-27 11:18:27,601
      2017-08-27 11:18:27,601
      2017-08-27 11:18:27,601
      2017-09-14 17:24:03,965
      2017-09-16 14:45:16,018
      2017-09-24 12:30:54,654
      2017-09-14 17:24:03,965
      2017-09-16 14:45:16,018
      2017-09-24 12:30:54,654
      2017-09-27 03:00:25,300
      2017-10-03 00:30:48,881
      2017-10-03 01:46:44,194
      2017-10-03 03:45:01,107
      2017-09-16 14:45:16,018
      2017-10-03 09:13:03,693

  • #82003

    Steve
    Participant

    I'm still working on learning hashtables and key value pairs

    My goal for this was to get a list of log files lastwritetime 40 days back.
    Sort that list by newest
    Find matches / sort matches by newest
    get timestamp on match
    compare timestamp to flag file who's purpose is to notify of 'cert' problems
    email new occurrence events

    This is the fix that solved everything:

    function Get-CertErr {
        $oc = Get-ChildItem C:\Users\Administrator\Desktop\Monitoring\Cert.txt
        $reviewer = Get-WmiObject win32_groupuser |
            Where-Object { $_.GroupComponent -match 'user' } |
                ForEach-Object {[wmi]$_.PartComponent } |
                    Where-Object {$_.Name -notmatch '.*test.*|to_be_default|.*User.*|INTERACTIVE'} |
                        ForEach-Object { $_.Name }
    
        $logs = Get-ChildItem -Path "C:\pathtolog\important.log*" | Where-Object { $_.LastWriteTime -ge ((Get-Date).AddDays(-40))} | Sort-Object LastWriteTime
        $var = Get-Content $logs -EA Ignore | Select-String -SimpleMatch "certificate" -Context 0,10    
        
        $sorted = @{}
        $datelist = @{}
        $errorlist = @{}
        
        if ($var){
            $sorted = foreach ($v in $var){
                $v -replace('> \[','') | Sort-Object Date
                }
            $datelist = $sorted | foreach {
                $items = $_.split(']',2)
                $items[0]
                }
            $errorlist = $sorted | foreach {
                $items = $_.split(']',2)
                $items[1]
                }
    
            $alert1 = [DateTime]::ParseExact($datelist[-1],'yyyy-MM-dd HH:mm:ss,fff', $null)
            $alert2 = $errorlist[-1]
            $alert3 = "$alert1 $alert2"
    
            if(!(Test-Path "C:\Users\Administrator\Desktop\Monitoring")){
                New-Item -ItemType directory -Path "C:\Users\Administrator\Desktop\Monitoring"
                }
            if(!(Test-Path "C:\Users\Administrator\Desktop\Monitoring\Cert.txt")){
                New-Item -ItemType file -Path "C:\Users\Administrator\Desktop\Monitoring\Cert.txt"
                }
        
            $oldcerts = get-content $oc
            $newsort = $oldcerts | Sort-Object { [DateTime]::ParseExact($_, 'yyyy-MM-dd HH:mm:ss,fff', $null) } | Select-Object -Last 1
            $onrecord = [DateTime]::ParseExact($newsort,'yyyy-MM-dd HH:mm:ss,fff', $null)
    
            if ($alert1 -gt $onrecord){
                Send-Email -To "thatonegroup@Contoso.com" -From "$reviewer@$env:COMPUTERNAME" -Subject "Certificate FAILURE on $reviewer@$env:COMPUTERNAME" -Body $MessageBody -Priority Normal -SMTPServer "relay.contoso.com"
                }
        }
        Filter-Certfile $oldcerts $oc
    }
    
     Function Send-Email ($To, $Cc, $Bcc, $From, $Subject, $Body, $Priority, $SMTPServer, $Attachments){
     $HTML = @"
    
    
    
    
    body {background-color: lightblue;}
    h1 {background-color: black;color: white;text-align: center;}
    h2 {background-color:lightGrey;}
    p {font-family: verdana;font-size: 12px;}
    p.ridge {border-style: ridge;}
    
    
    
     Certificate Failure 
     Failure Date: $(Get-date $alert1 -Format F)
    $($alert3|Out-String)
    
    
     Reviewer: $reviewer
    
     Workstation: $env:COMPUTERNAME
    
    
    "@
    
            $EmailParams = @{
                 To          = $To
                 Cc          = $Cc
                 Bcc         = $Bcc
                 From        = $From
                 Subject     = $Subject
                 Body        = $HTML
                 BodyAsHtml  = $True
                 Priority    = $Priority
                 SMTPServer  = $SMTPServer
                 Attachments = $Attachments
                 ErrorAction = 'Stop'
            }
    
            $list = New-Object System.Collections.ArrayList
    
            foreach ($h in $EmailParams.Keys) {
                if ($($EmailParams.Item($h)) -eq $null) {
                    $null = $list.Add($h)
                }
            }
    
            foreach ($h in $list) {
                $EmailParams.Remove($h)
            }
    
            Try { 
                Send-MailMessage @EmailParams;
                Write-Verbose "Send-Mail: Sending mail to: $To";
                If ($? -eq $true){
                Get-date $alert1 -Format 'yyyy-MM-dd HH:mm:ss,fff' | Out-File -FilePath "C:\Users\Administrator\Desktop\Monitoring\Cert.txt" -Append -NoClobber -Force
                }
            }
            Catch { 
                "Failed to send email to $($To) due to: $_"  
            }
            }
    
    function Filter-Certfile {
        [cmdletbinding()]
        param(
            [Parameter(ValueFromPipelineByPropertyName=$true)]
            $oldcerts,
            [Parameter(ValueFromPipelineByPropertyName=$true)]
            $oc
            )
    
        $redsort = $oldcerts | Sort-Object { [DateTime]::ParseExact($_, 'yyyy-MM-dd HH:mm:ss,fff', $null) } | Select-Object -Unique
        $Compare = Compare-Object $oldcerts $redsort
    
        if ($Compare){
            Remove-Item $oc -Force
    	    New-Item -ItemType File -Path "C:\Users\Administrator\Desktop\Monitoring\Cert.txt"
    	    $redsort | Out-File -FilePath "C:\Users\Administrator\Desktop\Monitoring\Cert.txt" -Append -NoClobber -Force
    	}
    }
    
    Get-CertErr
    

You must be logged in to reply to this topic.