Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / ASP.NET

Configure Email Providers (SMTP/GMail) using Managed Extensibility Framework (MEF)

5.00/5 (1 vote)
5 Aug 2013CPOL3 min read 8.9K   116  
Dynamically set

Introduction

This tip describes how to configure different email providers like SMTP, Gmail or any other third party email sender, without changing existing code in one liner plug & play email providers by using Microsoft Managed Extensibility Framework (MEF).

MEF Background

Basically MEF is a component of .NET Framework 4.0 for creating lightweight, extensible applications. MEF allows your application to be extended using components. MEF can be used for third-party plugin extensibility, or it can bring the benefits of a loosely-coupled plugin-like architecture to applications.

Basic Terminology Used

  • Import - This attribute is placed above a property to tell the system that something gets plugged in here. E.g. The following statement means IEmail interface is going to get plugged.
    VB
    [Import] 
    IEmail EmailSender;
  • Export - This attribute is placed above a class, method, or property/interface to indicate that this is an item to be plugged in somewhere. E.g. The following statement states that Interface IEmail is going to exported or plugged in somewhere.
    VB
    [Export]
    public interface IEmail 
  • ImportMany - ImportMany is a way to express that you want to import all “items” into a type. E.g. multiple export instances into one import by using ImportMany.
    VB
    [ImportMany] 
    IEnumerable<IEmail> EmailSenders;
  • InheritedExport - Any class that inherits from the item marked with InheritedExport will be exported. E.g. The following Interface IEmail, whichever class inherits this interface will get exported.
    VB
    [InheritedExport(typeof(IEmail))]
    public interface IEmail   
  • Composition container - Manages the composition of parts, i.e., matching up of import to export parts.
  • DirectoryCatalog - All the exports in all the assemblies in a directory.
  • PartNotDiscoverable - You don’t want a particular component to be discovered by the catalog, so use this attribute to hide the component.

Using the Code

The simplest way to see how MEF works to build a simple MEF application, here I have created a sample application to configure email provider, i.e., plug and play email providers by using MEF.

Please refer to the attached application containing the following projects:

  1. MEF.Contract - This is common library containing interface abstract method to send email.
  2. MEF.EmailSender - This class library will manage import export part. Manages email sending functionality like dynamically set provider.
  3. MEF.Email.SMTP - This is SMTP provider which references common IEmail interface and sends email using SMTP as server.
  4. MEF.Email.Gmail - This is provider which references common IEmail interface and sends email using GMail as server.
  5. Email Testing (Website) - This is a client application which uses MEF.EmailSender library and sends email, using dynamically set provider.

Following are the details of classes being used in this application:

MEF.Contract - This contains the common interface IEmail. This library also contains the class EmailInfo; common properties to send email like To, From, CC, Bcc, etc.

We need to add reference of the following namespaces to have MEF related classes.

using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;  
C#
//Any class that inherits from the item marked with [InheritedExport] will be exported
[InheritedExport(typeof(IEmail))]
public interface IEmail
{
    string ProviderName{get;}
    bool SendEmail(EmailInfo emailInfo);
}   

MEF.EmailSender - This is the heat of this application, containing the class Program.cs which manages the composition of MEF.

C#
public class Program
{
    //To put multiple export instances into one import by using ImportMany
    [ImportMany]
    IEnumerable<IEmail> EmailSenders;
    private CompositionContainer _container;
    public void Compose()
    {
        AggregateCatalog catalog = new AggregateCatalog();
        //Specify directory name where provider DLLs resides
        string directoryPath = @"D:\\Providers";
        catalog.Catalogs.Add(new DirectoryCatalog(directoryPath, "*.dll"));
        _container = new CompositionContainer(catalog);
        //this is area where the exported parts will be assembled with the imported.
        _container.ComposeParts(this);
    }
    public bool SendEmail(string providerName, EmailInfo ObjEmail)
    {
        Program prog = new Program();
        prog.Compose();
        foreach (var item in prog.EmailSenders)
        {
            //Based on selected provider this will check condition
            //and call send method of that provider.
            if (item.ProviderName.ToUpper() == providerName.ToUpper())
            {
                return item.SendEmail(ObjEmail);
            }
        }
        return true;
    }
}  

MEF.Email.SMTP/MEF.Email.Gmail - This library will inherit from the IEmail provider and set the actual implementation code here:

C#
public class SMTPSender : IEmail
{
    private string _ProviderName = "SMTP";
    public bool SendEmail(EmailInfo emailInfo)
    {
        MailMessage message = new MailMessage();
        message.To.Add(emailInfo.To);
        message.Subject = emailInfo.Subject;
        message.From = new System.Net.Mail.MailAddress(emailInfo.From);
        message.Body = emailInfo.Body;
        SmtpClient smtp = new SmtpClient("localhost");
        //smtp.Port = 25;
        try
        {
            smtp.Send(message);
            return true;
        }
        catch(Exception ex)
        {
            return false;
        } 
    }
    public string ProviderName
    {
        get
        {
            return _ProviderName;
        }
    }
}
//Set provider name.

EmailTesting - This is a client application website; containing a call to MEF.EmailSender SendEmail method, which will send the email.

C#
private void SendEmail()
{
    EmailInfo emailInfo = new EmailInfo();
    emailInfo.To = txtTo.Text.Trim();
    emailInfo.From = txtFrom.Text.Trim();
    emailInfo.Subject = txtSubject.Text;
    emailInfo.Body = txtBody.Text;
    Program obj = new Program();
    obj.SendEmail(ddlEmailServer.SelectedValue, emailInfo);        
}   

Interesting Points

  1. We can easily plug-in any third party email sender. MEF is useful in a plugin architecture where third party code has limited access to your application. This is designed for extensibility purposes.
  2. Here the Components/Email provider can be added at run-time, you just need to deploy a new provider DLL in the configured folder.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)