C# Argument out of Range while sending mail - c#

Sometimes, using the following code :
return SmtpClient.Send(message, OutboundClient.Host, OutboundClient.Port);
I retrieve the following error :
ArgumentOutOfRangeException: Count cannot be less than zero.Parameter name:count
at System.String.RemoveInternal(Int32 startIndex, Int32 count)
at ActiveUp.Net.Mail.TraceInfo.ToString()
at ActiveUp.Net.Mail.Header.ToHeaderString(Boolean removeBlindCopies)
at ActiveUp.Net.Mail.Message.ToMimeString(Boolean removeBlindCopies)
at ActiveUp.Net.Mail.Message.ToMimeString()
at ActiveUp.Net.Mail.SmtpClient.Send(Message message, String host, Int32 port)
In my code Host and Port are static values that never change message instead is (Message object) readen in another mailbox (but i have checked is always valorized even if this exception is thrown)
Anyone know why sometimes i get the exception above ?

You should check your version of MailSystem.NET.
There was a bug that look like yours on versions prior to 71651.
It happens when From, By, With, For, Via and Id are all empty.

Related

Discord.Net - Add reaction to previous message from command

From a command, I want to be able to grab the previous message from the chat and add reactions to that message. I am using this line of code to get the previous message but it returns a IEnumerable<IMessage>.
var messages = await Context.Channel
.GetMessagesAsync(Context.Message, Direction.Before, 1)
.FlattenAsync();
IMessages do not have an add reaction function. I tried going through multiple ways to get the socket user message from the last message but can not find any way to get a socket user message from an IMessage.
Simply cast to an IUserMessage.
If cache isn't enabled you won't be able to get a socket message, you'd get a rest message instead. That said, a socket message isn't required, so the interface should suffice.

The specified message does not exist. ErrorCode:MessageNotFound Prod-WorkerError Context

