protected virtual void OnGetMessage(MimeMessage message, string messageUid, bool unread, MailFolder folder) { var eventHandler = GetMessage; if (eventHandler != null) { eventHandler.Invoke(this, new MailClientMessageEventArgs(message, messageUid, unread, folder, Account, Log)); } }
private int LoadFolderMessages(IMailFolder folder, MailFolder mailFolder, int limitMessages) { var loaded = 0; ImapFolderUids folderUids; if (!Account.ImapIntervals.TryGetValue(folder.Name, out folderUids)) { folderUids = new ImapFolderUids(new List <int> { 1, int.MaxValue }, 1); // by default - mailbox never was processed before } var imapIntervals = new ImapIntervals(folderUids.UnhandledUidIntervals); var beginDateUid = folderUids.BeginDateUid; IList <UniqueId> allUids; try { allUids = folder.Fetch(0, -1, MessageSummaryItems.UniqueId, CancelToken).Select(r => r.UniqueId).ToList(); } catch (NotSupportedException) { const int start = 0; var end = folder.Count; const int increment = 1; allUids = Enumerable .Repeat(start, (end - start) / 1 + 1) .Select((tr, ti) => tr + increment * ti) .Select(n => new UniqueId((uint)n)) .ToList(); } foreach (var uidsInterval in imapIntervals.GetUnhandledIntervalsCopy()) { var interval = uidsInterval; var uidsCollection = allUids.Select(u => u) .Where(u => u.Id <= interval.To && u.Id >= interval.From) .OrderByDescending(x => x) .ToList(); if (!uidsCollection.Any()) { if (!uidsInterval.IsToUidMax()) { imapIntervals.AddHandledInterval(uidsInterval); } continue; } var first = uidsCollection.First().Id; var toUid = (int)(uidsInterval.IsToUidMax() ? first : Math.Max(uidsInterval.To, first)); var infoList = folder.Fetch(limitMessages > 0 ? uidsCollection.Take(limitMessages * 3).ToList() : uidsCollection, MessageSummaryItems.Flags | MessageSummaryItems.GMailLabels | MessageSummaryItems.InternalDate); foreach (var uid in uidsCollection) { try { if (!Imap.IsConnected || CancelToken.IsCancellationRequested) { break; } var message = folder.GetMessage(uid, CancelToken); var uid1 = uid; var info = infoList.FirstOrDefault(t => t.UniqueId == uid1); message.FixDateIssues(info != null ? info.InternalDate : null, Log); if (message.Date < Account.BeginDate) { Log.Debug("Skip message (Date = {0}) on BeginDate = {1}", message.Date, Account.BeginDate); imapIntervals.SetBeginIndex(toUid); beginDateUid = toUid; break; } var unread = info != null && (info.UserFlags.Contains("\\Unseen") || info.Flags.HasValue && !info.Flags.Value.HasFlag(MessageFlags.Seen)); message.FixEncodingIssues(Log); OnGetMessage(message, uid.Id.ToString(), unread, mailFolder); loaded++; } catch (OperationCanceledException) { break; } catch (Exception e) { Log.Error( "ProcessMessages() Tenant={0} User='******' Account='{2}', MailboxId={3}, UID={4} Exception:\r\n{5}\r\n", Account.TenantId, Account.UserId, Account.EMail.Address, Account.MailBoxId, uid, e); if (uid != uidsCollection.First() && (int)uid.Id != toUid) { imapIntervals.AddHandledInterval(new UidInterval((int)uid.Id + 1, toUid)); } toUid = (int)uid.Id - 1; if (e is IOException) { break; // stop checking other mailboxes } continue; } // after successfully message saving - lets update imap intervals state imapIntervals.AddHandledInterval( new UidInterval( uid.Id == uidsCollection.Last().Id&& uidsInterval.IsFromUidMin() ? uidsInterval.From : (int)uid.Id, toUid)); toUid = (int)uid.Id - 1; if (limitMessages > 0 && loaded >= limitMessages) { break; } } if (CancelToken.IsCancellationRequested || limitMessages > 0 && loaded >= limitMessages) { break; } } var updatedImapFolderUids = new ImapFolderUids(imapIntervals.ToIndexes(), beginDateUid); if (!Account.ImapIntervals.Keys.Contains(folder.Name)) { Account.ImapFolderChanged = true; Account.ImapIntervals.Add(folder.Name, updatedImapFolderUids); } else if (Account.ImapIntervals[folder.Name] != updatedImapFolderUids) { Account.ImapFolderChanged = true; Account.ImapIntervals[folder.Name] = updatedImapFolderUids; } return(loaded); }
private void AggregatePop3(TasksConfig tasksConfig, int limitMessages = -1) { if (!Pop.IsAuthenticated) { LoginPop3(); } var mailFolder = new MailFolder(MailFolder.Ids.inbox, "INBOX"); var loaded = 0; var newMessages = GetPop3NewMessagesIDs(tasksConfig); if (newMessages.Count == 0) { Log.Debug("New messages not found.\r\n"); return; } Log.Debug("Found {0} new messages.\r\n", newMessages.Count); try { var fstMailHeaders = Pop.GetMessageHeaders(newMessages.First().Key, CancelToken).ToList(); var lstMailHeaders = Pop.GetMessageHeaders(newMessages.Last().Key, CancelToken).ToList(); var fstDateHeader = fstMailHeaders.FirstOrDefault( h => h.Field.Equals("Date", StringComparison.InvariantCultureIgnoreCase)); var lstDateHeader = lstMailHeaders.FirstOrDefault( h => h.Field.Equals("Date", StringComparison.InvariantCultureIgnoreCase)); var found = false; if (fstDateHeader != null && lstDateHeader != null) { DateTime fstDate; DateTime lstDate; if (DateTime.TryParse(fstDateHeader.Value, out fstDate) && DateTime.TryParse(lstDateHeader.Value, out lstDate)) { found = true; if (fstDate < lstDate) { Log.Debug("Account '{0}' order is DESC", Account.EMail.Address); newMessages = newMessages .OrderByDescending(item => item.Key) // This is to ensure that the newest message would be handled primarily. .ToDictionary(id => id.Key, id => id.Value); } } } if (!found) { Log.Debug("Account '{0}' order is ASC", Account.EMail.Address); } } catch (Exception) { Log.Warn("Calculating order skipped! Account '{0}' order is ASC", Account.EMail.Address); } var skipOnDate = Account.BeginDate != MailBoxManager.MinBeginDate; var skipBreakOnDate = tasksConfig.PopUnorderedDomains.Contains(Account.Server.ToLowerInvariant()); foreach (var newMessage in newMessages) { if (!Pop.IsConnected || CancelToken.IsCancellationRequested) { break; } Log.Debug("Processing new message\tUID: {0}\tUIDL: {1}\t", newMessage.Key, newMessage.Value); try { var message = Pop.GetMessage(newMessage.Key, CancelToken); message.FixDateIssues(logger: Log); if (message.Date < Account.BeginDate && skipOnDate) { if (!skipBreakOnDate) { Log.Info("Skip other messages older then {0}.", Account.BeginDate); break; } Log.Debug("Skip message (Date = {0}) on BeginDate = {1}", message.Date, Account.BeginDate); continue; } message.FixEncodingIssues(); OnGetMessage(message, newMessage.Value, true, mailFolder); loaded++; if (limitMessages <= 0 || loaded < limitMessages) { continue; } Log.Debug("Limit of max messages per session is exceeded!"); break; } catch (OperationCanceledException) { break; } catch (Exception e) { Log.Error( "ProcessMessages() Tenant={0} User='******' Account='{2}', MailboxId={3}, MessageIndex={4}, UIDL='{5}' Exception:\r\n{6}\r\n", Account.TenantId, Account.UserId, Account.EMail.Address, Account.MailBoxId, newMessage.Key, newMessage.Value, e); if (e is IOException) { break; // stop checking other mailboxes } } } }
private void AggregatePop3(TasksConfig tasksConfig, int limitMessages = -1) { if (!Pop.IsAuthenticated) { LoginPop3(); } var mailFolder = new MailFolder(MailFolder.Ids.inbox, "INBOX"); try { var loaded = 0; var newMessages = GetPop3NewMessagesIDs(tasksConfig); if (newMessages.Count == 0) { Log.Debug("New messages not found.\r\n"); return; } Log.Debug("Found {0} new messages.\r\n", newMessages.Count); newMessages = FixPop3UidsOrder(newMessages); var skipOnDate = Account.BeginDate != MailBoxManager.MinBeginDate; var skipBreakOnDate = tasksConfig.PopUnorderedDomains.Contains(Account.Server.ToLowerInvariant()); foreach (var newMessage in newMessages) { if (!Pop.IsConnected || CancelToken.IsCancellationRequested) { break; } Log.Debug("Processing new message\tUID: {0}\tUIDL: {1}\t", newMessage.Key, newMessage.Value); try { var message = Pop.GetMessage(newMessage.Key, CancelToken); message.FixDateIssues(logger: Log); if (message.Date < Account.BeginDate && skipOnDate) { if (!skipBreakOnDate) { Log.Info("Skip other messages older then {0}.", Account.BeginDate); break; } Log.Debug("Skip message (Date = {0}) on BeginDate = {1}", message.Date, Account.BeginDate); continue; } message.FixEncodingIssues(); OnGetMessage(message, newMessage.Value, true, mailFolder); loaded++; if (limitMessages <= 0 || loaded < limitMessages) { continue; } Log.Debug("Limit of max messages per session is exceeded!"); break; } catch (OperationCanceledException) { // Skip log error } catch (Exception e) { Log.Error( "ProcessMessages() Tenant={0} User='******' Account='{2}', MailboxId={3}, MessageIndex={4}, UIDL='{5}' Exception:\r\n{6}\r\n", Account.TenantId, Account.UserId, Account.EMail.Address, Account.MailBoxId, newMessage.Key, newMessage.Value, e); if (e is IOException) { break; // stop checking other mailboxes } } } } catch (AggregateException aggEx) { if (aggEx.InnerException != null) { throw aggEx.InnerException; } throw new Exception("AggregatePop3 failed", aggEx); } }