Author Posts

June 1, 2016 at 9:01 pm

$eventsDC= Get-Eventlog security -Computer $DC -InstanceId 4625 -After (Get-Date).AddDays(-7) |
   Select TimeGenerated,ReplacementStrings |
   % {
     New-Object PSObject -Property @{
      Source_Computer = $_.ReplacementStrings[13]
      UserName = $_.ReplacementStrings[5]
      IP_Address = $_.ReplacementStrings[19]
      Date = $_.TimeGenerated
    }
   }
   
$eventsDC | ConvertTo-Html -Property Source_Computer,UserName,IP_Address,Date -head $HTML -body "Generated On $Date"|
	 Out-File $Report -Append

I am working with a script that uses the above line to create an html file containing data about failed logins, then attach the html file to an email.

How can I make the $eventsDC data become text placed into the body of an HTML email??

I have the code for sending the email, using PS 1.0 net.mail.mailmessage for now, and it all works to send the above $Report file as an attachment, but I want to try to have the $Report text converted into something that can become an email body.

function FuncMail {
    #param($strTo, $strFrom, $strSubject, $strBody, $smtpServer)
    param($To, $From, $Subject, $Body, $smtpServer)
    $msg = new-object Net.Mail.MailMessage
    $smtp = new-object Net.Mail.SmtpClient($smtpServer)
    $smtp.UseDefaultCredentials = $true
    $msg.From = $From
    $msg.To.Add($To)
    $msg.Subject = $Subject
    $msg.IsBodyHtml = 1
    $msg.Body = $Report
    $msg.Attachments.Add($Report)
    $smtp.Send($msg)
    $msg.Attachments.Dispose()
}

FuncMail -To "tlyczko@mmm.org" -From "dc2@mmm.org"  -Subject "Failed Login Report" -Body "Report $Report here" -smtpServer "smtp.mmm.org"	

Suggestions anyone??

I did try using a new variable and using Out-String but this wrote the output to the view/immediate window, not into anything that could be emailed, so far as I could see...

Thank you, Tom

  • This topic was modified 2 years, 3 months ago by  tommls.

June 1, 2016 at 11:59 pm

Or maybe there is some way I can read back out the contents of report.html into some variable that can be used as the body text??
Thank you, Tom

June 2, 2016 at 12:22 am

Yes!!! You're on the right track with the second post. You pumped out everything to a file and then tried to pass that 'file object' to FuncMail and it got confused. It only sees that you passed it a file. FuncMail doesn't know what it is or whats inside it. You say you want FuncMail to read the the files contents, interpret them as HTML code and insert them into an email???....but you don't tell FuncMail that.

Lesson 1: Object types (Use the cmdlet Get-Member to analyze objects in more detail)

Apart from that, there were several other areas in your code that needed attention. When you call FuncMail you use a parameter -Body yet you do not use that param inside the function. You call $Report instead? FuncMail doesn't know what $Report is because you haven't defined it within the variable scope.

Lesson 2: Variable Scope

We could go on but it would be easier to just show you. This is how I might accomplish what you are doing.

$ComputerName = "."
$InstanceID = "4625"
$Date = Get-Date
$CutoffDate = $Date.AddDays(-100)
$To = "tlyczko@mmm.org"
$From = "dc2@mmm.org"
$Subject = "Failed Login Report"
$SMTPServer = "smtp.mmm.org"

$Events = Get-EventLog -ComputerName $ComputerName -LogName Security -InstanceId $InstanceID -After $CutoffDate | ForEach-Object {
    New-Object PSObject -Property @{
        Source_Computer = $_.ReplacementStrings[13]
        UserName = $_.ReplacementStrings[5]
        IP_Address = $_.ReplacementStrings[19]
        Date = $_.TimeGenerated
    }
}

$Body = "Reported on $Date"
$Body += "-------------------------------------------------------------------------"
$Body += $Events | ConvertTo-Html -Fragment

Send-MailMessage -To $To -From $From -Subject $Subject -Body $Body -SmtpServer $SMTPServer

Send-MailMessage is a PoSh v3 cmdlet and does the same as FuncMail. Good luck!

June 2, 2016 at 12:26 am

I was indeed attempting to reuse other code wrt FuncMail.
So I will try your suggestion for emailing...I can still use the other code to generate the report file.
I think I can figure out how to append to $Body each time it does one of the 4 servers I am evaluating.
Thank you, Tom

June 2, 2016 at 11:33 am

You might choose to write that like this.

$body = @"
Reported on $Date
————————————————————————-
"@

$email = $events | ConvertTo-Html -head $a -body "$body" | out-string

Edit: There are html breaks following the $date and $body that the forum will not display.

  • This reply was modified 2 years, 3 months ago by  Dan Potter.
  • This reply was modified 2 years, 3 months ago by  Dan Potter.

June 2, 2016 at 3:27 pm

I tried to modify it to get events from 4 different servers, it works with 1 server, but with 4 servers, it runs forever and never sends anything:


$DCs = @('x5','x6','x7','x8')

$InstanceID = "4625"
$Date = Get-Date
$CutoffDate = $Date.AddDays(-1)
$To = "tlyczko@ms.org"
$From = "dc2@ms.org"
$Subject = "Failed Login Report"
$SMTPServer = "smtp.ms.org"

