Powershell script errors logs to send email

Skumar_CCSA
Skumar_CCSA used Ask the Experts™
on
i am new to the powershell scripting and at learnig stage.
i have scripts it works (experts helped me move on further)....it checks for file, upload the file in ftp.
i have written function to send email when process complete and also capture the errors and send email error alert.
i noticed the status email works with sending attacment and failure email alerts just capturing ERROR word but not sending email alert...
Like to request for help..
I want email alerts to come body message to have errors captured ? or if possible the log file context to write in the email body.
Also like to check what more parameters to set so that we get errors alerts in the log...for timeout ,username password wrong etc...Modify_Script.ps1Modify_Script.ps1



#Requires -version 3.0
$WarningPreference="Continue"

#variables
$ScriptPath = $(Split-Path -Parent $MyInvocation.MyCommand.Definition)

# Load WinSCP .NET assembly
[Reflection.Assembly]::LoadFrom( $(Join-Path $ScriptPath "WinSCPnet.dll") ) | Out-Null

#Log Timestamp
$date=Get-Date -Format ddMMMyyyyHHmmss
$logdate=Get-Date -Format ddMMMyyyy_HHmmss
$emaildate=Get-Date -Format dd/MM/yyyy_HH:mm:ss
$Logfile = "E:\INT\Log\Daily_$logdate.txt"

function LogWrite ([string]$logstring)
{  
   Add-content $Logfile -value $logstring
}
LogWrite ("$( Get-Date -Format "yyyy-MM-dd HH:mm:ss" ) START:`t"+"File Processing BEGIN`n")

#Zip Files and move to backup folder
$sourcefolder="E:\INT\PUT"
$backupFolder="E:\INT\Archive"

#check if source folder exists
if(!(Test-Path $sourcefolder)){
    $msj="The source folder ""$($sourcefolder)"" doesn't exists. Exiting..."
    LogWrite "$( Get-Date -Format "yyyy-MM-dd HH:mm:ss" ) ERROR:`t$msj"
    LogWrite -ForegroundColor Red $msj
    exit -1
}

#check if source files exists

$files   = 'CAT.xml', 'BAT.xml', 'RAT.xml'
$success = $true
foreach( $file in $files )
{
       $filename = Join-Path $sourcefolder $file
       if( Test-Path -LiteralPath $filename )
       {
              LogWrite "$( Get-Date -Format "yyyy-MM-dd HH:mm:ss" ) FILECHECK:`tFile exists: $filename"
       }
       else
       {
              $msj = "The source file '$fileName' doesn't exist"
              LogWrite "$( Get-Date -Format "yyyy-MM-dd HH:mm:ss" ) ACTION REQUIRED:`t$msj"
              $success = $false
       }
}
if( -not $success  )
{
    LogWrite "$( Get-Date -Format "yyyy-MM-dd HH:mm:ss" ) The mandatory files not found in the source directory hence the ODIN job process has been cancelled"
    sendError
    exit -1
}

function sendError() {
     Write-Host "Sending Email File Transfer Error Alert @ $emaildate"
     $smtpServer = "mailserver.mail.com"
     $msg = new-object Net.Mail.MailMessage
     $smtp = new-object Net.Mail.SmtpClient($smtpServer)
     $msg.From = "donotreply@mail.com"
     $msg.To.Add("admin@mail.com")
     $msg.subject = "ACTION REQUIRED : Error Alert @ $emaildate"
     $msg.Attachments.Add($Logfile)
     $msg.Body = "Dear All,
Please refer the attachment of errors
Regards,
Job Process"
$smtp.Send($msg)
}

