私は過去 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回実行され、何らかの形で競合しているということだけです??? 私は途方に暮れています….何が起こっているのかについて誰かが洞察を与えることができれば、それは多かれ少なかれ私の月になるでしょう! :/