A socket operation was attempted to an unreachable network [2a00:1450:4013:c01::6d]:993 when receiving Gmail email with S22 ImapClient - sockets

I'm trying to receive email from Gmail. Occaisionly (approx 1 out of 5 times) I get a System.Net.Sockets.SocketException, error message:
A socket operation was attempted to an unreachable network [2a00:1450:4013:c01::6d]:993
The network address is not always the same, but varies slightly. This error does appears occaisonally on all the Gmail boxes I want to check, but does not appear on my Office 365 mailbox at all.
My app is an MVC 5 applications hosted by Microsoft Azure. I use the S22 Imap library
The relevant part of the code to retrieve the email is:
using S22.Imap;
ImapClient Client;
List<MailMessage> NewMessages;
try
{
Client = new ImapClient(tenant.ImapHostName,
tenant.ImapPortNumber,
tenant.ImapUserName,
tenant.ImapPassword,
AuthMethod.Login, tenant.UseSsl);
}
catch (Exception e)
{
return;
}
try
{
NewMessages = GetUnseenMessages(Client);
}
catch (Exception e)
{
}
I've disable IPv6 on my Azure webservice (disabled it on the adapter) but still this error comes back over and over again.

imap.gmail.com returns several IP addresses (three right now, but the number might vary depending on time and location). You're supposed to try all three. If one fails in the manner you see, you're supposed to try the next address, so your next step is to find out whether S22 does that, and if not, how you can make that happen.

I had the same problem as OP and did following to retry multiple IP addresses with S22.Imap.dll
var ips = Dns.GetHostAddresses("imap.gmail.com");
foreach(var ip in ips)
{
try
{
return new ImapClient(ip.ToString(), "993", Email, Password, AuthMethod.Login, true);
}
catch(SocketException e) //error means server is down, try other IP
{
//nothing, check next IP for connection
}
}

Related

Milo: get IP of client

Is there a way to get a Clients IP in Context of a write?
I want to get the IP of an Client that writes to my Milo-OPCUA-Server, so I can handle these writes differently based on the Clients IP (local Clients should be able to write directly on the Server, whilst other writes should get forwarded to another Server)
Okay, this is not part of any official API right now, so it almost certainly will break in the future, but:
With the OperationContext you get when implementing AttributeManager#write(WriteContext, List<WriteValue>):
context.getSession().ifPresent(session -> {
UaStackServer stackServer = context.getServer().getServer();
if (stackServer instanceof UaTcpStackServer) {
ServerSecureChannel secureChannel = ((UaTcpStackServer) stackServer)
.getSecureChannel(session.getSecureChannelId());
Channel channel = secureChannel.attr(UaTcpStackServer.BoundChannelKey).get();
SocketAddress remoteAddress = channel.remoteAddress();
}
});
I'll have to add some official API to do this, probably something hanging off the Session object.

Internet Control Message Protocol for Java

