I want to send an email just once per day. There is one button and any user can click that button. So email must not be send 2 times. When first user click button then email is send and if some other user click button than email will not be send again.
This is how I implemented and it’s working. There are some cases, once a month, when 2 email are sent, but I don't know why.
I am sure that there is more elegant way to resolve this problem. Please share with me your ideas.
protected void Send(string email, String allRecipients, String subject, String body)
{
//Be sure that email is send just once:
//Lock an object, and if its already locked just continue,
if (Monitor.TryEnter(syncLock))
{
try
{
//Send email only if is not send already.
//Check in DB if is send.
//IsSend function return true if email is send already, else false.
if (!IsSent())
{
SendEmails(email, allRecipients, subject, body);
}
}
finally
{
Monitor.Exit(syncLock);
}
}
}
Function that sends email:
public static void SendEmails(string email, String allRecipients, String subject, String body)
{
//Flag if email is sent or not:
Boolean isEmailSend = false;
SmtpClient client = new SmtpClient();
//Message:
MailMessage message = new MailMessage(email, allRecipients, subject, body);
try
{
isEmailSend = true;
client.Send(message);
}
catch (SmtpException e)
{
isEmailSend = false;
throw new SmtpException(e.ToString());
}
catch (TimeoutException e)
{
//Problem: Not sure if is email send or not:
isEmailSend = false;
throw new TimeoutException("TIME OUT:" + e.ToString());
}
catch (Exception e)
{
//Problem: Not sure if is email send or not:
isEmailSend = false;
throw new Exception(e.ToString());
}
finally
{
if (isEmailSend)
{
//Update DB.
//Set that email is send.
//This update in DB that email for current day is send already.
SetAsSend();
}
}
}
Edit: IsSent function
//Check if meeting is sent today.
public static bool IsSent()
{
string connectionString = ConfigurationManager.ConnectionStrings["connectionString"].ConnectionString;
bool isSent = false;
const string CHECK_IF_SEND = "SELECT TOP 1 IsSent FROM MessageTable m WHERE m.date =@todayDate ";
SqlConnection conn = new SqlConnection(connectionString);
SqlCommand command = new SqlCommand(CHECK_IF_SEND, conn);
command.Parameters.Add("@todayDate", DbType.Date).Value = DateTime.Today;
try
{
conn.Open();
Object result = command.ExecuteScalar();
if (result != null)
{
isSent = (bool)result;
}
}
finally
{
conn.Close();
conn.Dispose();
}
return isSent;
}