简体   繁体   English

使用ASP.NET MVC发送500条电子邮件:限制

[英]Sending 500 email messages using ASP.NET MVC: throttling

I am trying to send 500 e-mail messages to our customers from an ASP.NET MVC 4 web application. 我正在尝试从ASP.NET MVC 4 Web应用程序向我们的客户发送500条电子邮件。 I simply use a foreach loop like the one below. 我只是使用一个foreach循环,如下所示。 After ~50 cycles I get a generic exception saying that the mail message cannot be send. 大约50个周期后,我收到一个通用异常消息,指出无法发送邮件。 I believe I am dealing with throttling and MS Exchange settings that limit my web application. 我相信我正在处理限制我的Web应用程序的限制MS Exchange设置 How do I simply implement throttling to bypass these limits? 我如何简单地实施节流以绕过这些限制?

Thanks. 谢谢。

foreach (var toAddress in addresses)
{
   var message = new MailMessage(fromAddress, toAddress)
   {
      Subject = subject,
      Body = body
   };

   message.IsBodyHtml = isHtml;

   try
   {
      using (var client = new SmtpClient())
      {
         client.Send(message);
      }
   }
   catch (Exception ex)
   {
      Debug.WriteLine("Cannot send e-mail to " + message.To + Environment.NewLine +
                      "Subject: " + subject + Environment.NewLine +
                      "Body: " + body + Environment.NewLine + 
                      "Exception: " + ex.Message);
   }
}

I would have a look at Quartz.NET and use a service to send the emails off. 我将看看Quartz.NET并使用一项服务来发送电子邮件。 As far as queuing, maybe look into either a simple file storage or a database. 就排队而言,也许要研究简单的文件存储或数据库。

If you use something like Thread.Sleep , keep in mind you'll be holding up the server from rendering the final output (eg if this is triggered via form submit, the resulting view won't be displayed until all emails are sent). 如果使用Thread.Sleep东西,请记住,您将阻止服务器渲染最终输出(例如,如果这是通过表单提交触发的,则在发送所有电子邮件之前,不会显示结果视图)。 By using a library like quartz, you can keep the server responsive to requests while off-loading the email send-off. 通过使用石英等库,您可以在减轻电子邮件发送负担的同时,使服务器对请求做出响应。

Also, for reference, there's another SO post about performing expensive operations without dragging the UX. 另外,作为参考,还有另一篇关于不执行UX即可执行昂贵操作的文章。 This can be found here , with (IMHO) the most relevant answer by TheCodeKing . 这可以在此处找到,(IMHO) TheCodeKing提供的最相关的答案。

If you using Exchange 2010 or above there is a RecipientRateLimit throttling policy parameter that specifies the limit on the number of recipients that a user can address in a 24-hour period. 如果您使用的是Exchange 2010或更高版本,则有一个RecipientRateLimit限制策略参数,该参数指定用户在24小时内可以解决的收件人数量限制。 If you want get around this limit you will need to change the throttling policy for the user that is sending those messages see http://www.slipstick.com/exchange/limit-number-of-internet-messages-user-can-send/ 如果要绕过此限制,则需要为发送这些消息的用户更改限制策略,请参阅http://www.slipstick.com/exchange/limit-number-of-internet-messages-user-can-发送/

Cheers Glen 干杯格伦

Our scenario is a remote Web Application using a local MS Exchange Server 2010 and the only working solution so far is the following. 我们的方案是使用本地MS Exchange Server 2010的远程Web应用程序,到目前为止,唯一可行的解​​决方案如下。 Using chunks of 20-30 messages every 10 seconds I can send the number of customized e-mail messages I want to our customers without the need to touch the MS Exchange Sever 2010 configuration (it requires many of hours of training). 每10秒钟使用20-30条消息,我可以将我想要的自定义电子邮件数量发送给我们的客户,而无需触摸MS Exchange Sever 2010配置(这需要大量的培训时间)。 In addition, everything is logged in a TXT file to be sure that the messages were actually sent. 此外,所有内容均记录在TXT文件中,以确保实际发送了消息。 I also recommend the MS Exchange Tracking Log Explorer tool to inspect if and what messages were sent. 我还建议使用MS Exchange 跟踪日志资源管理器工具来检查是否以及发送了哪些消息。

private void SendBulkEmail(List<KeyValuePair<Customer, Order>> customerList, MailAddress sender, string subject, string body, bool isHtml, string fileNamePrefix)
{
    const int chunkSize = 20;

    string rootPath = Server.MapPath("~");

    string path = Path.GetFullPath(Path.Combine(rootPath, "Logs"));

    string fileName = CommonUtils.GetLogFileName(path, fileNamePrefix);

    int len = customerList.Count;

    TextWriter tw = new StreamWriter(fileName);

    int chunkCount = (len / chunkSize) + 1;
    int remainder = len % chunkSize;

    for (int j = 0; j < chunkCount; j++)
    {
       int start = j * chunkSize;
       int end = start + chunkSize;

       if (j == chunkCount - 1)
       {
           end = start + remainder;
       }

       SmtpClient client = new SmtpClient();

       for (int i = start; i < end; i++)
       {
           Customer customer = customerList[i].Key;

           Guid userGuid = new Guid(customer.UserId.ToString());
           MembershipUser membershipUser = Membership.GetUser(userGuid);

           string memberUsername = membershipUser.UserName;
           string memberEmail = membershipUser.Email;

           SendMessage(sender, recipient, subject, body, tw, client, context);

       }

       client.Dispose();

       Thread.Sleep(10000); // 10 seconds

       tw.WriteLine("Completed chunk #" + j);
   }

   tw.Close();
 }

public static void SendEmail(MailAddress fromAddress, MailAddress toAddress, string subject, string body, TextWriter tw, SmtpClient smtpClient)
{
    MailMessage message = new MailMessage(fromAddress, toAddress)
    {
       Subject = subject,
       Body = body
    };

    try
    {
       smtpClient.Send(message);

       if (tw != null)
       {
          tw.WriteLine("\"" + toAddress + "\",");
       }
    }
    catch (Exception ex)
    {
       if (tw != null)
       {
          tw.WriteLine(toAddress + ": " + ex.Message + " " + ex.InnerException.Message);
       }

       Debug.WriteLine("Cannot send e-mail to " + toAddress + ", " + "Exception: " + ex.Message + (ex.InnerException != null ? ", " + ex.InnerException.Message : string.Empty));
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM