IMAP 4 Client Authentication issue - c#

I have a windows service which is scheduled to run below method every 5minutes and read emails and process the attachement i.e. convert tiff to pdf and update the database by reading the QR code of attachement, I have observed a issue recently the Service got hanged i.e. I could not stop it from services.msc and have to kill it from task manager although it worked well for last 2months without issue.
Upon investigating the log I observed the log entry was "IMAP 4 Client Authentication Started"
and it never reached "IMAP 4 Client Authentication Done" although as it is schedule to call this method every 5minutes I could see the logs from there on call to the below method
"call to processEmail for user Dept1 "
"call to processEmail for user Dept2 "
son on........
private readonly object _myLock = new object();
public void start()
{
// all the belwo variable read from config file...
Log.WriteLog("call to processEmail for user " + username);
ProcessEmail(host, username, password, connPort);
Log.WriteLog("Service Completed reading for user " + username);
}
public void ProcessEmail(string host, string username, string password, int connPort)
{
Monitor.Enter(_myLock); //_myLock defined at class level
Log.WriteLog("IMAP 4 Client Authentication Started");
using (Imap4Client imap = new Imap4Client())
{
try
{
imap.ConnectSsl(host, connPort); // port 993 for SSL Connect
imap.Login(username, password);
imap.Command("capability");
Log.WriteLog("IMAP 4 Client Authentication Done");
//fllowed by reading email from Inbox and junk emails.
}
catch (Exception ex)
{
Log.WriteLog(ex.Message);
}
finally
{
Monitor.Exit(_myLock);
}
}
}
My concern is if due to some reason imap.Login(username, password) fails, why the code block holds the lock by not allowing other instances to login as in finally block I am releasing the lock Monitor.Exit(_myLock), and I don't even see the exception recorded in log file, does imap.Login(username, password) trying to connect for ever to login, any suggestion/help on this would be of great help.
Again - this issue occurred today and from the log I could see this time
Message: Unable to read data from the transport connection: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond.
followed by -
Service Completed reading for user " + username
and then again sequentially...
**call to processEmail for user Dept1 **
**call to processEmail for user Dept2 **
Is this issue has something to do with Activeup.Net.Imap4 client or could itbe Deadlock issue as I don't see anything that would cause deadlock..

After looking into Imap4 I couldn't find much to do in connectssl,Login and command method as to why it's going unresponsive and causing deadlock I have plan to implement the below solution for the issue -
Log.WriteLog("IMAP 4 Client Authentication Started");
using (Imap4Client imap = new Imap4Client())
{
try
{
imap.ConnectSsl(host, connPort); // port 993 for SSL Connect
imap.Login(username, password);
imap.Command("capability");
Log.WriteLog("IMAP 4 Client Authentication Done");
//fllowed by reading email from Inbox and junk emails.
try
{
Monitor.Enter(_myLock);
ReadEmails(imap, "inbox");
LogHelper.WriteLogEntry("Retrieving junk e-mail unread emails started");
ReadEmails(imap, "junk");
}catch(Exception ex)
{
Log.WriteLog(ex.Message);
}
finally
{
Monitor.Exit(_myLock);
}
}
catch (Exception ex)
{
Log.WriteLog(ex.Message);
}
}
Please advice if any better solution.

Related

Is there any way to suppress a sent SMS message from appearing on the sending phone?

I'm using the following code to send a SMS message in the background using Plugin.Messaging:
public async void SendSMS(string pMessage, string pPhoneNumber)
{
try
{
var smsMessenger = CrossMessaging.Current.SmsMessenger;
if (smsMessenger.CanSendSmsInBackground)
smsMessenger.SendSmsInBackground(pPhoneNumber, pMessage);
}
catch (Exception ex)
{
Utils.LogError("App: OMLAndroid (TextMessage.cs) - An error occurred when trying to send a text, the error is: " + ex.Message);
}
}
Once the permissions are set properly, the SMS gets sent with no issues. Because there's a possibility that a user can send a lot at once, is there anyway I can suppress the display of the message in the messages app?
I can see hundreds of copies the same message being displayed with all the different numbers, all the answers I've seen suggest no unless your app is set as the default message system. I don't want the users to have to do that, but if there's no other way, it is what it is and I can instruct users to workaround that by setting my app as the default temporarily (ugly).

Azure Service Bus MessageReceiver Receive() web sockets error

