自动电子邮件发送与计时器控制

时间:2014-12-05 14:09:34

标签: c# winforms email date timer

我需要创建一个自动电子邮件发件人系统C#,它需要从一个数据库中读取数据。该数据主要是日期时间和ID。 对于每个日期,我需要计算插入日期和系统当前日期之间的差异。 我已经写了一些代码,发送邮件:

private void button1_Click(object sender, EventArgs e)
{   
 var fromAddress = new MailAddress("xxx@gmail.com", "NAME1");
 var toAddress = new MailAddress("aaa@gmail.com", "To Name");
 const string fromPassword = "pass";
 const string subject = "TEST";
 const string body = "WARNING";
 var smtp = new SmtpClient
  {
   Host = "smtp.gmail.com",
   Port = 587,
   EnableSsl = true,
   DeliveryMethod = SmtpDeliveryMethod.Network,
   UseDefaultCredentials = false,
   Credentials = new NetworkCredential(fromAddress.Address, fromPassword)
  };
 using (var message = new MailMessage(fromAddress, toAddress)
 {
  Subject = subject,
  Body = body
  })
  {
  smtp.Send(message);
  }
 }

我需要在每次启动应用程序时使用计时器来控制它,但只有在有日期到达限制时才会控制它。

在表单加载中,我阅读了所有日期以及需要通过此电子邮件通知日期结束的人员。我这样做:

string constring4 = Classe_Ligacao.cn;
string Query4 = "select DATE,IDPerson from Diligencia Where DATE IS NOT NULL";
SqlConnection cn4 = new SqlConnection(constring4);
SqlCommand cmd4 = new SqlCommand(Query4, cn4); 
try
{
 cn4.Open();
 using (SqlDataReader read4 = cmd4.ExecuteReader())
 {
  while (read4.Read())
  {
   string pr = (read4["DATE"].ToString());
   string ida = (read4["IDPerson"].ToString());

   string constring2 = Classe_Ligacao.cn;
   string query2 = "select name,Email  FROM Person WHERE IDPerson='" + ida + "'";
   SqlConnection cn2 = new SqlConnection(constring2); 
   SqlCommand cmd2 = new SqlCommand(query2, cn2);
   cn2.Open();
   using (SqlDataReader read2 = cmd2.ExecuteReader())
   {
     while (read2.Read())
     {
      string ab = (read2["Name"].ToString());
      string ema = (read2["Email"].ToString());
      MessageBox.Show(ab, ema);
     }
    }
   cn2.Close();
  }
 }
}
finally
{
cn4.Close();
}

我需要将阅读的电子邮件与发送日期和日期结束之前的日期相关联。我怎么能这样做,将所有与计时器相关联?

希望你能理解我的问题。

1 个答案:

答案 0 :(得分:1)

基本概念很容易实现:在循环中,从下一次操作时(即下次需要发送电子邮件时)减去当前时间,然后等待那段时间。

例如:

static async Task ProcessSchedule(IEnumerable<DateTime> schedule)
{
    // Release caller
    await Task.Yield();

    // Process the queue
    foreach (DateTime eventTime in schedule)
    {
        TimeSpan nextEvent = eventTime - DateTime.UtcNow;

        Console.Write(
            "waiting {0:0.000} seconds...", Math.Max(0, nextEvent.TotalSeconds));
        if (nextEvent.Ticks > 0)
        {
            await Task.Delay(nextEvent);
        }
        Console.WriteLine(eventTime);
    }
}

当我这样打电话时:

// Setup
double[] futureSeconds = { 1, 2.5, 3.7, 5, 9, 12.2, 15 };
BlockingCollection<DateTime> queue = new BlockingCollection<DateTime>();
Task task = ProcessSchedule(queue.GetConsumingEnumerable());

// This would be equivalent to whatever process you have generating
// the DateTime-based events (e.g. reading from a database)
DateTime startTime = DateTime.UtcNow;
foreach (DateTime eventTime in futureSeconds.Select(s => startTime + TimeSpan.FromSeconds(s)))
{
    queue.Add(eventTime);
}

// Don't call this until you want processing to stop
queue.CompleteAdding();

task.Wait();

我得到以下输出:

  

等待1.000秒... 12/5/2014 7:35:43 PM
  等待1.469秒... 12/5/2014 7:35:45 PM
  等待1.184秒... 12/5/2014 7:35:46 PM
  等待1.297秒... 12/5/2014 7:35:47 PM
  等待3.984秒... 12/5/2014 7:35:51 PM
  等待3.184秒... 12/5/2014 7:35:54 PM
  等待2.797秒... 2014年12月5日下午7:35:57

请注意,每次延迟都不是您初始化秒数所需的全部延迟。即虽然第二个事件发生在开始时间后2.5秒,但只有1.469秒的延迟。这是因为该技术会自动计算在前一个事件再次等待之前处理上一个事件所花费的时间。

当然,在上文中,您将使用包含详细信息的任何对象替换您的队列类型,例如用户下一封电子邮件通知的DateTime,当然还有他们发送电子邮件的详细信息他们。 ProcessSchedule()方法将包含实际发送电子邮件的逻辑。将事物添加到队列中的代码将是用于从数据库中提取信息的任何逻辑,您当然可以将您提到的限制添加到数据库中的基准日期,以确定实际的到期时间。 / p>

以上都认为你的一般状态相对不变。它可以轻松处理添加新事件,这些事件将比已经排队的任何其他事件发生得晚。对于任何更复杂的事情,例如处理在事件过期之前更新用户的基准时间的场景,或者添加基本时间早于已经排队的最新用户的新用户,需要进行一些更改。在底层队列中进行处理。

具体细节很大程度上取决于您实际需要做什么。希望上面的内容为您提供了正确的方向,以便您可以根据自己的特定需求进行优化,但当然如果您无法适应这一点,请随时提出另一个问题。