foreach ($DC in $DCs) {

$Events = Get-EventLog -ComputerName $DC -LogName Security -InstanceId $InstanceID -After $CutoffDate | ForEach-Object {
    New-Object PSObject -Property @{
        Source_Computer = $_.ReplacementStrings[13]
        UserName = $_.ReplacementStrings[5]
        #IP_Address = $_.ReplacementStrings[19]
        Date = $_.TimeGenerated
    }
}

$Body = "Reported on $Date"
# $Body += "-------------------------------------------------------------------------"
$Body += $Events | ConvertTo-Html -Fragment
}
}
# after foreach loop ends
Send-MailMessage -To $To -From $From -Subject $Subject -Body $Body -SmtpServer $SMTPServer -BodyAsHtml

What am I doing wrong with the foreach loop?? I get no feedback from PoSh.

Thank you, Tom

  • This reply was modified 2 years, 3 months ago by  tommls.

June 2, 2016 at 3:29 pm

@Dan if you edit your reply and use


tags the code will display better.

June 2, 2016 at 3:35 pm

I tried the pre tags as well.

This has a bunch of lessthan br greaterthan's








  • This reply was modified 2 years, 3 months ago by  Dan Potter.
  • This reply was modified 2 years, 3 months ago by  Dan Potter.

June 2, 2016 at 3:38 pm

OIC no worries, I read it several more times and I now understand your suggestion.
Maybe someone will reply on my foreach question.
Thank you, Tom

June 2, 2016 at 3:44 pm

tommls,

If you are doing a long report I find it easiest to output to htm and then attach to the message.

$events | convert-tohtml |out-file something.htm

$eventstwo | convert-tohtml |out-file something.htm -append

June 2, 2016 at 3:50 pm

It's not THAT long a report, my earlier original code does the report and attaches to a message but I am now trying to get it into an email body.
It's maybe 50-75 lines of HTML table lines, not a lot at all.
Thank you, Tom

June 2, 2016 at 4:18 pm

My point is if you have a report with multiple tables it's easier to append to an html file then retrieve the whole html file for the body.

You can formulate the html within the body parameter but it can get messy if you have too many things going on.

$emailbody = "words html break $events htmlbreak words $eventstwo"

June 2, 2016 at 4:24 pm

Based on the last code you posted you have one too many curly braces and the Send-MailMessage line has to be inside the foreach loop.

And Dan was correct I tried using HTML break tags that didn't translate in my earlier post.

June 2, 2016 at 4:25 pm

Ohhhhhhhhhhh...now I understand what you are suggesting, I would like to do that...that line with $emailbody is how I concatenate the HTML outputs of $events###??

Thank you, Tom

June 2, 2016 at 4:33 pm

Thank you for feedback on curly braces though PoSh did not complain.
I wanted the body things to be concatenated so I have 4 different tables, one for each server.
I want the email sent after the four servers have been reviewed, that's why send-mailmessage is outside the foreach loop, it's wanted to send all four server results in one email.
Thank you, Tom

June 2, 2016 at 4:35 pm

Yep, purely for visual formatting purpose in the email body only. Didn't really have any effect on the script itself. I like to make it purdy.

June 2, 2016 at 4:37 pm

note that send-mailmessage doesn't accept anything but strings for body.

to keep it simple (can't test this at the moment)

'report1','report2 | % {

switch($_){

report1{get-process | convert-tohtml -body "reportonetitle htmlbreak"| out-file reports.htm}
report2{get-service | convert-tohtml -body "reporttwotitle htmlbreak"| out-file reports.htm -append}

}

}

$emailbody = get-content reports.htm

send-mailmessage...

  • This reply was modified 2 years, 3 months ago by  Dan Potter.

June 2, 2016 at 4:45 pm

Oh, now I got ya. Then you'll need to accumulate the $Events each time the loop iterates. So change $Events = to $Events +=. You will also need to define $Events as an array before the foreach loop b/c powershell complains if you attempt to add elements to an array when it doesn't already know the variable is an array. So above the foreach add a line $Events = @().

June 2, 2016 at 4:48 pm

Ahhhhhhhhh....the missing link.
I will try all this after a looonnng meeting (ugh).
Thank you, Tom

June 2, 2016 at 4:49 pm

Also, take the bits about the $Body out of the foreach loop as well and define the body right before you send the email.

June 2, 2016 at 5:02 pm

Yea just looked at this again. Ignore my last two posts. Keep everything inside the foreach loop. Don't change $Events, you want that to be overwritten each iteration. It's the $Body = "Reported on $Date – $DC" line that needs to be changed to $Body +=. This way $Body isn't getting wiped out each time the loop iterates. You will have to define $Body as an array above the foreach loop though. And yea figure out some way to generate some sort of separator in between the dc reports since they'll all be mashed into the same email.

Sorry for the confusion! Carry on.

June 3, 2016 at 6:40 pm

With Jack's most recent suggestions I got it all working.
I have one foreach to create and store the daily html report file, which looks nicer than the email.
I have one foreach to put all the stuff into an email and send it to me nightly.
Thank you, Tom