Hello,
We are using Aspose.Email 4.0.0 and trying to fetch, process and delete emails out of an inbox through Imap client. I use asynchronous functions to fetch more emails in parallel, but limit it to 5 at a time. We hit a major problem in production when using this with Exchange server, it has a limit o 16 imap connections from a single IP, and it seems the Aspose client opens more connections than it should and depletes all 16, hitting an exception: Aspose.Email.Imap.ImapException: 004 NO LOGIN failed.
I tried to fix this and used Aspose.Email 4.3.0, but it still depletes all the connections, it doesn't produce the exception anymore, but at the point where it reaches too many, Exchange will stop responding and the Fetch task never completes. Here is a sample code that does an async list messages and fetches the first 10 of them asynchronously again and again, just for simplicity and reproducing it. Within minutes, this code reaches the 16 imap connections (you can check them via nestat command) and the program stops.
private static ImapClient imap = new ImapClient("exchange.ysoft.com", 143, "***", "***") { EnableSsl = false };
public static void Main() {
while (true) {
var list = Task.Factory.FromAsync(imap.BeginListMessages(), imap.EndListMessages).Result;
Console.WriteLine("Count: " + list.Count);
Fetch10(list);
}
}
static void Fetch10(ImapMessageInfoCollection list) {
Task[] fetches = new Task[10];
for (int i = 0; i < 10; i++)
fetches[i] = Fetch(list[i].UniqueId);
Task.WaitAll(fetches);
foreach (var fetch in fetches) Console.WriteLine("Subject: " + fetch.Result.Subject);
}
static Task Fetch(string id) {
return Task.Factory.FromAsync(imap.BeginFetchMessage(id), imap.EndFetchMessage);
}
There must be some leak in the async Imap implementation that creates more connections than it should need, at any point in time there are no more than 10 asynchronous methods being called/awaited. In our real code we only do 5 and it last for hours but eventually fails as well.
Martin
P.S. I wish you hadn't introduced a class named Task into the Aspose.Email namespace, that conflicts with a .NET framework one and it forced me to use fully quantified names everywhere :(