I am working with a c# program within my network and am able to post messages to an Azure Service Bus queue. When receiving them, I get an exception on MessageReceiver.Receive(). The code and error is below;
MessagingFactory factory = MessagingFactory.CreateFromConnectionString(QueueConnectionString);
//Receiving a message
MessageReceiver testQueueReceiver = factory.CreateMessageReceiver(QueueName);
using (BrokeredMessage retrievedMessage = testQueueReceiver.Receive(new TimeSpan(0, 0, 20)))
{
try
{
var message = new StreamReader(retrievedMessage.GetBody<Stream>(), Encoding.UTF8).ReadToEnd();
retrievedMessage.Complete();
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
retrievedMessage.Abandon();
}
}
The error gets thrown on the 'using' line at
testQueueReceiver.Receive(...);
The server rejected the upgrade request. 400 This endpoint is only for web-socket requests
I can't find anything on the web with the exception of one post which seems to suggest it is a firewall / ports issue. I have all the azure service bus ports outbound open (9350-9354, 80, 443) locally but there is a chance the 9000's are blocked at the firewall. Should it require these? Any pointers would be greatly appreciated !
Service MessagingCommunication Exception - The End point is only for web socket requests
I'm just wondering why don't you use OnMessage instead of polling the queue?
var connectionString = "";
var queueName = "samplequeue";
var client = QueueClient.CreateFromConnectionString(connectionString, queueName);
client.OnMessage(message =>
{
Console.WriteLine(String.Format("Message body: {0}", message.GetBody<String>()));
Console.WriteLine(String.Format("Message id: {0}", message.MessageId));
message.Complete()
});
This was fixed due to some proxy issues.
The account that the code was running under was an async service. I needed to log in as that account, open IE and go to connections (LAN) and remove the proxy checkboxes (detect settings automatically, etc). Once this was done, the code bypassed the proxy and worked fine.

Why does SmtpClient fail with several different Exceptions when using SSL?

