Добрый день!
Существует ли возможность перебора сообщений с сервера без предварительного скачивания всех запрошенных сообщений?
Пришлось немного взломать Вашу библиотеку для достижения нужной функциональности:
Существует ли возможность перебора сообщений с сервера без предварительного скачивания всех запрошенных сообщений?
Пришлось немного взломать Вашу библиотеку для достижения нужной функциональности:
internal static class Service
{
private static readonly Func<Folder, string, int, long[]> sf_SearchMessageIds_Method;
private static readonly Func<long, ImapClient, Folder, Message> sf_CreateMessage;
private static readonly Func<Folder, ImapClient> sf_GetFolderClient;
static Service()
{
var folger_type = typeof(Folder);
var SearchMessageIds_method = folger_type.GetMethod("SearchMessageIds", BindingFlags.Instance | BindingFlags.NonPublic);
var folger_parameter = Expression.Parameter(typeof(Folder), "folder");
var query_parameter = Expression.Parameter(typeof(string), "query");
var count_parameter = Expression.Parameter(typeof(int), "count");
Expression body = Expression.Call(folger_parameter, SearchMessageIds_method, query_parameter, count_parameter);
var SearchMessageIds_Expression = Expression.Lambda<Func<Folder, string, int, long[]>>
(
body, folger_parameter,
query_parameter,
count_parameter
);
sf_SearchMessageIds_Method = SearchMessageIds_Expression.Compile();
var message_type = typeof(Message);
var message_ctor = message_type.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null, new[] { typeof(long), typeof(ImapClient), typeof(Folder) }, new ParameterModifier[0]);
var id_parameter = Expression.Parameter(typeof(long), "id");
var client_parameter = Expression.Parameter(typeof(ImapClient), "client");
var folder_parameter = Expression.Parameter(typeof(Folder), "folder");
body = Expression.New(message_ctor, id_parameter, client_parameter, folder_parameter);
var new_message_expression = Expression.Lambda<Func<long, ImapClient, Folder, Message>>(body,
id_parameter, client_parameter, folder_parameter);
sf_CreateMessage = new_message_expression.Compile();
var folder_client_field = folger_type.GetField("_client", BindingFlags.Instance | BindingFlags.NonPublic);
body = Expression.Field(folder_parameter, folder_client_field);
sf_GetFolderClient = Expression.Lambda<Func<Folder, ImapClient>>(body, folder_parameter).Compile();
}
public static T Init<T>(this T obj, Action<T> action) { action?.Invoke(obj); return obj; }
public static long[] SearchMessageIDs(this Folder folder, string query = "ALL", int count = -1)
{
return sf_SearchMessageIds_Method(folder, query, count);
}
public static Message NewMessage(long id, ImapClient client, Folder folder)
{
return sf_CreateMessage(id, client, folder);
}
public static IEnumerable<Message> FetchMessages
(
this Folder folder,
string query = "ALL",
MessageFetchMode mode = MessageFetchMode.ClientDefault,
int count = -1
)
{
return
folder.SearchMessageIDs(query, count)
.Select(id => NewMessage(id, sf_GetFolderClient(folder), folder).Init(m => m.Download(mode)));
}
}
Теперь сообщения извлекаются из сервера по очереди и могут быть обработаны по мере поступления, а не все скопом: using(var client = new ImapClient())
{
Console.WriteLine("Connection {0}", client.Connect(c_ServerAddress, true) ? "successful" : "failed");
if(!client.IsConnected) return;
Console.WriteLine("Login {0}", client.Login(c_User, c_Password) ? "successful" : "failed");
if(!client.IsAuthenticated) return;
client.Behavior.MessageFetchMode = MessageFetchMode.Basic | MessageFetchMode.GMailExtendedData;
Console.WriteLine("INBOX messages");
foreach(var msg in client.Folders.Inbox.FetchMessages())
Console.WriteLine("{0}[from:{1}]:{2}", msg.Date, msg.From, msg.Subject);
}