Reputation: 95
I'm writing an application which sends a lot of emails throughout the app's lifecycle.
The users complained that the application was really unresponsive and generally slow. The only thing I could come up with as the reason, was the heavy email sending. So I thought I could solve the problem by sending the emails in a different thread!
I'm using the SendEmail method in the SPUtility helper class. Right now, I have a method that looks like this:
public static void SendEmail(SPWeb web, string to, string subject, string body)
{
//Some logic goes here
System.Threading.ThreadPool.QueueUserWorkItem(o =>
{
SPUtility.SendEmail(web, false, false, to, subject, body, false);
});
}
This method is defined in a DLL, and it's being called from a LOT of different webparts.
But this is not working. If I remove the QueueUserWorkItem bit, and just let it send emails outside of a thread, it works like a charm, but then again, it's slow.
How can I solve this?
Upvotes: 1
Views: 3464
Reputation: 649
Also there is an option to do something like this:
public static void SendEmail(SPWeb web, string to, string subject, string body)
{
var siteId = Web.Site.ID;
System.Threading.ThreadPool.QueueUserWorkItem(o =>
{
using (var site = new SPSite(siteId))
using (var myWeb = site.OpenWeb())
{
SPUtility.SendEmail(myWeb, false, false, to, subject, body);
}
});
}
Maybe it will be interesting to someone.
Upvotes: 5
Reputation: 1944
Are you getting any error message? I ran into this once and ended up putting a small delay (ex. Thread.Sleep(500)) before sending out each email. For some reason, the smtp server rejected some of the emails that were sent. In addition, you should follow @rushonerok's advice and send email via SMTP server instead. GlennFerrieLive is a much more robust solution and should looked at as well.
Upvotes: 0
Reputation: 11454
A quick fix until you can setup a more permanent solution would be to send your emails to an smtp server on the same machine and have it relay them for you.
Down the road I would create an email service and that is easy to call like a wcf service, which you can incorporate threading into.
Upvotes: 1
Reputation: 27405
I suspect you're better off using MailMessage Class (System.Net.Mail)
MailMessage mess =
new MailMessage(
SPContext.Current.Site.WebApplication.OutboundMailReplyToAddress,
sendTo,
subject,
message);
mess.IsBodyHtml = true;
SmtpClient smtp =
new SmtpClient(
SPContext.Current.Site.WebApplication.OutboundMailServiceInstance.Server.Address);
smtp.Send(mess);
this MSDN post is similar to your situation, Sending Email using SPUtility.SendEmail slow in production
Upvotes: 5
Reputation: 10400
You should consider a more distributed pattern for sending these emails. Specifically, I would define some structure to store "send requests". This can be a SharePoint List, a MSMQ, a Queue in Azure Storage, etc.
Your send email method would enqueue a request in this storage unit and you would have a separate process or processes poll that queue to check for new requests periodically. When new items are found they will be executed and dequeued.
if you chose to use multiple agents to process these requests, you may need to defined a more complex mechanism orchestrating these agents to prevent interference.
As for the host for the agent(s), this can be an app that is registered as a Scheduled Task, a Windows Service with a "Timer", or a SharePoint Workflow that is invoke my the Timer.
This is just one implementation, but ultimately you want to decouple the action of "requesting" the email send from the act of "executing" that email send.
Upvotes: 1