I'm trying to send a mail message using System.Net.Mail.SmtpClient with SSL enabled. While changing no external factors (i.e. hit F5, then hit F5 Again - or even in a loop) it works some times, but most of the times it fails.
Example code:
public void SendMail()
{
using (var client = new SmtpClient())
{
MailMessage mailMessage = new MailMessage();
client.EnableSsl = true;
client.Host = "smtp.example.com";
client.Timeout = 10000;
client.DeliveryMethod = SmtpDeliveryMethod.Network;
mailMessage.From = new MailAddress("from#example.com");
mailMessage.To.Add(new MailAddress("to#example.com"));
mailMessage.Subject = "Test";
mailMessage.Body = "Message " + DateTime.Now.ToString();
try
{
client.Send(mailMessage);
}
catch (Exception ex)
{
// This being a Pokemon block is besides the point
}
}
}
In my catch block I just get a timeout, but if I set up a trace for System.Net and System.Net.Sockets I can see a number of different exceptions:
Unable to read data from the transport connection: A blocking operation was interrupted by a call to WSACancelBlockingCall
Unable to read data from the transport connection: An established connection was aborted by the software in your host machine
Cannot access a disposed object
Reading is not supported on this stream
Writing is not supported on this stream
All of which happen post EHLO, STARTTLS and authentication. The client and the server are chatting along in their cryptographic ways when the exceptions are thrown.
System.Net.Mail.SmtpClient.Send() is the the only frame all call stacks have in common.
Of course I've tried changing the code in a number of ways, such as setting client.UseDefaultCredentials, using client.SendAsync() and whatnot. But I suspect it's something entirely different knocking the connection over at different times - a configuration error on one of the machines involved perhaps?
So I've checked the Event Logs for signs of something messing with the connection, but I haven't found anything.
Any suggestions as to what I should be looking for here?
Sometimes a timeout is just a timeout ...
Digging further into this issue I used Wireshark to see what was going on at the network level.
When the failures happened, the client machine invariably sent a TCP [RST, ACK] packet around 10 seconds after EHLO. A timespan conspicuously close to my timeout value. When I doubled the timeout value the mails came through without failure every single time.
Of course if we were to spend more than 10 seconds sending each mail, we'd soon be queuing up mails for hours in our production system, so I needed to find out why it took so long.
One detail caught my attention:
The client was spending upwards of four seconds between two packets. And it was generally spending hundreds of milliseconds between packets whereas the server would respond within tens.
The next step was to build the code without debug symbols and measure again without a debugger attached. The time spent per e-mail sent immediately went sub-second. Now it's no news to me that code runs slower with a debugger attached, but seeing it run that much slower was a surprise.
So the lessons for me to learn were: Try not to overanalyze, and when timing is involved kill the debugger once in a while.
This should be a comment (I don't have reputation to make comments), but it could be a firewall issue, given you're getting an "Unable to read data from the transport connection: An established connection was aborted by the software in your host machine" error (basically, firewall or anti-virus cancelled your attempt to send a mail).
The error "Unable to read data from the transport connection: A blocking operation was interrupted by a call to WSACancelBlockingCall" happens when a stream is closed - see this question - and the other errors you've listed seem like they're related to trying to access a stream when it's closed, too.
All these error point to a common cause, a connection cancelled somewhere between you and the server and most likely on your machine/ network, and you get different errors depending at what point the effect propagates through to your application.
Another thing is, if you use
Credentials = new NetworkCredential(fromAddress.Address, fromPassword)
then you have to enable ssl afterwards, not before, otherwise it's cleared.
I suppose you have missed to set Credentials property of your host. However the another reason for exceptions may be wrong host name and port.Try something like :
public void SendMail()
{
try
{
var fromAddress = new MailAddress("from#example.com", "Some text");
var toAddress = new MailAddress("to#example.com");
const string fromPassword = "from account password";
var smtp = new SmtpClient
{
Host = "smtp.example.com",
Port = "your host port", //for gmail is 587
EnableSsl = true,
DeliveryMethod = SmtpDeliveryMethod.Network,
UseDefaultCredentials = false,
Credentials = new NetworkCredential(fromAddress.Address, fromPassword)
};
using (var message = new MailMessage(fromAddress, toAddress)
{
Subject = "Test",
Body = "Message " + DateTime.Now.ToString()
})
{
smtp.Send(message);
}
}
catch (Exception ex)
{
//do something
}
}
It is tested with gmail host which is smtp.gmail.com and it works correctly

RabbitMQ throws Shared Queue closed error

We have been using RabbitMQ as messaging service in the project. We will be pushing message into a queue and which will be received at the message consumer and will be trying to make entry into database. Once the values entered into the database we will be sending positive acknowledgement back to the RabbitMQ server if not we will be sending negative acknowledgement.
I have created Message Consumer as Windows service.Message has been successfully entered and well received by the message consumer(Made entry in table)but with an exception log "Shared Queue closed".
Please find the code block.
while (true)
{
try
{
if (!Connection.IsOpen || !Channel.IsOpen)
{
CreateConnection(existConnectionConfig, QueueName);
consumer = new QueueingBasicConsumer(Channel);
consumerTag=Channel.BasicConsume(QueueName,false,consumer);
}
BasicDeliverEventArgs e = (BasicDeliverEventArgs)consumer.Queue.Dequeue();
IBasicProperties props = e.BasicProperties;
byte[] body = e.Body;
bool ack = onMessageReceived(body);
if (ack == true)
{
Channel.BasicAck(e.DeliveryTag, false);
}
else
Channel.BasicNack(e.DeliveryTag, false, true);
}
catch (Exception ex)
{
//Logged the exception in text file where i could see the
//message as "Shared queue closed"
}
}
I have surfed in net too but couldn't able to what the problem. It will be helpful if anyone able to help me out.
Thanks in advance,
Selva
In answer to your question, I have experienced the same problems when my Web Client has reset the connection due to App Pool recycling or some other underlying reason the connection has been dropped that appears beyond your scope. You may need to build in a retry mechanism to cope with this.
You might want to look at MassTransit. I have used this with RabbitMQ and it makes things a lot easier by effectively providing a management layer to RabbitMQ. MassTransit takes away the headache of retry mechanisms - see Connection management. It also provides a nice multi threaded concurrent consumer configuration.
This has the bonus of your implementation being more portable - you could easily change things to MSMQ should the requirement come along.

while reading from a socket

Sometimes when reading a socket from the TcpClient class, the stream comes in without interpreting the data instantly. For example if I connect to an IRC server and I want to interpret the text in the channel to recognize commands. If somebody types a command, !time and !time is a valid function, it would write back to the server the current time.
The problem is if someone spams that same command !time at a high rate, the socket would be flooded. If someone else tried to execute !time it would not write back to the server until the while() loop finished reading the flooded socket stream. This could take minutes if not at all if the user kept spamming/flooding the command.
static void Connect(String hostname, int port)
{
try
{
socket = new TcpClient(hostname, port);
socket.ReceiveBufferSize = 4096;
Console.WriteLine("Successfully connected to " + hostname);
NetworkStream stream = socket.GetStream();
reader = new StreamReader(stream);
writer = new StreamWriter(stream);
write("USER " + username + " 8 * :" + description, writer);
write("NICK " + username, writer);
write("NS IDENTIFY " + password, writer);//Authenticate account
read(reader);//read the stream
reader.Close();
writer.Close();
stream.Close();
socket.Close();
}
catch
{
Console.WriteLine("Failed to connect to " + hostname);
}
}
read() function below:
static void read(StreamReader reader)
{
try
{
while (true)
{
interpret(reader.ReadLine());
}
}
catch
{
Console.WriteLine("Unable to read from server");
}
}
What could I do so the stream cannot be harmed if it were to be flooded? So that if someone did flood the stream with !time it would not stop other users from also seeing the time if they so typed !time.
Thank you.
Chatbot solution
You will have to process all the incoming text at least far enough to separate messages, and determine what user sent each message. Then you can split them into separate queues by user. You can either process the queues round-robin, or randomly. Or, you can implement a token bucket scheme, where every n seconds all users are given a certain number of tokens, and every command uses up a token. Users aren't allowed to go above a limit of a certain number of tokens (p seconds worth of tokens they're allowed to hoard). If there's no token for that user when a command arrives, either throw it away or queue it for the next time tokens are given out.
Server-side solution
The other users have their own sockets, don't they?
A backlog on one socket doesn't prevent you from reading the others. You just have to write the application logic so it doesn't get stuck reading from one, it goes round-robin and only reads more from the first after everyone has had a chance.
Typically you use some function like select or WaitAny which yield a list of ready sockets. Don't always read from the first socket in the list, pick the one which most closely follows the last one you read, or else pick one randomly.

Categories

Resources