循环发送邮件时同一收件地址重复收到多封邮件问题求助
批量发信重复收件问题根因及修复方案
问题根因
- mail对象重复复用未重置:循环发信过程中你始终使用同一个
mail对象,每次调用SmtpServer.Send时没有清空上一次的收件人列表,之前的收件人会累积在mail.To集合中,导致后面每次发信都会连带发给之前所有的收件人,这是最核心的故障原因。 - dsCL表存在重复ID匹配记录:如果候选人唯一ID在dsCL表的第二列(索引1)存在重复行,同一个ID会匹配到多条记录,对应同一个邮箱的场景下就会触发多次Send调用。
- 数据库FMZ标记更新时机滞后:原代码是在发完所有匹配到的邮箱之后才更新FMZ字段,如果程序发信过程中意外中断重启,未完成标记的候选人会被再次识别为未联系状态,导致重复发信。
修复后代码示例
' 前置初始化SmtpClient,无需每次循环重复创建 Dim SmtpServer As New SmtpClient() SmtpServer.Credentials = New Net.NetworkCredential("你的发件邮箱地址", "发件授权码") SmtpServer.Port = 587 SmtpServer.Host = "你的SMTP服务器地址" SmtpServer.EnableSsl = True ' 预先加载dsCL表做去重处理,避免嵌套循环+重复匹配 Dim 候选邮箱映射 As New Dictionary(Of String, String) For x As Integer = 0 To dsCL.Tables(0).Rows.Count - 1 Dim 候选人ID = dsCL.Tables(0).Rows(x)(1).ToString() Dim 邮箱 = dsCL.Tables(0).Rows(x)(7).ToString() ' 同一个ID仅保留第一个有效邮箱,避免重复匹配 If 邮箱.Contains("@") AndAlso Not 候选邮箱映射.ContainsKey(候选人ID) Then 候选邮箱映射.Add(候选人ID, 邮箱) End If Next 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 If dsPoslovi.Tables(0).Rows(i)(8).ToString() <> "X" Then IDKandidataAP = dsPoslovi.Tables(0).Rows(i)(0).ToString() Dim 目标ID = dsPoslovi.Tables(0).Rows(i)(3).ToString() ' 从预生成的去重映射表取邮箱,无需嵌套循环查询 If 候选邮箱映射.TryGetValue(目标ID, out MailKandidata) Then ' 每次发信新建独立的mail对象,避免收件人累积 Dim mail As New MailMessage() mail.From = New MailAddress("你的发件邮箱地址") mail.To.Add(MailKandidata) mail.Subject = "岗位沟通邮件主题" mail.Body = "邮件正文内容" SmtpServer.Send(mail) ' 发信成功立刻更新标记,避免中断后重复发送 Dim cmd As New OleDbCommand(query, myCONN) myCONN.Open() cmd.Parameters.AddWithValue("FMZ", "X") cmd.Parameters.AddWithValue("ID", IDKandidataAP) cmd.ExecuteNonQuery() myCONN.Close() MsgBox(MailKandidata) ' 释放mail对象资源 mail.Dispose() End If End If End If Next ' 释放SmtpClient资源 SmtpServer.Dispose()
额外优化建议
- 建议添加发信异常捕获逻辑,避免单条邮件发送失败导致整个程序中断,发送失败的记录不更新FMZ标记,后续可重试发送。
- 单次发信量过千的场景可以在每次发信后添加1-2秒的间隔,避免被SMTP服务器判定为垃圾邮件触发限流。
内容的提问来源于stack exchange,提问作者Jovica
相关产品推荐
相关产品推荐

