Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Vb.net 内部exchange smtp服务器上包含system.net.mail的大量邮件超时_Vb.net_System.net.mail - Fatal编程技术网

Vb.net 内部exchange smtp服务器上包含system.net.mail的大量邮件超时

Vb.net 内部exchange smtp服务器上包含system.net.mail的大量邮件超时,vb.net,system.net.mail,Vb.net,System.net.mail,我正在制定一个计划,每周向我们公司的每位销售员工发送提醒/更新。每周大约120个,自动化,在短时间内完成。这是一个内部程序,仅面向内部收件人,我不担心垃圾邮件或不想要的消息,取消订阅也不是一个选项。每封邮件都根据每位销售人员的客户列表进行个性化处理,并包含每周“待办事项”,供他们致电客户 我在内部运行呼气2007,为我的开发环境和运行这些自动化项目的服务器提供了一个开放的内部SMTP连接器。该程序在一两家商店中运行良好,但当我为每家商店运行它时,在发送110条消息后,我会在某处超时 我并没有尝试

我正在制定一个计划,每周向我们公司的每位销售员工发送提醒/更新。每周大约120个,自动化,在短时间内完成。这是一个内部程序,仅面向内部收件人,我不担心垃圾邮件或不想要的消息,取消订阅也不是一个选项。每封邮件都根据每位销售人员的客户列表进行个性化处理,并包含每周“待办事项”,供他们致电客户

我在内部运行呼气2007,为我的开发环境和运行这些自动化项目的服务器提供了一个开放的内部SMTP连接器。该程序在一两家商店中运行良好,但当我为每家商店运行它时,在发送110条消息后,我会在某处超时

我并没有尝试将邮件排队或将它们分块存放,当我遍历销售人员列表,并执行每个相应的查找和邮件生成时,我正在尝试使用以下子项发送邮件

Sub doMail(ByRef MessageBody As String, ByVal nameString As String, ByVal sendTo As ArrayList, Optional ByVal markurgent As Boolean = False, _
                 Optional ByVal sendCC As ArrayList = Nothing, Optional ByVal sendBcc As ArrayList = Nothing)
    Try
        ' Setup Mail Message
        Dim oClient As SmtpClient = New SmtpClient(ConfigurationManager.AppSettings("mail_server").ToString())
        oClient.Timeout = 20000
        'oClient.Port = 50747
        Dim objMessage As New MailMessage()
        objMessage.From = New System.Net.Mail.MailAddress(ConfigurationManager.AppSettings("mail_from_address").ToString, ConfigurationManager.AppSettings("mail_from_name").ToString)
        objMessage.Subject = String.Format("Weekly Hitlist Report ~ {0}", nameString)

        If (ConfigurationManager.AppSettings("debugMode").ToString() = 1) Then
            Dim debugSB As StringBuilder = New StringBuilder

            For Each s As String In sendTo
                debugSB.AppendLine(String.Format("To: {0}<br>", s))
            Next
            For Each s As String In sendCC
                debugSB.AppendLine(String.Format("cc: {0}<br>", s))
            Next
            For Each s As String In sendBcc
                debugSB.AppendLine(String.Format("bcc: {0}<br>", s))
            Next
            MessageBody = String.Format("Debug Mode is Active. <br> {0} <br><hr noshade>{1}", debugSB.ToString, MessageBody)
            objMessage.To.Add(ConfigurationManager.AppSettings("mail_to_address").ToString)
        Else
            For Each receiver As String In sendTo
                Try
                    objMessage.To.Add(receiver.Trim())
                Catch ex As Exception
                    ' do nothing
                End Try
            Next
            For Each receiver As String In sendCC.ToArray
                Try
                    objMessage.CC.Add(receiver.Trim())
                Catch ex As Exception
                    ' do nothing
                End Try
            Next
            For Each receiver As String In sendBcc
                Try
                    objMessage.Bcc.Add(receiver.Trim())
                Catch ex As Exception
                    ' do nothing
                End Try
            Next
        End If



        objMessage.Body = MessageBody
        objMessage.Priority = IIf(markurgent, MailPriority.High, MailPriority.Normal)
        objMessage.IsBodyHtml = True
        oClient.Send(objMessage)
        oClient = Nothing
        Console.WriteLine(String.Format("{1} - message sent - {0} ", nameString, Now()))
    Catch ex As Exception
        Console.WriteLine(ex.Message)
        Console.WriteLine("****************")
        Console.WriteLine(ex.StackTrace)
    End Try
