Powershell - Get-WinEvent - send email with message from Event

666 Views Asked by At

I am new in powershell. I want to get the events from Task Scheduler/Operational with code of failure, and send an email with all events in the body.

# Get all events from yesterday with ID=103 and Text, put in table and send email
   
# Get the event entries.
$eventEntries = & {Get-WinEvent  -FilterHashtable @{ LogName='Microsoft-Windows-TaskScheduler/Operational'; StartTime=(Get-Date).AddDays(-1); ID='103'} | 
    Where {$_.Message.Contains('Task Scheduler failed to start instance')} | 
    select -Property ID,TimeCreated,Message |ft -wrap}
            
# Create a table row for each entry.
$array = @()

foreach ($eventEntry in $eventEntries)
{
     $array += $eventEntry
}
$array | Format-table

# Create the email.
$MailFrom = "[email protected]"
$MailTo = "[email protected]"
$Subject = "EventLogAlert"
$email = New-Object System.Net.Mail.MailMessage( $MailFrom , $MailTo )
$email.Subject = $Subject
$email.IsBodyHtml = $true
$email.Body = @"
<table style="width:100%;border">
     <tr>
         <th style="text-align: center; padding: 5px;">ID</th>
         <th style="text-align: center; padding: 5px;">TimeCreated</th>
         <th style="text-align: center; padding: 5px;">Message</th>
        </tr>
    
    $array
    </table>
"@

# Send the email.
$SmtpServer = "smtp.mail.outlook.com"
$SmtpPort = 587
$SmtpUser = "[email protected]"
$SmtpPassword = "passwordexample"
$SMTPClient=New-Object System.Net.Mail.SmtpClient($SmtpServer,$SmtpPort)
$SMTPClient.EnableSsl=$true
$SMTPClient.Credentials= New-Object System.Net.NetworkCredential($SmtpUser,$SmtpPassword);
$SMTPClient.Send($email)

The $array is created with values in it, can viewed with echo $eventEntries The result $email is not with values from table, it give this text

Microsoft.PowerShell.Commands.Internal.Format.FormatStartData Microsoft.PowerShell.Commands.Internal.Format.GroupStartData Microsoft.Powershell.Commands.Internal.Format.FormatEntryData Microsoft.PowerShell.Commands.Internal.Format.FormatEntryData Microsoft.PowerShell.Commands.Internal.Format.FormatEntryData Microsoft.PowerShell.Commands.Internal.Format.FormatEntryData Microsoft.PowerShell.Commands.Internal.Format.FormatEntryData Microsoft.PowerShell.Commands.Internal.Format.FormatEntryData Microsoft.PowerShell.Commands.Internal.Format.FormatEntryData Microsoft.PowerShell.Commands.Internal.Format.GroupEndData Microsoft.PowerShell.Commands.Internal.Format.FormatEndData 

Can somebody help me to write correct code to view all events in email.

And additionally, to create for each event an email separately.

Thanks in advance!

2

There are 2 best solutions below

4
Theo On BEST ANSWER

You should not use Format-Table if you plan on using the data any further, because that cmdlet is only meant for display purposes.

Try the code below:

$yesterday = (Get-Date).AddDays(-1).Date   # set to midnight
$filter    = @{LogName='Microsoft-Windows-TaskScheduler/Operational'; StartTime=$yesterday; ID='103'}
$events    = Get-WinEvent -FilterHashtable $filter -ErrorAction SilentlyContinue | 
             Where-Object {$_.Message -like '*Task Scheduler failed to start instance*'} | 
             Select-Object -Property TaskDisplayName,ID,TimeCreated,Message

