Option Explicit

'--------------------------------------------------------------
'						 FreeFileSync.vbs
'--------------------------------------------------------------
' Runs FreeFileSync.exe with specified batch file.
' Sends email with status, errors, and warnings on completion.
'--------------------------------------------------------------
' Author: Lane Beneke - SPC Mechanical Corporation
' Date: 2016.04.07
' Usage: cscript.exe FreeFileSync.vbs <hideconsole true|false>
'						 <exefile d:\path\to\freefilesync.exe>
'						<batchfile d:\path\to\batch.ffs_batch>
'			   <globalsettingsfile d:\path\to\batch.ffs_batch>
'				  <msgsubject "Message Subject for BatchName">
'							  <msgto recipient@somedomain.tld>
'							   <msgfrom sender@somedomain.tld>
'					<smtpserver smtp.somedomain.tld | n.n.n.n>
'												 <smtpport nn>
'											  <smtpauth 0|1|2>
'							  <smtpusername "user@mailserver">
'							  <smtppassword "user's password">
'										  <smtpssl true|false>
'
'  Notes: 1) Parameter/Value pairs can be specified at the 
'			 command line, or changed in code below.  Command
'			 line values override coded values.
'         2) If the word "BatchName" (case sensitive) is in the 
'			 subject line, it will be replaced by the name of 
'			 the batch file less path and extension.
'--------------------------------------------------------------
' Copyright 2012-2016 Lane Beneke - SPC Mechanical Corporation
' 
' This program is free software: you can redistribute it and/or 
' modify it under the terms of the GNU General Public License as 
' published by the Free Software Foundation, either version 3 of
' the License, or (at your option) any later version.
' 
' This program is distributed in the hope that it will be useful,
' but WITHOUT ANY WARRANTY; without even the implied warranty of
' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
' GNU General Public License for more details.
' 
' You should have received a copy of the GNU General Public License
' along with this program.  If not, see <http://www.gnu.org/licenses/>.
'--------------------------------------------------------------
'    Author: Lane Beneke - Southern Piping Company
'   Version: 2012.11.30 - Version 1.0
' Changelog: Initial release
'--------------------------------------------------------------
'    Author: Lane Beneke - Southern Piping Company
'   Version: 2012.12.05 - Version 1.1
' Changelog: Added functionality to scan log files for errors
'			 and warnings, adding them to the notification 
'			 email message. This included...
'			  - changing email msg format to HTML
'			  - finding, opening, and reading log file
'--------------------------------------------------------------
'    Author: Lane Beneke - Southern Piping Company
'   Version: 2013.01.17 - Version 1.2
' Changelog: Added HideConsole variable and associated code.
'			 Added command line parser.
'--------------------------------------------------------------
'    Author: Lane Beneke - Southern Piping Company
'   Version: 2014.01.27 - Version 1.3
' Changelog: Upgraded FreeFileSync program to ver 6.1. The new
'			 version changes the log file name, adding 
'			 " (Error)" ahead of the extension. Changed the 
'			 GetLogFile function to search old and new names.
'			 Also added constants IncludeErrorsInReport and 
'			 IncludeWarningsInReport to allow user to specify 
'			 what to include in email.
'--------------------------------------------------------------
'    Author: Lane Beneke - Southern Piping Company
'   Version: 2015.01.08 - Version 1.4
' Changelog: Found that my log-file-finding changes in 1.3 were
'			 incomplete. FFS may add any one of several things
'			 to the name of the log file including " (Error)"
'			 and " (Stopped)". So, I am now searching for log
'			 files regardless of what is appended to the log 
'			 file name after the date.
'--------------------------------------------------------------
'    Author: Lane Beneke - Southern Piping Company
'   Version: 2015.02.02 - Version 1.5
' Changelog: The log may also contain "Serious Error" messages.
'			 Adjusted detection to include these.
'--------------------------------------------------------------
'    Author: Lane Beneke - SPC Mechanical Corporation
'   Version: 2015.04.03 - Version 1.6
' Changelog: Turns out the log file name may not include the 
'			 date at all. Don't know what circumstances cause 
'			 this, but it bit me when I upgraded to version 6.14.
'			 Rewrote the GetLogFile function to look for a file
'			 in the log file folder with a filesystem Date 
'			 Created timestamp equal to FreeFileSync.exe's 
'			 execution time +/- one second.
'--------------------------------------------------------------
'    Author: Lane Beneke - SPC Mechanical Corporation
'   Version: 2016.02.03 - Version 1.7
' Changelog: Added an option to include the name of the host
'			 server in the emailed report. In my case, I have
'			 several jobs running on multiple servers.
'			 Knowledge of which server reported is necessary.
'			 See the 'IncludeServerNameInReport' option.
'			 Also fixed bug for failure to detect no log file
'			 configured if <LogFileFolder> exists but Limit=0.
'			 Also fixed a bug concerning the creation time of
'			 the log file. FreeFileSync previously created the
'			 log file at execution time. But now it isn't 
'			 created until completion time. So, I now match
'			 either-or.
'--------------------------------------------------------------
'    Author: Lane Beneke - SPC Mechanical Corporation
'   Version: 2016.03.17 - Version 1.8
' Changelog: I'm still having occasions where the log file is
'			 not located. Turns out there can be a significant
'			 delay between when the log file is written and
'			 when the program terminates. So, now I'm looking
'			 for a creation time anywhere between program 
'			 execution and program termination.
'--------------------------------------------------------------
'    Author: Lane Beneke - SPC Mechanical Corporation
'   Version: 2016.04.06 - Version 1.9
' Changelog: Trouble with emails not delivering lately. Added
'			 code to detect email send failure, and retry 
'			 MaxEmailSendAttempts times.
'--------------------------------------------------------------
'    Author: Lane Beneke - SPC Mechanical Corporation
'   Version: 2016.04.07 - Version 1.10
' Changelog: Bug fix: A math error (using CInt() where I should
'			 have used Fix()) was causing the script to end 
'			 prematurely in some cases. This may have also 
'			 caused inaccurate reporting of elapsed times.  
'			 While at it, I added user requested variables for 
'			 smtp authentication.
'--------------------------------------------------------------
'    Author: Stefan Mössner
'   Version: 2018.08.23 - Version 1.11
' Changelog: Bug fix: There is a change in the FFS batch files
'			 regarding the tags of the log folder configuration.
'			 Bug fix: Changed the behavior of checking the log
'			 file and added language based search strings for
'			 reading the the log file and finding the errors in
'			 the log file.
'--------------------------------------------------------------
'    Author: Stefan Mössner
'   Version: 2018.09.08 - Version 1.12
' Changelog: Bug fix: Sometimes the script checked the wrong log
'			 file. This is possible if there is more than one
'			 job running at the same time.
'--------------------------------------------------------------
'    Author: Stefan Mössner
'   Version: 2018.10.20 - Version 1.13
' Changelog: Added an option to define the path to another
'			 global settings file.
'--------------------------------------------------------------
'    Author: Stefan Mössner
'   Version: 2018.11.19 - Version 1.14
' Changelog: Added option to activate SSL for the SMTP
'			 connection.
'			 Bug fix: Added an exception handling when there's
'			 no other global settings file defined.
'--------------------------------------------------------------
'    Author: Stefan Mössner
'   Version: 2019.02.26 - Version 1.15
' Changelog: Bug fix: Parse command line error when there's
'			 a global settings file defined.
'--------------------------------------------------------------
'    Author: Stefan Mössner
'   Version: 2020.05.05 - Version 1.16
' Changelog: Bug fix: In some cases the log file can't be
'			 retrieved.
'--------------------------------------------------------------
'    Author: Stefan Mössner
'   Version: 2021.02.14 - Version 1.17
' Changelog: Bug fix: Corrected error handling for sending mail
'--------------------------------------------------------------