End Sub
我还尝试发送每个单独的商店和较小的子集。我只在一次为整个公司运行时收到此错误


我没有看到任何禁止此操作的交换,也没有看到高消息队列在等待。有没有关于发送消息的其他方法或其他尝试的建议?(我不希望使用第三方dll或外部组件)。

我经历了这个问题的痛苦。经过2年的研究,我还没能找出我的.net应用程序出现问题的确切原因。有许多问题和实施选项将有助于将此异常的影响降至最低。我们现在已经到了这样一个地步:这个问题不会以明显的方式影响最终用户

  • 您需要确保在*.config中设置了一些SMTP配置变量,以帮助根据您的环境调整应用程序。SMTP客户端超时、重试尝试、重试间隔时间等。我们发现在完全停止之前,尝试间隔约20秒,尝试间隔约5秒
  • 您将需要实现一个日志机制来记录它们发生的时间和频率,以便您可以设置上面的变量。我从机器和服务器事件日志中查找电子邮件的数量、一天中的时间、service pack安装、病毒检查器或防火墙干扰,试图找到原因
  • 实现一个non来管理所有电子邮件的发送,因为如果您通过代码发送大量邮件,您将遇到SMTP 4.4.1超时错误。这是一种模式,我发现这是一个相对容易实现的实现,对于这个问题非常成功。队列允许您确保电子邮件最终被发送。如果您想要一个完全的故障保护,您还可以将该队列持久化到磁盘。我们永远不需要依赖于那段代码
  • 在没有第三方工具的情况下,伪造或模拟.net SMTP实现来对代码进行单元测试是不容易的。我没有走这条路,因为在一天结束时,有太多的部分超出了我的控制。基本上,我只是假设它总是会失败,我放置了很多备用选项,等待问题自行解决
  • 我们尝试过的方法似乎对4.4.1超时异常的频率没有影响

  • 限制电子邮件发送到exchange的速率
  • 更改一天中的发送时间(也称为小时外)
  • 将电子邮件批处理成小块,然后通过垃圾收集从内存中清除所有.net组件
  • 希望有帮助

    代码窃贼

    ''' <summary>
    ''' Provide a mechanism to throttle the subsequent attempts to send emails.
    ''' </summary>
    ''' <param name="emailAddress"></param>
    ''' <param name="attemptNumber"></param>
    ''' <remarks>Need to implement a more dynamic function as attempts persist, pause for longer for a number of attempt, then add the email to a failed queue.</remarks>
    Private Shared Sub RestBeforeSendingAgain(ByVal emailAddress As String, ByVal attemptNumber As Integer)
    
        If attemptNumber > 1 Then
    
            '   Wait 30 seconds in between every attempt, or the value configured in the config file.
            Dim retryIntervalInSeconds As Integer = 30
            If Not String.IsNullOrEmpty(System.Configuration.ConfigurationManager.AppSettings.Item("SMTPFailureReTryIntervalInSeconds")) Then
                Integer.TryParse(System.Configuration.ConfigurationManager.AppSettings.Item("SMTPFailureReTryIntervalInSeconds"), retryIntervalInSeconds)
            End If
            logger.Warn("Problem emailing {0}. Waiting {1} seconds to help clear technical issues.", emailAddress, retryIntervalInSeconds.ToString)
            System.Threading.Thread.Sleep(System.TimeSpan.FromSeconds(retryIntervalInSeconds))
    
        End If
    End Sub
    
        ''' <summary>
    ''' Attempt to send an email message and record any issues with that mailmessage to the application log.
    ''' Allows the process to know the success or failure of that approach.
    ''' </summary>
    ''' <param name="mailClient"></param>
    ''' <param name="mailMessage"></param>
    ''' <param name="attemptNumber"></param>
    ''' <returns>The success or failure of the SMTP server to send the message without causing an error.</returns>
    ''' <remarks></remarks>
    Private Shared Function AttemptToSendEmail(ByRef mailClient As System.Net.Mail.SmtpClient, ByRef mailMessage As MailMessage, ByVal attemptNumber As Integer) As Boolean
        Dim result As Boolean = False
        Try
            logger.Trace("Started: AttemptToSendEmail", attemptNumber)
    
            RestBeforeSendingAgain(mailMessage.To.ToString, attemptNumber)
            mailClient.Send(mailMessage)
            result = True
    
        Catch smtpEx As SmtpException
            result = False
            logger.ErrorException(String.Format("{3}{1}{0}{1}{2}", ExceptionFormater.FormatException(smtpEx), Environment.NewLine, ExceptionFormater.FormatStack(smtpEx), "AttemptToSendEmail failed with Smtp exception."), smtpEx)
    
        Catch ex As Exception
            result = False
            logger.ErrorException(String.Format("{3}{1}{0}{1}{2}", ExceptionFormater.FormatException(ex), Environment.NewLine, ExceptionFormater.FormatStack(ex), "AttemptToSendEmail failed with generic exception."), ex)
    
        Finally
    
            If result Then
                logger.Trace("Succeeded: To email {0} on attempt {1}.", mailMessage.To.ToString, attemptNumber)
            Else
                logger.Warn("Failed: To email {0} on attempt {1}.", mailMessage.To.ToString, attemptNumber)
            End If
    
        End Try
    
        Return result
    
    End Function
    
    '   Configure the timeout in milliseconds from the App.Config file.
    '   200 seconds = 200,000 miliseconds
    MySmtpClient.Timeout = CInt(TimeSpan.FromSeconds(SmtpClientTimeoutSeconds).TotalMilliseconds)
    
    “”
    ''提供一种机制来阻止后续发送电子邮件的尝试。
    ''' 
    ''' 
    ''' 
    ''需要在尝试持续时实现更具动态性的功能,暂停更长时间以进行多次尝试,然后将电子邮件添加到失败队列。
    发送增益之前的私有共享子REST(ByVal emailAddress为字符串,ByVal attemptNumber为整数)
    如果尝试次数>1,则
    '在每次尝试或配置文件中配置的值之间等待30秒。
    Dim retryIntervalInSeconds为整数=30
    如果不是String.IsNullOrEmpty(System.Configuration.ConfigurationManager.AppSettings.Item(“SMTPFailureReTryIntervalInSeconds”)),则
    Integer.TryParse(System.Configuration.ConfigurationManager.AppSettings.Item(“SMTPFailureReTryIntervalInSeconds”),retryIntervalInSeconds)
    如果结束
    logger.Warn(“发送问题电子邮件{0}。等待{1}秒以帮助清除技术问题。”,emailAddress,retryIntervalInSeconds.ToString)
    System.Threading.Thread.Sleep(System.TimeSpan.FromSeconds(retryIntervalInSeconds))
    如果结束
    端接头
    ''' 
    ''尝试发送电子邮件,并将该邮件的任何问题记录到应用程序日志中。
    ''允许流程了解该方法的成功或失败。
    ''' 
    ''' 
    ''' 
    ''' 
    ''SMTP服务器发送邮件而不导致错误的成功或失败。
    ''' 
    私有共享函数attemptosendemail(ByRef mailClient作为System.Net.Mail.SmtpClient,ByRef mailMessage作为mailMessage,ByVal attemptNumber作为整数)作为布尔值
    将结果设置为布尔值=False
    尝试
    Trace(“启动:attemptosendemail”,attemptNumber)
    RestBeforeSendingAgain(mailMessage.To.ToString,attemptNumber)
    mailClient.Send(mailMessage)
    结果=真
    将smtpEx捕获为SmtpException
    结果=错误
    logger.ErrorException(String.Format(“{3}{1}{0}{1}{2}”)、ExceptionFormatter.FormatException(smtpEx)、Environment.NewLine、ExceptionFormatter.FormatStack(smtpEx)、“AttemptoSendmail因Smtp异常而失败”)、smtpEx)
    特例
    结果=错误
    logger.ErrorException(String.Format(“{3}{1}{0}{1}{2}”),ExceptionFormatter.FormatException(ex),Environment.New
    
    ''' <summary>
    ''' Provide a mechanism to throttle the subsequent attempts to send emails.
    ''' </summary>
    ''' <param name="emailAddress"></param>
    ''' <param name="attemptNumber"></param>
    ''' <remarks>Need to implement a more dynamic function as attempts persist, pause for longer for a number of attempt, then add the email to a failed queue.</remarks>
    Private Shared Sub RestBeforeSendingAgain(ByVal emailAddress As String, ByVal attemptNumber As Integer)
    
        If attemptNumber > 1 Then
    
            '   Wait 30 seconds in between every attempt, or the value configured in the config file.
            Dim retryIntervalInSeconds As Integer = 30
            If Not String.IsNullOrEmpty(System.Configuration.ConfigurationManager.AppSettings.Item("SMTPFailureReTryIntervalInSeconds")) Then
                Integer.TryParse(System.Configuration.ConfigurationManager.AppSettings.Item("SMTPFailureReTryIntervalInSeconds"), retryIntervalInSeconds)
            End If
            logger.Warn("Problem emailing {0}. Waiting {1} seconds to help clear technical issues.", emailAddress, retryIntervalInSeconds.ToString)
            System.Threading.Thread.Sleep(System.TimeSpan.FromSeconds(retryIntervalInSeconds))
    
        End If
    End Sub
    
        ''' <summary>
    ''' Attempt to send an email message and record any issues with that mailmessage to the application log.
    ''' Allows the process to know the success or failure of that approach.
    ''' </summary>
    ''' <param name="mailClient"></param>
    ''' <param name="mailMessage"></param>
    ''' <param name="attemptNumber"></param>
    ''' <returns>The success or failure of the SMTP server to send the message without causing an error.</returns>
    ''' <remarks></remarks>
    Private Shared Function AttemptToSendEmail(ByRef mailClient As System.Net.Mail.SmtpClient, ByRef mailMessage As MailMessage, ByVal attemptNumber As Integer) As Boolean
        Dim result As Boolean = False
        Try
            logger.Trace("Started: AttemptToSendEmail", attemptNumber)
    
            RestBeforeSendingAgain(mailMessage.To.ToString, attemptNumber)
            mailClient.Send(mailMessage)
            result = True
    
        Catch smtpEx As SmtpException
            result = False
            logger.ErrorException(String.Format("{3}{1}{0}{1}{2}", ExceptionFormater.FormatException(smtpEx), Environment.NewLine, ExceptionFormater.FormatStack(smtpEx), "AttemptToSendEmail failed with Smtp exception."), smtpEx)
    
        Catch ex As Exception
            result = False
            logger.ErrorException(String.Format("{3}{1}{0}{1}{2}", ExceptionFormater.FormatException(ex), Environment.NewLine, ExceptionFormater.FormatStack(ex), "AttemptToSendEmail failed with generic exception."), ex)
    
        Finally
    
            If result Then
                logger.Trace("Succeeded: To email {0} on attempt {1}.", mailMessage.To.ToString, attemptNumber)
            Else
                logger.Warn("Failed: To email {0} on attempt {1}.", mailMessage.To.ToString, attemptNumber)
            End If
    
        End Try
    
        Return result
    
    End Function
    
    '   Configure the timeout in milliseconds from the App.Config file.
    '   200 seconds = 200,000 miliseconds
    MySmtpClient.Timeout = CInt(TimeSpan.FromSeconds(SmtpClientTimeoutSeconds).TotalMilliseconds)