~/blogs/IvanDDimitrov/posts.aspx
Categories
Bloggers
Blogs RSS feed

Extend Sitefinity SmtpSender

by Ivan D.Dimitrov

Sitefinity offers very easy extensibility of our default SmtpSender class. Since our Email Campaigns module uses the Sitefinity's NotificationService to send out the campaign issues, the SmtpSender gets resolved dynamically and can be replaced from the Notification profile.

This article shows how you can inherits from the default SmtpSender and add logic that in this case detects whether a message has failed delivery due to  System.Net.Mail.SmtpStatusCode.MailboxBusy status code (450) and resends it if necessary.

If the message falls within this case the custom sender attempts to re-send it for a predefined number of retries and a predefined period between the retries. To ease configuring this logic we have exposed the numberOfRetriesPerMessage and waitBeforeRetry parameters to be read form your site's web.config <appSettings> section. In other words, here's the full implementation of the overridden SendMessage method of the custom SmtpSender:

public override SendResult SendMessage(IMessageInfo messageInfo, ISubscriberRequest subscriber)
        {
            var result = base.SendMessage(messageInfo, subscriber);
            var numberOfRetriesPerMessage = 3;
            if (!(ConfigurationManager.AppSettings["numberOfRetriesPerMessage"].IsNullOrEmpty()))
                int.TryParse(ConfigurationManager.AppSettings["numberOfRetriesPerMessage"],outnumberOfRetriesPerMessage);
            var waitBeforeRetry = 1000;
            if (!(ConfigurationManager.AppSettings["waitBeforeRetry"].IsNullOrEmpty()))
                int.TryParse(ConfigurationManager.AppSettings["waitBeforeRetry"],out waitBeforeRetry);
   
            for (int i = 0; i < numberOfRetriesPerMessage; i++)
            {
                if (result.HandledException != null)
                {
                    if(result.HandledException.GetType() ==typeof(System.Net.Mail.SmtpException)
                    && ((System.Net.Mail.SmtpException)result.HandledException).StatusCode == System.Net.Mail.SmtpStatusCode.MailboxBusy)
                    {
                        Thread.Sleep(waitBeforeRetry);
                        result =base.SendMessage(messageInfo, subscriber);
                    }
                    else
                        break;
                }
                else
                    break;
            }
   
            return result;
        }

As you can see above, we have explicitly restricted the logic for retrying the sending only to messages with status  System.Net.Mail.SmtpStatusCode.MailboxBusy. You are free to extend it as per your specific requirements.

Here is the full source of the CustomSenderSMTP class. In order to use it you need to include it in your project's solution, and build it. When done, you need to go to Adminsitration>Settings->Advanced->Notifications>Profiles->Default and change the SenderType property to the CLR type of the custom SmtpSender class (in our case that is SitefinityWebApp.CustomSenderSMTP). From this point on Sitefinity will use the custom SmtpSender instead of the default one, and the sending logic will go through the custom SendMessage implementation.

By default we have preset the number of times Sitefinity retries to send a message to 3, and the default period between retries is 1000ms (1 second). If you want to control these you can add the following entries in your web.config <appSettings> section:

<appSettings>
    <!--Indicates how many times Sitefintiy SMTP Sender will retry sending messages with status code 450-->
    <add key="numberOfRetriesPerMessage" value="5" />
    <!--Indicates how long Sitefintiy will wait before retying the send (in milliseconds)-->
    <add key="waitBeforeRetry" value="2000" />
 

Changing the values will change the logic behavior  accordingly. Here is a short  video of the sender in action.

 

Leave a comment