'--------------------------------------------------------------
' YOU MUST CHANGE THE FOLLOWING VALUES AS APPROPRIATE
Const HideConsole = True
'  LEAVE ExeFile BLANK TO USE CURRENT WORKING DIRECTORY
'  OTHERWISE SET TO FULL PATH OF FreeFileSync.exe
Const ExeFile = ""
'  SET TO PATH OF [somebatchfile].ffs_batch
'  IF BLANK AND NO COMMAND LINE ARGUMENT, THEN SCRIPT EXITS
Const BatchFile = ""
'  LEAVE GlobalSettingsFile BLANK TO USE STANDARD LOCATION OF
'  GLOBAL SETTINGS FILE OTHERWISE SET TO FULL PATH OF
'  GlobalSettings.xml OR [somesettingsfile].xml
Const GlobalSettingsFile = ""
'  "BatchName" IN MSGSUBJECT IS REPLACED WITH BATCH FILE 
'  NAME LESS PATH AND EXTENSION
Const MsgSubject = "FreeFileSync results for batch BatchName"
Const MsgFrom = "FreeFileSync@Do.Not.Reply"
Const MsgTo = "recipient@yourdomain.com"
Const SMTPServer = "yourserver.yourdomain.tld"
'  SMTPAuth 0=off, 1=clear text, 2=NTLM.  IF YOU SET THIS 
'  TO 1, THEN YOU MUST ALSO SET THE SMTPUSERNAME AND 
'  SMTPPASSWORD FIELDS.
Const SMTPAuth = 0
Const SMTPPort = 25
Const SMTPUsername = "your.smtp.username"
Const SMTPPassword = "your.smtp.password"
'  SET SMTPSsl=True FOR ACTIVATING SSL ENCRYPTION OF THE SMTP
'  CONNECTION, SMTPSsl=False FOR A DECRYPTED SMTP CONNECTION
Const SMTPSsl = False
'  THE SCRIPT WILL ATTEMPT TO SEND THE MESSAGE MaxEmailSendAttempts
'  TIMES BEFORE GIVING UP.  IF THE MESSAGE FAILS TO SEND, THE
'  SCRIPT WILL SET THE DOS ERRORLEVEL TO 1 UPON EXIT.
Const MaxEmailSendAttempts = 10
Const SleepSecondsBeforeRetryingEmailSend = 301
'  DoDebug CAUSES DIAGNOSTIC OUTPUT TO BE WRITTEN TO THE
'  CONSOLE.  NOTE THAT WSCRIPT.EXE USES DIALOG BOXES FOR
'  OUTPUT. SO USE CSCRIPT.EXE WHEN DODEBUG IS TRUE.
Const DoDebug = False
'  IF DODEBUG IS TRUE, AND THE SHELL IS EXECUTED FROM A SCHEDULE
'  OR SOME OTHER PROCESS, THEN THE VALUE BELOW WILL DELAY CLOSING
'  OF THE WINDOW SO YOU CAN EXAMINE THE DEBUG OUTPUT.
Const SleepSecondsBeforeClosingShell = 15
Const IncludeErrorsInReport = True
Const IncludeWarningsInReport = True
Const IncludeRuntimeStringInReport = True
Const IncludeRuntimeNumbersInReport = False
Const IncludeServerNameInReport = True
Const IncludeServerNameInSubject = False
'  LOG FILE SEARCH STRINGS, LANGUAGE BASED
'  PLEASE SELECT THE CORRESPONDING STRINGS
'  GERMAN
'Const sLogFileError = "]  Fehler:"
'Const sLogFileWarning = "]  Warnung:"
'Const sLogFileSeriousError = "]  Schwerer Fehler:"
'  ENGLISH
Const sLogFileError = "]  Error:"
Const sLogFileWarning = "]  Warning:"
Const sLogFileSeriousError = "]  Serious Error:"
'--------------------------------------------------------------

