CmdMail: Command line email utility

Category:
C#, VB.NET, ASP.NET
Type:
Applications
Difficulty:
Intermediate

Author: Anonymous

Version Compatibility: Visual Basic.NET

More information:
Application to send email messages from the command line which is handy for network alerts and the like. Copy and paste into a VB.Net console application. Command line arguments are fairly straight forward (run /? to see basics or just look at the code below!). As an example: cmdmail.exe /s "mail.server.com.au" /u "Test Subject" /f "from@somewhere.com.au" /t "to@somewhere.com.au" /y "c:\test\MyHTMLBody.htm" /o 1 /a "c:\test\_TestFile.txt;c:\test2\_TestFile2.txt" The body of the message can be specified in one of two ways - using /d parameter where you write the body as part of the command line or /y where you specify a file to load the body from. This is helpful when sending HTML messages (format /o 1) where the command line can get a bit unwieldy. .Net Technologies used: WebMail (email) File I/O Reflection

Instructions: Copy the declarations and code below and paste directly into your VB project.

Declarations:

Code:Module basCmdMail Const m_csPARAM_HELP As String = "/?" Const m_csPARAM_VERBOSE As String = "/V" Const m_csPARAM_SERVER As String = "/S" Const m_csPARAM_SUBJECT As String = "/U" Const m_csPARAM_BODY As String = "/D" Const m_csPARAM_BODYFROMFILE As String = "/Y" Const m_csPARAM_FORMAT As String = "/O" Const m_csPARAM_FROM As String = "/F" Const m_csPARAM_TO As String = "/T" Const m_csPARAM_CC As String = "/C" Const m_csPARAM_BCC As String = "/B" Const m_csPARAM_ATTACHMENTS As String = "/A" Private Structure tagEmailParams Public fHelp As Boolean Public iVerbose As Integer Public fHaveAttachments As Boolean Public sServer As String Public sSubject As String Public sBody As String Public uFormat As Web.Mail.MailFormat Public sFrom As String Public sTo As String Public sCC As String Public sBCC As String Public saAttachments() As String End Structure ' ' ROUTINE: Main ' ' PURPOSE: Application entry ' ' NOTES: ... ' Sub Main(ByVal saCommandLineArgs() As String) Dim sAttachment As String Dim udtEmailParams As tagEmailParams Console.WriteLine() Try If saCommandLineArgs.Length > 0 Then udtEmailParams = fnExtractEmailParams(saCommandLineArgs) Else udtEmailParams.fHelp = True End If ' if help required If udtEmailParams.fHelp Then Console.WriteLine("CmdMail: Parameters") Console.WriteLine() Console.WriteLine(" Server: " & m_csPARAM_SERVER & " (required)") Console.WriteLine(" From: " & m_csPARAM_FROM & " (required)") Console.WriteLine(" To: " & m_csPARAM_TO & " and/or") Console.WriteLine(" Cc: " & m_csPARAM_CC & " and/or") Console.WriteLine(" Bcc: " & m_csPARAM_BCC) Console.WriteLine(" Subject: " & m_csPARAM_SUBJECT) Console.WriteLine(" Body Text: " & m_csPARAM_BODY & " or") Console.WriteLine(" Body From File: " & m_csPARAM_BODYFROMFILE) Console.WriteLine(" Format (0:Text or 1:HTML): " & m_csPARAM_FORMAT) Console.WriteLine(" Attachments (delimit with ;): " & m_csPARAM_ATTACHMENTS) Console.WriteLine(" Help: " & m_csPARAM_HELP) Console.WriteLine(" Verbose (Level 1 to 4): " & m_csPARAM_VERBOSE) Console.WriteLine() Console.WriteLine("Press ENTER to continue...") Console.Read() GoTo EXIT_ROUTINE End If Catch ex As Exception Console.WriteLine("One or more parameters were not valid: " & ex.Message) GoTo EXIT_ROUTINE End Try ' create the new message... Dim sFilePath As String Dim oMsg As MailMessage = New MailMessage Try With oMsg .From = udtEmailParams.sFrom .To = udtEmailParams.sTo .Cc = udtEmailParams.sCC .Bcc = udtEmailParams.sBCC .Subject = udtEmailParams.sSubject If udtEmailParams.fHaveAttachments Then ' add each attachment For Each sAttachment In udtEmailParams.saAttachments If sAttachment <> "" Then .Attachments.Add(New MailAttachment(sAttachment)) Next End If .BodyFormat = udtEmailParams.uFormat .Body = udtEmailParams.sBody End With ' send the message... SmtpMail.SmtpServer = udtEmailParams.sServer Console.WriteLine("Sending message...") SmtpMail.Send(oMsg) Catch ex As Exception Console.WriteLine("Errors occurred sending the message: " & ex.Message) GoTo EXIT_ROUTINE End Try Console.WriteLine("Message sent!") Console.WriteLine() EXIT_ROUTINE: Exit Sub End Sub ' ' ROUTINE: fnExtractEmailParams ' ' PURPOSE: Extracts parameters from saCmdLineArgs and loads and returns ' them to a tagEmailParams structure. ' ' NOTES: ... ' Private Function fnExtractEmailParams(ByVal saCmdLineArgs() As String) As tagEmailParams Dim iIndex As Integer Dim iUBound As Integer = saCmdLineArgs.Length Dim sMsg As String Dim sFilePath As String Dim sLine As String Dim sr As StreamReader Dim udtEmailParams As tagEmailParams ' check if help is required If iUBound = 0 Then udtEmailParams.fHelp = True GoTo EXIT_ROUTINE Else For iIndex = 0 To iUBound - 1 Step 2 If String.Compare(saCmdLineArgs(iIndex), m_csPARAM_HELP, True) = 0 Then udtEmailParams.fHelp = True GoTo EXIT_ROUTINE ElseIf String.Compare(saCmdLineArgs(iIndex), m_csPARAM_VERBOSE, True) = 0 Then Console.WriteLine("Running as verbose mode..." & vbCrLf) udtEmailParams.iVerbose = CInt(Val(saCmdLineArgs(iIndex + 1))) End If Next End If If iUBound Mod 2 <> 0 Then sMsg = "Invalid parameter count supplied" Throw New ApplicationException(sMsg) End If ' set defaults With udtEmailParams ' set defaults .sServer = "mail" .uFormat = MailFormat.Text For iIndex = 0 To iUBound - 1 Step 2 If String.Compare(saCmdLineArgs(iIndex), m_csPARAM_SERVER, True) = 0 Then .sServer = saCmdLineArgs(iIndex + 1) ElseIf String.Compare(saCmdLineArgs(iIndex), m_csPARAM_SUBJECT, True) = 0 Then .sSubject = saCmdLineArgs(iIndex + 1) ElseIf String.Compare(saCmdLineArgs(iIndex), m_csPARAM_BODY, True) = 0 Then If .sBody = "" Then .sBody = saCmdLineArgs(iIndex + 1) ElseIf String.Compare(saCmdLineArgs(iIndex), m_csPARAM_BODYFROMFILE, True) = 0 Then ' load body from a file (usually an html) sFilePath = fnGetFilePath(saCmdLineArgs(iIndex + 1), .iVerbose) ' If .sBody = "" And sFilePath <> "" Then sr = File.OpenText(sFilePath) ' sLine = sr.ReadLine() ' While Not sLine Is Nothing .sBody = .sBody & sLine & vbNewLine sLine = sr.ReadLine End While ' sr.Close() : sr = Nothing End If ElseIf String.Compare(saCmdLineArgs(iIndex), m_csPARAM_FORMAT, True) = 0 Then .uFormat = CType(Val(saCmdLineArgs(iIndex + 1)), Web.Mail.MailFormat) ElseIf String.Compare(saCmdLineArgs(iIndex), m_csPARAM_FROM, True) = 0 Then .sFrom = saCmdLineArgs(iIndex + 1) ElseIf String.Compare(saCmdLineArgs(iIndex), m_csPARAM_TO, True) = 0 Then .sTo = saCmdLineArgs(iIndex + 1) ElseIf String.Compare(saCmdLineArgs(iIndex), m_csPARAM_CC, True) = 0 Then .sCC = saCmdLineArgs(iIndex + 1) ElseIf String.Compare(saCmdLineArgs(iIndex), m_csPARAM_BCC, True) = 0 Then .sBCC = saCmdLineArgs(iIndex + 1) ElseIf String.Compare(saCmdLineArgs(iIndex), m_csPARAM_ATTACHMENTS, True) = 0 Then ' extract each attachment If InStr(saCmdLineArgs(iIndex + 1), ";") > 0 Then .saAttachments = Split(saCmdLineArgs(iIndex + 1), ";") Else ReDim .saAttachments(0) .saAttachments(0) = saCmdLineArgs(iIndex + 1) End If ' .fHaveAttachments = True End If Next ' check resulting params are valid If .sFrom = "" Or InStr(.sFrom, "/") > 0 Then sMsg = "FROM (" & _ m_csPARAM_FROM & _ ") parameter was not valid: [" & _ .sFrom & "]" Throw New ApplicationException(sMsg) ElseIf .sTo = "" And .sCC = "" And .sBCC = "" _ Or InStr(.sTo, "/") > 0 _ Or InStr(.sCC, "/") > 0 _ Or InStr(.sBCC, "/") > 0 Then sMsg = "No recipient was supplied" Throw New ApplicationException(sMsg) ElseIf .sServer = "" Or InStr(.sFrom, "/") > 0 Then sMsg = "SERVER (" & _ m_csPARAM_SERVER & _ ") parameter was not valid: [" & _ .sServer & "]" Throw New ApplicationException(sMsg) End If ' check each file exists If .fHaveAttachments Then For iIndex = 0 To .saAttachments.Length - 1 .saAttachments(iIndex) = fnGetFilePath(.saAttachments(iIndex), .iVerbose) ' If udtEmailParams.iVerbose > 0 And .saAttachments(iIndex) <> "" Then Console.WriteLine("Attachment [" & CStr(iIndex) & "]: " & .saAttachments(iIndex)) ElseIf udtEmailParams.iVerbose > 0 And .saAttachments(iIndex) = "" Then Console.WriteLine("Attachment [" & CStr(iIndex) & "]: ") End If Next End If End With EXIT_ROUTINE: Return (udtEmailParams) Exit Function End Function ' ' ROUTINE: fnGetFilePath ' ' PURPOSE: Checks the sFileName (attachment file) specified exists. ' ' If found returns full file name and path. If not returns empty string. ' ' NOTES: If the sFileName is not found routine searches exe paths. This is ' mostly to help with debugging. ' Private Function fnGetFilePath(ByVal sFileName As String, ByVal iVerbose As Integer) As String Dim sFilePath As String ' get the exe's filepath Dim sExePath As String = GetExecutingAssembly.Location ' check file exists If InStr(sFileName, ":") > 0 And File.Exists(sFileName) Then sFilePath = sFileName Else ' remove the exe's name leaving the path sExePath = Left$(sExePath, InStrRev(sExePath, "\") - 1) If iVerbose > 0 Then Console.WriteLine("Exe Path (1): " & sExePath) sFilePath = sExePath & "\" & sFileName ' check file exists If Not File.Exists(sFilePath) Then ' if not exists check path (next folder up from exe's "bin" folder) sExePath = Left$(sExePath, InStrRev(sExePath, "\") - 1) If iVerbose > 0 Then Console.WriteLine("Exe Path (2): " & sExePath) sFilePath = sExePath & "\" & sFileName ' no file found If Not File.Exists(sFilePath) Then Console.WriteLine("File does not exist: [" & sFilePath & "]") sFilePath = "" End If End If End If Return sFilePath End Function End Module