I have a worker role which consumes messages from an Azure Queue does some processing in the background.
When I check my log there appears to be no exception logged while processing the message but still in my logs I get the following Exception(pasting some of the relevant texts from the long error log only):
System.Net.WebException
Microsoft.WindowsAzure.Storage.StorageException Exception messages:
The remote server returned an error: (404) Not Found. The remote
server returned an error: (404) Not Found. Stack Traces: at
System.Net.HttpWebRequest.GetResponse() at
Microsoft.WindowsAzure.Storage.Core.Executor.Executor.ExecuteSync[T](RESTCommand1
cmd, IRetryPolicy policy, OperationContext operationContext) --- Next
Call Stack: at
Microsoft.WindowsAzure.Storage.Core.Executor.Executor.ExecuteSync[T](RESTCommand1
cmd, IRetryPolicy policy, OperationContext operationContext) at
Microsoft.WindowsAzure.Storage.Queue.CloudQueue.DeleteMessage(String
messageId, String popReceipt, QueueRequestOptions options,
OperationContext operationContext) at
InnovativeExams.Azure.CloudStorage.AzureQueue`1.DeleteMessage(T
message) The specified message does not exist.
ErrorCode:MessageNotFound Prod-WorkerError Context
Here is the code I have in the worker role:
private void ProcessQueueMessage(object queueMessageToProcess)
{
var queueMessage = queueMessageToProcess as EventCompletedQueueMessage;
try
{
if (_eventCompletedProcessor.Process(queueMessage))
_azureQueue.DeleteMessage(queueMessage);
}
catch (Exception ex)
{
_logger.LogError(string.Format("Event Completed message <{0}> was not processed due to an exception", queueMessage.Id), ex, LogSources.WorkerRole_EventCompletedDispatcher);
}
}
The above exception is caught in the above catch block and logged.
I think there is some problem when the worker role tries to Delete the message in the Queue and the message is not found.
Need help from someone to help me resolve this error and to know the background what's going wrong here.
Few Questions asked in comment:
1) Are you running multiple instances of your worker role?
A: This is an existing application and I figured out we are using ThreadPool to pre-instantiate, threads which stand ready to be given work.
2) How are you "getting" the messages in your worker role? Are you using some kind of leader election pattern to decide which instance gets the messages?
A: Yes there is a framework which determines the appropriate dispatcher for a QueueMessage to be processed.
3) When you get messages, what's the visibility timeout for those messages?
A: Its set to 120.
4) How long does it take for you to process these messages i.e. how much time between getting the message and deleting the messages?
A: I am not sure on this.
Let me explain under what situation you would get the error you're encountering.
When you dequeue a message (i.e. GET Messages in Azure terminology), Azure Queue Service returns something called popreceipt which must be used to delete or update a message. This popreceipt is an opaque value (i.e. you should not build any business logic around it) which remains valid till the time that same message is dequeued again. When a message is dequeued again, you get a new value for popreceipt and you should use this new value to delete or update the message.
If you try to use an old popreceipt value to delete a message while the message was dequeued again (by some other process), you will get the error you're getting.
My guess is that this is what is happening in your application. Please check if this is indeed the case:
One of the worker role instances dequeues the message and starts working on that message. Based on what you told above, you hide the message for 120 seconds when you dequeue a message. I am assuming that the actual time taken for processing the message is more than 120 seconds and thus the message reappears in the queue. There's another process which now dequeues this message (and thus you get a new popreceipt). However soon after the 2nd process dequeued the message, 1st process finished working on the message and now it wants to delete the message using the popreceipt it has. Because this popreceipt is no longer valid, any attempt to perform delete operation on that message using this popreceipt will cause a message not found error.

System.Net.Sockets.SocketException (0x80004005)

I'm writing a bot for moderating my twitch.tv channel in C#.
Here's the basic code for the loop, which is done by a background worker to avoid UI freezes. There's a TCPClient (Client), StreamReader (Reader), StreamWriter (Writer), and NetworkStream (Stream).
private void listener_dowork(object sender, DoWorkEventArgs e)
{
string Data = "";
while ((Data = Reader.ReadLine()) != null)
{
//Perform operations on the received data
}
Console.WriteLine("Loop ended");//this shouldn't happen
}
private void listener_workercompleted(object sender, RunWorkerCompletedEventArgs e)
{
//basically, display a console message that says "OOPS!" and try to reconnect.
}
I get the message "Loop ended" and "OOPS!" and at that point, I get the exception (which I cannot for the life of me catch).
The thing is, I can physically unplug the network cable from my computer wait 30 seconds and plug it back in, and it'll continue just fine.
The full exception is:
System.Net.Sockets.SocketException (0x80004005): An established connection was aborted by the software in your host machine
at System.Net.Sockets.Socket.Send(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags)
at System.Net.Sockets.NetworkStream.Write(Byte[] buffer, Int32 offset, Int32 size)
Note the lack of a line number, which is present in every other kind of exception I've had, which means I have no idea which part of the program is causing the exception, even though I've put every possible line inside a try/catch.
I guess what I'm looking for is some insight into why this is occurring.
It happens invariably every time I start the bot and leave it running for a few minutes on any channel, though the number of minutes varies.
As I already said in the comments Twitch.tv uses IRC as underlying system for their chat. In order to stay connected with the server you need to reply to "PING" requests that are frequently sent by the server (usually every 30 seconds, may vary depending on the servers implementation). You can read up more about the IRC client protocol in RFC 2812.
You said you already have a StreamWriter and Reader, all you need to do is check if the line contains "PING" and reply with a "PONG":
if (Data.Contains("PING"))
{
_streamWriter.WriteLine(Data.Replace("PING","PONG");
_streamWriter.Flush();
}

Partial work being done twice (ThreadPool.QueueUserWorkItem)

I have created a newsletter system that allows me to specify which members should receive the newsletter. I then loop through the list of members that meet the criteria and for each member, I generate a personalized message and send them the email asynchronously .
When I send out the email, I am using ThreadPool.QueueUserWorkItem.
For some reason, a subset of the members are getting the email twice. In my last batch, I was only sending out to 712 members, yet a total of 798 messages ended up being sent.
I am logging the messages that get sent out and I was able to tell that the first 86 members received the message twice. Here is the log (in the order the messages were sent)
No. Member Date
1. 163992 3/8/2012 12:28:13 PM
2. 163993 3/8/2012 12:28:13 PM
...
85. 164469 3/8/2012 12:28:37 PM
86. 163992 3/8/2012 12:28:44 PM
87. 163993 3/8/2012 12:28:44 PM
...
798. 167691 3/8/2012 12:32:36 PM
Each member should receive the newsletter once, however, as you can see member 163992 receives message #1 and #86; member 163993 received message #2 and #87; and so on.
The other thing to note is that there was a 7 second delay between sending message #85 and #86.
I have reviewed the code several times and ruled out pretty much all of the code as being the cause of it, except for possibly the ThreadPool.QueueUserWorkItem.
This is the first time I work with ThreadPool, so I am not that familiar with it. Is it possible to have some sort of race-condition that is causing this behavior?
=== --- Code Sample --- ===
foreach (var recipient in recipientsToEmail)
{
_emailSender.SendMemberRegistrationActivationReminder(eventArgs.Newsletter, eventArgs.RecipientNotificationInfo, previewEmail: string.Empty);
}
public void SendMemberRegistrationActivationReminder(DomainObjects.Newsletters.Newsletter newsletter, DomainObjects.Members.MemberEmailNotificationInfo recipient, string previewEmail)
{
//Build message here .....
//Send the message
this.SendEmailAsync(fromAddress: _settings.WebmasterEmail,
toAddress: previewEmail.IsEmailFormat()
? previewEmail
: recipientNotificationInfo.Email,
subject: emailSubject,
body: completeMessageBody,
memberId: previewEmail.IsEmailFormat()
? null //if this is a preview message, do not mark it as being sent to this member
: (int?)recipientNotificationInfo.RecipientMemberPhotoInfo.Id,
newsletterId: newsletter.Id,
newsletterTypeId: newsletter.NewsletterTypeId,
utmCampaign: utmCampaign,
languageCode: recipientNotificationInfo.LanguageCode);
}
private void SendEmailAsync(string fromAddress, string toAddress, string subject, MultiPartMessageBody body, int? memberId, string utmCampaign, string languageCode, int? newsletterId = null, DomainObjects.Newsletters.NewsletterTypeEnum? newsletterTypeId = null)
{
var urlHelper = UrlHelper();
var viewOnlineUrlFormat = urlHelper.RouteUrl("UtilityEmailRead", new { msgid = "msgid", hash = "hash" });
ThreadPool.QueueUserWorkItem(state => SendEmail(fromAddress, toAddress, subject, body, memberId, newsletterId, newsletterTypeId, utmCampaign, viewOnlineUrlFormat, languageCode));
}
Are you sure the query you are running to get the list of members to send the email to does not have duplicates in it? Are you joining to another table? What you could do is:
List<DomainObjects.Members.MemberEmailNotificationInfo> list = GetListFromDatabase();
list = list.Distinct().ToList();
Having 800+ threads running on the server is not a good practice!
Although you are using a ThreadPool, threads are being queued on the server and run whenever old threads return back to the pool and release the resource. This might take several minutes on the server and many situations like Race Conditions or Concurrencies might happen during that time.
You could instead queue one work item, over one protected list:
lock (recipientsToEmail)
{
ThreadPool.QueueUserWorkItem(t =>
{
// enumerate recipientsToEmail and send email
});
}
Things to check (I'm assuming you have a way to mock the sending of emails):
Is the number of duplicate emails always exactly the same? What if you increase/decrease the number of input values? Is it always the same user IDs which are duplicated?
Is SendEmail() doing anything of significance? (I don't see your code for it)
Is there a reason that you aren't using the framework's SendAsync() method?
Do you get the same behavior without multithreading?
For what it's worth, sending bulk email from your own site--even when it is completely legitimate--is not always worth the trouble. Spam blocking services are very aggressive and you don't want your domain to end up blacklisted. Third party services remove that risk, provide many tools, and also manage this part of the process for you.
If this code:
foreach (var recipient in recipientsToEmail)
{
_emailSender.SendMemberRegistrationActivationReminder(eventArgs.Newsletter
,eventArgs.RecipientNotificationInfo, previewEmail: string.Empty);
}
matches what you are actually doing... you have an obvious bug. namely that you are doing a foreach but not using the returned value, so you will send the same email to eventArgs.RecipientNotificationInfo for each entry in recipientsToEmail.
One common cause of tasks getting performed twice in code where you queue the task to a background thread is faulty error handling. You might double-check your code to make sure that if there's an error that you don't always retry, regardless of the type of error (some errors warrant a retry; others don't).
Having said that, the code you've posted doesn't include enough information to definitively answer your question; there are many possibilities.
FWIW, are you aware that the SmtpClient class has a SendAsync() method, that doesn't require the use of a separate worker thread?
In your code sample, we can't see where your logging takes place.
Maybe the mehod that sends the email erronously thought that something wrong occured then, the system tried again, which could result in an email sent twice.
Also, as written in other answers and comment, I would check again that I don't get duplicated entries in the list of recipients, and test it in a non-parallel context.

How to check if a server is listening without exception handling

I'm working on two apps that connect to eachother using TCP. At one point, one of them is trying to connect using a TcpClient, but the other app is not guaranteed to have started listening yet (using TcpListener).
My first attempt was this:
TcpClient c = null;
while (true)
{
try
{
c = new TcpClient();
c.NoDelay = true;
c.Connect( ip, port );
break;
}
catch (SocketException ex)
{
Console.WriteLine(string.Format("Could not connect to {0}:{1}, retrying...", ip, port));
Thread.Sleep( 500 );
}
}
However, the problem with this is that it relies on exception handling which is a bit of a nuisance for me, because I have VS set up to catch any thrown exceptions ("Debug -> Exceptions..." menu). So every time it tries to connect, it breaks into VS and I have to press continue.
The exception I get is:
No connection could be made because the target machine actively refused it 127.0.0.1:50000
I would imagine that there would be a way to check if a server is listening on a specific port without actually trying to connect to it. I understand that just checking wouldn't be enough anyway - the server could go down between the check and the connect attempt, but it would still be much better for me while I'm developing it.
Or something like this:
TcpClient tcpClient = new TcpClient();
while ( !tcpClient.TryConnect(....) )
{ Thread.Sleep(1000); }
Analogous to this:
if (bool.TryParse( "false" ))
{ ... }
I also tried using async methods (Begin/End Connect) and setting the timeout for the ManualResetEvent manually, but that didn't work either. I've scoured the internets but I haven't been able to find a solution to this problem, which is why I'm finally posting here :)
The problem being that VS is breaking on the Exception? You you can always have VS ignore a specific family of Exceptions.
In VS, in the Debug Menu, choose "Exceptions..." and in the dialog presented you can control this.
I was going to suggest not catching an exception, so before I suggested that I test it myself, and if you set it to throw all exceptions even if you don't throw an exception its all exceptions are still being thrown. I will have to agree with Shiv Kumar, either adjust your settings while you debug your application, or accept the limitations of what you are doing.
The reason bool.TryParse works is it verifys each and every character, similarly to how Int32.TryParse makes sure that each character in the string is 0-9 or any other valid numerical symbol.
You could of course write your own networking class and not throw an exception when the connection fails.
TryParse will not throw an exception, you must catch any exception that is thrown if you use bool.Parse by try{}catch{} otherwise if you attempt to parse something that is not a boolean value it will throw an unhandled exception. TryParse was added later in the history of .NET, Parse is more of the classic method, allowing the programmer to handle all unexpected input and to validate input before trying to parse the data.
I should add that TryParse will return false if its unable to parse the value at both the method's result is false and the out variable I do believe is false.This is at least the case with Int32
http://msdn.microsoft.com/en-us/library/system.boolean.tryparse.aspx
I guess the point of pointing out how TryParse and Parse works is that they are entirely different beasts compare to TcpClient. I suppose I should clarify that the basic validation process is similar, except one throws an exception and the other one doesn't and of course one returns what was actually parsed.

Categories

Resources