我有一个每5分钟运行一次的Windows服务来发送电子邮件。一次性发送最多可能发送500封电子邮件。就在最近我们转移到Gmail发送电子邮件,这导致服务重复(每小时几次)投下以下消息:
"操作完成前经过的超时时间或服务器没有响应"
在后台有一个计时器,每5分钟就会发送一次,以发送所有堆积的电子邮件。触发后,它会停止计时器,使用Entity Framework 6获取电子邮件,循环并发送所有这些电子邮件,最后再次启动计时器。
private void FetchAndSendEmails(object sender, ElapsedEventArgs elapsedEventArgs)
{
_serverTimer.Stop();
try
{
var db = new MainServerContext();
var emailsToSend = db.Mails
.Where(x => x.IsSent.Equals(false) && x.IsDeleted.Equals(false))
.OrderBy(x => x.Priority)
.ThenBy(x => x.EntryCreated)
.Take(_maxEmailsToSendPerExecution)
.Select(x => new MailItem() { Id = x.MailId, Recipient = x.Recipient }) }).ToList(); // Fetches a lot more fields here
for (int i = 0; i < emailsToSend.Count(); i++)
{
var dbEmail = emailsToSend[i];
SendEmail(0, dbEmail, ref db);
continue;
}
}
catch (Exception ex)
{
// Log error
}
finally
{
_serverTimer.Start();
}
}
SendEmail方法
var mailClient = new SmtpClient();
mailClient.UseDefaultCredentials = true;
mailClient.Host = _host; // smtp.gmail.com
mailClient.Port = _port; // 465
mailClient.EnableSsl = _useSSL;
mailClient.DeliveryMethod = SmtpDeliveryMethod.Network;
mailClient.Credentials = new NetworkCredential(mailerItem.Username, mailerItem.Password);
mailClient.Timeout = 20000;
//add recipient, body, attachments etc.
mailClient.Send(message);
// Update mail sent
var item = db.Mails.First(x => x.MailId.Equals(mail.Id));
item.IsSent = true;
item.Sent = DateTime.Now;
item.FromEmail = mailerItem.FromEmailAddress;
db.SubmitChanges();
我可能会过去使用异步吗?以不同方式声明EF?更改一些Gmail设置?
有什么想法吗?
答案 0 :(得分:0)
我遇到了与Gmail相同的问题,他们的邮件服务器在哪些应用程序发送电子邮件方面受到很大保护。另外,请确保您没有该帐户的两步验证。
我切换到SMTP2Go(smtp2go.com),我可以发送尽可能多的电子邮件。
以下是我用来发送大量电子邮件的代码片段:http://pastie.org/10876521
答案 1 :(得分:0)
确保代码等待FetchAndSendEmails()完成,即使花费的时间超过5分钟。
一次加载和处理1封电子邮件,而不是500批次。
使用后处理DbContext。
using (var db = new MainServerContext())
{
...
}
可能会卡在一封电子邮件中。记录每封电子邮件的尝试次数,并轮流发送。
确保在调用FetchAndSendEmails()时没有TransactionScope有效,因为事务的硬编码最大时间限制为10分钟 - 并且没有实际的方法来扩展该限制(事务是假设的)是短暂的)。如果超出该限制,您将获得例外。