异步邮件阻塞MVC请求
问题代码如下:
public class EmailHelper
{
private MailHost mailHost = null;
private HttpContext context;
public event SendMailComplete SendComplete;
private SmtpClient client;
public EmailHelper()
{
context = HttpContext.Current;
client = new SmtpClient();
mailHost = new MailHost();
mailHost.Host = GetAzureAppSetting("MailServer");
mailHost.UserName = GetAzureAppSetting("MailUserName");
mailHost.Password = GetAzureAppSetting("MailPassword");
}
public void SendMail(string From, string[] To, string[] CC, string Subject, string Body)
{
client.Host = mailHost.Host;
client.UseDefaultCredentials = false;
client.Credentials = new NetworkCredential(mailHost.UserName, mailHost.Password);
client.DeliveryMethod = SmtpDeliveryMethod.Network;
MailMessage message = new MailMessage();
MailAddress mailfrom = new MailAddress(From, GetDisplayName(From));
Encoding mailencoding = Encoding.UTF8; // Encoding.GetEncoding(GetEncoding(dt.Rows[0]["CharacterSet"].ToString()));
message.From = mailfrom;
foreach (string to in To)
{
if (to != string.Empty)
{
message.To.Add(to);
}
}
foreach (string cc in CC)
{
if (cc != string.Empty)
{
message.CC.Add(cc);
}
}
message.Subject = Subject;
message.Sender = mailfrom;
message.Body = Body;
message.BodyEncoding = mailencoding;
message.SubjectEncoding = mailencoding;
message.IsBodyHtml = true;
// use new async email as the old one above will block mvc request/response
client.SendCompleted += new SendCompletedEventHandler(SendCompletedCallback);
client.SendAsync(message, null);
}
解决方法如下:
public static void InternalSendEmail(MailMessage mail, SmtpClient smtpClient)
{
InternalSendEmail(mail, smtpClient, true);
}
public static void InternalSendEmail(MailMessage mail, SmtpClient smtpClient, Boolean Async)
{
if (Async)
{
InternalSendEmailDelegate ised = new InternalSendEmailDelegate(smtpClient.Send);
AsyncCallback acb = new AsyncCallback(InternalSendEmailResponse);
ised.BeginInvoke(mail, acb, ised);
}
else
{
smtpClient.Send(mail);
}
}
private delegate void InternalSendEmailDelegate(MailMessage m);
private static void InternalSendEmailResponse(IAsyncResult ar)
{
InternalSendEmailDelegate ised = (InternalSendEmailDelegate)(ar.AsyncState);
ised.EndInvoke(ar);
}
参考:
http://weblogs.asp.net/jeffwids/archive/2009/10/12/asynchronously-sending-a-system-net-mail-mailmessage-in-c.aspx?CommentPosted=true#commentmessage
https://connect.microsoft.com/VisualStudio/feedback/details/688210/smtpclient-sendasync-blocking-my-asp-net-mvc-request#details