'--------------------------------------------------------------
' CHANGE NOTHING FROM THIS POINT FORWARD
Dim bHideConsole, sExeFile, sBatchFile, sBatchName, sGlobalSettingsFile, dtExecutionTime, dtCompletionTime
Dim oMsg, fso, sLogFile, Args, i, j, ArgTemp, ArgLen, ArgFound, ArgErrors
Set oMsg = CreateObject("CDO.Message")
Set fso = CreateObject("Scripting.FileSystemObject")

bHideConsole = HideConsole
sExeFile = ExeFile
sBatchFile = BatchFile
sGlobalSettingsFile = GlobalSettingsFile
oMsg.Subject = MsgSubject
oMsg.From = MsgFrom
oMsg.To = MsgTo
oMsg.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/smtpserver") = SMTPServer
oMsg.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/smtpauthenticate") = SMTPAuth
oMsg.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/smtpserverport") = SMTPPort
oMsg.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/sendusing") = 2 'SendUsingPort
oMsg.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/sendusername") = SMTPUsername
oMsg.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/sendpassword") = SMTPPassword
oMsg.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/smtpusessl") = SMTPSsl
Const sDashedLine = "--------------------------------------------------------------"
Const sErrLogNotFound = "Unable to locate Log file for processing."
Const sErrLogNotCfgrd = "No log file is configured for this batch."
' THESE VALUES MATCH THE EXIT CODES FOR THE FreeFileSync.exe PROGRAM
Dim ExitCodeArray(3)
ExitCodeArray(0) = "Synchronization completed successfully"
ExitCodeArray(1) = "Synchronization completed with warnings"
ExitCodeArray(2) = "Synchronization completed with errors"
ExitCodeArray(3) = "Synchronization was aborted"