function sendstatus() {
     Write-Host "Sending Email File Processing Sucess Alert @ $emaildate"
     $smtpServer = "mailserver.mail.com"
     $msg = new-object Net.Mail.MailMessage
     $smtp = new-object Net.Mail.SmtpClient($smtpServer)
     $msg.From = "donotreply@mail.com"
     $msg.To.Add("admin@mail.com")
     $msg.subject = "INFO : Sucess Alert @ $emaildate"
     $msg.Attachments.Add($Logfile)
     $msg.Body = "Dear All,
Please refer the attachment
Regards,
Job Process"
     $smtp.Send($msg)
}
try
{
# Set up session options
    $sessionOptions = New-Object WinSCP.SessionOptions
    $sessionOptions.Protocol = [WinSCP.Protocol]::Ftp
    $sessionOptions.HostName = "ftp.com"
    $sessionOptions.PortNumber = 854
    $sessionOptions.UserName =  $config.Configuration.UserName
    $sessionOptions.Password = Decrypt-String $key $config.Configuration.Password
    $sessionOptions.FtpSecure = [WinSCP.FtpSecure]::Implicit
    $sessionOptions.TlsHostCertificateFingerprint='BF:BC:BV:AZ:AQ:AC:AX:AS:GD:DF:WS:KS:MG:9H:IL:ID:KS:DG:AB:ZX'
    $session = New-Object WinSCP.Session
try
    {
        # Connect    
        $localPath =  "E:\INT\PUT\*"
        $remotePath = "/Upload/to/"
        $backupPath = "E:\INT\Archive\"
        # Upload files, collect results
        $session.Open($sessionOptions)
        $transferResult = $session.PutFiles($localPath, $remotePath)
        # Iterate over every transfer
        foreach ($transfer in $transferResult.Transfers)      
        {
            # Success or error?
            if ($transfer.Error -eq $Null)
            {              
                LogWrite ("$( Get-Date -Format "yyyy-MM-dd HH:mm:ss" ) UPLOAD:`t"+"UPLOAD file {0} succeeded   " -f $transfer.FileName + "   Server Path   " + $transfer.Destination)
                # Upload succeeded, move source file to backup
                $fileWithOutExt = [io.path]::GetFileNameWithoutExtension($transfer.FileName)
                $MoveFile1 = "$backupPath\$($fileWithOutExt)_$date.p7"
                Move-Item $transfer.FileName $MoveFile1
                LogWrite ("$( Get-Date -Format "yyyy-MM-dd HH:mm:ss" ) ARCHIVE:`t"+"Moving file {0} succeeded   " -f $MoveFile1)
            }
            else
            {
                LogWrite ("Upload of {0} failed: {1}" -f
                    $transfer.FileName, $transfer.Error.Message)
            }
     
        }
       
    }
catch [Exception]
{
    LogWrite $_.Exception.Message
    sendError
    exit 1
}

}
    finally
    {
        # Disconnect, clean up
        LogWrite ("`n$( Get-Date -Format "yyyy-MM-dd HH:mm:ss" ) END:`t`t"+"File Processing ENDED.")
        $session.Dispose()
        sendstatus
    }
exit 0
Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
Top Expert 2016

Commented:
put the send email code into its own function

I renamed it to Send-Status  (verb-noun) same with Send-Error

on error close the logfile
then $body= get-content $logfile and pass that to your send-email
#Requires -version 3.0
$WarningPreference = 'Continue'

function Send-Mail
{
  param (
    [string] $Email_Subject,
    [string] $Email_Body,
    [string] $Email_Attachment
  )
    
  Send-MailMessage -SmtpServer 'mailserver.mail.com' `
  -Body $Email_Body `
  -From 'donotreply@mail.com' `
  -To 'admin@mail.com' `
  -Subject $Email_Subject `
  -Attachments $Email_Attachment
}

function Send-Error
{
  Write-Host "Sending Email File Transfer Error Alert @ $emaildate"
  $subject = "ACTION REQUIRED : Error Alert @ $emaildate"
  $Body = 'Dear All, 
    Please refer the attachment of errors
    Regards,
  Job Process'
  Send-Mail -Email_Subject $subject -Email_Body $Body -Email_Attachment $Logfile
}

function send-status 
{
  Write-Host "Sending Email File Processing Sucess Alert @ $emaildate"
  Send-Mail -Email_subject  "INFO : Sucess Alert @ $emaildate" -Email_Attachment $Logfile -Email_Body ''
}

function LogWrite ([string]$logstring)
{
  Add-Content $Logfile -Value $logstring
}


#variables
$ScriptPath = $(Split-Path -Parent -Path $MyInvocation.MyCommand.Definition) 

# Load WinSCP .NET assembly
$null = [Reflection.Assembly]::LoadFrom( $(Join-Path -Path $ScriptPath -ChildPath 'WinSCPnet.dll') )

#Log Timestamp
$date = Get-Date -Format ddMMMyyyyHHmmss
$logdate = Get-Date -Format ddMMMyyyy_HHmmss
$emaildate = Get-Date -Format dd/MM/yyyy_HH:mm:ss
$Logfile = ('E:\INT\Log\Daily_{0}.txt' -f $logdate)
LogWrite ("$( Get-Date -Format 'yyyy-MM-dd HH:mm:ss' ) START:`t"+"File Processing BEGIN`n")

#Zip Files and move to backup folder
$sourcefolder = 'E:\INT\PUT'
$backupFolder = 'E:\INT\Archive'

#check if source folder exists
if(!(Test-Path $sourcefolder))
{
  $msj = "The source folder ""$($sourcefolder)"" doesn't exists. Exiting..."
  LogWrite "$( Get-Date -Format 'yyyy-MM-dd HH:mm:ss' ) ERROR:`t$msj"
  LogWrite -ForegroundColor Red $msj
  exit -1
}

#check if source files exists

$files   = 'CAT.xml', 'BAT.xml', 'RAT.xml'
$success = $true
foreach( $file in $files )
{
  $filename = Join-Path -Path $sourcefolder -ChildPath $file
  if( Test-Path -LiteralPath $filename )
  {
    LogWrite "$( Get-Date -Format 'yyyy-MM-dd HH:mm:ss' ) FILECHECK:`tFile exists: $filename"
  }
  else
  {
    $msj = "The source file '$filename' doesn't exist"
    LogWrite "$( Get-Date -Format 'yyyy-MM-dd HH:mm:ss' ) ACTION REQUIRED:`t$msj"
    $success = $false
  }
}
if( -not $success  )
{
  LogWrite "$( Get-Date -Format 'yyyy-MM-dd HH:mm:ss' ) The mandatory files not found in the source directory hence the ODIN job process has been cancelled"
  Send-Error
  exit -1
}

