Contents tagged with Email

  • a quick service that sends emails

    Tags: EmailNotification, Atlas, Autofac, AutoMapper, Email, Quartz

    As promised in my previous post I will show you how to put together a service in a matter of a few minutes using what I showed you in sending emails made easy and a quick way to create a windows service using Autofac, Quartz and Atlas. In this example I am going to wire up a service that will be powered by atlas so that it makes the service easy to install/uninstall and debug. I then use autofac to manage my IoC container. I also will use quartz for managing the schedule of my service, instead of just a standard timer. I then will use auto mapper to handle the mapping between entities. Finally I will use EmailNotification to send my emails. The final product will query a table every minute and send out emails, it will then update the table with the sent date for history tracking.

    To get started you will just create a new console application. You can quickly reference all of the references to atlas, autofac, auto mapper, email notification, and quartz using nuget.

    Once things are referenced lets make sure our database table and the entity that is used is wired up using auto mapper. Auto mapper takes care of the translation/mapping between my entity and the email notification MessageQueueEntity. So I will wire that up painlessly.

    public class AutomapperRegistrations
    {
        public void RegisterMappings()
        {
            CreateEmailMessageToMessageQueueMapping();
            CreateMessageQueueToEmailMessageMapping();
        }
    
        private void CreateEmailMessageToMessageQueueMapping()
        {
            Mapper.CreateMap<MessageQueueEntity, EmailMessage>()
                  .ForMember(from => from.EmailMessageId, dest => dest.MapFrom(from => from.Identifier));
        }
    
        private void CreateMessageQueueToEmailMessageMapping()
        {
            Mapper.CreateMap<EmailMessage, MessageQueueEntity>()
                  .ForMember(from => from.Identifier, dest => dest.MapFrom(from => from.EmailMessageId));
    
        }
    }
    

    Now I will create my autofac module which handles all the registrations into my IoC container.

    public class ServiceModule : Module
    {
        protected override void Load(ContainerBuilder builder)
        {
            LoadQuartz(builder);
            LoadServices(builder);
    
            builder.Register(c => new EmailRepository()).As<IEmailRepository>();
        }
    
        private static void LoadQuartz(ContainerBuilder builder)
        {
            builder.Register(c => new StdSchedulerFactory().GetScheduler()).As<IScheduler>().InstancePerLifetimeScope();
            builder.Register(c => new AutofacJobListener(ContainerProvider.Instance)).As<IJobListener>();
        }
    
        private static void LoadServices(ContainerBuilder builder)
        {
            builder.RegisterType<EmailService>().As<IAmAHostedProcess>().PropertiesAutowired();
        }
    }
    
    

    Now I will setup my job which processes the email(s). Since I am using Quartz it will inherit an IJob and I will implement the execute method. When Execute is called it will retrieve the unsent message from the database and send them using the power of EmailNotification.

    public class SendEmailJob : IJob
    {
        public IEmailRepository EmailRepository { get; set; }
    
        public void Execute(IJobExecutionContext context)
        {
            SendEmails();
        }
        
        public void SendEmails()
        {
            //Get Emails from the repository and translate them to the messagequeueentity. MessageQueueEntity is the defined email object.
            var emails = EmailRepository.GetUnsentEmails().ToMessageQueueEntities();
    
            //Use the web config configuration.
            var configuration = Master.UseAppConfig().WithEmails(emails);
    
            //The service will now send out the emails and return the results.
            var result = Master.Execute(configuration);
    
            //Set the sent date for each email that has been sent.
            foreach (var email in result.Emails.Where(e => e.IsSent))
            {
                var e = EmailRepository.GetEmail((long)email.Identifier);
                e.IsSent = email.IsSent;
                e.Sent = email.Sent;
    
                e.Save();
            }
    
            //Save any errors that were caught.
            foreach (var email in result.Emails.Where(e => !e.IsSent && e.SentException != null))
            {
                var e = EmailRepository.GetEmail((long) email.Identifier);
                e.ErrorMessage = email.SentException.Message;
    
                e.Save();
            }
        }
    }
    

    Now that we have our job I will go ahead and create the service using Quartz. Quartz will need a job that will call our SendEmailJob and a trigger. I will set the trigger to fire on an interval, every minute. You can set the trigger up many different ways, take a look at Quartz trigger options in there documentation.

    public class EmailService : IAmAHostedProcess
    {
        public IScheduler Scheduler { get; set; }
        public IJobListener AutofacJobListener { get; set; }
    
        public void Start()
        {
            //create the job with quartz
            var job = JobBuilder.Create<SendEmailJob>()
            .WithIdentity("SendEmail")
            .Build();
    
            //define the trigger in quartz to fire every minute
            var trigger = TriggerBuilder.Create()
                .WithIdentity("SendEmailTrigger")
                .StartNow()
                .WithCalendarIntervalSchedule(x => x.WithIntervalInMinutes(1))  //Run's every minute
                .Build();
    
            //schedule the job within quartz
            Scheduler.ScheduleJob(job, trigger);
            Scheduler.ListenerManager.AddJobListener(AutofacJobListener);
            Scheduler.Start();  //kick off the quartz job
        }
    
        public void Stop()
        {
            //shut quartz down
            Scheduler.Shutdown();
        }
    
        public void Resume()
        {
            //resume the quartz jobs
            Scheduler.ResumeAll();
        }
    
        public void Pause()
        {
            //pause the quartz jobs
            Scheduler.PauseAll();
        }
    }
    

    Finally we wire up the final piece which is to wire up the entry point of the application. I chose to use atlas since it makes it real easy for me to install/uninstall/debug a windows service. I will use the application config, tell it to use my autofac module and run my automapper registrations before atlas begins.

    static class Program
    {
        //Standard entry point for an application.
        static void Main(string[] args)
        {
            //Register Atlas using app.config, register the autofac module and setup any automapper registrations.
            var configuration = Host.UseAppConfig<EmailService>()
                .WithRegistrations(b => b.RegisterModule(new ServiceModule()))
                .BeforeStart(() => new AutomapperRegistrations().RegisterMappings())
                .WithArguments(args);
    
            //Kick off atlas
            Host.Start(configuration);
        }
    }
    

    Last thing we need to do is setup the app.config for both EmailNotification and atlas.

    <?xml version="1.0" encoding="utf-8"?>
    <configuration>
      <configSections>
        <section name="atlas" type="Atlas.Configuration.XmlConfiguration, Atlas" />
        <section name="EmailNotificationSettings" type="EmailNotification.Config.EmailNotificationConfigurationSectionHandler, EmailNotification" allowLocation="false" allowDefinition="Everywhere" />
      </configSections>
      <startup>
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
      </startup>
      <atlas>
        <host name="Email Service" displayName="My Sample Email Service" description="This sample email service will send emails using the email notification service." allowMultipleInstances="true">
          <runtime accounttype="networkservice" startup="automatic" />
        </host>
      </atlas>
      <EmailNotificationSettings isEnabled="true">
        <ServerSettings smtpServer="10.252.3.157" smtpServerPort="25" isSSLEnabled="false" smtpServerConnectionLimit="-1" smtpServerPassword="" smtpServerUser="" smtpServerRequiredLogin="false" useDefaultCredentials="true" />
        <TestEmailAccounts isTestEmailAccountsBlocked="false">
          <add account="mailinator.com"></add>
        </TestEmailAccounts>
      </EmailNotificationSettings>
    </configuration>
    

    That’s it were complete! Lets fire the thing up and see it fly. Remember when you go to install all you have to do is run at the command prompt Service.exe –i it will install and can be found in your windows service list using the name you set in the atlas section of your app.config. I hope you found setting up the service to be painless and easy, I’ve included the code for you to download.

  • sending emails made easy

    Tags: Email, EmailNotification

    I released a library a while back that makes some email functionality easier with a wrapper around the built in .NET email functionality called Email Notification. I prefer to use a library like this to segregate the email functionality from the code base of my application. The wrapper gives you the ability to easily configure emails using either fluent syntax or use the configuration file of your website or application. It also handles some of the common exceptions thrown by email servers and handles them for you. The project has been open sourced and can be found on CodePlex at http://emailnotification.codeplex.com

    I’ll give you a quick an easy basic use case for the service in a web site instance. In a future post I’ll share with you an example of sending emails through a windows service quickly and painlessly.

    So for this example I started with a basic MVC 4 project (you could use MVC 3). Once the project is setup, start with the configuration file. I’ll drop the following couple lines into the web.config. I set my SMTP server and port, tell it not to use SSL and tell it the server doesn’t require a login. I also want to make sure I tell it about my test email accounts used by my UI tester, this way I prevent mail from being sent out to these accounts when my auto UI test is activated.

    <configSections>
      <section name="EmailNotificationSettings" type="EmailNotification.Config.EmailNotificationConfigurationSectionHandler, EmailNotification" allowLocation="false" allowDefinition="Everywhere"/>
    </configSections>
    <EmailNotificationSettings isEnabled="true">
      <ServerSettings smtpServer="smtp.myserver.com" smtpServerPort="25" isSSLEnabled="false" smtpServerConnectionLimit="-1" smtpServerPassword=""
                      smtpServerUser="" smtpServerRequiredLogin="false" useDefaultCredentials="true"/>
      <TestEmailAccounts isTestEmailAccountsBlocked="true">
        <add account="myserver.com"></add>
      </TestEmailAccounts>
    </EmailNotificationSettings>

    Let’s create a view “Index.cshtml” that will send out a single email, this view uses a basic Email { To, From, Subject Body} model.

    @{ Ajax.BeginForm("SendEmail", "Email", new AjaxOptions { HttpMethod = "POST", OnSuccess = "SendEmailSuccess"}); }
    
    <div style="width:500px; background-color: #EEEEEE; border:solid 1px black; padding:5px;">
        <div><span class="label">To:</span>@Html.TextBoxFor(t => t.To, new { style = "width:350px;" })</div>
        <div><span class="label">From:</span>@Html.TextBoxFor(t => t.From, new { style = "width:350px;" })</div>
        <div><span class="label">Subject:</span> @Html.TextBoxFor(t => t.Subject, new { style="width:350px;"})</div>
        <div><span class="label">Body:</span>@Html.TextAreaFor(t => t.Body, new { style = "width:350px;" })</div>
        <div style="text-align: center;">
            <input type="submit" value="send" />
        </div>
    </div>
    
    @{ Html.EndForm(); }
    

    Now here comes the easy part, but also the meat, wiring up the controller to send the email. I grab the email from the view, convert the model to an email the Email Notification wrapper is able to read and send the email out using the configuration from the web.config. That result is then sent back to the view where its handled there through javascript.

    [HttpPost]
    public JsonResult SendEmail()
    {
        var email = new EmailMessage();
    
        if (TryUpdateModel(email))
        {
            var emails = new List<MessageQueueEntity>
                             {
                                 new MessageQueueEntity
                                     {
                                         To = email.To,
                                         From = email.From,
                                         Body = email.Body,
                                         Subject = email.Subject,
                                         BodyFormat = BodyFormat.PlainText,
                                         Created = DateTime.Now
                                     }
                             };
    
            var configuration = Master.UseAppConfig().WithEmails(emails);
            var result = Master.Execute(configuration);
            return Json(result);
        }
    
        return new JsonResult { Data = new { IsSuccess = false} };
    }
    

    The javascript on the view is pretty simple, it will check to make sure that each of the emails sent to the wrapper were successful or not. If not successful I display the error message in an alert window.

    <script type="text/javascript">
        function SendEmailSuccess(data) {
            console.log(data);
    
            $.each(data.Emails, function (index, value) {
                console.log(value);
    
                if (value.SentException != null) {
                    alert("Email " + index + " couldn't be sent because: " + value.SentException.Message);
                } else {
                    alert("Email " + index + " was successfully sent to : " + value.To);
                }
            });
        }
    </script>
    

    Hopefully you find the Email Notification wrapper as useful as I do. I’ve included the example for you to download, the libraries source code can also be found on CodePlex. As a bonus I threw in a multi-email example for some fun. If you find any issues with the library or have suggestions feel free to start up a discussion or post an issue on the source at CodePlex

    image