自动电子邮件发送与定时控制 [英] Automatic email sending with timer control

查看:175
本文介绍了自动电子邮件发送与定时控制的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要创建一个需要从一个数据库读取数据的自动电子邮件发件人系统C#。这个数据主要是datetime和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)
};
使用(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();
使用(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();
使用(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();
}

我需要将阅读的电子邮件,发送日期和日期相关联直到日期结束。我如何做到这一点,将所有人关联到一个计时器?



希望你能理解我的问题。

解决方案

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



例如:

  static async任务ProcessSchedule( IEnumerable< DateTime> schedule)
{
//释放调用者
等待Task.Yield();

//处理队列
foreach(日期时间eventTime)
{
TimeSpan nextEvent = eventTime - DateTime.UtcNow;

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

当我这样打电话时:

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

//这将相当于您生成的任何进程
//基于DateTime的事件(例如从数据库读取)
DateTime startTime = DateTime.UtcNow;
foreach(DateTime eventTime in futureSeconds.Select(s => startTime + TimeSpan.FromSeconds(s))
{
queue.Add(eventTime);
}

//直到你想要处理才能停止
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秒... 12/5/2014 7:35:57 PM


请注意,延迟并不完全是您从初始化秒数的预期。即而第二个事件发生在开始时间的2.​​5秒后,只有1.469秒的延迟。这是因为该技术自动计算在处理前一个事件之前花费的时间才能等待再次等待。



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

以上所有都假定你的一般状态是相对不变的。它可以轻松处理添加将比任何已排队的其他事件发生的新事件。对于任何更复杂的事情,例如处理用户的基准时间在其事件到期之前进行更新的场景,或者添加一个基于早于已排队的基准时间的新用户,则需要在底层排队和处理。



确切的细节取决于您实际需要做的事情。希望上面给你一个足够好的推动方向,你可以改进,以适应你的具体需求,但当然如果你有麻烦适应这个,请随时提出另一个问题。


I need to create an auto email sender system, C#, that needs to read data from one database. That data is, mostly, a datetime and an ID. For each date I'll need to calculate the diff between the date inserted and the current date of the system. I've already wrote pieces of code, to send mail:

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);
  }
 }

I need to control this with a timer and everytime the application is started, but only if there are dates coming to the limit.

In the form load I read all the dates and the person who needs to be informed with this email about the ending of the date. I do that with:

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();
}

I need to associate the email read to send, the date and the days left until the end of the date. How can I do that, associating all to a timer?

Hope you can understand my question.

解决方案

The basic concept is very easy to implement: in a loop, subtract the current time from the time of the next operation (i.e. when you next need to send email), and then wait for that length of time.

For example:

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);
    }
}

When I call the above like this:

// 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();

I get the following output:

waiting 1.000 seconds...12/5/2014 7:35:43 PM
waiting 1.469 seconds...12/5/2014 7:35:45 PM
waiting 1.184 seconds...12/5/2014 7:35:46 PM
waiting 1.297 seconds...12/5/2014 7:35:47 PM
waiting 3.984 seconds...12/5/2014 7:35:51 PM
waiting 3.184 seconds...12/5/2014 7:35:54 PM
waiting 2.797 seconds...12/5/2014 7:35:57 PM

Note that each delay is not quite the full amount you'd expect from the initialized seconds. I.e. while the second event is occurs 2.5 seconds after the start time, there's only a 1.469 second delay. This is because the technique automatically accounts for the time spent processing the previous event before it gets to the point of waiting again.

Of course, in the above you would replace your queue type with whatever object you have that contains the particulars, like the DateTime of the user's next email notice along with of course their particulars for emailing them. The ProcessSchedule() method would contain the logic to actually send the email. The code to add things to the queue would instead be whatever logic you have for pulling the information from the database, where you of course add the limit you mentioned to the base date in the database to determine when the actual expiration time would be.

The above all assumes that your general state is relatively unchanging. It can easily deal with adding new events that will occur later than any other event already queued. For anything more sophisticated, such as handling a scenario where a user's base time is updated before their event has expired, or adding a new user with a base time earlier than the most recent already queued, some changes would need to be made in the underlying queue and processing.

The exact details of that depend a lot on what you actually need to do. Hopefully the above gives you a good enough push in the right direction that you can refine to suit your specific needs, but of course if you have trouble adapting this, feel free to ask another question.

这篇关于自动电子邮件发送与定时控制的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