smtp-клиенты, метод `SendAsync()`

 Protected Sub btnLocalSubmit_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnLocalSubmit.Click

            Dim logic = New connections
            logic.emailsToSend(User.Identity.Name, getURL, reportedBy)
            SendAsync()
            Response.Redirect(getRedirectionPath, False)
        Catch ex As Exception
            Response.Write(ex.Message)
        Finally
            _con.Close()
            _con.Dispose()
            _sqlComm.Dispose()

        End Try
    End Sub

    Sub SendAsync()

        Dim _con As New SqlConnection(ConfigurationManager.ConnectionStrings("CitizenJDBConnectionString").ConnectionString)
        Dim _sqlDataAdapter As New SqlDataAdapter("SELECT * FROM EmailSender", _con)
        Dim _table As New System.Data.DataTable

        Try
            _con.Open()
            _sqlDataAdapter.Fill(_table)
            _con.Close()

            For i As Integer = 0 To _table.Rows.Count - 1


                Dim AppPath As String = Request.PhysicalApplicationPath

                Dim sr As New StreamReader(AppPath & "EmailTemplates/NewReport.txt")
                Dim message As New MailMessage()

                message.IsBodyHtml = True

                message.From = New MailAddress("[email protected]")

                message.To.Add(New MailAddress(_table.Rows(i).Item(1)))


                message.Subject = "New User registration !"

                message.Body = sr.ReadToEnd()

                sr.Close()

                message.Body = message.Body.Replace("<%ReporterName%>", _table.Rows(i).Item(3))

                message.Body = message.Body.Replace("<%ReportURL%>", _table.Rows(i).Item(2))

                Dim client As New SmtpClient()
                client.Host = "smtp.xxxxx.com"
                'smtp.gmail.com
                client.Port = 25
                client.UseDefaultCredentials = True
                client.Credentials = New System.Net.NetworkCredential("[email protected]", "123456")
                'client.EnableSsl = True
                Dim userState As Object = message

                'wire up the event for when the Async send is completed
                AddHandler client.SendCompleted, AddressOf SmtpClient_OnCompleted

                client.SendAsync(message, userState)

            Next

        Catch ex As Exception
            Response.Write(ex.Message)
        End Try


    End Sub 'SendAsync

    Public Sub SmtpClient_OnCompleted(ByVal sender As Object, ByVal e As AsyncCompletedEventArgs)
        'Get the Original MailMessage object
        Dim message As MailMessage = CType(e.UserState, MailMessage)

        'write out the subject
        Dim subject As String = message.Subject

        If e.Cancelled Then
            Console.WriteLine("Send canceled for mail with subject [{0}].", subject)
        End If
        If Not (e.Error Is Nothing) Then
            Console.WriteLine("Error {1} occurred when sending mail [{0}] ", subject, e.Error.ToString())
        Else
            Console.WriteLine("Message [{0}] sent.", subject)
        End If
    End Sub 'SmtpClient_OnCompleted

Я использую функцию smtp-клиентов SendAsync() для асинхронной отправки писем... но эта функция не работает... почему?? я не получаю никаких электронных писем... когда я отправляю их синхронно... я получаю электронные письма, это означает, что мои настройки верны... так что же не так с методом SendAsync()??


person user1150440    schedule 18.03.2012    source источник
comment
Вы пробовали отправлять синхронно и проверять наличие ошибок?   -  person    schedule 18.03.2012
comment
Похоже, вы правильно используете SendAsync() (согласно моему предложению). Несколько вещей приходят на ум: - Сколько писем вы отправляете? возможно, удаленный хост запрещает/регулирует соединения, потому что они приходят слишком быстро. - Настройте Visual Studio на прерывание всех исключений (Отладка -> Исключения), чтобы увидеть, не выдается ли SmtpException в другом потоке. - Получаете ли вы какую-либо информацию от обратного вызова? Предполагается, что он содержит сообщение об ошибке (и ваш код выглядит так, как будто он пришел прямо из MSDN, поэтому он должен быть правильным)   -  person Tim Medora    schedule 18.03.2012
comment
Вы должны подключиться к SendCompleted событие и посмотрите, было ли возвращено вам исключение.   -  person casperOne    schedule 18.03.2012
comment
на данный момент я отправляю только 3 письма... я не могу отлаживать, потому что я нахожусь за прокси-сервером (мой колледж использует один), поэтому письма не отправляются, так как нет возможности установить настройки прокси с помощью smtp... поэтому я разверните проект и попробуйте отправить письмо, чтобы проверить его.   -  person user1150440    schedule 18.03.2012
comment
я пробовал Response.Write(ex.message) и у меня не получилось отправить почту   -  person user1150440    schedule 18.03.2012
comment
@TimMedora Я добавил Async="true" в директиву страницы, и теперь она работает нормально ... но долго ждет и отправляет электронное письмо, а затем обновляет страницу ... я имею в виду, что с помощью Async="true" она работает, но как синхронная почта.   -  person user1150440    schedule 18.03.2012
comment
@TimMedora http://stackoverflow.com/questions/9756936/can-anyone-explain-this   -  person user1150440    schedule 18.03.2012
comment
@TimMedora мне помогла эта статья решить проблему ... Спасибо за ваше время.   -  person user1150440    schedule 18.03.2012


Ответы (1)


Я делаю это все время, и после многих лет я предлагаю (2) решение вашей проблемы:

  1. Рефакторинг фактического кода отправки электронной почты (материал System.Net) в службу WCF или отдельную .dll (я предпочитаю службу).
  2. Продолжайте использовать асинхронный вызов делегата со своей страницы ASP.NET, но делайте это по принципу «запустил и забыл», когда вы не подключаете никаких обратных вызовов.

Вы можете сказать, что вам нужно знать, если что-то пошло не так с отправкой электронного письма. Пусть служба WCF, которая отправляет электронные письма, обрабатывает это. Сделайте любую регистрацию в сервисе. В конце концов, все, что вы действительно делали в любом случае, это ведение журнала. Если вам нужно усложнить рабочий процесс в случае сбоя электронной почты, есть способы, которыми ваш ASP.NET может быть помечен, но я думаю, вы обнаружите, что как только служба для отправки электронных писем станет стабильной, у вас будет очень мало проблем.

Фактически, я использовал именно этот метод в течение многих лет, используя службу, называемую ASP.NET, для отправки электронных писем и отправил 10 тысяч различных электронных писем, и у меня никогда не было проблем с этим дизайном «выстрелил и забыл».

И, наконец, установка страницы Async=True заставляет страницу действовать в целом синхронно в конце, блокируя основной поток, пока не будут завершены все асинхронные процессы. Это может замедлить загрузку страниц и, как правило, нежелательно.

person atconway    schedule 28.03.2012