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
                    }
                }
            }
        }
Beispiel #4
0
        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);
            }
        }