' PARSE THE COMMAND LINE
Dim ArgArray(12,1)
ArgArray(0,0) = "HideConsole"
ArgArray(0,1) = "bHideConsole"
ArgArray(1,0) = "ExeFile"
ArgArray(1,1) = "sExeFile"
ArgArray(2,0) = "BatchFile"
ArgArray(2,1) = "sBatchFile"
ArgArray(3,0) = "GlobalSettingsFile"
ArgArray(3,1) = "sGlobalSettingsFile"
ArgArray(4,0) = "MsgSubject"
ArgArray(4,1) = "oMsg.Subject"
ArgArray(5,0) = "MsgFrom"
ArgArray(5,1) = "oMsg.From"
ArgArray(6,0) = "MsgTo"
ArgArray(6,1) = "oMsg.To"
ArgArray(7,0) = "SMTPServer"
ArgArray(7,1) = "oMsg.Configuration.Fields.Item(""http://schemas.microsoft.com/cdo/configuration/smtpserver"")"
ArgArray(8,0) = "SMTPAuth"
ArgArray(8,1) = "oMsg.Configuration.Fields.Item(""http://schemas.microsoft.com/cdo/configuration/smtpauthenticate"")"
ArgArray(9,0) = "SMTPPort"
ArgArray(9,1) = "oMsg.Configuration.Fields.Item(""http://schemas.microsoft.com/cdo/configuration/smtpserverport"")"
ArgArray(10,0) = "SMTPUsername"
ArgArray(10,1) = "oMsg.Configuration.Fields.Item(""http://schemas.microsoft.com/cdo/configuration/sendusername"")"
ArgArray(11,0) = "SMTPPassword"
ArgArray(11,1) = "oMsg.Configuration.Fields.Item(""http://schemas.microsoft.com/cdo/configuration/sendpassword"")"
ArgArray(12,0) = "SMTPSsl"
ArgArray(12,1) = "oMsg.Configuration.Fields.Item(""http://schemas.microsoft.com/cdo/configuration/smtpusessl"")"

Set Args = WScript.Arguments
ArgErrors = ""
For i = 0 To Args.Count - 1
	ArgFound = False
	For j = 0 To UBound(ArgArray,1)
		ArgTemp = ArgArray(j,0)
		ArgLen = Len(ArgTemp)
		If UCase(ArgTemp) = Left(UCase(Args.Item(i)),ArgLen) Then 'FOUND OUR ARGUMENT
			ArgFound = True
			If DoDebug Then WScript.Echo "Argument " & Args.Item(i) & " matches " & ArgArray(j,0)
			If Len(Args.Item(i)) > ArgLen And Mid(Args.Item(i),ArgLen+1,1) = "=" Then
				Execute( ArgArray(j,1) & " = " & "Mid(Args.Item(i),ArgLen+2)" )
				If DoDebug Then WScript.Echo "Argument processed: " & ArgArray(j,1) & " = " & Mid(Args.Item(i),ArgLen+2)
			ElseIf Len(Args.Item(i)) = ArgLen Then
				i = i + 1
				If Args.Item(i) = "=" Then i = i + 1
				Execute( ArgArray(j,1) & " = " & "Args.Item(i)" )
				If DoDebug Then WScript.Echo "Argument processed: " & ArgArray(j,1) & " = " & Args.Item(i)
			End If
		End If
	Next
	If Not ArgFound Then ArgErrors = ArgErrors & vbCrLf & "Error: Invalid Argument: " & Args.Item(i)
