Is there any way to get sent error from the smtp to check if the mail is sent successfully?
var smtpClient = new SmtpClient("SmtpServer");
smtpClient.SendCompleted += new SendCompletedEventHandler(SendCompletedCallback);
smtpClient.SendAsync(mail, userId);
The errors I am looking for are: mail can't be deliver because the mail address not exists, mail box full etc...
Regards,
Meir.
I am not sure what you are trying to achieve but this will helps you.
I assume you're already aware of the DeriveryNotificationOptions property on System.Net.Mail.MailMessage. The only tricky part to using that property is that its enum type represents a bitfield, so you should set it to the sum of the options you want to apply.
For example, if you want delivery notification on delay, failure, or success, you should set the property to
DeliveryNotificationOptions.Delay + DeliveryNotificationOptions.OnFailure + DeliveryNotificationOptions.OnSuccess
Or
this is one method to capture the failure report or any error when the mail has not been sent (failure report)
// Change your Try-Catch to call the new method named 'CheckExceptionAndResend'
// Error handling for sending message
try
{
smtpClient.Send(message);
// Exception contains information on each failed receipient
}
catch (System.Net.Mail.SmtpFailedRecipientsException recExc)
{
// Call method that will analyze exception and attempt to re-send the email
CheckExceptionAndResend(recExc, smtpClient, message);
}
catch (System.Net.Mail.SmtpException smtpExc)
{
// Log error to event log using StatusCode information in
// smtpExc.StatusCode
MsgBox((smtpExc.StatusCode.ToString + " ==>Procedure SmtpException"));
}
catch (Exception Exc)
{
// Log error to event log using StatusCode information in
// smtpExc.StatusCode
MsgBox((Exc.Message + " ==>Procedure Exception"));
}
private void CheckExceptionAndResend(System.Net.Mail.SmtpFailedRecipientsException exObj, System.Net.Mail.SmtpClient smtpClient, MailMessage emailMessage)
{
try
{
for (int recipient = 0; (recipient <= (exObj.InnerExceptions.Length - 1)); recipient++)
{
System.Net.Mail.SmtpStatusCode statusCode;
// Each InnerException is an System.Net.Mail.SmtpFailed RecipientException
statusCode = exObj.InnerExceptions(recipient).StatusCode;
if (((statusCode == Net.Mail.SmtpStatusCode.MailboxBusy)
|| (statusCode == Net.Mail.SmtpStatusCode.MailboxUnavailable)))
{
// Log this to event log: recExc.InnerExceptions(recipient).FailedRecipient
System.Threading.Thread.Sleep(5000);
smtpClient.Send(emailMessage);
}
else
{
// Log error to event log.
// recExc.InnerExceptions(recipient).StatusCode or use statusCode
}
}
MsgBox((exObj.Message + " ==>Procedure SmtpFailedRecipientsException"));
}
catch (Exception ex)
{
// At this point we have an non recoverable issue:
// NOTE: At this point we do not want to re-throw the exception because this method
// was called from a 'Catch' block and we do not want a hard error to display to the client.
// Options: log error, report issue to client via msgbox, etc. This is up to you.
// To display issue as you have before:
MsgBox((exObj.Message + " ==>Email was not sent"));
}
}
Such kind of errors have a asnychronous nature. When sending mail you talk to the local smtp server of your provider. That server afterwards starts to deliver the mail to the target mail system.
So the SmtpClient class can only show you errors occuring while talking to your local smtp server.
Typically when an error like "unknown user" occures on the target system, it will send an email with the failure message to the originator email address.
This post is helpful to me.
By the way if you're using .net 4.0 this one will be the changes on the above code. Sorry for my first post i don't know why it appears that way.
Here's the code:
private void CheckExceptionAndResend(System.Net.Mail.SmtpFailedRecipientsException exObj, System.Net.Mail.SmtpClient smtpClient, MailMessage emailMessage)
{
try
{
for (int recipient = 0; (recipient <= (exObj.InnerExceptions.Length - 1)); recipient++)
{
System.Net.Mail.SmtpStatusCode statusCode;
// Each InnerException is an System.Net.Mail.SmtpFailed RecipientException
//for .net 4.0
//statusCode = exObj.InnerExceptions(recipient).StatusCode;
statusCode = exObj.StatusCode;
//if (((statusCode == Net.Mail.SmtpStatusCode.MailboxBusy) || (statusCode == Net.Mail.SmtpStatusCode.MailboxUnavailable)))
//for .net 4.0
if (((statusCode == System.Net.Mail.SmtpStatusCode.MailboxBusy)
|| (statusCode == System.Net.Mail.SmtpStatusCode.MailboxUnavailable)))
{
// Log this to event log: recExc.InnerExceptions(recipient).FailedRecipient
System.Threading.Thread.Sleep(5000);
smtpClient.Send(emailMessage);
}
else
{
// Log error to event log.
// recExc.InnerExceptions(recipient).StatusCode or use statusCode
}
}
//MsgBox((exObj.Message + " ==>Procedure SmtpFailedRecipientsException"));
}
catch (Exception ex)
{
// At this point we have an non recoverable issue:
// NOTE: At this point we do not want to re-throw the exception because this method
// was called from a 'Catch' block and we do not want a hard error to display to the client.
// Options: log error, report issue to client via msgbox, etc. This is up to you.
// To display issue as you have before:
// MsgBox((exObj.Message + " ==>Email was not sent"));
}
}
Related
I am currently working on a project that depends on .net 4.5, which I am why forced to use Microsoft.Servicebus - and thus message factory
Creating a messagefactory object, doesn't seem to be problem, but creating the message sender seem to be the issue here.
I am not sure what the entity path for my azure message queue is, and don't know how I should look it up?
I initialized my message factory as such;
public Microsoft.ServiceBus.Messaging.MessagingFactory client = Microsoft.ServiceBus.Messaging.MessagingFactory.CreateFromConnectionString(ServiceBusConnectString);
Where servicebusconnectionstring, is the primary conenctionstring extracted from the azure queue, or by following this guide: https://learn.microsoft.com/en-us/azure/service-bus-messaging/service-bus-dotnet-get-started-with-queues#1-create-a-namespace-using-the-azure-portal
The message sender is created as such:
Microsoft.ServiceBus.Messaging.MessageSender sender = client.CreateMessageSender(destinationQueue,queueName);
Again destionationQueue, and queueName are strings, which are defined from azure?
The message is to be send is created as such:
Microsoft.ServiceBus.Messaging.BrokeredMessage message = new Microsoft.ServiceBus.Messaging.BrokeredMessage(e.ToXml());
e is just an object, which has publich function which can convert it to an xml string.
Here is where I send the message:
try
{
IntegrationLogger.Write(LogLevel.Verbose, "Sending message to azure");
sender.Send(message);
}
catch(System.Exception ex)
{
if(ex is System.TimeoutException)
{
IntegrationLogger.Write(LogLevel.Error, "Timeout exeption");
}
if (ex is System.ArgumentException)
{
IntegrationLogger.Write(LogLevel.Error, "Message is empty");
}
}
IntegrationLogger is a log function I use - and the last message being logged is "Sending message to azure", meaning somethng goes wrong when I send it.
even catch does not catch the exception?..
What could be the problem here?
Am I using the sender incorrectly?
I am not sure what the enity path for my azure message queue is, and don't know how i should look it up?
If we want to create queue MessageSender, we could use following code.
var sender = client.CreateMessageSender(queueName);
We also could use queueclient to send and receive the broker messsage.
var client = QueueClient.CreateFromConnectionString("servicebus connection string", queueName);
// how to send message
var sendMessage = new BrokeredMessage(data);
client.Send(sendMessage);
//how to receive message
client.OnMessage(message =>
{
var dataInfo = message.GetBody<T>();
});
IntegrationLogger is a log function I use - and the last message being logged is "Sending message to azure", meaning somethng goes wrong when I send it. even catch does not catch the exepetion?..
In your case I recommand that you could add the log info to check whether there is any exception during send message.
try
{
IntegrationLogger.Write(LogLevel.Verbose, "Sending message to azure");
sender.Send(message);
//add log
IntegrationLogger.Write(LogLevel.Verbose, "Send message successfully");
}
I am using TLSharp library for implementing a custom Telegram client. when I run the code below:
public async Task<string> SendCodeRequest(string phoneNumber)
{
var completed = false;
TL.AuthSendCodeRequest request = null;
while (!completed)
{
request = new TL.AuthSendCodeRequest(phoneNumber, 5, _apiId, _apiHash, "en");
await _sender.Send(request);
await _sender.Receive(request);
completed = true;
}
// TODO handle other types (such as SMS)
if (request.Result is TL.AuthSentCodeType)
{
var result = (TL.AuthSentCodeType)request.Result;
return result.PhoneCodeHash;
}
else
{
var result = (TL.AuthSentAppCodeType)request.Result;
return result.PhoneCodeHash;
}
}
I gives me the following exception :
Your phone number registered to {dcIdx} dc. Please update settings.
See https://github.com/sochix/TLSharp#i-get-an-error-migrate_x for
details.
The mentioned github page says that TLSharp Handles these exceptions by itself. So I guess something is wrong with the library core because the code should resolve data center IPs by itself not generating an exception.
Any help would be appreciated.
TlSharp Currently doesn't handle this exception you have to catch the exception and get the data center number then Try to reconnect to the Data Center using the ReconnectToDc() Function.
In the MtProtoSender.cs file you can find the following line of code that generates the exception:
throw new InvalidOperationException($"Your phone number registered to {dcIdx} dc. Please update settings. See https://github.com/sochix/TLSharp#i-get-an-error-migrate_x for details.");
Replace it with the following code so that the Exception that is generated has the required Data Center number for connecting to it.
InvalidOperationException exception = new InvalidOperationException($"Your phone number registered to {dcIdx} dc. Please update settings. See https://github.com/sochix/TLSharp#i-get-an-error-migrate_x for details.");
exception.Data.Add("dcId", dcIdx);
throw exception;
Change your code like this:
while (!completed)
{
request = new TL.AuthSendCodeRequest(phoneNumber, 5, _apiId, _apiHash, "en");
try
{
await _sender.Send(request);
await _sender.Receive(request);
completed = true;
}
catch (InvalidOperationException ex)
{
if (ex.Message.StartsWith("Your phone number registered to") && ex.Data["dcId"] != null)
{
await ReconnectToDc((int)ex.Data["dcId"]);
}
else
{
throw;
}
}
}
In the Code above the Data Center number that was attached to the Exception is used for reconnecting to the Data center.
Probably your phone number is not in the format accepted by Telegram.
Phone number must start with plus sign, use country code and phone number without gap, for example: +989333333333
Overview of Problem:
I need to connect to an IRC Server. Once connected, the program will send a message to the channel, and a response will occur over multiple lines back. I need to read these lines and store in a variable for later use. A special character at the end of the message (]) will define the end of the message over multiple lines. Once we have received this character, the IRC session should disconnect and processing should continue.
Situation:
I am using the Smartirc4net library. Calling irc.Disconnect() takes about 40 seconds to disconnect the session. Once we've received the ] character, the session should be disconnected, Listen() should not be blocking, and the rest of the program should continue to run.
Research:
I have found this: smartirc4net listens forever, can't exit thread, and I think it might be the same issue, however, I am unsure of what I need to do to resolve the problem.
Code:
public class IrcCommunicator
{
public IrcClient irc = new IrcClient();
string data;
public string Data { get { return data; } }
// this method we will use to analyse queries (also known as private messages)
public void OnQueryMessage(object sender, IrcEventArgs e)
{
data += e.Data.Message;
if (e.Data.Message.Contains("]"))
{
irc.Disconnect(); //THIS TAKES 40 SECONDS!!!
}
}
public void RunCommand()
{
irc.OnQueryMessage += new IrcEventHandler(OnQueryMessage);
string[] serverlist;
serverlist = new string[] { "127.0.0.1" };
int port = 6667;
string channel = "#test";
try
{
irc.Connect(serverlist, port);
}
catch (ConnectionException e)
{
// something went wrong, the reason will be shown
System.Console.WriteLine("couldn't connect! Reason: " + e.Message);
}
try
{
// here we logon and register our nickname and so on
irc.Login("test", "test");
// join the channel
irc.RfcJoin(channel);
irc.SendMessage(SendType.Message, "test", "!query");
// here we tell the IRC API to go into a receive mode, all events
// will be triggered by _this_ thread (main thread in this case)
// Listen() blocks by default, you can also use ListenOnce() if you
// need that does one IRC operation and then returns, so you need then
// an own loop
irc.Listen();
// when Listen() returns our IRC session is over, to be sure we call
// disconnect manually
irc.Disconnect();
}
catch (Exception e)
{
// this should not happen by just in case we handle it nicely
System.Console.WriteLine("Error occurred! Message: " + e.Message);
System.Console.WriteLine("Exception: " + e.StackTrace);
}
}
}
IrcBot bot = new IrcBot();
bot.RunCommand();
ViewBag.IRC = bot.Data;
As you can see, once this
Thank you for your time to look at this code and read my problem description. If you have any thoughts, or other suggestions, please let me know.
Mike
I was able to successfully disconnect straight away by calling RfcQuit() within OnQueryMessage(), before irc.Disconnect();
I have the following piece of code
try
{
if (!bDebug)
smtp.Send(m);
}
catch (Exception e)
{
wl("Meldingen kunne ikke sendes til en eller flere mottakere.", ConsoleColor.Red);
wl(e.Message, ConsoleColor.DarkRed);
using (var errorfile = System.IO.File.CreateText("error-" + DateTime.Now.Ticks + ".txt"))
{
errorfile.WriteLine(e.StackTrace);
if (e.GetType() == typeof(SmtpFailedRecipientException))
{
var se = (SmtpFailedRecipientException) e;
errorfile.WriteLine(se.FailedRecipient);
}
errorfile.WriteLine(e.ToString());
}
}
Where wl is a shortcut for writing to the console with color, and the text in the first line says "The message could not be sent to one or more recipients.
Previously I only caught the SmtpFailedRecipientException, but when it started failing in some other steps I shoved the generic Exception in there. So the part I'm wondering about is where I'm casting the Exception object into a more specific object to get the FailedRecipient property. Could/should this be done in another more proper way? It seems a bit clunky...
You can have multiple catch branches:
catch (SmtpFailedRecipientException se)
{
using (var errorfile = System.IO.File.CreateText("error-" + DateTime.Now.Ticks + ".txt"))
{
errorfile.WriteLine(se.StackTrace);
// variable se is already the right type, so no need to cast it
errorfile.WriteLine(se.FailedRecipient);
errorfile.WriteLine(se.ToString());
}
}
catch (Exception e)
{
wl("Meldingen kunne ikke sendes til en eller flere mottakere.", ConsoleColor.Red);
wl(e.Message, ConsoleColor.DarkRed);
// for other error types just write the info without the FailedRecipient
using (var errorfile = System.IO.File.CreateText("error-" + DateTime.Now.Ticks + ".txt"))
{
errorfile.WriteLine(e.StackTrace);
errorfile.WriteLine(e.ToString());
}
}
You can try somthing like this(source):
We're going to learn how to catch/handle different types of
exceptions/errors that might occur while sending an email using
ASP.Net. We'll implement error/exception handling using different
exception classes available in System.Net.Mail.
First to learn how to send an email using ASP.Net visit this
link. Notice that in the above article (lead by link) the
'SendEmails' catches only a generic exception and in case ASP.Net
encounters an error while sending email it would be like 'Sending
email failed etc'. We'll extend the error handling functionality for
the above article. So lets get started by openning the solution we
created previously. We already have put a try-catch block that catches
a generic exception that tells very little about what might have gone
wrong. Let's catch different types of exception right away:
Catch the SmtpException: The SmtpException class has a property
'StatusCode' which is actually an enumeration that gets the
error/exception code value returned by the SMTP server when an email
message is transmitted. It also provides more details of
error/exception that can occur during the email sending process. e.g.
catch (SmtpException smtpException)
{ // You can put a switch block to check for different exceptions or errors
// To checks if the destination mailbox is busy
if (smtpException.StatusCode == SmtpStatusCode.MailboxBusy)
throw smtpException;
// To check if the client is authenticated or is allowed to send email using the specified SMTP host
if (smtpException.StatusCode == SmtpStatusCode.ClientNotPermitted)
throw smtpException;
// The following code checks if the email message is too large to be stored in destination mailbox
if (smtpException.StatusCode == SmtpStatusCode.ExceededStorageAllocation)
throw smtpException;
// To check if the email was successfully sent to the SMTP service
if (smtpException.StatusCode == SmtpStatusCode.Ok)
throw smtpException;
// When the SMTP host is not found check for the following value
if (smtpException.StatusCode == SmtpStatusCode.GeneralFailure)
throw smtpException;
}
Catch the SmtpFailedRecipientException: The
SmtpFailedRecipientException class deals with the exception related to
the recipient of the email e.g. SMTP is not able to send the email to
a recipient. The SmtpFailedRecipientException occurs when SmtpClient
is not able to complete a SmtpClient.Send() or SmtpClient.SendAsync()
operation to a particular recipient. To catch this exception use the
following code:
catch (System.Net.Mail.SmtpFailedRecipientException smtpFailedRecipientException)
{
// Get the email that is causing email sending failed exception
String emailCausingException = smtpFailedRecipientException.FailedRecipient;
// Get the status code why and what is actually causing an email sending error
System.Net.Mail.SmtpStatusCode statusCode = smtpFailedRecipientException.StatusCode;
// Take some action either re-send the email again or do some error handling code here
}
Catch the SmtpFailedRecipientsException: The
SmtpFailedRecipientsException is actually a collection of
SmtpFailedRecipientException objects serving the same purpose. It is
used to handle exceptions when SmtpClient is not able to send emails
to one or more recipients.
catch (System.Net.Mail.SmtpFailedRecipientsException smtpFailedRecipientsException)
{
ArrayList emailCausingException = new ArrayList();
foreach (SmtpFailedRecipientException smtpFailedRecipientException
in smtpFailedRecipientsException.InnerExceptions)
{
// Get the email that is causing email sending failed exception
// Add it to a list of emails with exceptions
emailCausingException.Add(smtpFailedRecipientException.FailedRecipient);
// Get the status code why and what is actually causing an email sending error
System.Net.Mail.SmtpStatusCode statusCode = smtpFailedRecipientException.StatusCode;
// Take some action either re-send the email again or do some error handling
// You can also log or print this status code for an individual recipient here
if (statusCode == SmtpStatusCode.MailboxBusy)
{
//Re-Send email after some time
System.Threading.Thread.Sleep(1000);
//smtpClient.Send();
//Email sending code here
}
}
}
I am using Waitin RC2, WatiN-2.0.20.1089, Windows XP OS with IE8 With VS2008 and NUnit-2.5.7.10213. I have added the sites to the trusted list, I have thread sleeps, I have tried "WaitForComplete". yet when the script goes "back" I am still getting an unauthorized access exception.
Here is a chunk of my code, the exceptions are never caught inspite of the fact that most of the code is in try catch blocks.
public string FindAllLinks()
{
/*
* This function is designed to find and use all of the links on a given page.
* After clicking on a link it waits for 400 milliseconds on the page so the page
* has some time to load and then the function "hits the back button" reseting
* to the originating page.
* This function is not meant to be recursive.
*/
string message = "";
bool flag = true;
//Get a list of all links from the browser instance
foreach (Link link in browserInstance.Links)
{
System.Threading.Thread.Sleep(1000);
Console.WriteLine(link);
try
{//clicking on the link to make sure it leads somewhere
link.Click(); //If the click fails hopefull we will thrwo out of the try block and not execute the next two commands.
//Console.WriteLine(link);
}
catch (Exception)
{//OOPs we have an error let's log a message.
message = message + "The link titled " + link + " was not found, or did not work.\n";
flag = false;
}
if (flag)
{
System.Threading.Thread.Sleep(1000);
//browserInstance.WaitForComplete;
try { browserInstance.Back(); }
catch (UnauthorizedAccessException)
{
//do nothing
}
}//close if flag
}//close for each
//return the message
return (message);
}//Close function
[STAThread]
[Test]
public void TestTitleHomePage()
{
bool testPassed = false;
if (browserInstance.Title.Contains("<title>"))
{
string message = FindAllLinks();
if (message == "") { testPassed = true; }
}//close if
else { message = "The Title was not the same."; }
Assert.IsTrue(testPassed, message);
}// end TestTitleHomePage
I tried your code and I also get the exception. I think I understand what happens. When you first do Browser.Links, you get all the links of the current page, then you navigate to another page and return to the first page, but for WatiN it is a new page. So your enumeration cannot work because you enumerate though the links of the first page.
What I suggest you could do is to get all the Uri of the links, then try them one by one in a new browser
IEnumerable<Uri> uris = Browser.Links.Select(l => l.Uri);
foreach(Uri uri in Uris)
{
try
{
using(var browser = new IE(uri))
{
// do nothing or detect 404, 403, etc errors
}
// no error
}
catch(exception)
{
// log error
}
}