1

私は過去 2 週間、この問題を解決するのに苦労してきました。できる限り絞り込んで、誰かが私の分析を確認し、おそらく行動方針を提案できることを期待して、これを投稿しています.

全員が同じページにいるように、アプリケーションのこの時点までに何が起こっているかを順を追って説明します。このアプリケーションは、データベースにクエリを実行し、ユーザー情報とユーザーの電子メール アドレスを含む 3 つのランダム レコードを取得するように作成されています。次に、返された各レコードのタイプを確認し、タイプに基づいて電子メールを送信します。私はこのプロセスをローカルでテストし、毎回問題なく実行されますが、これが実行可能ファイルにコンパイルされ、サーバーに配置されて 15 分ごとに実行されると、ユーザーは同じメールを複数受信することに不満を持ち始めました。記録….コードの一部を投稿し、この時点までにわかったことを説明します。

Module Module1

Sub Main()

    CreateExecutionLogFile(DateTime.Now.ToString, "BEGIN")

    Dim dtEmails As DataTable = RetreiveEmailsToSend()

    For Each dr As DataRow In dtEmails.Rows
        With dr
            Select Case .Item("EmailType").ToString.Trim
                Case "NEW"
                    SendNewEmail(.Item("EmpUserID").ToString.Trim, .Item("EmpEmailAddress").ToString.Trim, .Item("EmpFullName").ToString.Trim, _
                                       CInt(.Item("RecordIDPK").ToString.Trim), .Item("SupervisorEmailAddress").ToString.Trim)
                Case "24H"
                    Send24hEmail(.Item("EmpUserID").ToString.Trim, .Item("EmpEmailAddress").ToString.Trim, .Item("EmpFullName").ToString.Trim, _
                                       CInt(.Item("RecordIDPK").ToString.Trim), .Item("SupervisorEmailAddress").ToString.Trim)
                Case "48H"
                    Send48hEmail(.Item("EmpUserID").ToString.Trim, .Item("EmpEmailAddress").ToString.Trim, .Item("EmpFullName").ToString.Trim, _
                                       CInt(.Item("RecordIDPK").ToString.Trim), .Item("SupervisorEmailAddress").ToString.Trim)
            End Select
            UpdateRecordAfterEmail(CInt(.Item("RecordIDPK").ToString.Trim), .Item("EmailType").ToString.Trim)
        End With
    Next

    CreateExecutionLogFile(DateTime.Now.ToString, "END")

End Sub

''Send24hEmail() and Send48hEmail() are mirrors of this function with only the wording in the email body being changed
''therefore I only include the following function to make things easier to read in this post
Private Sub SendNewEmail(ByVal EmpUserID As String, ByVal EmpEmailAddress As String, ByVal EmpFullName As String, ByVal RecordID As Integer, ByVal SupEmailAddress As String)
    Dim strFrom As String = "DoNotReply@test.place"
    Dim strTo As String = EmpEmailAddress
    Dim strSubject As String = "TEST SUBJECT"
    Dim strCC As String = SupEmailAddress.Trim
    Dim strMessage As New StringBuilder

    With strMessage
        .Append("Hello!//EMAIL BODY IS BUILT HERE")
        .Append(DateTime.Now.ToString())
    End With

    SendEmail(strFrom, strTo, strSubject, strMessage.ToString, strCC, RecordID.ToString, "NEW", EmpUserID)
End Sub

Private Sub UpdateRecordAfterEmail(ByVal RecordID As Integer, ByVal EmailType As String)
    'Connects to database and runs query to update the record as sent
End Sub

Public Sub SendEmail(ByVal strFrom As String, ByVal strTo As String, ByVal strSubject As String, ByVal strMessage As String, ByVal strCC As String, ByVal recordID As String, ByVal type As String, ByVal userID As String)
    If CheckIfEmailSent(recordID, type) = False Then
        If strTo > "" Then
            Try
                Dim MailMsg As New MailMessage()
                strTo = strTo.Trim(CChar(","))

                MailMsg.To.Add(strTo)

                If strCC.Trim <> "" Then
                    MailMsg.CC.Add(strCC)
                End If

                MailMsg.From = New MailAddress(strFrom, "FROM MESSAGE")
                MailMsg.BodyEncoding = Encoding.Default
                MailMsg.Subject = strSubject.Trim()
                MailMsg.Body = strMessage.Trim() & vbCrLf
                MailMsg.Priority = MailPriority.High
                MailMsg.IsBodyHtml = False

                Dim mailClient As New SmtpClient("mail.name.place")
                mailClient.UseDefaultCredentials = True
                mailClient.Send(MailMsg)
                MailMsg.Dispose()

                CreateLogFile(recordID, type, userID, strTo)

            Catch innerException As Exception

                Dim MailMsg As New MailMessage()

                MailMsg.To.Add("nullReference@name.place")

                MailMsg.From = New MailAddress(strFrom, "FROM MESSAGE - ERROR")
                MailMsg.BodyEncoding = Encoding.Default
                MailMsg.Subject = strSubject.Trim()
                MailMsg.Body = strMessage.Trim() & vbCrLf & vbCrLf & vbCrLf & innerException.Message
                MailMsg.Priority = MailPriority.High
                MailMsg.IsBodyHtml = False

                Dim mailClient As New SmtpClient("mail.name.place")
                mailClient.UseDefaultCredentials = True
                mailClient.Send(MailMsg)
                MailMsg.Dispose()

            End Try
        End If
    Else
        CreateLogFile("*ERROR* ATTEMPTED RESEND" + " " + recordID, type, userID, strTo)
    End If

End Sub

Private Function CheckIfEmailSent(recordID As Integer, type As String) As Boolean
    ''Connect to database determine if recordID has already been sent
    ''If it has return true, else return false
End Function

Private Sub CreateLogFile(ByVal recordID, ByVal type, ByVal userID, ByVal email)
    ''Create log file on server containing information passed to function and
    ''current datetime
End Sub

Private Sub CreateExecutionLogFile(time As String, beginEnd As String)
    ''Create log file on server containing the time passed and either "BEGIN"
    ''or "END" depending on the value in "beginEnd"
End Sub

End Module

私は元々、データベースに接続する SendEmail() ルーチン (CheckIfEmailSent()) 内にパッチを配置し、別の電子メールを送信する前に、レコードが既に送信済みとしてマークされているかどうかを確認していました。これで問題はすぐに解決すると思いましたが、すぐに間違っていることがわかりました。

上記のパッチの後も問題が持続したため、smtp メール クライアントがハングアップして複数の電子メールを送信したことに関係があると考え始めましたが、そうではないことに気付きました。つまり、SendEmail() 関数に送信される前に、SendNewEmail() 関数を 2 回実行して、メールの本文文字列に配置する新しい時刻値を生成する必要がありました….0_0….はい… .

電子メールが送信されるたびに書き込まれるログ ファイルには、最初の電子メールが送信されたことが示されるだけで、2 番目の電子メールは記録されません。さらに奇妙なことです。この時点で私が考えられる唯一のことは、プロセスがサーバーから最初に1回、次に最初のプロセスがまだ実行されている間に2回実行され、何らかの形で競合しているということだけです??? 私は途方に暮れています….何が起こっているのかについて誰かが洞察を与えることができれば、それは多かれ少なかれ私の月になるでしょう! :/

4

1 に答える 1