Next
If ArgErrors <> "" Then 
	WScript.Echo "Unable to continue due to command line errors..."
	WScript.Echo ArgErrors
	WScript.Quit
End If

'--------------------------------------------------------------
'					  BEGIN MAIN PROGRAM
'--------------------------------------------------------------
If sExeFile = "" Then sExeFile = ".\FreeFileSync.exe"
If Not fso.FileExists(sExeFile) Then
  WScript.Echo "Error: Cannot find executable file " & sExeFile
  WScript.Quit
End If
If DoDebug Then
	If sGlobalSettingsFile <> "" Then
		WScript.Echo "Executing program: """ & sExeFile & """ """ & sBatchFile & """ """ & sGlobalSettingsFile & """"
	Else
		WScript.Echo "Executing program: """ & sExeFile & """ """ & sBatchFile & """"
	End If
End If
Dim WshShell, iExitCode
Set WshShell = WScript.CreateObject("WScript.Shell")
dtExecutionTime = Now() 'MUST OCCUR IMMEDIATELY BEFORE PROGRAM EXECUTION
If sGlobalSettingsFile <> "" Then
	iExitCode = WshShell.Run( """" & sExeFile & """ """ & sBatchFile & """ """ & sGlobalSettingsFile & """", iif(bHideConsole,0,1), True )
