Thursday, December 20, 2007

A cmdlet-like email script

I'm currently working on a database monitoring, datacollection and automation project using PowerShell. In this project I often find m self in need of sending a status or warning email when some event occurs - For a while I've just used code much like what I posted here on my blog back in december 2006, but last night I spend a bit of time writing up a cmdlet like "Send-SMTPmail" function once and for all.
Please feel free to comment the script, its functionality and implementation.

# PowerShell 1.0 script to send email through SMTP
# by Jakob Bindslet (jakob@bindslet.dk), 20. december 2007
# Current Script version 1.0
#
#NAME
# Send-SMTPmail
#
#SYNOPSIS
# Sends an email by use of an SMTP server
#
#SYNTAX
# Send-SMTPmail -to -from -subject -body
# [-smtpserver ] [-port ] [-attachment ] [-html "yes"]
# [-cc ] [-bcc ] [-alert "yes"] [-timeout ]
#
#PARAMETERS
# No specific order of the parameters are required:
# -to
# -from
# -subject
# -body
# Optional arguments are:
# -smtpserver
# Address of the smtp server to be used. This is only optional if a
# default smtpserver has been specified
# -port
# port number of the smtp server, used only if it differs from the
# standard port 25.
# -attachment
# Complete path to file to attach, ie. "c:\boot.ini"
# -html "yes"
# Indicates that the email will be in HTML format. The HTML
# content itself should be specified in the -body parameter.
# -cc
# Recipient(s) to be included as "carbon copy" on the email.
# -bcc
# Recipient(s) to be included as "blind carbon copy" on the email.
# -alert "yes"
# The email will be treatet as an alert (the standard sharepoint
# alert icon will be used in outlook).
# -timeout
# Sets the timeout in miliseconds, for the send mail operation.
# This includes the time it take to upload any attachments, so
# be careful of setting this too low if using attached file.
#
#NOTES
#
# -------------------------- EXAMPLE 1 --------------------------
# C:\PS>send-SMTPmail -to hans@contoso.msft -from theBoss@contoso.msft
# -subject "Congratulations!" -smtpserver "smtp.contoso.msft"
# -body "You'll get one extra week of vacation year"
# -bcc "theMiddleBoss@contoso.msft"

function Send-SMTPmail() {
## Setting defaults
$to = $null; $from = $null; $from = $null; $subject = $null; $body = $null;
$attachment = $null; $html = $null; $cc = $null; $bcc = $null; $port = $null
$alert = $null; $timeout = $null

$smtpserver = "smtp.myserver.com"
$LastArg = $args.length -1
for ($i = 0; $i -le $LastArg; $i += 2) {
if ($args[$i].substring(0,1) -eq "-") {
Write-Host "param" $args[$i] "value" $args[$i+1] ##debug line, can be removed
switch ($args[$i]) {
-smtpserver {$smtpserver = $args[$i+1]}
-to {$to = $args[$i+1]}
-from {$from = $args[$i+1]}
-subject {$subject = $args[$i+1]}
-body {$body = $args[$i+1]}
-attachment {$attachment = $args[$i+1]}
-html {$html = "yes"}
-cc {$cc = $args[$i+1]}
-bcc {$bcc = $args[$i+1]}
-port {$port = $args[$i+1]}
-alert {$alert = "yes"}
-timeout {$timeout = $args[$i+1]}
}
}
}
$mailer = new-object Net.Mail.SMTPclient($smtpserver)
if ($port -ne $null) {$mailer.port = $port}
if ($timeout -ne $null) {$mailer.timeout = $timeout}
$msg = new-object Net.Mail.MailMessage($from,$to,$subject,$body)
if ($html -eq "yes") {$msg.IsBodyHTML = $true}
if ($cc -ne $null) {$msg.cc.add($cc)}
if ($bcc -ne $null) {$msg.bcc.add($bcc)}
if ($alert -eq "yes") {$msg.Headers.Add("message-id", "<3bd50098e401463aa228377848493927-1>")}
if ($attachment -ne $null) {
$attachment = new-object Net.Mail.Attachment($attachment)
$msg.attachments.add($attachment)
}
$mailer.send($msg)
}

4 comments:

Anonymous said...

Fun stuff. Is it similiar to the one in pscx (community extensions) ?I wanted the send-stmp mail cmmdlet they had in there but didn't want to install the whole shebang.

BFHobbes said...

just to let you know, you can simplify this by using parameters in your function.
You can specify defaults in the parameter list, and you can mimick required parameters if you throw an exception as the default value for the parameter. When you have parameters like this, powershell allows you to set their value using the same syntax as you have attempted to mimick with the argument processing.
Also, the [switch] attribute allows you to specify a parameter that doesn't need a value, if the parameter is specified by the caller as -alert for instance then the parameter $alert is set to $true

function Send-SMTPmail(
$smtpserver = "smtp.myserver.com",
$to = $(throw "to parameter required"),
[switch]$alert,
$port=25,
... etc ...
)
{
.... function body ....
}

Jakob Bindslet said...

Thanks for the improvement "bfhobbes" - I had already incorporated some in the version 1.2 of the script on the page.

Virtu-Al said...

You will also need to close the attachment after sending it using $attachment.dispose() otherwise the file will remain locked....

http://teckinfo.blogspot.com/2008/10/powershell-email-locks-attachment.html