Pls help me guys. I end my work for one simple program. I need to check a servers status. I tried to use InetAdress.isReacheble and Socket. But sometimes if server on windows I get a server status false. After reading a lot of information, I realized that this is one of the bug of java enter link description here. But the sources are old. Is this problem still relevant?
I tried using code this comment enter link description here
private static boolean isReachable(String addr, int openPort, int timeOutMillis) {
try {
// Any Open port on other machine
// openPort = 22 - ssh, 80 or 443 - webserver, 25 - mailserver etc.
try (Socket soc = new Socket()) {
soc.connect(new InetSocketAddress(addr, openPort), timeOutMillis);
}
return true;
} catch (IOException ex) {
return false;
}
If server on Windows I use port RDP (3389).
But the customer does not like. He wants me to check the status through ICMP. Is this possible?
I found the app ICMP enter link description here. Tried to connect from the application library but nothing happened.
I will be grateful for any information!
InetAddress.isReacheble by default uses icmp enter link description here
Pls sorry for my stupid question

AndroidAsync TCP -- proper way to detect socket is no longer available using write?

I am wondering what is the proper way to check on the client side that a TCP socket opened using the AndroidAsync library is no longer available? This is in the case the (plain TCP, non-AndroidAsync) server did not initiate explicitly closing the socket (so the ClosedCallback is not invoked). For instance, when the server has been cold rebooted.
It seems that the DataCallback is available only when the server sends back data and can't be used to receive error messages.
It seems to me also that
Util.writeAll(socket, (byte[]) payload.array(), new CompletedCallback()
{
#Override
public void onCompleted(Exception ex)
{
if (ex != null)
{
Log.e(TAG, "write failed with ex message= " + ex.getMessage());
throw new RuntimeException(ex);
}
}
});
does not throw an Exception either.
So at this point I'm not sure how to detect the socket is no longer available even if the client periodically writes data to it.
It will throw an IOexception if you send enough data or call it enough times. It won't throw on the first call due to TCP buffering at both ends.
I ended up implementing some sort of a "ping"-alike periodic check. The client opens and immediately closes a TCP connection to the very same port using a plain Java NIO socket call (not using AndroidAsync). If that one times out, it is assumed that the connection has been lost, and a recovery attempt is made once it succeeds again. This periodic check is performed only when the app has focus, or is just awakened. This is clearly a far from ideal workaround but it seems to work for my purposes.
You could use the closed/end callbacks
socket.setClosedCallback(new CompletedCallback()
{
#Override
public void onCompleted(Exception ex)
{
}
});
socket.setEndCallback(new CompletedCallback()
{
#Override
public void onCompleted(Exception ex)
{
}
});

keep all connected clients' ip in netty

My TCP server uses netty.The situation is: When a client connects to the server,I will save the client's ip in a global variable(such as a Map); When the client is disconnected,I will remove the IP from the map.
I used channelConnected() and channelDisconnected() method in SimpleChannelHandler.But my problem is ,some times the channelDisconnected() method cannot catch the event when I think the client is disconnected(maybe the computer closed,or the client process closed,or some other situations...) Can you give me some suggestions.
Just use DefaultChannelGroup which will automatically remove the Channel from it when it was closed.
Alternative you can register a ChannelFutureListener to the Channels close future to do the removal from your map.
Something like this:
channel.getCloseFuture().addListener(new ChannelFutureListener() {
public void operationCompleted(ChannelFuture f) {
map.remove(f.getChannel());
}
});

Smack service discovery without login gives bad-request(400)

I am trying to discover items that a pubsub service provides. When I log into the target server, I can get the response successfully. But when I connect bu do not login, it gives a bad request error.
This is the code:
ConnectionConfiguration config = new ConnectionConfiguration(serverAddress, 5222);
config.setServiceName(serviceName);
connection = new XMPPConnection(config);
connection.connect();
connection.login(userName, password); //!!!when I remove this line, bad request error is received
ServiceDiscoveryManager discoManager = ServiceDiscoveryManager.getInstanceFor(connection);
DiscoverItems items;
try {
items = discoManager.discoverItems("pubsubservice." + serverName);
} catch (XMPPException e) {
e.printStackTrace();
}
Is there a way to discover items when the user is not logged in, but the connection is established?
No, you must authenticate to send stanzas to any JID in XMPP (otherwise they would not be able to reply to you, since they wouldn't know your address).
Perhaps one option for you is anonymous authentication. Most servers support it, and it creates a temporary account on the server for you, with a temporary JID. You don't need a password, and login time is quick.
#MattJ is correct and you could try using anon login. That will get you part way there.
Your current request will only get you the nodes though, after which you will have to get the items for each node. It would be simpler to use PubsubManager to get the information you want since it provides convenience methods for accessing/using all things pubsub.
Try the documentation here, the getAffiliations() method is what you are looking for.
BTW, I believe the typical default service name for pubsub is pubsub not pubsubservice. At least this is the case for Openfire.