locked
Powershell scripting to send emails based on events in event viewer **PROBLEM IS SENDING attachment of log** RRS feed

  • Question

  • $emailFrom = "administrator@domain.com"
    $emailTo = "IT@domain.com"
    $subject = "$env:COMPUTERNAME : A VM was successfully migrated."
    $body = "$env:COMPUTERNAME : A VM was successfully migrated."
    $smtpServer = "smtp.domain.com"
    $smtp = new-object Net.Mail.SmtpClient($smtpServer)
    $smtp.Send($emailFrom, $emailTo, $subject, $body)

    this is a template of a ps1 script i wrote. This will send the above email based on a specific event ID for the microsoft failover cluster / operational, say ID 5143 for example. My question is how do i include in that script to also include a copy of the log for that event ID in the body of the email ?

    Tuesday, February 26, 2013 5:01 PM

Answers

  • Quick update, i got it working however using the wevtutil

    File creation script:

    wevtutil qe Microsoft-Windows-Backup "/q:*[System [(EventID=4)]]" /f:text /rd:true /c:1 > C:\query.txt

    email script:

    $To      = "IT@Domain.com" 
    $From    = "administrator@Domain.com" 
    $Subject = "testing new script" 
    $Body    = "testing new script." 
    # Create mail message 
    $Message = New-Object System.Net.Mail.MailMessage $From, $To, $Subject, $Body 
    $AttchmentText = get-content C:\query.txt
    # Now create Attachement content type
    $ct = new-object System.Net.Mime.Contenttype
    $ct.name = 'backupPass.txt'
    # Now create an attachment of that type
    $attachment = [System.Net.Mail.Attachment]::CreateAttachmentFromString($attchmenttext,$ct)
    # Next add Attachment to the message
    $message.Attachments.Add($attachment)
    # and now create smtp server
    $smtpServer = "smtp.Domain.com"
    $smtp = new-object Net.Mail.SmtpClient($smtpServer)
    $smtp.Send($message)

    • Marked as answer by Ahmad Alkaysey Wednesday, February 27, 2013 1:55 PM
    Tuesday, February 26, 2013 9:01 PM

