when I send email using STMP in C#, I can't make sure that the email has been send although I have used SendCompleted Event Handler. this is my code:
private void btnLogin1_Click(object sender, EventArgs e)
{
try
{
MailAddress FromAddress = new MailAddress("*******", "*******");
MailAddress ToAddress = new MailAddress("*****");
String FromPassword = "******";
SmtpClient SMTP = new SmtpClient();
SMTP.Host = "smtp.yandex.com";
SMTP.Port = 587;
SMTP.EnableSsl = true;
SMTP.DeliveryMethod = SmtpDeliveryMethod.Network;
SMTP.UseDefaultCredentials = false;
SMTP.Credentials = new NetworkCredential(FromAddress.Address, FromPassword);
SMTP.SendCompleted += SMTP_SendCompleted;
MailMessage Message = new MailMessage();
Message.From = FromAddress;
Message.To.Add(ToAddress);
Message.Subject = "Welcome";
Message.SubjectEncoding = Encoding.UTF8;
Message.Priority = MailPriority.High;
Message.IsBodyHtml = true;
Message.Body = "<b>Test Mail</b>";
Message.BodyEncoding = Encoding.UTF8;
SMTP.Send(Message);
}
catch { }
}
private void SMTP_SendCompleted(object sender, AsyncCompletedEventArgs e)
{
MessageBox.Show("Sent");
}
}
Thanks in advance.
You need to put some error handling code inside
Catch {...}
Otherwise, you are just catching an error and ignoring it.
If the catch block doesn't fire, then as far as you can be reasonably sure (without checking for a delivery receipt), then you can assume the email has been successfully sent.
If you are using the SendCompleted event, then the email needs sent asynchronously using SendAsync. Otherwise, the method will not return control until after the email is either sent or fails.
In the example you posted, the empty catch is swallowing up any errors that may be occurring to even determine that much.
So either use the SendAsync so that your event gets fired, or actually see if any exceptions are being caught. Empty catch blocks that aren't even catching any specific exception are terrible ideas in nearly every situation. They lead to all sorts of problems.
Related
For some reason my program does not send email using SMTP server, it stops somewhere in this code, and I can't debug it, because it happens with the compiled .exe
public static void sendLog(MailMessage mail) {
SmtpClient SmtpServer = new SmtpClient("smtp.gmail.com");
mail.From = new MailAddress(Constants.EMAIL_SENDER);
mail.To.Add(Constants.EMAIL_RECEIVER);
mail.Subject = Environment.UserName;
SmtpServer.Port = 587;
SmtpServer.Credentials = new NetworkCredential(Constants.EMAIL_SENDER, Constants.EMAIL_SENDER_PASSWORD);
SmtpServer.EnableSsl = true;
SmtpServer.Send(mail);
}
what I need is to know what try/catch to use, and to handle the proper Exception to write in a .txt file?
You should use proper SMTP Exception
catch (SmtpException ex)
{
// write to log file
string msg = "Failure sending email"+ex.Message+" "+ex.StackTrace;
}
I was wondering if theres a way to send email asynchronously in asp.net c#. I've used the following code to send the emails:
if (checkObavijest.Checked)
{
List<hsp_Kupci_Newsletter_Result> lista = ServisnaKlasa.KupciNewsletter();
for (int i = 0; i < lista.Count; i++)
{
MailMessage mail = new MailMessage();
mail.From = new MailAddress("*******");
mail.To.Add(lista[i].Email);
mail.Subject = "Subject";
mail.SubjectEncoding = Encoding.UTF8;
mail.BodyEncoding = Encoding.UTF8;
mail.IsBodyHtml = true;
mail.Priority = MailPriority.High;
mail.Body = "Some message";
SmtpClient smtpClient = new SmtpClient();
Object state = mail;
smtpClient.Credentials = new NetworkCredential("****#gmail.com", "****");
smtpClient.Port = 587;
smtpClient.Host = "smtp.gmail.com";
smtpClient.EnableSsl = true;
smtpClient.SendCompleted += new SendCompletedEventHandler(smtpClient_SendCompleted);
try
{
smtpClient.SendAsync(mail, state);
}
catch (Exception ex)
{
}
}
void smtpClient_SendCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
{
MailMessage mail = e.UserState as MailMessage;
if (!e.Cancelled && e.Error != null)
{
string poruka = "Emailovi poslani!";
ClientScript.RegisterStartupScript(this.GetType(), "myalert", "alert('" + poruka + "');", true);
}
}
But when I tick the option for sending emails, the page loads like 40 seconds, then after 40 seconds emails are sent then. As you can see I'm pulling out like 20-30 emails currently out of my DB. I thought this was the correct way to send mails asynchronously, but apparently its not... How can I push the email sending to another thread so it doesn't affects the user who is using this page? Can someone help me out with this ? Thanks !
The reason is mentioned here on the MSDN documentation on SmtpClient.SendAsync
After calling SendAsync, you must wait for the e-mail transmission to
complete before attempting to send another e-mail message using Send
or SendAsync.
You could call SendAsync using ThreadPool thru a wrapped method call. This would give you something like a fire-and-forget scenario.
Something like this:
public void SendViaThread(System.Net.Mail.MailMessage message) {
try {
System.Threading.ThreadPool.QueueUserWorkItem(SendViaAsync, message);
} catch (Exception ex) {
throw;
}
}
private void SendViaAsync(object stateObject) {
System.Net.Mail.SmtpClient smtp = new System.Net.Mail.SmtpClient();
System.Net.Mail.MmailMessage message = (MmailMessage)stateObject;
...
smtp.Credentials = new NetworkCredential("...");
smtp.Port = 587;
smtp.Host = "...";
...
smtp.SendCompleted += new SendCompletedEventHandler(smtpClient_SendCompleted);
...
smtp.Send(message);
}
And you would call SendViaThread(mail) in your code. So, your loop now becomes:
for (int i = 0; i < lista.Count; i++) {
MailMessage mail = new MailMessage();
mail.From = new MailAddress("...");
mail.To.Add(lista[i].Email);
mail.Subject = "...";
...
mail.Body = "...";
SendViaThread(mail);
}
If you want to not have your main thread waiting, try tossing it in a Task.
Task.Factory.StartNew( () => {
// do mail stuff here
});
Be aware, though that each time you spawn a task, it'll spawn a new (or re-use) a thread that your system has made. If you're firing off 30 e-mails, you have the potential of firing off a lot of threads (the system has a programmable cap, too). Task.Factory.StartNew is a very simple way to do a fire-and-forget process.
http://msdn.microsoft.com/en-us/library/dd321439%28v=vs.110%29.aspx
(in this example, the code is also keeping a collection of Tasks, which is nice if you care to manage them -- but in reality, you only need the Task.Factory.StartNew(()=>{ bit if you want to fire-and-forget. Just be careful because you don't want to have orphaned threads pegging your memory usage.
I've been making a Real Time Modding Tool for Call of Duty and am trying to make a report bug system, but I'm getting this error:
the codes that I'm using for this are as follows:
private void button4_Click(object sender, EventArgs e)
{
// Create the mail message
MailMessage mail = new MailMessage();
// Set The Addresses
mail.From = new MailAddress("brinkerzbhtests#gmail.com");
mail.To.Add("brinkerzbhtests#gmail.com");
// Login to that email
// Set The Content
mail.Subject = "RTM Tool Bug";
mail.Body = textBox1.Text;
// Send The Message
SmtpClient smtp = new SmtpClient("smtp.gmail.com", 587);
NetworkCredential info = new NetworkCredential("brinkerzbhtests#gmail.com", "PasswordNotBeingGivenHere");
smtp.DeliveryMethod = SmtpDeliveryMethod.Network;
smtp.EnableSsl = true;
try
{
smtp.Send(mail);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
Picture of full help screen:
NetworkCredential info = new NetworkCredential("brinkerzbhtests#gmail.com", "PasswordNotBeingGivenHere");
smtp.Credentials =info ; // add this line
You create your network credentials and don't associate them with the smtp client.
Try adding the line:
smtp.Credentials = Info;
I have been roaming forums and not finding any answer to my question.
all of the solution (and question) is about using Microsoft.Office.Interop.Outlook;
for some reason I am not allowed to use any office.interop.
I even tried:
MailAddress fromAddress = new MailAddress("sender#server.com");
System.Net.Mail.MailMessage message = new System.Net.Mail.MailMessage();
message.From = fromAddress;
message.To.Add("receiver#theirServer.com");
message.CC.Add("receiver2#theirServer.com");
message.Subject = "theSubject";
message.Body = "TheBody";
SmtpClient smtpClient = new SmtpClient("zzz.server.xxx");
smtpClient.Credentials = new NetworkCredential("sender#server.com", "password");
smtpClient.Send(message);
the code fail to authenticate the credential, even after I hard-coded the password, but I feel that there must be a better way.
There is a lot to be desired of your question. Can you post the response from the server or the error you are receiving?
Here are some observations and feedback that may help you
Specify the port
SmtpClient smtpClient = new SmtpClient("zzz.server.xxx", PORTNUMBER);
Set some of the basic properties
smtpClient.Timeout = 10000;
smtpClient.DeliveryMethod = SmtpDeliveryMethod.Network;
smtpClient.UseDefaultCredentials = false; //must be set prior to credentials
smtpClient.Credentials = new NetworkCredential("username", "pass");
Set the message encoding
message.SubjectEncoding = System.Text.Encoding.UTF8;
message.BodyEncoding = System.Text.Encoding.UTF8;
Send Asyncronously and use a callback to determine the result
//add callback
smtpClient.SendCompleted += new SendCompletedEventHandler(SendCompletedCallback);
//set token
string userToken = "tokenString";
//send asynchronously
smtpCient.SendAsync(message, userToken);
public static void SendCompletedCallback(object sender, AsyncCompletedEventArgs e)
{
// Get the unique identifier for this asynchronous operation.
String token = (string) e.UserState;
if (e.Cancelled)
{
//do something if it was cancelled
}
if (e.Error != null)
{
MessageBox.Show( e.Error.ToString());
} else
{
MessageBox.Show("Message sent.");
}
}
Have you verified the credentials, including the format of the username through configuring the account in an alternative client, such as Outlook?
You might need:
smtpClient.Credentials = new NetworkCredential("sender", "password");
or
smtpClient.Credentials = new NetworkCredential("DOMAIN\sender", "password");
Is your email server an Exchange Server? If so, you can use the Exchange Web Services (EWS) to send emails and save copies in the Sent Items folder. A simple example can be seen here:
Send Exchange Email
More Sample Code
here is the code.
void sendMail()
{
MailMessage mail = new MailMessage();
mail.To.Add("abc#gmail.com");
mail.From = new MailAddress("abc#gmail.com", txt_name.Text);
mail.Subject = txt_subject.Text;
mail.Body = txt_body.Text;
SmtpClient smtp = new SmtpClient("smtp.gmail.com");
smtp.EnableSsl = true;
NetworkCredential yetki = new NetworkCredential("abc#gmail.com", "11111111");
smtp.Credentials = yetki;
smtp.Send(mail);
Response.Write("mailiniz başarılı bir şekilde gönderilmiştir");
}
protected void btn_gonder_Click(object sender, EventArgs e)
{
sendMail();
}
Use a try/catch block
void sendMail() {
try{
MailMessage mail = new MailMessage();
mail.To.Add("abc#gmail.com");
mail.From = new MailAddress("abc#gmail.com", txt_name.Text);
mail.Subject = txt_subject.Text;
mail.Body = txt_body.Text;
SmtpClient smtp = new SmtpClient("smtp.gmail.com");
smtp.EnableSsl = true;
NetworkCredential yetki = new NetworkCredential("abc#gmail.com", "11111111");
smtp.Credentials = yetki;
smtp.Send(mail);
Response.Write("mailiniz başarılı bir şekilde gönderilmiştir");
}
catch(Exception e){
Response.Write(e.Message);
}
}
The error indicating it is unhandled means you didn't catch the exception. Now what you actually do in the catch block to handle the exception is up to you, such as logging it to a file, queuing a retry, or showing a message box. Or trying to do something to prevent the exception in the first place.
protected void btn_gonder_Click(object sender, EventArgs e)
{
try{
sendMail();
}
catch(Exception ex)
{
}
}
Also note you can access ex.Message to see the exception message, or add a break point to the catch block and inspect ex. It is possible there is more you need to do to get it to work with gmail because of the requirements for authentication. I don't know if the network credentials are enough. I've always had trouble with it and resorted to using my ISP's email account that doens't require authentication.
You add a try/catch block to your code and ignore the error, or you post the entire exception message so that we can help you solve the actual problem.
According to this page when sending mail over SSL you should use port 465 i.e.
SmtpClient smtp = new SmtpClient("smtp.gmail.com");
smtp.EnableSsl = true;
smtp.Port = 465;
...
You should probably still wrap the call to Send in a try/catch block and handle any SmtpException that gets thrown if you can do anything about it.
Note you can also put smtpClient configuration in the web.config file (see here for example).
You haven't specified the port number for Gmail which is 587.
smtp.port = 587;
And your problem should be solved. Otherwise your code looks good.