Отправка почты через цикл отправляет несколько писем на один и тот же адрес

#vb.net #smtp #sendmail

#vb.net #smtp #отправить почту

Вопрос:

Я пытаюсь отправить электронное письмо кандидатам, которые подали заявку на работу, иногда мне нужно отправить несколько сотен или даже тысяч писем, поэтому код будет полезным.

Это то, что я написал, но проблема в том, что почта отправляется несколько раз на один и тот же адрес (на некоторые адреса один или два раза, а иногда и больше).

Небольшое объяснение приведенного ниже кода. Код считывает активную базу данных заданий и выбирает кандидатов, которые не были включены (столбец FMZ в базе данных, «X»), затем считывает уникальный идентификатор кандидата в другой базе данных для адреса электронной почты, на который будет отправлено письмо. Даже базовый msgbox, приведенный ниже SmtpServer.Send(mail) , активируется для каждого кандидата только один раз, но почта отправляется несколько раз. Вот код.

 'Step 1 - All candidates in DBAP that applied for ClientID/Job ID
For i As Integer = 0 To dsPoslovi.Tables(0).Rows.Count - 1
    If dsPoslovi.Tables(0).Rows(i)(1).ToString() = ATS_IDKlijent AndAlso dsPoslovi.Tables(0).Rows(i)(2).ToString() = ATS_IDPosao Then
        'Step 2 - Send mails to those not contacted yet (X in FMZ column)
        If dsPoslovi.Tables(0).Rows(i)(8).ToString() <> "X" Then
            IDKandidataAP = dsPoslovi.Tables(0).Rows(i)(0).ToString()
            IDKandidataAP2 = dsPoslovi.Tables(0).Rows(i)(3).ToString()
            'Read mail addresses
            For x As Integer = 0 To dsCL.Tables(0).Rows.Count - 1
                If dsPoslovi.Tables(0).Rows(i)(3).ToString() = dsCL.Tables(0).Rows(x)(1).ToString() Then

                    MailKandidata = dsCL.Tables(0).Rows(x)(7).ToString()

                    If MailKandidata.Contains("@") = True Then
                        SmtpServer.Send(mail)
                        MsgBox(MailKandidata)
                    End If
                End If
            Next

            'Update active job database
            Dim cmd As New OleDbCommand(query, myCONN)
            myCONN.Open()
            cmd.Parameters.AddWithValue("FMZ", "X")
            cmd.Parameters.AddWithValue("ID", IDKandidataAP)

            cmd.ExecuteNonQuery()
            myCONN.Close()

        End If

    End If
Next
 

Комментарии:

1. Отсутствует некоторый код: как mail определяется и изменяется. Я предполагаю, что вы добавляете одного и того же получателя к mail объекту несколько раз. Вы можете проверить и / или опубликовать код здесь.

2. Спасибо. Я этого не знал (SmtpServer. Отправка (почта)) не должна быть в цикле, только mail.To.Add(

Ответ №1:

Поскольку я не люблю печатать, я разрешил значение DataSet.Tables a DataTable и перебрал Rows коллекцию. Для меня это более читабельно.

Я думаю, что проблема в mail.To коллекции. Каждая итерация добавляет получателя и отправляет электронное письмо каждому получателю. Я создаю коллекцию внутри циклов и отправляю почту только один раз вне цикла. Почта будет отправлена каждому получателю в коллекции.

Я не уверен, что происходит с. IDKandidataAP2 Похоже, что он не используется в этом методе и перезаписывается на каждой итерации.

Я исправил код базы данных. Соединение и команда должны быть объявлены в Using блоке один раз вне циклов. Я создаю коллекцию параметров вне цикла и изменяю значение параметра @ID только внутри цикла. Я догадался, как может выглядеть строка обновления. Этот Add метод предпочтительнее AddWithValue . Я догадался о типах данных. Проверьте свою базу данных на наличие фактических типов.

 Private ATS_IDKlijent As String = "" '?
Private ATS_IDPosao As String = "" '?
Private dsCL As New DataSet
Private dsPoslovi As New DataSet
Private mail As New MailMessage
Private SmtpServer As New SmtpClient()
Private IDKandidataAP As String
Private IDKandidataAP2 As String

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    Dim dt As DataTable = dsPoslovi.Tables(0)
    'Step 1 - All candidates in DBAP that applied for ClientID/Job ID
    Dim query = "Update SomeTable Set FMZ = @FMZ Where ID = @ID;"
    Using myCONN As New OleDbConnection("Your connection string"),
            cmd As New OleDbCommand(query, myCONN)
        cmd.Parameters.Add("@FMZ", OleDbType.VarChar).Value = "X"
        cmd.Parameters.Add("@ID", OleDbType.VarChar)
        myCONN.Open()
        For Each row As DataRow In dt.Rows
            If row(1).ToString() = ATS_IDKlijent AndAlso row(2).ToString() = ATS_IDPosao Then
                'Step 2 - Send mails to those not contacted yet (X in FMZ column)
                If row(8).ToString() <> "X" Then
                    IDKandidataAP = row(0).ToString()
                    IDKandidataAP2 = row(3).ToString()
                    'Read mail addresses
                    Dim dt2 As DataTable = dsCL.Tables(0)
                    For Each row2 As DataRow In dt2.Rows
                        If row(3).ToString() = row2(1).ToString() Then
                            Dim MailKandidata = row2(7).ToString()
                            If MailKandidata.Contains("@") = True Then
                                Dim ToAddress As New MailAddress(MailKandidata)
                                mail.To.Add(ToAddress)
                                MsgBox(MailKandidata)
                            End If
                        End If
                    Next
                    'Update active job database
                    cmd.Parameters("@ID").Value = IDKandidataAP
                    cmd.ExecuteNonQuery()
                End If
            End If
        Next
    End Using 'Closes and disposes the connection and disposes the command.
    SmtpServer.Send(mail)
End Sub