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
Skumar_CCSAAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

David Johnson, CD, MVPOwnerCommented:
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

1
Skumar_CCSAAuthor 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.
0
David Johnson, CD, MVPOwnerCommented:
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

1

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Skumar_CCSAAuthor 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 }
1
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Powershell

From novice to tech pro — start learning today.