服务器超时后,c#中的电子邮件发送服务无法恢复

时间:2014-07-08 13:59:33

标签: c# email .net-4.5 smtpclient

几个月来我一直有这个问题,这让我疯了。 我有一个用C#(.NET 4.5)编写的Windows服务,它基本上使用Outlook帐户发送电子邮件(我认为它是一个office365服务)。我知道“凭证顺序”问题,这对我没有影响(许多电子邮件发送正确)。

服务正常启动并开始发送电子邮件。有时当有太多时,我得到服务器错误等待,服务等待几分钟并继续完全自己。

在这些情况下,我得到错误A:

 System.Net.Mail.SmtpException: The operation has timed out.
   at System.Net.Mail.SmtpClient.Send(MailMessage message)
   at Cobranzas.WinService.Email.SendEmail(String subject, String body, String mailTo, String attPath)
   at Cobranzas.WinService.CobranzasEmailService.SendEmails(IEnumerable`1 toSend, RepositoryEf emailRepo)

问题:有时,我无法找到模式,它每隔几天就会发生一次,它会出现超时错误,并且永远不会恢复(重新启动服务会立即修复) 。所有后续发送尝试都失败并出现相同的错误。在这种情况下,我得到错误A和:

的混合
 System.Net.Mail.SmtpException: Failure sending mail. ---> System.Net.WebException: The operation has timed out.
   at System.Net.ConnectionPool.Get(Object owningObject, Int32 result, Boolean& continueLoop, WaitHandle[]& waitHandles)
   at System.Net.ConnectionPool.GetConnection(Object owningObject, GeneralAsyncDelegate asyncCallback, Int32 creationTimeout)
   at System.Net.Mail.SmtpConnection.GetConnection(ServicePoint servicePoint)
   at System.Net.Mail.SmtpTransport.GetConnection(ServicePoint servicePoint)
   at System.Net.Mail.SmtpClient.GetConnection()
   at System.Net.Mail.SmtpClient.Send(MailMessage message)
   --- End of inner exception stack trace ---
   at System.Net.Mail.SmtpClient.Send(MailMessage message)
   at Cobranzas.WinService.Email.SendEmail(String subject, String body, String mailTo, String attPath)
   at Cobranzas.WinService.CobranzasEmailService.SendEmails(IEnumerable`1 toSend, RepositoryEf emailRepo)

我的服务逻辑如下:我有一个计时器,每隔5分钟就会重复发送很多电子邮件,每次执行

Thread.Sleep(2000); 
try
{
    emailService.SendEmail(asunto, nuevoCuerpo, mail.Email, mail.AlertMessage.Attach);
}
catch (Exception ex)
{
    if (ex is System.Net.Mail.SmtpException)
    {
        Thread.Sleep(20000); // Lo hacemos esperar 20 segundos
    }
}

SendEmail方法是:

var mailMessage = new MailMessage();

mailMessage.To.Add(mailTo);

mailMessage.Subject = subject;
mailMessage.Body = WebUtility.HtmlDecode(body);
mailMessage.IsBodyHtml = true;
mailMessage.From = new MailAddress(emailFromAddress, emailFromName); 
mailMessage.Headers.Add("Content-type", "text/html; charset=iso-8859-1");

// Attachment
if (attPath != null)
{
    var data = new Attachment(attPath, MediaTypeNames.Application.Octet);
    mailMessage.Attachments.Add(data);
}

var cred =
    new NetworkCredential(emailFromAddress, emailFromPassword); 

using (var mailClient =
    new SmtpClient(emailSmtpClient, emailSmtpPort) 
                     {
                         EnableSsl = true,
                         DeliveryMethod = SmtpDeliveryMethod.Network,
                         UseDefaultCredentials = false,
                         Timeout = 20000,
                         Credentials = cred
                     })
{
    mailClient.Send(mailMessage);
}

foreach (Attachment attachment in mailMessage.Attachments)
{
    attachment.Dispose();
}

使用SmtpClient和附件处理是新的,我们添加它们试图解决这个问题。没有行为改变。 T̶h̶e̶̶T̶h̶r̶e̶a̶d̶.̶S̶l̶e̶e̶p̶̶a̶f̶t̶e̶r̶̶t̶h̶e̶̶t̶i̶m̶e̶o̶u̶t̶̶̶̶̶̶̶̶̶̶̶̶̶̶̶̶̶̶̶̶̶̶̶̶<<<<。

鉴于重新启动服务修复了它,我怀疑没有正确关闭/清理的东西,但我已经检查过,无法找到它可能是什么。我刚才发现了this链接,但看起来很旧。

非常感谢任何帮助!

[PROGRESS]

我已经测试了超时后的20“等待,没有,它仍然以同样的方式失败。有什么想法吗?我们真的很难过。

2 个答案:

答案 0 :(得分:10)

我有完全相同的问题。我在这里找到了解决方案:

发出两个以上并发WebRequest时发生System.Net.WebException http://www.wadewegner.com/2007/08/systemnetwebexception-when-issuing-more-than-two-concurrent-webrequests/

基本上,我将同时允许的最大连接数更改为单个外部服务器。默认情况下,根据该文档它是2.虽然,它有一个超时(它等待一个时间,直到一个被释放然后继续),有时,它是不够的,它挂起。

<configuration>
    <system.net>
        <connectionManagement>
        <add address="*" maxconnection="100" />
        </connectionManagement>
    </system.net>
</configuration>

我无法在第一次超时后找到如何恢复,但希望这会在一段时间内消除“超时”错误。

答案 1 :(得分:0)

增加最大连接数可能会有所帮助,但我不能 100% 确定它是否不会推迟问题,直到达到这些连接数。我决定改用 MailKit。它有自己的 SMTP 客户端实现,几乎是替代品,可以使用常规 MailMessage 对象(如果您依赖它)。它根本不使用连接池,所以它可能是一个更安全的解决方案。