This post is on the older side and its content may be out of date.
Be sure to visit our blogs homepage for our latest news, updates and information.
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 inherit 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 re-sends 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"
],out numberOfRetriesPerMessage);
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 Administration>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.
In addition to the sample, there are cases where you need to catch exceptions related to the custom sender at runtime. This can be done by replacing the base SendMessage method in a try-catch statement, so that when an issue occurs, the error generated can be caught and dealt with appropriately by either logging it or handling it with additional logic. Here is the modification to the sample:
public
override
SendResult SendMessage(IMessageInfo messageInfo, ISubscriberRequest subscriber)
{
//the result will be a SendResult object which will either be success or contain an exception
//you can use this for logging/debugging purposes
SendResult result;
try
{
result =
base
.SendMessage(messageInfo, subscriber);
}
catch
(Exception)
{
//implement additional logging
//can be used for debugging purposes as well
}
var numberOfRetriesPerMessage = 3;
if
(!(ConfigurationManager.AppSettings[
"numberOfRetriesPerMessage"
].IsNullOrEmpty()))
int
.TryParse(ConfigurationManager.AppSettings[
"numberOfRetriesPerMessage"
],
out
numberOfRetriesPerMessage);
//In millliseconds
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;
}
}
}
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 Sitefinity SMTP Sender will retry sending messages with status code 450-->
<
add
key
=
"numberOfRetriesPerMessage"
value
=
"5"
/>
<!--Indicates how long Sitefinity will wait before retying the send (in milliseconds)-->
<
add
key
=
"waitBeforeRetry"
value
=
"2000"
/>
Additionally. our default SmtpClient.Timeout is set to 100 000 milliseconds (100 seconds). If you wish to increase this value, you can override the System.Net.Mail.SmtpClient to get a value you have set in the web.config:
protected
override
System.Net.Mail.SmtpClient CreateSmtpClient(Telerik.Sitefinity.Services.Notifications.Configuration.SmtpSenderProfileElement profile)
{
var client =
base
.CreateSmtpClient(profile);
//In millliseconds. The default value is 100,000 (100 seconds).
var smtpClientTimeout = 100000;
if
(!(ConfigurationManager.AppSettings[
"smtpClientTimeout"
].IsNullOrEmpty()))
int
.TryParse(ConfigurationManager.AppSettings[
"smtpClientTimeout"
],
out
smtpClientTimeout);
client.Timeout = smtpClientTimeout;
return
client;
}
This allows you to add an additional key to the appSettings node of the web.config named and smtpClientTimeout. Adding a value to it will alter the default one.
Subscribe to get all the news, info and tutorials you need to build better business apps and sites