Tuesday, February 26, 2013

Send email from cmd script using Powershell

In C#, sending mail is a simple task. We create an instance of System.Net.Mail.SmtpClient class and then call Send method with MailMessage object. Sometimes smalle task is done by using windows shell script. If we have to use shell script in .cmd file, how do we send email? Well, shell command does not have a command for sendmail, so we probably can use third party utility. If we do not want to download and install the 3rd party tool on your system on whatever reason, we can utilize Powershell which can create and use .NET classes.
Let's say we have a .cmd file that runs an application and we want to send an alert email when the app is failed. The following code snippet shows that it runs MyApp.exe and check its exit code and  some literal text (Result=Pass) to verify that the app is successful. If it fails, it calls Powershell script (sendmail.ps1) which is located in the same folder.

@ECHO OFF
REM Run App
MyApp.exe data.ini > MyApp.out 2>&1

echo EXIT_CODE : %errorlevel%

REM Check exit code
if %errorlevel% NEQ 0 (
  echo ErrorLevel is "%errorlevel%"
  GOTO Error
)

REM Check valid output
find /i "Result=Pass" MyApp.out
if %errorlevel% NEQ 0 (
  echo Result : Fail
  GOTO Error
)

echo Result : Pass
GOTO End

:Error
Powershell .\sendmail.ps1
EXIT /B -1

:End
EXIT /B 0
@ECHO ON

The next code is powershell script that sends email. It creates various .NET objects related to mail and set their properties as we do in other languages like C#. If SMTP server is valid server name and client credential is valid, the mail will be delivered via SMTP.

#
# sendmail.ps1
#
$from = New-Object system.net.mail.MailAddress "sender@live.com"
$to = New-Object system.net.mail.MailAddress "receiver@live.com"
$message = new-object system.net.mail.MailMessage $from, $to
$message.Subject = "[FAILED] Scheduled Task Failed"
$message.Body = "Scheduled Task failed on Machine1. Please investigate the failure."

$smtpserver = "smtphost.domain.com"
$client = new-object system.net.mail.smtpclient $smtpserver
$client.UseDefaultCredentials = $TRUE
$client.Send($message)