Connecting to gmail with Mailkit ImapClient using TLS not SSL - c#

I'm trying to poll a gmail account in C# code.
I am using the Mailkit libraries (https://github.com/jstedfast/MailKit).
I can connect successfully when I tell the client to use SSL:
using (var client = new ImapClient ())
{
client.Connect ("imap.friends.com", 993, true);
client.Authenticate ("joey", "password");
client.Disconnect (true);
}
But it's my understanding (possibly wrong) that SSL is insecure and we shouldn't be using it. So I'm trying to force a TLS connection:
using (var client = new ImapClient ())
{
client.Connect ("imap.friends.com", 993, SecureSocketOptions.StartTls);
client.Authenticate ("joey", "password");
client.Disconnect (true);
}
But this errors on the client.connect line:
Message: The IMAP Server has unexpectedly disconnected
Stack Trace:
at MailKit.Net.Imap.ImapStream.<ReadAheadAsync>d__54.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at MailKit.Net.Imap.ImapStream.<ReadTokenAsync>d__69.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at MailKit.Net.Imap.ImapEngine.<ConnectAsync>d__140.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
at MailKit.Net.Imap.ImapClient.<ConnectAsync>d__81.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at MailKit.Net.Imap.ImapClient.Connect(String host, Int32 port, SecureSocketOptions options, CancellationToken cancellationToken)
I'm running with the protocol logger, but that's not telling me much, it holds only 1 line:
Connected to imap://imap.gmail.com:993/?starttls=always
So I guess my questions are:
1) Should I be worried about using insecure SSL 3.0 to access gmail? I find it hard to believe that they are forcing me to use a deprecated security protocol.
2) If so, how can I force a TLS connection, so I can keep SSL3.0 turned off for clients on my application server?

