Archive

Posts Tagged ‘Powershell’

Sending Mail from Powershell 2.0 CTP3 with Attachments

March 14th, 2009
Comments Off

I had seen a number of scripts detailing how to send mail from Powershell v2.0, but the limitation that always seemed to appear was that they used SMTP to do so and didnt allow complex mail formation… So I investigated .Net to see if it was possible, low and behold I came accross the following Class….

System.net.mail Namespace

and then more specifically

System.net.mail.mailmessage Class

It was this mail message class I based the following script on

#Collect Events from That are errors and report
$A = Get-date -hour 0 -minute 0 -Second 0
$logfile = $env:Temp,"applog.html" -join ""
$logfile2 = $env:Temp,"syslog.html" -join ""
$SmtpClient = new-object system.net.mail.smtpClient
$SmtpServer = "smtp.domain.com.au"
$SmtpClient.host = $SmtpServer
$log2 = Get-EventLog -LogName System -After $a -EntryType Error
$log = Get-EventLog -LogName Application -After $a -EntryType Error
If (($log.count + $log2.count) -gt 0)
{
$MailMessage = new-object system.net.mail.Mailmessage -Args "system@domain.com.au","user@domain.com.au"
$MailMessage.From = "System Log <ystem@domain.com.au>"
$MailMessage.Subject = "Syslogs for $a"
If ($log.count -gt 0){
$log | convertto-html -Property index, TimeGenerated, InstanceID, Source, Message   -Title "Application Log for $a" > $logfile
$mailmessage.attachments.add($logfile)
}
if ($log2.count -gt 0){
$log2 | convertto-html -Property index, TimeGenerated, InstanceID, Source, Message   -Title "System Log for $a" > $logfile2
$mailmessage.attachments.add($logfile2)
}
$SmtpClient.send($mailmessage)
$mailmessage.finalize
$mailmessage.dispose()
$SmtpClient.finalize
If (Test-Path $logfile){Remove-Item -Force -Path $logfile}
If (Test-Path $logfile2){Remove-Item -Force -Path $logfile2}
}

So thats the entire script…now onto a breakdown

So we start with this

$logfile = $env:Temp,"applog.html" -join ""
$logfile2 = $env:Temp,"syslog.html" -join ""

Here I declare two objects containing two temporary files I intend to fill with information and then attach to an email. $env:temp simply takes the default temp directory path and appends it two the file name with a join. A new cmdlet is planned called new-path which I think will be a better alternative here.

$SmtpClient = new-object system.net.mail.smtpClient
$SmtpServer = "smtp.domain.com.au"
$SmtpClient.host = $SmtpServer

This section declares a new object as a net smtpclient – this object will send my mail a little later.

$log2 = Get-EventLog -LogName System -After $a -EntryType Error
$log = Get-EventLog -LogName Application -After $a -EntryType Error

Here I am getting some info to send my self  – in this case I am asking for any errors in the application and system logs that have occured today. I define a$ previously as

$A = Get-date -hour 0 -minute 0 -Second 0

Basically a time call.  Okay now I need to process my data a little do some checking to ensure I am not processing nothing and then send the mail.

If (($log.count + $log2.count) -gt 0)
{

This just checks that one of the logs actually returned some entries otherwise we are wasting our time and I dont need empty emails!

$MailMessage = new-object system.net.mail.Mailmessage -Args "system@domain.com.au","user@domain.com.au"
$MailMessage.From = "System Log <ystem@domain.com.au>"
$MailMessage.Subject = "Syslogs for $a"

Now this part is the message.   I created a new object based on the Mailmessage class.  You need to specify the from and to address’s as args as the class property of  “to” is readonly and if you tried to declare it like

$mailmessage.to ="user@domain.com"

You would get an error stating the property was readonly.

Now some more error checking to ensure  which log returned values.  Then only attach that result.

If ($log.count -gt 0){
$log | convertto-html -Property index, TimeGenerated, InstanceID, Source, Message   -Title "Application Log for $a" > $logfile
$mailmessage.attachments.add($logfile)
}

Here we see I parse the result to a html file.  It makes for a nice easy read.  Then I call the Add method of the mailmessage.attachment property and add the log file to the message.

The attachments property is actually a collection and you can use a single command to add more that 1 file as long as you delimit each file with a comma.

I repeated the process for log2

$SmtpClient.send($mailmessage)

And then I send the message

Now I need to clean up. This part is really important particularly if the script is executed in a continually running powershell session rather than a 1 off instance.  For two reasons.  The mail message class once you add a file locks it.  Even once the script ends the file will remain locked.  It will only unlock after the powershell instance ends.  Thats too late as you cant remove your temp files and clean up after yourself which is just rude!

So I need to call two methods, firstly I finalize mailmessage, I am not sure if this was actually neccessary but reading the technet docs it seemed the smart way to go.  Then I dispose of the mailmessage object.  This unhooks it and leaves the files that you added open to removal.  I think after going a bit of reading net objects have a habit of doing this and it is probably good policy to always dispose the objects once you are finished if its possble.

So her goes

$mailmessage.finalize
$mailmessage.dispose()
$SmtpClient.finalize
If (Test-Path $logfile){Remove-Item -Force -Path $logfile}
If (Test-Path $logfile2){Remove-Item -Force -Path $logfile2}
}

And we are done.  One last comment

I hate errors, so I test for the existence of each logfile before removing them …just to avoid errors in case I never created them.

The Script above is based on
Windows Powershell 2.o CTP2
.NET Framework 3.5
It may not work onother .NET versions.
Upgrade to the latest version if possible.
Windows PowerShell 2.0 includes several significant features that extend its use, improve its usability, and allow you to control and manage Windows-based environments more easily and comprehensively. Windows PowerShell 2.0 is backward compatible. Cmdlets, providers, snap-ins, scripts, functions, and profiles that were designed for Windows PowerShell 1.0 work in Windows PowerShell 2.0 without changes.

Share/Save/Bookmark

benjiC Script, System Management , , , , , ,