How to Send Emails with SMTP in VB.NET


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, &quot;.txt&quot;, &quot;n&quot;)

If Not String.IsNullOrEmpty(attachment) Then
attachements.Add(attachment)

End If

Next

For Each item In attachements

WriteToLog(&quot;Attachment File : &quot; + item)

Next

If attachements.Count = 0 Then

WriteToLog(&quot;No attachments were found. Exiting mail sending process&quot;)

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(&quot;Message sent&quot;)

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.

PLUG AND PLAY REPORTS TOO [Part 1] The concepts and Tools


PLUG AND PLAY REPORTS TOO

PLUG AND PLAY REPORTS TOO

In this tutorial, we shall be going how you can create pluggable RDLC/RDL reports.

We shall be.

You can download the full source code here…  PLUG AND PLAY REPORTS TOO SOURCE

When you have several deployed enterprise applications in the wild and several reports are designed for different applications per week, you can choose to

  1. Design the report, add it in code and rebuild application. Go there the next morning and update the application … at least that what we used to do.
  2. Design a plug and play report engine

The second option, as it’s more efficient. I get to design the report, email it to the application manager, they plug it in, you have your peace and the world is a better place again.

RDL/RDLC

RDL files are created by the SQL Server 2005 version of Report Designer. RDLC files are created by the Visual Studio 2005 version of Report Designer.

RDL and RDLC formats have the same XML schema. However, in RDLC files, some values (such as query text) are allowed to be empty. I shall be using Microsoft SQL Server Business Intelligence Development Studio in creating the RDL files.

LINQPad

LINQPad is a free software utility for Microsoft .NET to interactively query SQL databases and other data sources such as OData or WCF Data Services using LINQ. LINQPad supports the following LINQ dialects:

  • LINQ to Objects
  • LINQ to SQL
  • Entity Framework
  • LINQ to XML

It also supports writing queries in SQL as well.

Aside being useful for writing queries,LINQPad can be used to interactively write C# code and quickly see it in action outside visual studio

Now lets get started.  Come along , lets go to PLUG AND PLAY REPORTS TOO [Part 2] Designing an RDL Report