我有一个名为 SchedulerService 的类,其中有一个 SendMail 函数,当需要在特定时间发送电子邮件时调用该函数。当我调用 SendMail 函数时,我传入了一个对象,该对象包含有关将电子邮件发送给谁以及电子邮件来自谁的信息。现在,我添加了一个 SendCompleted 处理程序,以便我可以重新发送电子邮件,以防万一发生导致它无法发送的情况。我有发送邮件的代码:
var recipients = EmailTo.Split(',').ToList();
if (String.IsNullOrEmpty(EmailFrom))
EmailFrom = recipients[0];
using (MailMessage message = new MailMessage())
{
message.From = new MailAddress(EmailFrom);
recipients.ForEach(a => message.To.Add(new MailAddress(a)));
message.Attachments.Add(new Attachment(LocationOfResults));
message.Subject = String.Format("{0:MM-dd-yyyy} Results for task: {1}.", DateTime.Now, Description);
message.Body = "Attached is the results file specified for the task: " + Description;
smtpClient.SendCompleted += new SendCompletedEventHandler(SendCompletedCallback);
smtpClient.UseDefaultCredentials = true;
smtpClient.SendAsync(message, null);
}
这是事件处理器
private void SendCompletedCallback(object sender, AsyncCompletedEventArgs e)
{
if (e.Cancelled)
{
MailMessage mail = (MailMessage)e.UserState;
using (mail)
{
smtpClient.Send(mail);
}
}
if (e.Error != null)
{
Log(e.Error.ToString() + " in SendCompletedHandlerEvent", EventLogEntryType.Error);
}
}
问题是,我发现这样做是行不通的,因为“收件人”和“发件人”字段是空的,这会在发送电子邮件时导致错误。我应该如何从发送失败的电子邮件中回收收件人/发件人字段?
请您参考如下方法:
如果你想使用异步发送,那么你应该摆脱 using block ,它会处理你初始化的 message 变量。相反,您可以从 SendCompleted 事件处理程序调用 Dispose() 或仅从初始化方法调用 Dispose:
/*...*/
smtpClient.SendAsync(message, null);
message.Dispose();
您也可以在 this page 上找到这种方法MSDN
此外,您应该以某种方式重写您的初始化,使其看起来像这样:
smtpClient.Credentials = new NetworkCredential("somemail@gmail.com", "pass");
smtpClient.Port = 587;
smtpClient.Host = "smtp.gmail.com";
smtpClient.SendAsync(message, null);
smtpClient.SendCompleted += new SendCompletedEventHandler(smtpClient_SendCompleted);
也就是说,我的意思是 SendAsync 和 Credentails 以及执行操作所需的其他参数应该首先设置。
UPD 它将解决处理原始 message 变量的问题,这就是为什么“To 和 From 字段为空”的原因。
关于重新发送 - 请提供更多代码或情况示例,无论您将如何以及在哪里避免消息发送取消和重新发送。
另外,取消消息重发到底是什么意思?您想再次发送已取消的消息是否正确?据我了解,您无法继续发送在您的情况下使用 SendAsyncCancel() 取消的消息。
在执行 SendAsyncCancel 的情况下,它仍然会引发 SendCompleted 事件,但传递的参数表明操作已取消。所以,你无法逃避它。你可能想看看 this page ,当然还有 MSDN。
如果您需要发送这么多消息,以防万一出现取消发送的问题,请重新发送:
/*your SendCompleted EventHandler*/
if (e.Canceled)
{
//if you use using(message) {...} here, you'll get ObjectDisposedException again
SmtpClient smtp;
smtp = new SmtpClient();
smtp = GetClient(smtp); //method of your smtpClient initialization
MailMessage mess = new MailMessage();
mess = GetMessage(mess, smtp); //method of your mailMessage initialization
try
{
//sending message again
smtp.SendAsync(mess, null);
}
catch (ObjectDisposedException e)
{
MessageBox.Show("The email message was not sent. See the details:\n"+e.Message,
"Error sendiing message")
}
}
我使用 SendAsyncCancel 方法对其进行了测试,因此我希望考虑到大部分取消原因。