$style = @'
<style>
    body {font-family: Calibri, Tahoma, Helvetica, sans-serif; color: black;}
    table {width: 100%; border-width: 1px; border-style: solid; border-color: black; border-collapse: collapse;}
    th {text-align: center; padding: 5px; background-color: #6495ED; color: white;}
    td {border-width: 1px; padding: 3px; border-style: solid; border-color: black;}
</style>
'@

# to use for both the email as the subject for this email
$subject = 'EventLogAlert {0:yyyy-MM-dd HH:mm:ss}' -f (Get-Date)

# create the email body using the style above for the table
$body = $events | ConvertTo-Html -Head $style -PreContent "<h2>$subject</h2>"

# Create the email.
$MailFrom = "[email protected]"
$MailTo   = "[email protected]"
$email    = New-Object System.Net.Mail.MailMessage($MailFrom, $MailTo)
$email.Subject    = $subject
$email.IsBodyHtml = $true
$email.Body       = $body -join [environment]::NewLine

# Send the email.
$SmtpServer   = "smtp.mail.outlook.com"
$SmtpPort     = 587
$SmtpUser     = "[email protected]"
$SmtpPassword = "passwordexample"
$SMTPClient   = New-Object System.Net.Mail.SmtpClient($SmtpServer, $SmtpPort)
$SMTPClient.EnableSsl   = $true
$SMTPClient.Credentials = New-Object System.Net.NetworkCredential($SmtpUser, $SmtpPassword);
$SMTPClient.Send($email)

Notes:

  • I'm using the -like operator rather than the .Contains() string method, because the latter is case-sensitive
  • I have set yesterda's date to midnight by appending .Date
  • The styling is all up to you, this is just an example you may or may not like..
2
LordPupazz On

We do something similar with a script that sends a weekly count of our Office 365 license allocation to a couple of distribution groups. Perhaps this might help you get your script up and running:

Import-Module AzureAD
$username = "[email protected]"
$pwd = Get-Content "c:\scripts\LicenseCheckPW.txt" | ConvertTo-SecureString -Key (1..32)
$cred = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $username, $pwd
Connect-MsolService -Credential $cred

$outarray = @()

foreach($sku in (Get-MsolAccountSku))
{
    $name = $sku.AccountSkuID
    $partno = $sku.SkuPartNumber
    $active = $sku.ActiveUnits
    $used = $sku.ConsumedUnits
    $remaining = ($sku.ActiveUnits - $sku.ConsumedUnits)
    if($active -eq 0)
    {
        $premaining = 0
    }
    else
    {
        $premaining = [math]::Round(100-($sku.ConsumedUnits / $sku.ActiveUnits * 100), 2)
    }
    $outobj = New-Object Object
    $outobj | Add-Member -Type Noteproperty -Name "Name" $name
    $outobj | Add-Member -Type Noteproperty -Name "Part No" $partno
    $outobj | Add-Member -Type Noteproperty -Name "Active Units" $active
    $outobj | Add-Member -Type Noteproperty -Name "Consumed Units" $used
    $outobj | Add-Member -Type Noteproperty -Name "Remaining Units" $remaining
    $outobj | Add-Member -Type Noteproperty -Name "Percentage Remaining" $premaining
    $outarray += $outobj
}

$style = "<head><title>Office365 License Check</title></head><style>"
$style += "BODY{background-color:peachpuff; text-align: center;}"
$style += "TABLE{border-width:1px; border-style: solid; border-color: black; border-collapse: collapse; text-align: center;}"
$style += "TH{border-width: 1px; padding: 5px; border-style: solid; border-color: black; background-color: thistle;}"
$style += "TD{border-width: 1px; padding: 5px; border-style: solid; border-color: black; background-color: palegoldenrod;}"
$style += "</style>"

$body = "<h2>Office365 License Check</h2><p>Output generated: " + (Get-Date -Format D)

$html = ($outarray | ConvertTo-HTML -head $style -body $body)

$server = "smtp.exchange.server.com"
$msg = New-Object Net.Mail.MailMessage
$smtp = New-Object Net.Mail.SmtpClient($server)
$msg.From = "[email protected]"
$msg.To.Add("[email protected]")
$msg.To.Add("[email protected]")
$msg.Subject = "Corporate O365 License Check"
$msg.Body = $html
$msg.IsBodyHtml = $true
$smtp.Send($msg)