I am trying to send an email automatically using timer. the given below code is I have used for send email. But it is not responding. While using the same code under button click event, its working perfectly. Help me to find a proper solution. Thank you.
Code:
namespace AlertMail
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void timer1_Tick(object sender, EventArgs e)
{
MailMessage loginInfo = new MailMessage();
string em = "toAddress#gmail.com";
loginInfo.To.Add(em.ToString());
loginInfo.From = new MailAddress("fromAddress#gmail.com");
loginInfo.Subject = "Alert Information";
loginInfo.Body = "Hai";
loginInfo.IsBodyHtml = true;
SmtpClient smtp = new SmtpClient();
smtp.Host = "smtp.gmail.com";
smtp.Port = 587;
smtp.EnableSsl = true;
smtp.Credentials = new System.Net.NetworkCredential("fromAddress#gmail.com", "Password");
smtp.Send(loginInfo);
label6.Text = "Alert is send to your email..!!";
}
}
}
In many web application we need to send schedule(automatic) emails and we schedule them.
like:
Sends emails on a regular basis
Send the message at daily, weekly, monthly or yearly intervals.
For this, we normally used windows services or windows application.
As we know the web server IIS is continuously running, we can add a timer in the application and the timer can manage all these activities
//Inside Global.ascx
void Application_Start(object sender, EventArgs e)
{
// Code that runs on application startup
System.Timers.Timer myTimer = new System.Timers.Timer();
// Set the Interval to 5 seconds (5000 milliseconds).
myTimer.Interval = 5000;
myTimer.AutoReset = true;
myTimer.Elapsed += new ElapsedEventHandler(myTimer_Elapsed);
myTimer.Enabled = true;
}
public void myTimer_Elapsed(object source, System.Timers.ElapsedEventArgs e)
{
// use your mailer code
clsScheduleMail objScheduleMail = new clsScheduleMail();
objScheduleMail.SendScheduleMail();
}
// inside your class
public void SendScheduleMail()
{
// Write your send mail code here.
}
Usually when I need to run something on a schedule on a Windows server, I use a Scheduled Task. You can write your e-mail piece as a Console application, save it to a location on the server, and then have a scheduled task run the application on a given time interval. I'm not sure what version of Windows you are running, but these instructions apply to Windows 2008, Windows 8, and Windows 2012:
http://technet.microsoft.com/en-us/library/cc725745.aspx
Related
I have complete code for send daily mail to expiration mail to user. my description of code is below:
Global.asax :
void Application_Start(object sender, EventArgs e)
{
System.Timers.Timer myTimer = new System.Timers.Timer();
double inter = (double)GetNextInterval();
myTimer.Interval = inter;
myTimer.AutoReset = true;
myTimer.Elapsed += new ElapsedEventHandler(myTimer_Elapsed);
myTimer.Enabled = true;
}
private double GetNextInterval(){
string timeString;
timeString = "12:00 AM";
DateTime t = DateTime.Parse(timeString);
TimeSpan ts = new TimeSpan();
int x;
ts = t - System.DateTime.Now;
if (ts.TotalMilliseconds < 0)
{
ts = t.AddDays(1) - System.DateTime.Now;
}
return ts.TotalMilliseconds;
}
public void myTimer_Elapsed(object source, System.Timers.ElapsedEventArgs e)
{
// My Mail Code
}
This code is work for first time mail but i want to daily basis send mail.
How it possible?
Create a console application that sends an E-Mail and schedule a task to run your console application every day using task scheduler.
You can create Scheduled Tasks for .aspx Files also. It will open a browser and send mail , than u have to create another Scheduled Tasks to close it.
Here is Example :
https://mohammednv.wordpress.com/2008/01/08/how-to-create-scheduled-tasks-for-aspx-files/
You can schedule any procedure on the code side using Quartz.NET
But there is a problem. If an asp.net application stays inactive ( Not receiving any requests) it is put to sleep from IIS.
So you have 2 options.
Change IIS Settings to keep your app pool always awake
or poke your application with dummy requests to any method to prevent it from sleeping
My suggestion and implementation is the following which i think is the most professional way of doing it.
Expose your timely tasks as wcf services.
Develop a Windows Service which runs Quartz and invokes those wcf services in a timely manner.
The pros are you get to keep your business logic code in one place and it works also in server farm scenarios
I need to send different e-mails to different people. A different body of the e-mail is generated for every recipient and then I call the following method. That is, if there are 10 recipients, the following method is called 10 times:
public int Send_Mail(string send_from_bc, string send_to_bc, string subject_bc, string body_bc)
{
try
{
int count_returned = 0;
var send_from = new MailAddress(send_from_bc, "The Admin");
var send_to = new MailAddress(send_to_bc);
string subject = subject_bc;
string body = body_bc;
var smtp = new SmtpClient
{
Host = "**my smtp host**",
Port = 25,
DeliveryMethod = SmtpDeliveryMethod.Network,
Timeout = 300000
};
using (var message = new MailMessage(send_from, send_to)
{
Subject = subject,
Body = body
})
{
message.IsBodyHtml = true;
smtp.Send(message);
count_returned += 1;
}
return count_returned;
}
catch (Exception ex)
{
throw new Exception("Exception caught in Send_Mail", ex);
}
}
The problem is that this is taking an incredible amount of time to send even a few mails (like 10 or 15 mails). It takes around 2-5 minutes to send a single mail. Now, I do believe that partly the SMTP host provided to me is at fault. But what can I do to speed things up?
Also, is there some way to achieve this: Right now, the user clicks on a button and then say, for sending two mails, he/she has to wait 2-5 minutes (sometimes even more) before control is returned and the value of a label is changed to "E-mails sent.". Can something be done so that the user just clicks on the button, and the e-mail sending is initiated and he/she could just close the window and get on with his work?
I'm stuck on a critical stage right now and any help would be appreciated.
First thing first - don't make the user wait for this action. The session could well time out if you have to wait 2-5 minutes. Instead make this action an asynchronous task that runs in the background.
I'd then consider popping up a notification stating that the emails have been sent to the user later on, rather than forcing them to wait.
A starter for 10 - move your sending email code into a separate class:
public class EmailSender
{
public EmailSender(/* Parameters required, e.g. list of emails */)
{ }
public void SendEmails()
{
// Long running task
}
}
Then in your page, say a button is clicked:
protected void btn_SendEmails_Clicked(object sender, EventArgs e)
{
EmailSender emailSender = new EmailSender(/* Any setup code required */);
ThreadPool.QueueUserWorkItem(emails => emailSender.SendEmails());
}
To handle the notifications back to the user you'll want to raise an Event when the emails have finished and probably using something like SignalR to alert the browser.
Note that I've not tried compiling this code but should give you the general idea.
I'm trying to send confirmation mails to users periodically in ASP.NET.
To do this I polulate a queue with mails and check it every 30 seconds. Any confirmation emails in the queue at this time are sent and then cleared from the queue.
Does anyone know how to do this?
Here is my sending mail code
public static bool SendMail(string AdminMail,string AdminPassword,string subject,string toAddress, string content,DateTime SendTime)
{
toAddressListProperty.Enqueue(toAddress);
if(date==null)
{
date = DateTime.Now.Second;
}
if (date-SendTime.Second > 120)
{
var message = new MailMessage
{
From = new MailAddress(AdminMail)
};
foreach (var toAddressl in toAddressListProperty)
{
message.To.Add(new MailAddress(toAddressl));
}
message.Subject = subject;
message.Body = content;
message.IsBodyHtml = true;
var smtp = new SmtpClient
{
Credentials = new System.Net.NetworkCredential(AdminMail, AdminPassword),
Port = 587,
Host = "smtp.gmail.com",
EnableSsl = true
};
smtp.Send(message);
//date = SendTime;
return true;
}
return false;
}
I have done this using a background thread. I did a little research, and I believe this is an ok approach. There are a few dangers, which this blog details.
The main thing is to ensure you never throw an exception from a background thread, as I believe that will cause the web process to restart. Also, incase the thread dies, I ensure it is running on every call.
I have been using this approach for a few months, and so far no issues.
Also I run it every 1 second, this minamizes the amount of time you might loose emails due to an app shutdown.
public class BackgroundSmtpService
{
private ILog _log = LogManager.GetLogger(typeof(BackgroundSmtpService));
private readonly SmtpService SmtpService;
private static Thread _watchThread;
private static List<Email> _emailToSend = new List<Email>();
public BackgroundSmtpService(SmtpService smtpService)
{
SmtpService = smtpService;
}
public void Send(Email email)
{
lock (_emailToSend)
{
_emailToSend.Add(email);
}
EnsureRunning();
}
private void EnsureRunning()
{
if (_watchThread == null || !_watchThread.IsAlive)
{
lock (SmtpService)
{
if (_watchThread == null || !_watchThread.IsAlive)
{
_watchThread = new Thread(ThreadStart);
_watchThread.Start();
}
}
}
}
private void ThreadStart()
{
try
{
while (true)
{
Thread.Sleep(1000);
try
{
lock (_emailToSend)
{
var emails = _emailToSend;
_emailToSend = new List<Email>();
emails.AsParallel().ForAll(a=>SmtpService.Send(a));
}
}
catch (Exception e)
{
_log.Error("Error during running send emails", e);
}
}
}
catch (Exception e)
{
_log.Error("Error during running send emails, outer", e);
}
}
}
You might want to consider using Quartz.net library. It have decent documentation and it's fairly easy to use.
The biggest challenge you'll have with this is that any time your application pool recycles it will take a new request to kick stats your "timer". If you had an HTTP monitor application such as Pingdom to poll your server it shouldn't be a problem, but then again you could also just use a third party monitor tool to hit your a page on your site every N seconds that would send out the mail and issue a response.
I myself would use a Windows service to pull a queue from a database and send out messages that way.
Easiest way is to create a VBScript that sends an HTTP GET request to http://localhost/SendConfirmationEmails.aspx
You'd start the VBScript in your global.asax Application_Start method.
The SendConfirmationEmails.aspx would act as a simple web service (you could use an ashx, or actual web service asmx if you wanted). It would only be accessible on the localhost so remote users wouldn't be able to spam it.
Using a windows service is probably the best practice method, but a simple VBScript will get the job done.
surl="http://localhost/SendConfirmationEmails.aspx"
set oxmlhttp=createobject("msxml2.xmlhttp")
with oxmlhttp
.open "GET",surl,false
.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
.send srequest
end with
You'd put the code above in a while wend loop with a Sleep to delay every 30 seconds...
I made a small program in which I can basically send an email through the yahoo smtp server. My Code:
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Net;
using System.Net.Mail;
using System.Drawing;
using System.IO;
using System.Text;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
try
{
MailMessage message = new MailMessage();
message.From = new MailAddress("myid#yahoo.com");
message.To.Add("anotherid#yahoo.com");
message.Subject = "afdasdfasfg";
message.Body = "Hgfk4564267862738I";
message.IsBodyHtml = true;
message.Priority = MailPriority.High;
SmtpClient sC = new SmtpClient("smtp.mail.yahoo.com");
sC.Port = 587;
sC.Credentials = new NetworkCredential("myid", "mypassword");
//sC.EnableSsl = true;
sC.Send(message);
MessageBox .Show ("Mail Send Successfully");
}
catch (Exception ex)
{
MessageBox .Show (ex + "Mail Sending Fail's") ;
}
}
}
}
The bizarre thing is that it worked for the first week. I could send messages with no problem. Then just yesterday, the program just starts freezing and doesn't respond( I didn't change the code). Why did this happen? How can I mend my program?
Edit: #Andreas Niedermair Right now I just tried the program and left it for a whole minute then an error showed:ContextSwitchDeadlock was detected
Message: The CLR has been unable to transition from COM context 0x21eb78 to COM context 0x21ece8 for 60 seconds. The thread that owns the destination context/apartment is most likely either doing a non pumping wait or processing a very long running operation without pumping Windows messages. This situation generally has a negative performance impact and may even lead to the application becoming non responsive or memory usage accumulating continually over time. To avoid this problem, all single threaded apartment (STA) threads should use pumping wait primitives (such as CoWaitForMultipleHandles) and routinely pump messages during long running operations.
Thanks for your help!
does your catch ever get reached?
i assume, that you are not patient enough to reach the default value of the Timeout property (100seconds)...
you could decrease the value to get an earlier completion.
as long as you are not working with an async-pattern, your UI-thread gets blocked anyway. an alternative would be to use the SendAsync method (there are sample implementations in the msdn-entries for the specific methods).
Edit:
as the author mentioned a possible fu**ed port: yes, it could be. but you would have to read the specification paper, which tells us:
SMTP server: plus.smtp.mail.yahoo.com
Use SSL
Port: 465
Use authentication
Account Name/Login Name: Your Yahoo! Mail ID (your email address without the "#yahoo.com", for example, “testing80”)
Email Address: Your Yahoo! Mail address (for example, testing80#yahoo.com)
Password: Your Yahoo! Mail password
[...] try setting the SMTP port number to 587 when sending email via Yahoo!'s SMTP server.
but even if you meet the specifications: you should really go for the async-pattern :)
Edit:
the mentioned exception is related to COM ... a bit googeling, and i've found this:
What's probably happening is that you
have a COM object in a form, and
you're doing work on the UI thread. If
your UI gets blocked by the processing
for >60 seconds, the COM component can
complain.
Edit:
otherwise: did you change anything within the exceptions-dialog of visual studio? then this could be your solution, or this one (with some basic explanation)...
As per Andreas Niedermair edit the issue is you are blocking the main thread for more than 60 secconds. The best thing to do is put this operation on a background thread.
using System;
using System.ComponentModel;
using System.Net;
using System.Net.Mail;
using System.Windows.Forms;
namespace Sandbox_Form
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
bw = new BackgroundWorker();
bw.DoWork +=new DoWorkEventHandler(bw_DoWork);
bw.RunWorkerCompleted +=new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
}
void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if(e.Error != null)
MessageBox.Show(e.Error.ToString() + "Mail Sending Fail's") ;
else
MessageBox.Show("Mail Send Successfully");
}
BackgroundWorker bw;
void bw_DoWork(object sender, DoWorkEventArgs e)
{
using(MailMessage message = new MailMessage())
{
message.From = new MailAddress("myid#yahoo.com");
message.To.Add("anotherid#yahoo.com");
message.Subject = "afdasdfasfg";
message.Body = "Hgfk4564267862738I";
message.IsBodyHtml = true;
message.Priority = MailPriority.High;
using(SmtpClient sC = new SmtpClient("smtp.mail.yahoo.com"))
{
sC.Port = 587;
sC.Credentials = new NetworkCredential("myid", "mypassword");
//sC.EnableSsl = true;
sC.Send(message);
}
}
}
private void button1_Click(object sender, EventArgs e)
{
bw.RunWorkerAsync();
}
}
}
EDIT:
per Andreas Niedermair suggestion, here is a version using the async method instead.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
try
{
MailMessage message = new MailMessage();
message.From = new MailAddress("myid#yahoo.com");
message.To.Add("anotherid#yahoo.com");
message.Subject = "afdasdfasfg";
message.Body = "Hgfk4564267862738I";
message.IsBodyHtml = true;
message.Priority = MailPriority.High;
SmtpClient sC = new SmtpClient("smtp.mail.yahoo.com");
sC.Port = 587;
sC.Credentials = new NetworkCredential("myid", "mypassword");
//sC.EnableSsl = true;
//sC.Send(message);
sC.SendCompleted += new SendCompletedEventHandler(sC_SendCompleted);
sC.SendAsync(message, null);
}
catch (Exception ex)
{
MessageBox.Show(ex + "Mail Sending Fail's");
}
}
void sC_SendCompleted(object sender, AsyncCompletedEventArgs e)
{
if(e.Error != null)
MessageBox.Show(ex + "Mail Sending Fail's");
else
MessageBox.Show("Mail Send Successfully");
}
}
I have a newsletter tool that I am trying to setup to run as a background process to send out the emails. The code below works without any issues but the problem I have is that it is slow.
If there are 50 emails to send it can be very slow for the end user as they have to stare at the screen for up to 1min 30secs. This becomes a bigger problem for me if they client is sending an email to a larger group of people.
The reason I send each mail individually as apposed to sending 1 and bcc'ing the email list is that each email contains certain specific content for each user - like unsubscribe link codes, personal name at the start of the mail, etc.
I am looking for a solution where I can let the user click on a button and have .net run the sending email part in the background while the front end user is brought to a page saying that their email is being sent. Ideally, it should take no longer than a regular postback for all that to occur - not the current few minutes.
Any thoughts on how best to achieve this?
Thanks for your help,
Rich
if (Page.IsPostBack)
{
if (JustMeButton.Checked)
{
SendMail("emailme#address", EmailTemplate);
}
if (EveryoneButton.Checked)
{
//setup background process
BackgroundWorker bw = new BackgroundWorker();
bw.WorkerReportsProgress = false;
bw.WorkerSupportsCancellation = false;
bw.DoWork += new DoWorkEventHandler(bw_DoWork);
bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
bw.RunWorkerAsync();
//bring user to next screen and display message
Response.Redirect("emailSendingMessageScreen.aspx");
}
}
private void bw_DoWork(object sender, DoWorkEventArgs e)
{
DataTable emailTable = (DataTable)Session["emailTable"];
foreach (DataRow row in emailTable.Rows)
{
SendMail(row["email"], row["name"], EmailTemplate);
}
}
private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (!(e.Error == null))
{
SendMail("admin#address", "Error sending <br><br>" + e.Error.Message);
}
else
{
SendMail("admin#address", "emails sent successfully.");
}
//clear out the sessions created for sending this email
Session.Remove("emailTable");
}
private void SendMail(string email, string emailMessage)
{
MailMessage mailMessage = new MailMessage();
mailMessage.From = new MailAddress("from#address");
mailMessage.To.Add(new MailAddress(email));
mailMessage.Subject = Server.HtmlEncode(EmailSubject.Text.Trim());
mailMessage.Body = emailMessage;
mailMessage.IsBodyHtml = true;
SmtpClient smtpClient = new SmtpClient();
Object userState = mailMessage;
smtpClient.SendCompleted += new SendCompletedEventHandler(smtpClient_SendCompleted);
smtpClient.Timeout = 10000;
try
{
smtpClient.SendAsync(mailMessage, userState);
}
catch (SmtpException smtpExc)
{
MailMessageTxt.Text += "Error Code: " + smtpExc.StatusCode;
MailMessageTxt.Visible = true;
}
catch (Exception ex)
{
MailMessageTxt.Text += "Error is: " + ex;
MailMessageTxt.Visible = true;
}
}
void smtpClient_SendCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
{
MailMessage mailMessage = e.UserState as MailMessage;
if (e.Error != null)
{
MailMessageTxt.Text = "Error occured, info=" + e.Error.Message;
MailMessageTxt.Visible = true;
}
}
I did this very thing sending a newsletter with the BeerHouse in the new version. You can get the book now and the source code is on CodePlex, http://thebeerhouse.codeplex.com/
http://professionalaspnet.com/archive/2009/10/07/ASP.NET-3.5-Problem-1320-Design-2D00-Solution.aspx
alt text http://Professionalaspnet.com/images/187586-fg0705.jpg
The Solution uses AJAX to send the e-mails and allows the user to keep browsing around the site without being concerned about the newsletter being sent out. When it is done it just takes care of itself and the user can check on as they want. Its chapter 7 in the book, enjoy.
A thread created within an ASP page will get killed if the ASP worker process is recycled for whatever reason. A Windows service that performs the task via a message queue is ideal for long running jobs. Another "trick" solution is using cache expiry, explained here: http://www.codeproject.com/KB/aspnet/ASPNETService.aspx
Move all the work of sending the email to separate class and run it using ThreadPool
MailSender sender = new MailSender(parameters. ....);
ThreadPool.EnqueueUserItem(sender.sendAllEmails)
Using background worker won't work. It will be disposed when it goes out of context, meaning on Response.End
I have found trying to do tasks like this within the ASP.NET process is problematic as you cannot guarantee the process will complete or be successful. If the process gets cut off you have no recovery. I would have all your emails saved to a DB first and then have a service that polls for new entries in this database or table that handles the actual sending of the emails.
The advantage to this is that if your email provider or ASP.NET process goes down you don't lose any emails and you have a history of all emails sent with their details of when, who, etc... You can also rip out or change the emailer to do more, like send to Twitter or a phone text message etc. This effectively decouples your notifications from your application.
All applications I have made recently use this type of model and it has stopped emails from being lost due to service failures and other reasons. It has also made it possible to lookup all emails that have gone through the system and get metrics that allows me to optimize the need to send emails by storing extra information in the email record like reason sent, if it's to report an error, etc... Adding on additions such as routing notifications (eg go to text message instead if email) based on time of day or user has been possible with no changes to the primary applicaton.
Simply use ajax to execute the process.let the user continue their activity while the server bares the burden.