try
{
  # Set up session options
  $sessionOptions = New-Object -TypeName WinSCP.SessionOptions
  $sessionOptions.Protocol = [WinSCP.Protocol]::Ftp
  $sessionOptions.HostName = 'ftp.com'
  $sessionOptions.PortNumber = 854
  $sessionOptions.UserName = $config.Configuration.UserName
  $sessionOptions.Password = Decrypt-String $key $config.Configuration.Password
  $sessionOptions.FtpSecure = [WinSCP.FtpSecure]::Implicit
  $sessionOptions.TlsHostCertificateFingerprint = 'BF:BC:BV:AZ:AQ:AC:AX:AS:GD:DF:WS:KS:MG:9H:IL:ID:KS:DG:AB:ZX' 
  $session = New-Object -TypeName WinSCP.Session
  try
  {
    # Connect    
    $localPath = 'E:\INT\PUT\*'
    $remotePath = '/Upload/to/'
    $backupPath = 'E:\INT\Archive\'
    # Upload files, collect results
    $session.Open($sessionOptions)
    $transferResult = $session.PutFiles($localPath, $remotePath) 
    # Iterate over every transfer
    foreach ($transfer in $transferResult.Transfers)       
    {
      # Success or error?
      if ($transfer.Error -eq $null)
      {               
        LogWrite ("$( Get-Date -Format 'yyyy-MM-dd HH:mm:ss' ) UPLOAD:`t"+'UPLOAD file {0} succeeded   ' -f $transfer.FileName + '   Server Path   ' + $transfer.Destination)
        # Upload succeeded, move source file to backup
        $fileWithOutExt = [io.path]::GetFileNameWithoutExtension($transfer.FileName)
        $MoveFile1 = "$backupPath\$($fileWithOutExt)_$date.p7" 
        Move-Item $transfer.FileName $MoveFile1
        LogWrite ("$( Get-Date -Format 'yyyy-MM-dd HH:mm:ss' ) ARCHIVE:`t"+'Moving file {0} succeeded   ' -f $MoveFile1)
      }
      else
      {
        LogWrite ('Upload of {0} failed: {1}' -f
        $transfer.FileName, $transfer.Error.Message)
      }
    }
  }
  catch [Exception]
  {
    LogWrite $_.Exception.Message
    send-Error
    exit 1
  }
}
finally
{
  # Disconnect, clean up
  LogWrite ("`n$( Get-Date -Format 'yyyy-MM-dd HH:mm:ss' ) END:`t`t"+'File Processing ENDED.')
  $session.Dispose()
  send-status
}
exit 0

Open in new window

Author

Commented:
In my existing code i put below line it works....but not organized.
$body= (Get-Content $OutputFile | out-string )

Like to ask for help..
where to put this in script...$body= get-content $logfile  ?
Also like to have html body email...

Error email notification..

Dear All,

Please refer the technical errors encountered during the job run.
Next line like to have output of logfile..
1....
2....
3...

Regards,
Job Run.
Top Expert 2016
Commented:
from powershell to see the parameters for sent-mailmessage type
get-help send-mailmessage -examples /code]
one of the parameters is -BodyAsHtml

[code]function Send-Error
{
  Write-Host "Sending Email File Transfer Error Alert @ $emaildate"
  $subject = "ACTION REQUIRED : Error Alert @ $emaildate"
  $logcontents = get-content $Logfile | Out-String
  $Body = 'Dear All,\nPlease refer the attachment of errors\n" + $logcontents + '\nRegards,\nJobRun'
  Send-Mail -Email_Subject $subject -Email_Body $Body -Email_Attachment $Logfile
}

Open in new window

Author

Commented:
thanks for help....
it works good with text format.
Anyway my original question is not html related.


function Send-Mail
{
  param (
    [string] $Email_Subject,
    [string] $Email_Body,
    [string] $Email_Attachment
  )
   
  Send-MailMessage -SmtpServer 'mailserver.com' `
  -Body $Email_Body `
  -From 'donotreply@mail.com' `
  -To 'admin@mail.com' `
  -Subject $Email_Subject `
  -Attachments $Email_Attachment
}

function Send-Error
{
  Write-Host "Sending Error Alert @ $emaildate"
  $subject = "ERROR : Error Alert @ $emaildate"
  $logcontents = get-content $Logfile | Out-String
  $Body = "Dear All,`n`nThis email sent by system for errors highlighted below."  + $logcontents + "`n Regards,`n Job Process"
  Send-Mail -Email_Subject $subject -Email_Body $Body -Email_Attachment $Logfile }


function send-status
{
  Write-Host "Sending Success Alert @ $emaildate"
  $subject = "INFO : Success Alert @ $emaildate"
  $logcontents = get-content $Logfile | Out-String
  $Body = "Dear All,`n`nThis email sent by system for your information"  + $logcontents + "`n Regards,`n Job Process"
  Send-Mail -Email_Subject $subject -Email_Body $Body -Email_Attachment $Logfile }

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial