' +----------------------------------------------------------------------------+ ' | Jeffrey M. Hunter | ' | jhunter@idevelopment.info | ' | www.idevelopment.info | ' |----------------------------------------------------------------------------| ' | Copyright (c) 1998-2011 Jeffrey M. Hunter. All rights reserved. | ' |----------------------------------------------------------------------------| ' | FILE : Mail.vbs | ' | CLASS : Miscellaneous Functions | ' | PURPOSE : Demonstrates how to send email using Microsoft Collaboration | ' | Data Objects (CDO). | ' | PARAMETERS : For a list of parameters and descriptions, see the function | ' | showHelpMessageExtended(). | ' | TRACING : Set the WSHTRACE Windows environment variable to the level | ' | (1-n) of tracing you would like to capture. | ' | USAGE : | ' | | ' | cscript Mail.vbs [recipient list] | ' | -from [sender] | ' | -cc [list] | ' | -bcc [list] | ' | -s "Subject" | ' | -b "Message Body" | ' | -file "Text File" | ' | -a "File Attachment" | ' | -smtp smtpserver.domain.com | ' | -? Extended Help Message | ' | //NoLogo | ' | | ' | NOTE : As with any code, ensure to test this script in a development | ' | environment before attempting to run it in production. | ' +----------------------------------------------------------------------------+ Option Explicit ' ----------------------------------------------------------------------------- ' EXPLICIT VARIABLE DECLARATION & STANDARD GLOBALS ' ----------------------------------------------------------------------------- Const g_SCRIPT_VERSION="1.0" Dim g_strScriptPath, g_strScriptName, g_strScriptFolder, g_strScriptNameNoExt Dim g_bytTraceLevel Dim g_objShell Dim strBannerText, i ' ----------------------------------------------------------------------------- ' DECLARATION OF SCRIPT GLOBALS ' ----------------------------------------------------------------------------- Dim strTo, strFrom, strCC, strBCC, strSubject, strTextBody Dim blnHelp Dim strAttachment Dim strSMTPServer Dim arrAttachment() ReDim arrAttachment(0) blnHelp = False ' ----------------------------------------------------------------------------- ' SET STANDARD GLOBALS & CREATE GLOBAL OBJECTS ' ----------------------------------------------------------------------------- g_strScriptPath = WScript.ScriptFullName g_strScriptName = WScript.ScriptName g_strScriptFolder = Left(g_strScriptPath, Len(g_strScriptPath) - Len(g_strScriptName)) i = InStr(g_strScriptName, ".") If i <> 0 Then g_strScriptNameNoExt = Left(g_strScriptName, i - 1) Else g_strScriptNameNoExt = g_strScriptName End If Set g_objShell = CreateObject("WScript.Shell") ' ----------------------------------------------------------------------------- ' SHOW SIGNON BANNER ' ----------------------------------------------------------------------------- strBannerText = VbCrLf strBannerText = strBannerText & g_strScriptName strBannerText = strBannerText & " - Version " & g_SCRIPT_VERSION & VbCrLf strBannerText = strBannerText & "Copyright (c) 1998-2011 Jeffrey M. Hunter. All rights reserved." strBannerText = strBannerText & VbCrLf WScript.Echo strBannerText ' ----------------------------------------------------------------------------- ' SETUP TRACING CONTROL FROM THE "WSHTRACE" WINDOWS ENVIRONMENT VARIABLE ' ----------------------------------------------------------------------------- i = g_objShell.Environment("Process").Item("WSHTRACE") If IsNumeric(i) Then g_bytTraceLevel = CInt(i) WScript.Echo VbCrLf & "DEBUGGING TURNED ON AT LEVEL: " & g_bytTraceLevel & VbCrLf Else g_bytTraceLevel = 0 End If ' ----------------------------------------------------------------------------- ' CALL MAIN FUNCTION ' ----------------------------------------------------------------------------- i = Main ' ----------------------------------------------------------------------------- ' CLEAN UP AND EXIT SCRIPT ' ----------------------------------------------------------------------------- Set g_objShell = Nothing Trace 2, "D: Exit Code = " & i WScript.Quit(i) ' ------------------------------------------------------------------------------ ' --------------------------- < END OF SCRIPT > ------------------------------ ' ------------------------------------------------------------------------------ ' ////////////////////////////////////////////////////////////////////////////// ' | Main ' | ' | Main function used to enclose the primary script logic. ' | ' | Returns ' | Exit code from primary script logic. ' ////////////////////////////////////////////////////////////////////////////// Function Main Trace 1, "> Main" ' -------------------------------------------- ' Set all mail variables to some default value ' -------------------------------------------- strTo = "" strFrom = "MailScript@localhost" strSubject = "Subject" strTextBody = "" strSMTPServer = "" ' ------------------------ ' Set all script arguments ' ------------------------ If Not SetScriptArguments Then ShowHelpMessage Trace 2, "D: Failed with setting script arguments. Returning error." Trace 1, "< Main(1)" Main = 1 Exit Function End If ' --------------------------------------- ' Check to see if the user requested help ' --------------------------------------- If (blnHelp) Then showHelpMessageExtended trace 2, "D: Exiting with script usage message requested by user." trace 1, "< Main(0)" Main = 0 Exit Function End If ' ---------------------------------------- ' Check to see if the user entered a valid ' recipient email address. ' ---------------------------------------- If (strTo = "") Then showHelpMessage WScript.Echo "ERROR: No valid email address." trace 2, "D: No valid email address." trace 1, "< Main(1)" Main = 1 Exit Function End If ' ------------------------------------------------------- ' Check that the local SMTP service is running or ' that the user provided an SMTP server used to send this ' email. If neither, then prompt user with the error and ' exit this script. ' ------------------------------------------------------- If (strSMTPServer = "") Then If Not (serviceCheck("localhost", "SMTPSVC")) Then Dim strErrorMessage strErrorMessage = VbCrLf & _ "ERROR: Could not find the local SMTP service running " & VbCrLf & _ " and no SMTP server was provided as an argument " & VbCrLf & _ " to this script. If you want to use the local " & VbCrLf & _ " SMTP service, ensure that it is installed and " & VbCrLf & _ " running. If not, you will need to specify an " & VbCrLf & _ " external SMTP server using the '-smtp [server]' " & VbCrLf & _ " argument to this script. For more help with " & VbCrLf & _ " script arguments, use:" & VbCrLf & VbCrLf & _ " cscript Mail.vbs -?" WScript.Echo strErrorMessage Trace 2, "D: Exiting with no SMTP error." Trace 1, "< Main(1)" Main = 1 Exit Function End If End If Mail strTo, strFrom, strCC, strBCC, strSubject, strTextBody, arrAttachment, strSMTPServer Main = 0 Trace 1, "< Main(0)" End Function ' ////////////////////////////////////////////////////////////////////////////// ' | mail ' | ' | Used to generate and send an email using either a local or external SMTP ' | server. ' ////////////////////////////////////////////////////////////////////////////// Function Mail(strTo, strFrom, strCC, strBCC, strSubject, strTextBody, arrAttachment, strSMTPServer) Trace 1, "> Mail" Dim objCDOConfiguration, objCDOConfigurationFields, objMessage Dim strMsSchema, i Set objCDOConfiguration = CreateObject("CDO.Configuration") If Not (strSMTPServer = "") Then strMsSchema = "http://schemas.microsoft.com/cdo/configuration/" objCDOConfiguration.Fields.Item(strMsSchema + "sendusing") = 2 objCDOConfiguration.Fields.Item(strMsSchema + "smtpserverport") = 25 objCDOConfiguration.Fields.Item(strMsSchema + "smtpserver") = strSMTPServer objCDOConfiguration.Fields.Item(strMsSchema + "smtpconnectiontimeout") = 60 objCDOConfiguration.Fields.Update() End If Set objMessage = CreateObject("CDO.Message") objMessage.Configuration = objCDOConfiguration objMessage.To = strTo objMessage.From = strFrom objMessage.CC = strCC objMessage.BCC = strBCC objMessage.Subject = strSubject objMessage.TextBody = strTextBody For i = LBound(arrAttachment) To UBound(arrAttachment) - 1 objMessage.AddAttachment(arrAttachment(i)) Next objMessage.Send WScript.Echo WScript.Echo "Successfully sent email." & VbCrLf WScript.Echo "To : " & objMessage.To WScript.Echo "From : " & objMessage.From WScript.Echo "CC : " & objMessage.CC WScript.Echo "BCC : " & objMessage.BCC WScript.Echo "Subject : " & objMessage.Subject WScript.Echo "Body : " & objMessage.TextBody WScript.Echo "SMTP Server : " & strSMTPServer For i = LBound(arrAttachment) To UBound(arrAttachment) - 1 WScript.Echo("Attachment[" & i & "] : " & arrAttachment(i)) Next Trace 1, "< Mail" End Function ' ////////////////////////////////////////////////////////////////////////////// ' | ReadTextFile ' | ' | Read a text file And return the contents. ' ////////////////////////////////////////////////////////////////////////////// Function ReadTextFile(strFileName) Trace 1, "> ReadTextFile" Dim objFSO Dim objTextFile Dim strReadLine strReadLine = "" Set objFSO = CreateObject("Scripting.FileSystemObject") If (objFSO.FileExists(strFileName)) Then Set objTextFile = objFSO.OpenTextFile(strFileName, 1) Do While objTextFile.AtEndOfStream <> True strReadLine = strReadLine & objTextFile.ReadLine() & VbCrLf Loop objTextFile.Close Else strReadLine = "Error reading file: " & strFileName End If Trace 1, "< ReadTextFile" ReadTextFile = strReadLine End Function ' ////////////////////////////////////////////////////////////////////////////// ' | ShowHelpMessage ' | ' | Display help message for this script. ' ////////////////////////////////////////////////////////////////////////////// Sub ShowHelpMessage Trace 1, "> ShowHelpMessage" Dim strMessage strMessage = _ "Usage: cscript " & g_strScriptName & " [recipient list]" & VbCrLf & _ " -from [sender]" & VbCrLf & _ " -cc [list]" & VbCrLf & _ " -bcc [list]" & VbCrLf & _ " -s ""Subject""" & VbCrLf & _ " -b ""Message Body""" & VbCrLf & _ " -file ""Text File""" & VbCrLf & _ " -a ""File Attachment""" & VbCrLf & _ " -smtp smtpserver.domain.com" & VbCrLf & _ " -? Extended Help Message" & VbCrLf & _ " //NoLogo" & VbCrLf & VbCrLf WScript.Echo strMessage Trace 1, "< ShowHelpMessage" End Sub ' ////////////////////////////////////////////////////////////////////////////// ' | showHelpMessageExtended ' | ' | Display extended help message For this script. ' ////////////////////////////////////////////////////////////////////////////// Sub ShowHelpMessageExtended Trace 1, "> ShowHelpMessageExtended" Dim strMessage ShowHelpMessage strMessage = _ " Parameter Descriptions:" & VbCrLf & _ " ---------------------------------------------------------------" & VbCrLf & _ " [list] A list of email addresses delimited by" & VbCrLf & _ " a single comma with no spaces between " & VbCrLf & _ " the comma(s)." & VbCrLf & _ " -from [sender] The sender of the email message using the" & VbCrLf & _ " format: sender@domain.com." & VbCrLf & _ " -cc [list] All carbon copy recipients." & VbCrLf & _ " -bcc [list] All blind carbon copy recipients." & VbCrLf & _ " -s ""Subject"" Subject of the email message, enclosed " & VbCrLf & _ " by double quotes." & VbCrLf & _ " -b ""Body"" The content (or body) of the message, " & VbCrLf & _ " enclosed by double quotes." & VbCrLf & _ " -file [Text File] The name of a text file whose contents will" & VbCrLf & _ " be included as part (or all) of the body." & VbCrLf & _ " This parameter can be used in conjunction " & VbCrLf & _ " with the -b Message Body parameter." & VbCrLf & _ " -a [File Name] Name of a file to be included as an " & VbCrLf & _ " attatchment to the email message. You can" & VbCrLf & _ " include this parameter more than once." & VbCrLf & _ " -smtp [server] Name of an external SMTP server that will" & VbCrLf & _ " be used to send this email message. Used " & VbCrLf & _ " you do not have a local SMTP service" & VbCrLf & _ " running." & VbCrLf & _ " -p Instructs this script to look for piped" & VbCrLf & _ " input from an external program. This is" & VbCrLf & _ " specified with the pipe character |. " & VbCrLf & _ " Note that when piping input to this script," & VbCrLf & _ " the piping must be done to cscript.exe then" & VbCrLf & _ " followed by the script name." & VbCrLf & _ " -? Help screen. (This screen)" & VbCrLf & VbCrLf & _ " Examples:" & VbCrLf & _ " ---------------------------------------------------------------" & VbCrLf & _ " cscript " & g_strScriptName & " jhunter@iDevelopment.info " & VbCrLf & _ " -s ""Message Subject"" " & VbCrLf & _ " -b ""Body of the message..."" " & VbCrLf & _ " -cc ahunter@iDevelopment.info,admin@iDevelopment.info" & VbCrLf & _ " -a ""c:\\web\\images\\image1.jpg"" " & VbCrLf & _ " -a ""c:\\web\\images\\image2.jpg"" " & VbCrLf & _ " -smtp smtp.mydomain.com" & VbCrLf & VbCrLf & _ " type message.txt | cscript " & g_strScriptName & " jhunter@iDevelopment.info -p" & VbCrLf & _ VbCrLf WScript.Echo strMessage Trace 1, "< ShowHelpMessageExtended" End Sub ' ////////////////////////////////////////////////////////////////////////////// ' | Trace ' | ' | Debug script tracing by using the g_bytTraceLevel and WSHTRACE environment ' | variable ' | ' | Parameters ' | bytLevel Trace level. Used to control if trace information will be ' | printed. Only display if <= WSHTRACE ' | nLevel Tracing Information ' | ------ ---------------------------------------------------- ' | 1 Includes sub routine "enter" and "exit" data. Also ' | includes sub routine arguments (A[n]:) as well as ' | critical errors (E:). ' | 2 Includes all nLevel 1 plus debugging and warning ' | tracing information. ' | strText Text to display ' | ' | Notes ' | The following tokens may be used at the beginning of each Trace ' | line to make reading trace information easier to read: ' | ' | > "Sub Routine" Use at the begining of a sub routine to indicate ' | entering the sub routine code. ' | < "Sub Routine" Use when exiting sub routine code. ' | A[n]: Used when tracing sub routine arguments. ' | D: Used to print debugging text to the trace file. ' | V: Used to print out a variable name to the trace file. ' | W: Used to indicate a warning message to the trace file. ' | E: Used to indicate a critical error to the trace file. ' ////////////////////////////////////////////////////////////////////////////// Sub Trace (bytLevel, strText) If (g_bytTraceLevel >= bytLevel) Then WScript.Echo strText End If End Sub ' ////////////////////////////////////////////////////////////////////////////// ' | setScriptArguments ' | ' | Sets all required parameters used for mailing. All parameters are passed ' | by reference. ' ////////////////////////////////////////////////////////////////////////////// Function SetScriptArguments Trace 1, "> SetScriptArguments" Dim i, strArgValue Dim colArgs Dim objRegExp Set colArgs = WScript.Arguments Set objRegExp = CreateObject("VBScript.RegExp") If (colArgs.Length = 0) Then Trace 2, "D: User didn't enter any parameters." Trace 1, "< SetScriptArguments" SetScriptArguments = False Exit Function End If For i = 0 to colArgs.Length - 1 strArgValue = LCase(colArgs.Item(i)) Trace 2, "D: Looking at ARG[" & i & "] = " & strArgValue ' -------------------------- ' Is this a named parameter? ' -------------------------- objRegExp.Pattern = "^-" If (objRegExp.Test(strArgValue)) Then ' ---------------------- ' Did user ask for help? ' ---------------------- If ((strArgValue = "-help") Or (strArgValue = "-?")) Then blnHelp = True Trace 2, "D: User requested help." Trace 1, "< setScriptArguments" SetScriptArguments = True Exit Function End If ' --------------- ' Argument: FROM ' --------------- If (strArgValue = "-from") Then If (i+1 > colArgs.length-1) Then Trace 2, "D: Exiting with error in -from." Trace 1, "< setScriptArguments" SetScriptArguments = False Exit Function End If strFrom = colArgs.Item(i+1) i = i + 1 End If ' ------------- ' Argument: CC ' ------------- If (strArgValue = "-cc") Then If (i+1 > colArgs.length-1) Then Trace 2, "D: Exiting with error in -cc." Trace 1, "< setScriptArguments" SetScriptArguments = False Exit Function End If strCC = colArgs.Item(i+1) i = i + 1 End If ' -------------- ' Argument: BCC ' -------------- If (strArgValue = "-bcc") Then If (i+1 > colArgs.length-1) Then Trace 2, "D: Exiting with error in -bcc." Trace 1, "< setScriptArguments" SetScriptArguments = False Exit Function End If strBCC = colArgs.Item(i+1) i = i + 1 End If ' ------------ ' Argument: S ' ------------ If (strArgValue = "-s") Then If (i+1 > colArgs.length-1) Then trace 2, "D: Exiting with error in -s." trace 1, "< setScriptArguments" SetScriptArguments = False Exit Function End If strSubject = colArgs.Item(i+1) i = i + 1 End If ' ------------ ' Argument: B ' ------------ If (strArgValue = "-b") Then If (i+1 > colArgs.length-1) Then trace 2, "D: Exiting with error in -b." trace 1, "< setScriptArguments" SetScriptArguments = False Exit Function End If strTextBody = strTextBody + colArgs.Item(i+1) i = i + 1 End If ' ------------ ' Argument: A ' ------------ If (strArgValue = "-a") Then If (i+1 > colArgs.length-1) Then Trace 2, "D: Exiting with error in -a." Trace 1, "< setScriptArguments" SetScriptArguments = False Exit Function End If ReDim Preserve arrAttachment(UBound(arrAttachment) + 1) arrAttachment(UBound(arrAttachment) - 1) = colArgs.Item(i+1) i = i + 1 End If ' --------------- ' Argument: SMTP ' --------------- If (strArgValue = "-smtp") Then If (i+1 > colArgs.length-1) Then Trace 2, "D: Exiting with error in -smtp." Trace 1, "< setScriptArguments" SetScriptArguments = False Exit Function End If strSMTPServer=colArgs.Item(i+1) i = i + 1 End If ' --------------- ' Argument: FILE ' --------------- If (strArgValue = "-file") Then If (i+1 > colArgs.length-1) Then trace 2, "D: Exiting with error in -file." trace 1, "< setScriptArguments" SetScriptArguments = False Exit Function End If strTextBody = strTextBody & readTextFile(colArgs.Item(i+1)) i = i + 1 End If ' ------------ ' Argument: P ' ------------ If (strArgValue = "-p") Then Do While (WScript.StdIn.AtEndOfStream) <> True strTextBody = strTextBody & WScript.StdIn.ReadAll() Loop End If Else objRegExp.Pattern = "@" If (objRegExp.Test(strArgValue)) Then strTo = strArgValue Else Trace 2, "D: This is not an email address or an argument." Trace 2, "D: Skipping this argument value." End If End If Next Trace 1, "< SetScriptArguments" SetScriptArguments = True End Function ' ////////////////////////////////////////////////////////////////////////////// ' | ServiceCheck ' | ' | Checks if the local SMTP service is installed and running using WMI. ' ////////////////////////////////////////////////////////////////////////////// Function ServiceCheck(strMachineName, strServiceName) Trace 1, "> ServiceCheck" Dim strWMI Dim objServiceName strWMI = "WinMgmts://" & strMachineName & "/root/cimv2:Win32_Service='" & strServiceName & "'" Trace 2, "D: Looking at: " & strWMI On Error Resume Next Set objServiceName = GetObject(strWMI) Trace 2, "D: Service Status: " & objServiceName.State If (Err > 1) Then Trace 2, "D: Service is not installed." ServiceCheck = False Exit Function Else Trace 2, "D: Service is installed. Continuing ..." End If If (objServiceName.State = "Running") Then trace 1, "D: SMTP service is running. Returning true." trace 1, "< ServiceCheck" ServiceCheck = True Exit Function End If Trace 1, "D: SMTP service is not running. Returning false." Trace 1, "< ServiceCheck" ServiceCheck = False End Function