Email Package

Introduction

The ability to send email from a .NET program has been around for about as long as .NET itself has been around. The abstractions in the System.Net.Mail namespace do a great job, but, they could be better. For instance, SmtpClient does a great job of sending email via the SMTP protocol but the class doesn’t allow for any other sort of email technique. That makes sense, considering SMTP is the accepted standard for sending emails and, honestly, it would be a little odd if the SmtpClient class sent emails any other way …

Still, there are are other ways to send emails and it would be nice if there was better support for switching between various options without having to refactor code each time. I thought about the problem and realized a thin API crafted on top of my existing Builder library might work nicely, so, I wrote and released my CG.Email NUGET package.

This article lays out the design of that package, including an add-on provider for SMTP operations.

 

Architecture

The package is constructed on top of the CG.Builder, CG.Builder.Strategy and CG.Builder.Policy NUGET packages. I have written about those packages before so feel free to look back, if you need to.

Like most of my other NUGET packages, this one is designed to be very lightweight and to use providers to supply plug-in behaviour(s) at runtime. This way, the architecture stays flexible without forcing anyone to pay for things they aren’t actively using.

The architecture starts with the IEmail interface, which is shown here:

The interface is built on the IBuilderProduct interface, which makes sense, since we are leveraging the Builder in the CG.Builder NUGET package. The interface contain a synchronous and asynchronous send method, which is used to send emails. Later, we’ll use some extension methods to supply some useful variations of these two methods.

 

A stripped down version of the EmailProduct class itself is show here:

There a bit of code in this class so let’s look at what’s going on. The class derives from BuilderProductBase, since it leverages the Builder library. The class also contains two properties: Policy and Strategies. Policy contains an optional policy that is injected into the Product through the builder. Strategies contains a collection of Strategy objects that are also injected by the builder.

The Send and SendAsync methods both do the same thing, one just works synchronously while the other works asynchronously. Because of that, I’ll describe the workings of both methods at once. The method checks for the presence of a Policy and, if one is found, it is used to calls a corresponding Send method on each Strategy in the Strategies collection. The use of a Policy here allows us much greater flexibility In how we send emails. If a Policy is not present then the method uses the first Strategy in the Strategies collection to send the email. The return value is copied either from the Policy or the Strategy.

The EmailProduct class is initialized by the Builder through the OnInitialize method. That method looks for an IPolicyProvider in the Providers collection (inherited from the BuilderProductBase class). if a PolicyProvider is found, it is used to obtain a Policy object, which is then stored in the Policy property.

The Strategies property is populated by mining the Providers property for any IEmailStrategyProvider objects.

When the EmailProduct is eventually disposed of, the framework calls the Dispose method. Here the class cleans up any managed resources, including the Policy and Strategies properties.

 

The EmailProduct class is designed to be created from a Builder. That class is called EmailBuilder and the trimmed down code for that is shown here:

The class derives from the BuilderBase class, which is part of the CG.Builder NUGET package. The various constructors are for embedding an EmailBuilder object within a Product class, or anywhere that might contains a shared collection of Provider objects.

The Build method itself returns the IEmail instance, which is actually an instance of the EmailProduct class. For an overview of the BuilderBase class, feel free to look back at earlier articles where I covered the CG.Builder NUGET package.

 

The EmailProduct class, like any other Product class, is designed to use Provider and Setup objects at runtime. In this particular case, one of the providers that it included in the CG.Email NUGET package is an SMTP provider. Configuring an EmailBuilder to use the SMTP provider is done by using the AddSmtpEmail method of the IBuilderExtensions class. The trimmed down code for that method is shown here:

This is the same pattern used for practically any builder: (1) create a builder, (2) configure the builder, (3) call Build and do something with the results.

So where does the SmtpEmailStrategySetup class come from? It’s part of the CG.Email package. Here is a trimmed down look at that class:

Nothing too complicated. Just a few methods to set/get property values. The class derives from the EmailStrategySetupBase class, which is also part of the CG.Email NUGET package, and is shown here:

This class is the base for all concrete email Strategy Setup classes and is the starting point for creating your own specialized email Strategy Setup classes.

The Provider associated with the SmtpEmailStrategySetup class is the SmtpEmailStrategyProvider class, which is shown here:

The only purpose for this Provider is to return an email strategy to the EmailProduct class, at runtime, using the GetStrategy method. Notice that the SmtpEmailStrategyProvider class derives from the EmailStrategyProviderBase class. The code for that class is listed here:

Once again, this class is used as the base for all concrete email Provider classes. This is the starting point if you want to create a custom Provider type, for your project.

The real work of actually sending emails takes place in the email Strategy objects. In our case, since we are using SMTP, that means we’ll be using the SmtpEmailStrategy class. The trimmed down code for that is shown here:

Just like in the EmailProduct class, there are synchronous and asynchronous versions of the Send method. I’ll just cover of them, since they essentially do the same thing.

The first thing the method does is call the BuildAMessage method, to create the actual email message object required by the .NET SmtpClient. Once a message object is created, the address, port, user name and password are fetched from the Setup, in preparation for creating the email client. The next step is to create the SmtpClient object. Based on the contents of the setup, either custom or default credentials are then supplied to the client. Once the email client is ready for use the only thing left to do is tell it to send the email message.

The BuildAMessage method contains all the email message related code that is common to both the synchronous and asynchronous versions of the Send methods. Here is where the MailMessage object is created, then configured with everything needed to outfit the message before it is sent via the .NET email client.

 

Once the EmailProduct is created and returned from the Builder, the user is left with an object that implements the IEmail interface. Unfortunately, the two Send methods on that interface aren’t always the easiest things to work with. In cases where things like CC, BCC, or attachments are needed, it would be nice to support a few simpler versions of the Send methods. Luckily, that’s also part of the CG.Email NUGET package. Let’s go look at that code now:

I won’t go through each overloaded method here. There are just too many for that. The thing to take away is that this extension class gives the IEmail type several simpler alternatives for sending an email.

There are a few other minor pieces to the library, but nothing that really needs to be understood to use the library to send emails. There is one other thing to go over though, I outlined a basic use of the email library to send a message through a single Strategy, in our case, SMTP. What about using a Policy with a collection of more than one Strategy objects? Let’s go look at how we might create a Builder for that scenario:

So, I’ve left off some properties for the Addxxx methods, on the Builder, just to keep things clean and easy to understand. Also, the AddSomeOtherEmail method is made up, it doesn’t exist. I’m using it here to indicate a custom email strategy, other than SMTP, that we can use for this advanced example.

Notice that when we add the policy to the Builder, we also set the ordering for the Strategey objects. That ordering is down inside the Policy, when the Policy’s Apply method is called. What that list of strategy names does is, it orders the collection but it also produces a collection that may have some Strategy objects in it more than once. For instance, see how I added “SMTP” twice. That means, which this Policy is applied, it will first attempt to send the email using the SMTP Strategy. If that fails, for whatever reason, it then moves on to try the “Other” Strategy. Finally, if the email still hasn’t been sent without errors, it will try the SMTP Strategy.

Why give the policy the ability to try a Strategy more than once? Because I can see where retries might turn out to be a good thing. However, you don’t have to use any Strategy more than once, if you don’t want to.

 

Wrapup

That’s pretty much it for my email library. If you’re interested in this NUGET package, it can be downloaded, for free, from :

https://www.nuget.org/packages/CG.Email

The source code for the CG.Email package lives on Github and can be obtained for free at

https://github.com/CodeGator/CG.Email

I hope this article was helpful. Have fun with the code!