All replies

  • You problem with this code is that the SMTPClient send method does not handle attachements.

    Instead, try creating the message, using the system.net.mail.mailmessage class to create the message.Then create a mail attachment. Finally, add the attachment to the message. This allows you to craate an attachment, then use the SMTPServer object to send that mail.

    The code should look something like this:

    $To      = "doctordns@gmail.com"
    $From    = "jane@cookham.net"
    $Subject = "Using the .NET SMTP client."
    $Body    = "Using this .NET feature, you can send an e-mail message from an application very easily."
    # Create mail message
    $Message = New-Object System.Net.Mail.MailMessage $From, $To, $Subject, $Body
    $AttchmentText = get-content C:\foo\aaaaaaa.txt  # or whatever
    # Now create Attachement content type
    $ct = new-object System.Net.Mime.Contenttype
    $ct.name = 'text/plain'
    # Now create an attachment of that type
    $attachment = [System.Net.Mail.Attachment]::CreateAttachmentFromString($attchmenttext,$ct)
    # Next add Attachment to the message
    $message.Attachments.Add($attachment)
    # and now create smtp server
    $smtpServer = "COOKHAM8"
    $smtp = new-object Net.Mail.SmtpClient($smtpServer)
    $smtp.Send($message)

    I tested this script on my system and it works. You may need to play around a bit with the attachment, in terms of content type, etc.


    Thomas Lee <DoctorDNS@Gmail.Com>

    • Proposed as answer by Thomas Lee Tuesday, February 26, 2013 5:33 PM
    • Marked as answer by Ahmad Alkaysey Tuesday, February 26, 2013 6:25 PM
    • Unmarked as answer by Ahmad Alkaysey Tuesday, February 26, 2013 6:48 PM
    Tuesday, February 26, 2013 5:33 PM
  • Alright this is the answer i was looking for but it only solves 1/2 the problem, heh. 

    i see this line: $AttchmentText = get-content C:\count.txt   #just a sample file i created

    how would i refer to the event log for a specific ID instead of a specific file ?

    Tuesday, February 26, 2013 6:46 PM
  • I'm not sure what you mean.

    If you want a specific log file, instead of this line

    $AttchmentText = get-content C:\foo\aaaaaaa.txt

    Just point to the log file you want to send. Assuming you wanted to send an actual file.

    If you want the event log entry - then use Get-EventLog to get the specific event log history and the do something like this

    $event = Get-Event -logname xxx                                    # etc to get the log entry you want 
    $attachmenttext  =   "Category: $(Event.Category)        # build up a attachment string, line
    $attachmenttext  += "Message: $(Event.Message)         # by line
    $attachmenttext  += "Index:      $($Event.Index)            # by line

    etc...

    The do what I suggested in terms of attaching that string as an attachment and sending it off.


    Thomas Lee <DoctorDNS@Gmail.Com>

    Tuesday, February 26, 2013 7:00 PM
  • Alright, i think this would be easier though what do you think ?

    wevtutil qe Security "/q:*[System [(EventID=4648)]]" /f:text /rd:true /c:1 > C:\query.txt

    Only problem is, the log im accessing or monitoring so to speak is the following in event viewer: 

    applications and service logs/microsoft/windows/failoverclustering/operational

    How do i point to that event log ? 

    in the above code you see 'system', thats pointing to the Windows Logs/System event log...if i can get this figured out i believe i should be in good shape.

    or even in the case i choose to use your method: 

    $event = Get-Event -logname xxx,#How would i point to the above log i mentioned?

    Thanks



    Tuesday, February 26, 2013 7:14 PM
  • webtutil is effectively the same as get-EventLog

    I suggest you do something like this:

    # Use Get-EventLog to get the event you want
    Get-EvetLog -Log <logfilename> | where {conditions} | Format-List * > xxx.txt
    $AttachmentText = Get-Content xxx.txt

    # Now create Attachement content type
    $ct = new-object System.Net.Mime.Contenttype
    $ct.name = 'text/plain'
    # Now create an attachment of that type
    $attachment = [System.Net.Mail.Attachment]::CreateAttachmentFromString($attchmenttext,$ct)
    etc


    Thomas Lee <DoctorDNS@Gmail.Com>

    Tuesday, February 26, 2013 7:20 PM
  • get-eventlog is not allowing me to access the microsoft/windows/failoverclustering/operational log is this because its in a directory ?
    Tuesday, February 26, 2013 7:25 PM
  • just do this

    Send-mailmessage -from "name <email>" `
     -to "name <email>" `
     -Subject "type subject" `
     -Body "message" `
     -Attachment "C:\whatever" `
     -smtpServer "server"

    Tuesday, February 26, 2013 7:26 PM
  • I' don;t have clustering here so can't check.  If this is one of the windows event log files, then get-EventLog should get you that log.

    What error are you getting.

    If you are in the ISE try this. Type

    Get-EventLog * will get you the names of the logs you can use Get-EVentLog with. If the event log has a space in the name, enclose the full log in delimiters, eg:

    Get-EventLog -Log 'Windows PowerShell'


    Thomas Lee <DoctorDNS@Gmail.Com>

    Tuesday, February 26, 2013 7:29 PM
  • You should have this to test: Applications and Service Logs/Microsoft/Windows/GroupPolicy/Operational

    currently stuck at this point.

     i can access any event log under applications and service logs BUT in this case since this log is located in a microsoft/windows/* its not finding it.

    Tuesday, February 26, 2013 7:34 PM
  • I have no idea what you are talking about. ; I do not know what the reference is you are making - where are you pointing and with what tool? Can you describe specifically I should be looking for. Oh = and what OS are you using?

    More to the point, waht, specifically, are you trying to get to? Which Event Log? Earier you talked about a clustering log - now you are talking about a GP log.

    Did you actually try what I suggested (i.e. Get-EVentLog *) to see what event logs PowerShell can see? If so, what was the result?


    Thomas Lee <DoctorDNS@Gmail.Com>



    • Edited by Thomas Lee Tuesday, February 26, 2013 7:40 PM
    Tuesday, February 26, 2013 7:36 PM
  • Nice answer - but the OP's issue is that he doesn't know how to get the attachment file created.


    Thomas Lee <DoctorDNS@Gmail.Com>

    Tuesday, February 26, 2013 7:37 PM
  • I have no idea what you are talking about. ; I do not know what the reference is you are making - where are you pointing and with what tool? Can you describe specifically I should be looking for. Oh = and what OS are you using?

    More to the point, waht, specifically, are you trying to get to? Which Event Log? Earier you talked about a clustering log - now you are talking about a GP log.

    Did you actually try what I suggested (i.e. Get-EVentLog *) to see what event logs PowerShell can see? If so, what was the result?


    Thomas Lee <DoctorDNS@Gmail.Com>



    Yes i tried that, you said you didnt have the failoverclustering log so i figured i should use a log that you should have which is the gp log since failoverclustering is a feature that needs to be installed. Im running Windows server 2012 standard. 

    If you open event viewer, navigate down to "applications and service logs" then expand the selection, you should see a list of logs starting with "active directory web services" all the way to "windows Powershell", in there is a folder called "Microsoft" the logs im referring to are located in that folder under sub directories windows/*.

    I got the answer for how to create an attachment file to be sent via email but now i need to be able to attach the right log to that email heh.

    Tuesday, February 26, 2013 7:45 PM
  • Ahh - I see. Sorry for being thick tonite! I thought you meant the normal WIndows event logs, not the newer Vista operational logs!

    To get the log events from the operational log:

    Get-WinEvent -path C:\Windows\System32\winevt\logs\Microsoft-Windows-GroupPolicy%4Operational.evtx

    That will get all of them - just pipe the output to a where clause.

    Two things:

    1. in some cases, the message is not stripped out of the event log with Get-WinEvent.

    2. You may need to adjust your permissions to c:\windows\system32\winevt\logs.


    Thomas Lee <DoctorDNS@Gmail.Com>


    • Edited by Thomas Lee Tuesday, February 26, 2013 8:11 PM typo
    Tuesday, February 26, 2013 8:10 PM
  • Ok, so heres what im trying to do but its not working:

    get-winevent -path C:\Windows\System32\winevt\Logs\Microsoft-Windows-GroupPolicy%4Operational.evtx | where {(EventID=144)} | Format-List * > c:\xxx.txt

    am i doing something wrong with the eventID? ?

    also whats "format-list" ?


    Tuesday, February 26, 2013 8:24 PM
  • Quick update, i got it working however using the wevtutil

    File creation script:

    wevtutil qe Microsoft-Windows-Backup "/q:*[System [(EventID=4)]]" /f:text /rd:true /c:1 > C:\query.txt

    email script:

    $To      = "IT@Domain.com" 
    $From    = "administrator@Domain.com" 
    $Subject = "testing new script" 
    $Body    = "testing new script." 
    # Create mail message 
    $Message = New-Object System.Net.Mail.MailMessage $From, $To, $Subject, $Body 
    $AttchmentText = get-content C:\query.txt
    # Now create Attachement content type
    $ct = new-object System.Net.Mime.Contenttype
    $ct.name = 'backupPass.txt'
    # Now create an attachment of that type
    $attachment = [System.Net.Mail.Attachment]::CreateAttachmentFromString($attchmenttext,$ct)
    # Next add Attachment to the message
    $message.Attachments.Add($attachment)
    # and now create smtp server
    $smtpServer = "smtp.Domain.com"
    $smtp = new-object Net.Mail.SmtpClient($smtpServer)
    $smtp.Send($message)

    • Marked as answer by Ahmad Alkaysey Wednesday, February 27, 2013 1:55 PM
    Tuesday, February 26, 2013 9:01 PM
  • Begin - you are not doing this correctly due to a misreading of the help.

    Get-WinEvent get the logs directly.  It does not read online event logs by file name.

    I recommend going back and reviewing the documentation for the new event log and how it works.

    YOU do not need to use the net client to send mail attachments in PowerShell V2 and later.

    $msgprops=@{
        To='IT@Domain.com'
        From='administrator@Domain.com' 
        Subject='testing new script'
        Body='testing new script'
        SMTPServer='smtp.Domain.com'
    }
    Send-MailMessage -Property @msgprops -Attachments C:\query.txt

    The SMTPServer can be defaulted by setting $PSSMTPServer in your profile.  We usually set this to the local company server.

    All of the other things are taken care of automatically by the CmdLet.

    Access to all event logs may require that you run as an elevated admin.  All security log entries require elevation.


    ¯\_(ツ)_/¯


    • Edited by Thomas Lee Tuesday, February 26, 2013 9:23 PM typos fixed
    Tuesday, February 26, 2013 9:21 PM
  • @JRV

    I think you are misunderstanding. The OP wants one of the new style post Vista Operational logs which are very much files. However, they are not files read by Get-EventLog. Instead, you need to use Get-WinEvent and specify the path of the specific log you want.


    Thomas Lee <DoctorDNS@Gmail.Com>

    Tuesday, February 26, 2013 9:25 PM
  • To continue - to get the loded operational event log fo rGP:

    Get-WinEvent Microsoft-Windows-GroupPolicy/Operational -MaxEvents 3

    for others:

    get-winevent Microsoft-Failover-Cluster/Operational -MaxEvents 3

    You can also use a filter to target specif events and groups of events.  This can be easily sent to Format-Table and then sent to the body to an email.

    This is how these CMdLets are intended to be used,  Ther is no need to attempt to read teh file directly.  File reading with the eventlog tools is for parsing exported and saved logs and not for use with online logs.

    WEVUTIL wil not give you a manageble record output that can be formatted in as many ways as Get-WinEvent will.  The filter syntax is also not as powerful or flexible.  With PowerShell we can easily decompose an event into all of its parameters in an object and use that to generate a very sophisticated report.

    If Admins can learn to use Get-WinEvent they will find that is is an awesome CmdLet.  It can even dump raw XML.


    ¯\_(ツ)_/¯

    Tuesday, February 26, 2013 9:32 PM
  • Awesome, changed it to this method mentioned above and works wonderfully. 

    One FINAL question, if i were to keep using this method:

    wevtutil qe Microsoft-Windows-Backup "/q:*[System [(EventID=14)]]" /f:text /rd:true /c:1 > C:\delme.txt

    Say i wanted to put multiple EventID's, how would i do so:

    wevtutil qe Microsoft-Windows-Backup "/q:*[System [(EventID=14)]]" /f:text /rd:true /c:1 > C:\delme.txt
    wevtutil qe Microsoft-Windows-Backup "/q:*[System [(EventID=4)]]" /f:text /rd:true /c:1 > C:\delme.txt

    ^this isnt working simply because if event ID 4 exists it will overwrite the file that event ID 14 was written, perhaps an AND or an OR modifier ??

    Tuesday, February 26, 2013 9:57 PM
  • @JRV

    I think you are misunderstanding. The OP wants one of the new style post Vista Operational logs which are very much files. However, they are not files read by Get-EventLog. Instead, you need to use Get-WinEvent and specify the path of the specific log you want.


    Thomas Lee <DoctorDNS@Gmail.Com>

    I did no misundersrtand.  I have been quering post 2003 event logs for years,.  We do not need to use teh file path.  Just use the name of the operational or diagnostic log as posted with my format above.  They are all Microsoft-logname-subname\Operational.  Just read the name in the event viewer.  You can also just copy it from the screen and paste it into powershell.

    This is why I suggested going back and reading how the new event logs are designed to work.


    ¯\_(ツ)_/¯

    Tuesday, February 26, 2013 10:03 PM
  • Any tips on how to include multiple eventID's in one script to create a file? 
    Tuesday, February 26, 2013 10:19 PM
  • Any tips on how to include multiple eventID's in one script to create a file? 

    You can use below function for multiple Event ID's

    ====

    [(EventID=4 or EventID=14 or EventID=1)]]

    ====

    Friday, February 21, 2014 11:09 AM
  • change this  ...

    wevtutil qe Security "/q:*[System [(EventID=4648)]]" /f:text /rd:true /c:1 > C:\query.txt

    to this ...

    wevtutil qe Microsoft-Windows-FailOverClustering/Operational "/q:*[System [(EventID=4648)]]" /f:text /rd:true /c:1 > C:\query.txt

    Wednesday, October 29, 2014 12:16 PM
  • Hi All

    By using powershell we can do like this script to monitor on each hour their state:

    BEGIN {Import-Module FailoverClusters}
    
    PROCESS {
    			$Cluster = Get-Cluster
    			
    			ForEach ($i in (Get-ClusterNode -Cluster $Cluster | Select-Object -ExpandProperty Name))
    			{
    				
    			    Invoke-Command -ComputerName $i -ScriptBlock {$Nearby = (Get-Date) - (New-TimeSpan -hour 1);Get-WinEvent  `
    				-path "c:\windows\System32\Winevt\Logs\Microsoft-Windows-FailoverClustering%4Operational.evtx" | `
    			     Where-Object {$_.ID -eq 1641 -and $_.Message -like "*moving*" -and $_.TimeCreated -gt $Nearby}} | Select-Object -Property PSComputerName,TimeCreated,Message									  
    			}
    }
    
    END {}
    


    Wednesday, March 23, 2016 3:53 AM