MailKit has 2 different ways of doing SSL/TLS:
Use SSL/TLS immediately upon connecting to the remote server
Use the STARTTLS command to toggle into SSL/TLS mode after connecting and reading the greeting to check if the server supports it
You are trying to use the second mode but you are connecting to a port (993) which requires the first mode.
Which version of SSL vs TLS gets used with either of these modes is entirely dependent upon what the server supports (actually, technically, MailKit doesn't support any version of SSL by default, it only supports TLSv1.0, TLSv1.1, and TLSv1.2 - I removed SSLv3 by default a few years ago).
The way that you can change the supported SSL and/or TLS versions that you'd like to limit MailKit to can be done by setting the client.SslProtocols property.

Related

UWP App cannot resolve local domain from hosts file

I have a modified hosts file which is as follows:
192.168.10.10 library.test
and I try to connect to this domain from a UWP app using HttpClient like so
var client = new HttpClient();
var result = await client.GetAsync("http://library.test");
Console.WriteLine(result.StatusCode);
but this fails with the following exception
HResult=0x80072EFD
Message=An error occurred while sending the request.
Source=System.Net.Http
StackTrace:
at System.Net.Http.HttpClientHandler.<SendAsync>d__111.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Net.Http.HttpClient.<FinishSendAsyncBuffered>d__58.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at WordsmithsApp.ViewModels.LoginViewModel.<TryLogin>d__4.MoveNext() in C:\Users\dubif\mods-n-stuff\Coding\Projects\WordsmithsApp\WordsmithsApp\WordsmithsApp\ViewModels\LoginViewModel.cs:line 37
Inner Exception 1:
COMException: The text associated with this error code could not be found.
A connection with the server could not be established
This same code works fine when using a host such as https://google.com
I did not reproduce your problem, when I try to modify the website library.test in the host and direct it to the local webpage, it can be accessed normally.
Please check the following:
Is 192.168.10.10 an accessible IP address? If you only access the local, you can change to 127.0.0.1.
If you do not set a port number, then the default is access to port 80, please ensure that there is accessible content under this port.

Google NLP authentication/call issue

I am working on an MVC web application that uses Google Natural Language Processing API to parse different input from users.
I have successfully consumed and implemented the API operations and everything works fine as long as I run the application on my local machine. But as soon as I publish a version and upload it on a server I receive the following error on calling the API methods (e.g. AnalyzeSentiment):
Status(StatusCode=Unauthenticated, Detail="Getting metadata from plugin failed with error: Exception occured in metadata credentials plugin.")
With the help of the answers from post: Google Datastore authentication issue - C# I was able to further get details on the error (using gRCP):
An error occurred while sending the request.
Stacktrace: at Google.Apis.Http.ConfigurableMessageHandler.<SendAsync>d__58.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Google.Apis.Auth.OAuth2.Requests.TokenRequestExtenstions.<ExecuteAsync>d__0.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Google.Apis.Auth.OAuth2.ServiceAccountCredential.<RequestAccessTokenAsync>d__19.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Google.Apis.Auth.OAuth2.ServiceCredential.<GetAccessTokenForRequestAsync>d__23.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Google.Apis.Auth.OAuth2.ServiceAccountCredential.<GetAccessTokenForRequestAsync>d__20.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Grpc.Auth.GoogleAuthInterceptors.<>c__DisplayClass2_0.<<FromCredential>b__0>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Grpc.Core.Internal.NativeMetadataCredentialsPlugin.<GetMetadataAsync>d__11.MoveNext()
This seemed like an authentication issue so I double checked the jsonKey file which is fine. Please note, I have used code to set the credentials in Environment variables:
Environment.SetEnvironmentVariable("GOOGLE_APPLICATION_CREDENTIALS", jsonPath);
and verified it using:
Environment.GetEnvironmentVariable("GOOGLE_APPLICATION_CREDENTIALS")
The call is made as follows:
private AnalyzeSentimentResponse AnalyzeSentiment(string statement)
{
GrpcEnvironment.SetLogger(new MyLogger());
var client = LanguageServiceClient.Create();
var response = client.AnalyzeSentiment(new Document()
{
Content = statement,
Type = Document.Types.Type.PlainText
});
return response;
}
Cannot figure out why it works fine when I run it on my local machine and fails when it is deployed on the server. There is also no restrictions of any kind on the said server.
The result for:
GoogleCredential.GetApplicationDefaultAsync().Result.Underly‌​ingCredential.GetTyp‌​e()
is:
Google.Apis.Auth.OAuth2.ServiceAccountCredential
Note: The server is our own (Windows Server 2012R2)
With the suggestion given by #JonSkeet, I copied the code into a console application and executed the call. Unfortunately, the issue persisted. What I did next was to move the console application onto another server, it worked there.
So, it was indeed an issue with the server where there maybe some features missing (the firewall is disabled). Network dept is checking it out whereas I have deployed my web application on another server.
Update: There was an issue on the server where some required framework features were not installed. The issue has been resolved by moving the deployment to another server.

SignlaR not working with load balancing

We already had a server with signalr hub where clients connect using signalr. We recently moved it to two nodes with a load balancer for scalability. But after moving it to load balancer now clients are unable to connect to the server using signalr. Clients first try using web sockets and it gives the following error on signalr trace.
fae26beb-a806-4957-b52a-39b80856e492 - Auto: Failed to connect to using transport webSockets. System.Net.WebSockets.WebSocketException (0x80004005): Unable to connect to the remote server ---> System.Net.WebException: The underlying connection was closed: An unexpected error occurred on a receive. ---> System.IO.IOException: Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host. ---> System.Net.Sockets.SocketException: An existing connection was forcibly closed by the remote host
at System.Net.Sockets.Socket.EndReceive(IAsyncResult asyncResult)
at System.Net.Sockets.NetworkStream.EndRead(IAsyncResult asyncResult)
--- End of inner exception stack trace ---
at System.Net.Security._SslStream.EndRead(IAsyncResult asyncResult)
at System.Net.TlsStream.EndRead(IAsyncResult asyncResult)
at System.Net.PooledStream.EndRead(IAsyncResult asyncResult)
at System.Net.Connection.ReadCallback(IAsyncResult asyncResult)
--- End of inner exception stack trace ---
at System.Net.HttpWebRequest.EndGetResponse(IAsyncResult asyncResult)
at System.Threading.Tasks.TaskFactory`1.FromAsyncCoreLogic(IAsyncResult iar, Func`2 endFunction, Action`1 endAction, Task`1 promise, Boolean requiresSynchronization)
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Net.WebSockets.ClientWebSocket.<ConnectAsyncCore>d__21.MoveNext()
at System.Net.WebSockets.ClientWebSocket.<ConnectAsyncCore>d__21.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNet.SignalR.Client.Transports.WebSocketTransport.<PerformConnect>d__1.MoveNext()
But after couple of times trying to connect it manages to connect using SSE (Server Sent Events).
fae26beb-a806-4957-b52a-39b80856e492 - SSE: OnMessage(Data: {"C":"s-0,BA9F","S":1,"M":[]})
fae26beb-a806-4957-b52a-39b80856e492 - ChangeState(Connecting, Connected)
fae26beb-a806-4957-b52a-39b80856e492 - SSE: OnMessage(Data: {"C":"s-0,BAA0","M":[{"H":"PrintConnectorHub","M":"SignalRConnectedSuccessfully","A":[true]}]})
fae26beb-a806-4957-b52a-39b80856e492 - OnMessage({"R":false,"I":"3"})
But when the server tries to send a message back to the client, client does not receive the message. We have implemented SignalR scale out with SQL Server and following are the log traces in the server.
TRACE SignalR.SqlMessageBus Stream 0 : SqlReceiver last payload ID=47781, new payload ID=47782 (Microsoft.AspNet.SignalR.SqlServer.SqlReceiver.ProcessRecord)
TRACE SignalR.SqlMessageBus Stream 0 : Updated receive reader initial payload ID parameter=47782 (Microsoft.AspNet.SignalR.SqlServer.SqlReceiver.ProcessRecord)
TRACE SignalR.SqlMessageBus Stream 0 : Payload 47782 containing 1 message(s) received (Microsoft.AspNet.SignalR.SqlServer.SqlReceiver.ProcessRecord)
TRACE SignalR.SqlMessageBus Stream 0 : 1 records received (Microsoft.AspNet.SignalR.SqlServer.ObservableDbOperation.ExecuteReaderWithUpdates)
TRACE SignalR.SqlMessageBus Created DbCommand: CommandType=Text, CommandText=SELECT [PayloadId], [Payload], [InsertedOn] FROM [SignalR].[Messages_0] WHERE [PayloadId] > #PayloadId, Parameters= [Name=PayloadId, Value=47782] (Microsoft.AspNet.SignalR.SqlServer.DbOperation.TraceCommand)
Signalr initialization in clients
signalrHostUrl = "SignalR_Host";
try
{
hubConnection = new HubConnection(signalrHostUrl);
hubConnection.Error += ex =>
{
signalRlogger.Error(ex, "Exception from hubConnection");
};
hubConnection.ConnectionSlow += () => ConnectionSlow();
hubConnection.Closed += () => SignalrConnectionConnectionClosed();
hubConnection.StateChanged += signalRConnectionStateController.StateChanged;
hubConnection.Start().Wait();
}
catch (Exception ex)
{
signalRlogger.Error(ex, "initialzing hub connection");
}
Before moving to the load balancer the clients were perfectly able to connect via web sockets and communicate. But after moving to load balancer it completely fails to connect via web sockets. We even tried to open a web socket connection by this tool (https://chrome.google.com/webstore/detail/simple-websocket-client/pfdhoblngboilpfeibdedpjgfnlcodoo?hl=en) which also fails to open a connection. Although it manages to connect via SSE it still unable to communicate to clients. What are the complications when using web sockets in load balancing and in this situation why signalr fails to make a connection to the clients?
When the other machine tries to decrypt the connection token you got when negotiating the connection it can't and the request fails. You need to ensure that all machines you are using have the same machine key. This way all the machines will be able to decrypt connectionTokens created by other machines.
Are you able to enable stickyness on the load balancers? For example session based stickyness. This will make sure the clients connect to the same machine. The downside is that if a machine fails the client won't be able to reconnect.

OperationCanceledException on stress test

I just made an WebApi (C#, .net 4.5.2) and published it to the web. In order to make sure it working good, I started a to test it.
The REST web-service failed the "stress" test. I sent the service 30+- http requests, each second, and got back this typical error message:
System.OperationCanceledException: The operation was canceled.
at System.Threading.CancellationToken.ThrowOperationCanceledException()
at System.Net.Http.HttpContentExtensions.<ReadAsAsyncCore>d__0`1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Web.Http.ModelBinding.FormatterParameterBinding.<ExecuteBindingAsyncCore>d__0.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Web.Http.Controllers.HttpActionBinding.<ExecuteBindingAsyncCore>d__0.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Web.Http.Controllers.ActionFilterResult.<ExecuteAsync>d__2.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at System.Web.Http.Controllers.ExceptionFilterResult.<ExecuteAsync>d__0.MoveNext()
Same error occurred many times in the log.
When I entered the specific machine, I saw that the CPU is on 100% and the RAM is on 80%. Which mean, the machine gives her best to handle the load.
Questions
According to the StackTrace I provided above, I cannot understand
where exactly was the problem in my code?
My code is scale out automatically (hosted in the cloud). But, new machine created only after 5 minutes (depends on the average CPU > 50%). How should I handle sudden mass of HTTP request? Maybe the server should say: "Hey, try agian in 30 seconds" or something like that? What is the right solution?
System.OperationCanceledException: The operation was canceled.
This usually indicates that the client connecting to the service closed the connection before the service could send a response. In terms of api layer this usually means that you have specified a timeout while establishing the http connection, or the library that you are using for making http calls has a default timeout.
You may want to check the iis request logs to see what is going wrong. Since this is happening on a stress test, my guess is your service is running short of threads (Read this for more details) . You may want to consider async model for your request handlers to improve the scalability and utilize threads better. (Read this)

WNS error 0x880403E8 on device

I am developing a WP8.1 silverlight app, that receives WNS notification. It works fine on the emulator, but on the device (lumia 640), it crashes at the following api call:
var channel = await Windows.Networking.PushNotifications.PushNotificationChannelManager.CreatePushNotificationChannelForApplicationAsync();
I receive the following error:
_exception {System.Exception: Exception from HRESULT: 0x880403E8
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter1.GetResult()
at BC_Menu.App.<UploadChannel>d__0.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter1.GetResult()
at BC_Menu.StartUp.FirstPage.d__4.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.b__3(Object state)} System.Exception
If I try on another device (lumia 920), it works fine. The immediate difference between the devices are that I have a dummy account on the Lumia 640 and no sim card, but I am able to install and update programs. Which should mean the account is correctly initialized. What else could be the issue?
You're crashing because the Windows.Networking.PushNotifications.PushNotificationChannelManager.CreatePushNotificationChannelForApplicationAsync() call is throwing an exception because the device is not connected to WNS. Make sure you handle that case (e.g. with a try/catch) - your users may not always be connected to the internet, which is required to get a channel.
As for why that device isn't connecting to WNS - if you have no SIM card, the device should connect via Wi-Fi. If you're developing in an enterprise make sure they're not blocking outbound connections (which would cause the device to be unable to connect to WNS). If you have a SIM card installed but it has no data, there is a known bug where the device will still try to connect via cellular data (which of course fails). If that's the case, just remove the data-less SIM or disable cellular.

Categories

Resources