Link to home
Start Free TrialLog in
Avatar of Skumar_CCSA
Skumar_CCSAFlag for India

asked on

Powershell script errors logs to send email

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
Avatar of David Johnson, CD
David Johnson, CD
Flag of Canada image

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

Avatar of Skumar_CCSA

ASKER

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.
ASKER CERTIFIED SOLUTION
Avatar of David Johnson, CD
David Johnson, CD
Flag of Canada image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
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 }