我正在尝试以异步方式发送电子邮件,但是当我从Threadpool或简单的线程中调用我的SendMailMesage()方法时,电子邮件就不会被发送。
任何方式如何实现这一目标?定期发送电子邮件sendind会大大减慢我的申请速度。
PS:如果重要,SendMailMesage()将从引用的项目而不是MVC项目本身发送。
感谢。
修改:我的代码。
namespace App.Core.Utils.Mailer
{
public static class Sender
{
/// <summary>
/// Sends a MailMessage object using the SMTP settings.
/// </summary>
public static void SendMailMessage(MailMessage message)
{
if (!Settings.Instance.SendEmails)
{
return;
}
if (message == null)
throw new ArgumentNullException("message");
try
{
message.IsBodyHtml = true;
message.BodyEncoding = Encoding.UTF8;
var smtp = new SmtpClient(Settings.Instance.SmtpServer);
// don't send credentials if a server doesn't require it,
// linux smtp servers don't like that
if (!string.IsNullOrEmpty(Settings.Instance.SmtpUserName))
{
smtp.Credentials = new System.Net.NetworkCredential(Settings.Instance.SmtpUserName, Settings.Instance.SmtpPassword);
}
smtp.Port = Settings.Instance.SmtpServerPort;
smtp.EnableSsl = Settings.Instance.EnableSsl;
smtp.Send(message);
}
catch (SmtpException)
{
//OnEmailFailed(message);
}
finally
{
// Remove the pointer to the message object so the GC can close the thread.
message.Dispose();
}
}
public static void SendMailMessageAsync(MailMessage message)
{
ThreadPool.QueueUserWorkItem(state => SendMailMessage(message));
}
}
}
请注意:这在WebForms中有效。我将代码复制到MVC项目,如果我调用SendMailMessageAsync
方法,现在没有任何内容被发送。没有错误。
答案 0 :(得分:1)
我们在MVC中使用它,效果很好。由于它实现了一个接口,你可以将一个实例注入到Controller构造函数中,而不是使用静态方法:
public class MvcEmailSender : ISendEmails
{
public MvcEmailSender(ILogExceptions logger,
IQueryEntities queryables, IUnitOfWork unitOfWork)
{
// save args to readonly fields on the instance
}
public void Send(EmailMessage message)
{
// constructor really passes more args here
var sender = new SmtpEmailSender(message, arg2, arg3, arg4);
var thread = new Thread(sender.Send);
thread.Start();
}
}
public class SmtpEmailSender
{
private readonly EmailMessage _emailMessage;
private int _retryCount;
public SmtpEmailSender(EmailMessage emailMessage, ILogExceptions logger,
IQueryEntities queryables, IUnitOfWork unitOfWork)
{
if (emailMessage == null)
throw new ArgumentNullException("emailMessage");
_emailMessage = emailMessage;
// save other constructor args to readonly fields
}
public void Send()
{
try
{
// assemble message, send, & update database
}
catch (Exception ex)
{
// log exception, then retry like so:
if (_retryCount++ <= 3)
{
Thread.Sleep(10000);
Send();
}
}
}
}
我们也在web.config中提供了一些设置,对吗?如果是这样,请使用web.config中的system.net部分更新您的问题。
要使用它,我们只需从控制器调用ISendEmails.Send(EmailMessage)。实现负责线程化,MVC不知道。
这两个类和ISendEmails接口都在引用的项目中声明,而不是MVC项目(接口在API程序集中,上面的两个类在IMPL程序集中)。
<强>更新强>
我已经更新了代码以回应评论。请注意,这些类的构造函数确实具有比最初描述的更多依赖性。我们(构造函数)也注入ILogExceptions,IQueryEntities和IUnitOfWork依赖项。在try块内,除了将EmailMessage转换为MailMessage并发送之外,还在数据库中更新EmailMessage域对象,并在SmtpClient.Send(MailMessage)成功后更新其SentOnUtc值。这就是我们证明电子邮件实际发送的方式。捕获异常时,会在重试之前记录该异常。