How to Send Emails with SMTP in VB.NET
March 3, 2015 Leave a comment
A friend’s office has been using a VB6 script to send Emails for years now. That code needed to be updated and more functionality added. So I took it up and designed a console application to send emails using SMTP in VB.NET.
In this brief tutorial,
- We shall be using my friends office process as a case study
- we shall be using Microsoft Visual Studio as our IDE
- And VB.NET as the programming language.
You can download the project source files here …….. ProjectMol
The case Study
A service is created on the company server to run the project executable. Any time the service runs, the application picks attachment file(s) with a defined file extension, located in a specific folder. The application will then create a mail, attaches the files if they exist, and sends it to a specified email address.
Finally the attachments are copied into an archive folder and the original file is deleted.
Some Features of the Solution
The solution provided in this tutorial has the following features
- All configurations are read from a configuration file so no need to go into code when configurations changes. By this you can add as many recipients, CC, attachment file paths as you want by just specifying them in the configuration file with a semi-colon separated delimiter.
- All status messages are written into a log file. By this a folder is created for every day when the application runs and then within that day, all the logs are appended onto a log file of that particular day
Create a Console application project using Microsoft Visual Studio. Launch Visual Studio, goto File>>New>>Project. Name the Project as ProjectMol.
Configuration file and Class
We will be putting the entire configuration in an application configuration file. Applications can store their user defined configurations in the appSettings block in the application figuration file.
To do this right click the Project in the Solution explorer and then goto Add >> New Item. In the General Category of the file templates, select Application Configuration file template. Name it as App.Config.
This file is basically an XML file that stores the applications general configuration. The App.Config file content is as follows.
<?xml version="1.0" encoding="utf-8" ?> <configuration> <startup> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" /> </startup> <appSettings> <add key="smtpServer" value="smtp.gmail.com"/> <add key="smtpPort" value="587"/> <add key="smtpTimeOut" value="120000"/> <add key="sender" value="sender@gmail.com"/> <add key="senderPassword" value="MPS123mps"/> <add key="recipients" value="recipient@gmail.com.com"/> <add key="cc" value="cc@gmail.com"/> <add key="subject" value="Sending Mail with SMTP"/> <add key="body" value="This mail come from code, thats nice"/> <add key="attachmentDir" value="\\192.168.1.2\codec\out\; \\192.168.1.11\coar\out\"/> </appSettings> </configuration>
In order to have access to the configuration in an App.Config file, we will model an Object Oriented representation of the appSettings block. In this class , we shall define a property for each of the configurations in the appSettings block, and a method that will read the XML file and populate the Object’s Properties with their respective data.
Imports System.Configuration Public Class Config Public Property smtpServer As String Public Property smtpPort As Int32 Public Property smtpTimeOut As Int32 Public Property sender As String Public Property senderPassword As String Public Property recipients As List(Of String) Public Property cc As List(Of String) Public Property subject As String Public Property body As String Public Property attachmentDir As List(Of String) Public Shared Function FromConfigFile() As Config Dim config = New Config Dim settings = ConfigurationManager.AppSettings config.smtpServer = settings("smtpServer") config.smtpPort = settings("smtpPort") config.smtpTimeOut = settings("smtpTimeOut") config.sender = settings("sender") config.senderPassword = settings("senderPassword") config.recipients = New List(Of String) config.recipients.AddRange(config.ExtractEmails(settings("recipients"))) config.cc = New List(Of String) config.cc.AddRange(config.ExtractEmails(settings("cc"))) config.attachmentDir = New List(Of String) config.attachmentDir.AddRange(config.ExtractEmails(settings("attachmentDir"))) Return config End Function Public Function ExtractEmails(ByVal value As String) As List(Of String) Dim v = value.Split(";") Return v.ToList() End Function End Class
The CC and recipients configuration are comma separated, this allow for multiple values. The ExtractEmails Method is used to split them in a List of Values
Writing to Log Files
Since the Application is most like to run on remote servers, we need to write down the application logs, so that we can monitor the application via its logs. The code to do so is at follows
Imports System.Net.Mail Imports System.Security.AccessControl Imports System.ComponentModel Imports System.IO 'Imports System.Web.Mail Module EdiSender Sub Main() WriteToLog(Environment.NewLine) WriteToLog(DateTime.Now.ToString) WriteToLog("Starting ProjectMol EdiSender..........") End Sub Public Function CreateLogStream() As StreamWriter Dim d = DateTime.Now.Date.ToString("yyyMMdd") Dim info = New IO.DirectoryInfo("./logs/" + d) If info.Exists = False Then info.Create() End If Dim file = New IO.FileInfo(info.FullName + "/log.txt") If file.Exists = False Then file.Create() End If Dim stream = IO.File.AppendText(file.FullName) Return stream End Function Public Sub WriteToLog(ByVal message As String) Dim oldOut = Console.Out Using stream = CreateLogStream() Console.SetOut(stream) Console.WriteLine(message) End Using Console.SetOut(oldOut) End Sub End Module
So in the CreateLogStream Method, a folder and a log file is created for a particular date. If the file already exists, the existing one is used hence a new one is not created. The WriteToLog simply uses the file returned by CreateLogStream for application logs.
Finding the attachments
Now we will find all the attachment files. If we do not find any attachments, then we will not send the mail. Please note that the file is found based on the file extension .txt
'some codes before this block Dim attachements As New List(Of String) For Each item In configs.attachmentDir Dim attachment = GetFileInDirectory(item.Trim, ".txt", "n") If Not String.IsNullOrEmpty(attachment) Then attachements.Add(attachment) End If Next For Each item In attachements WriteToLog("Attachment File : " + item) Next If attachements.Count = 0 Then WriteToLog("No attachments were found. Exiting mail sending process") Environment.Exit(0) Return End If
Finally let’s send the mail
We will then create a MailMessage, add all our recipients, add a subject, a body, and attach our attachments. The attachments files are copied into an archive directory and the version of the file in the original folder is deleted.
Using mail As New MailMessage() mail.From = New MailAddress(configs.sender) For Each item In configs.recipients mail.To.Add(item.Trim) Next mail.Subject = configs.subject mail.Body = configs.body For Each item In configs.cc mail.CC.Add(item.Trim) Next mail.IsBodyHtml = True For Each item In attachements mail.Attachments.Add(New Attachment(item)) Next smptClient.Send(mail) WriteToLog("Message sent") End Using
In this tutorial, we have used MailMessage, SmtpClient and DirectoryInfo to achieve our purpose. You can download the whole source files from here, Take time and digest the codes.
Leave comments if you have any question.
Recent Comments