Else
	iExitCode = WshShell.Run( """" & sExeFile & """ """ & sBatchFile & """", iif(bHideConsole,0,1), True )
End If
dtCompletionTime = Now() 'MUST OCCUR IMMEDIATELY AFTER PROGRAM COMPLETION
If DoDebug Then 
	WScript.Echo "Program execution start time was " & dtExecutionTime
	WScript.Echo "Program execution finish time was " & dtCompletionTime
	WScript.Echo "Program execution completed with exitcode: " & iExitCode & "-->" & ExitCodeArray(iExitCode)
End If

' GET BATCH NAME
	sBatchName = Mid(sBatchFile,InStrRev(sBatchFile,"\")+1)
	sBatchName = Left(sBatchName,InStrRev(sBatchName,".")-1)
	If DoDebug Then WScript.Echo "BatchName = " & sBatchName

' ADD SERVER NAME AND BATCH NAME TO BODY OF EMAIL MESSAGE
If IncludeServerNameInReport Then oMsg.HTMLBody = "FreeFileSync batch " & sBatchName & " running on " & WshShell.ExpandEnvironmentStrings( "%COMPUTERNAME%" ) & "<br>"

' ADD EXIT CODE DESCRIPTION TO EMAIL MESSAGE
oMsg.HTMLBody = oMsg.HTMLBody & ExitCodeArray(iExitCode) & "<br><br>"

' ADD RUNTIME TO EMAIL MESSAGE
If IncludeRuntimeStringInReport Or IncludeRuntimeNumbersInReport Then
  Dim strElapsed, strElapsedNum, Elapsed, TimeArray
  strElapsed = ""
  strElapsedNum = ""
  Elapsed = DateDiff("s", dtExecutionTime, dtCompletionTime)
  If DoDebug Then WScript.Echo "Program elapsed seconds = " & Elapsed
  TimeArray = Array("Week",604800,"Day",86400,"Hour",3600,"Minute",60,"Second",1)
  For i = 0 To 9 Step 2
    j = Fix(Elapsed / TimeArray(i+1))
    strElapsedNum = strElapsedNum & Lpad(j,"0",2) & ":"
    If j >= 1 Then strElapsed = strElapsed & j & " " & TimeArray(i) & iif(j>1,"s "," ")
    Elapsed = Elapsed - (j * TimeArray(i+1))
  Next
  i = Len(strElapsedNum)
  strElapsedNum = Mid(strElapsedNum,1,i-10) & " " & Mid(strElapsedNum,i-8,8)
  If strElapsed = "" Then strElapsed = "0 seconds "
  If DoDebug Then 
    WScript.Echo "Elapsed Time String = " & strElapsed
    WScript.Echo "Elapsed Numb String = " & strElapsedNum
  End If 
  If IncludeRuntimeStringInReport Then oMsg.HTMLBody = oMsg.HTMLBody & "Duration: " & strElapsed & "<br><br>"
  If IncludeRuntimeNumbersInReport Then oMsg.HTMLBody = oMsg.HTMLBody & "Duration: " & strElapsedNum & "<br><br>"
End If

' RETRIEVE LOG FILE FOLDER FROM ffs_batch FILE
sLogFile = GetLogFile

' CHECK LOG FILE
Select Case sLogFile
	Case "None"
		If DoDebug Then WScript.Echo sErrLogNotCfgrd
		oMsg.HTMLBody = oMsg.HTMLBody & "<br><br>" & sErrLogNotCfgrd
	Case ""
		If DoDebug Then WScript.Echo sErrLogNotFound
		oMsg.HTMLBody = oMsg.HTMLBody & "<br><br>" & sErrLogNotFound
	Case Else
		oMsg.HTMLBody = oMsg.HTMLBody & "<br><br>" & "Log File: " & sLogFile
		
		' IF WE DIDN'T COMPLETE SUCCESSFULLY, THEN SCAN FOR ERRORS AND WARNINGS
		If iExitCode <> 0 Then
			Dim objFS, objFil, sLine, DoRead
			oMsg.HTMLBody = oMsg.HTMLBody & "<br><br>" & "Error(s) and/or Warning(s)" & "<br>" & "____________________________"
			If DoDebug Then WScript.Echo "Scanning Log File"
			Set objFS = CreateObject("Scripting.FileSystemObject")
			Set objFil = objFS.OpenTextFile(sLogFile, 1) ' OPEN LOG FILE FOR READING
			DoRead = True
			Do Until objFil.AtEndOfStream
				If DoRead Then sLine = objFil.ReadLine
				DoRead = True
				If DoDebug Then WScript.Echo "Readline1 = " & sLine
				If InStr(sLine, sLogFileError       ) > 0 _
				Or InStr(sLine, sLogFileWarning     ) > 0 _
				Or InStr(sLine, sLogFileSeriousError) > 0 Then
					If ( InStr(sLine, sLogFileError       ) > 0 And IncludeErrorsInReport   ) _
					Or ( InStr(sLine, sLogFileWarning     ) > 0 And IncludeWarningsInReport ) _
					Or ( InStr(sLine, sLogFileSeriousError) > 0 And IncludeErrorsInReport   ) Then
							oMsg.HTMLBody = oMsg.HTMLBody & "<br><br>" & sLine
					End If
					If Not objFil.AtEndOfStream Then
						sLine = objFil.ReadLine
						If DoDebug Then WScript.Echo "Readline2 = " & sLine
						Do Until objFil.AtEndOfStream Or Left(sLine,1) = "["
							oMsg.HTMLBody = oMsg.HTMLBody & "<br>" & sLine
							sLine = objFil.ReadLine
							If DoDebug Then WScript.Echo "Readline3 = " & sLine
						Loop
						DoRead = False
					End If
				End If
			Loop
			objFil.Close
		End If
End Select

' SEND THE EMAIL, RETRY ON FAILURE
' ADD SERVER NAME AND BATCH NAME TO BODY OF EMAIL MESSAGE
oMsg.Subject = Replace(oMsg.Subject, "BatchName", sBatchName)
If IncludeServerNameInSubject Then oMsg.Subject = oMsg.Subject & " on " & WshShell.ExpandEnvironmentStrings( "%COMPUTERNAME%" )
oMsg.Configuration.Fields.Update

Dim LastSendError, SendAttemptCount
SendAttemptCount = 0
Do
	SendAttemptCount = SendAttemptCount + 1
	If DoDebug Then WScript.Echo "Attempting Message Send"
	On Error Resume Next
	oMsg.Send
	LastSendError = Err.Number
	Err.Clear
	On Error Goto 0
	If LastSendError = 0 Then
		If DoDebug Then
			WScript.Echo vbCrLf & sDashedLine
			WScript.Echo "Subject: " & oMsg.Subject
			WScript.Echo "   From: " & oMsg.From
			WScript.Echo "     To: " & oMsg.To
			WScript.Echo sDashedLine
			WScript.Echo Replace(oMsg.HTMLBody, "<br>", vbCrLf)
			WScript.Echo sDashedLine
		End If
	Else ' MESSSAGE FAILED TO SEND
		If DoDebug Then WScript.Echo "Email send failed, sleeping " _
		  & SleepSecondsBeforeRetryingEmailSend & " seconds before retry."
		' SLEEP BEFORE ATTEMPTING AGAIN
		WScript.Sleep SleepSecondsBeforeRetryingEmailSend * 1000
	End If
Loop While LastSendError <> 0 And SendAttemptCount < MaxEmailSendAttempts

' IF DEBUGGING SLEEP FOR VIEWING BEFORE WINDOW CLOSES.	
If DoDebug Then
	WScript.Echo "Sleeping " & SleepSecondsBeforeClosingShell & " seconds before exiting."
	WScript.Sleep SleepSecondsBeforeClosingShell * 1000
End If
If LastSendError <> 0 Then WScript.Quit(1)

'--------------------------------------------------------------
'		  END MAIN PROGRAM - BEGIN FUNCTIONS AND SUBS
'--------------------------------------------------------------
Function GetLogFile
	Dim objFile, sLine, x, sLogFolder, colFiles, sLogFileName, dtSavedExecutionTime
	Set objFile = fso.OpenTextFile(sBatchFile, 1) ' OPEN BATCH FILE FOR READING

	' RETRIEVE THE LOG FILE FOLDER FROM THE BATCH FILE
	sLine = ""
	Do Until objFile.AtEndOfStream Or sLine <> ""
		sLine = objFile.ReadLine
		If InStr( sLine, "LogFolder" ) Then ' FIND LINE CONTAINING LOG FILE FOLDER
			' IF NUMBER OF LOG FILES LIMIT IS SET TO 0, THEN NO LOG FILE WILL BE GENERATED
			If InStr( sLine, "Limit=""0""" ) Then
				GetLogFile="None"
				Exit Function
			End If
			' GET DATA BETWEEN FIRST GREATER THAN SIGN AND LAST LESS THAN SIGN
			x = InStr( sLine, ">" )+1
			sLogFolder = Mid(sLine, x, InStr(x, sLine, "<" ) - x )
		Else
			sLine = ""
		End If
	Loop
	objFile.Close
	Set objFile = Nothing
	If DoDebug Then WScript.Echo "Log File Folder = " & sLogFolder

	' LOOP THROUGH LOG FILES LOOKING FOR CREATED AT OUR START TIME
	If sLine <> "" Then
		Dim f, f1, fc, sJobName
		Set f = fso.GetFolder(sLogFolder)
		Set fc = f.Files
		' GET JOB NAME
		sJobName = sBatchName
		If DoDebug Then WScript.Echo "Job Name = " & sJobName
		For Each f1 in fc ' FOR EACH FILE IN THE LOGS FOLDER
			If InStr( f1.Name, sJobName ) Then ' CHECK IF LOG FILE NAME IS CORRESPONDING TO BATCH NAME
				If DoDebug Then WScript.Echo f1.Name & " was created " & f1.DateCreated
				If ( f1.DateCreated > dtExecutionTime  - (1.0/86400)) And _
			       ( f1.DateCreated < dtCompletionTime + (1.0/86400)) Then
					sLine = f1.Path
				Else
					sLine = ""
				End If
				If sLine <> "" Then Exit For
			End If
		Next
	Else
		sLine = "None"
	End If
	If DoDebug Then WScript.Echo "GetLogFile return value = " & sLine
	GetLogFile = sLine
End Function

Function ZeroPad( number, chars )
	ZeroPad = String(chars - Len(number), "0") & number
End Function

Function iif( test, trueresult, falseresult )
	If test Then iif = trueresult Else iif = falseresult
End Function

Function Lpad (inputStr, padChar, lengthStr) 
    Lpad = string(lengthStr - Len(inputStr),padChar) & inputStr 
End Function