Example #1
0
        private void GetCapa(Pop3Client client)
        {
            try
            {
                var capaParams = client.GetServerCapabilities();

                if (capaParams.Length <= 0) return;
                var index = Array.IndexOf(capaParams, "LOGIN-DELAY");
                if (index > -1)
                {
                    int delay;
                    if (int.TryParse(capaParams[index], NumberStyles.Integer, CultureInfo.InvariantCulture, out delay))
                        Account.ServerLoginDelay = delay;
                }

                _isUidlSupported = Array.IndexOf(capaParams, "UIDL") > -1;
            }
            catch
            { // CAPA NOT SUPPORTED 
                try
                { // CHECK UIDL SUPPORT
                    client.GetUniqueIds();
                    _isUidlSupported = true;
                }
                catch
                { // UIDL NOT SUPPORTED 
                    _isUidlSupported = false;
                }
            }
        }
Example #2
0
        private Dictionary<int, string> GetPop3NewMessagesIDs(Pop3Client client)
        {
            var newMessages = new Dictionary<int, string>();

            var emailIds = client.GetUniqueIds();

            if (!emailIds.Any() || emailIds.Count == Account.MessagesCount)
                return newMessages;

            var i = 0;
            var chunk = tasksConfig.ChunkOfPop3Uidl;

            var emails = emailIds.Skip(i).Take(chunk).ToList();

            do
            {
                var checkList = emails.Select(e => e.UniqueId).Distinct().ToList();

                var existingUidls = mailBoxManager.CheckUidlExistance(Account.MailBoxId, checkList);

                if (!existingUidls.Any())
                {
                    foreach (
                        var item in
                            emails.Select(email => new KeyValuePair<int, string>(email.Index, email.UniqueId))
                                  .Where(item => !newMessages.Contains(item)))
                    {
                        newMessages.Add(item.Key, item.Value);
                    }
                }
                else if (existingUidls.Count != emails.Count)
                {
                    foreach (var item in (from email in emails
                                          where !existingUidls.Contains(email.UniqueId)
                                          select new KeyValuePair<int, string>(email.Index, email.UniqueId)).Where(
                                              item => !newMessages.Contains(item)))
                    {
                        newMessages.Add(item.Key, item.Value);
                    }
                }

                i += chunk;

                emails = emailIds.Skip(i).Take(chunk).ToList();

            } while (emails.Any());

            return newMessages;
        }
        // Returns: True if all messages are proccessed. False if at least one new message is not processed.
        private bool ProcessMessagesPop(Pop3Client client, int max_messages_per_session, WaitHandle stop_event, out int processed_messages_count)
        {
            UpdateTimeCheckedIfNeeded();
            processed_messages_count = max_messages_per_session;
            var bad_messages_exist = false;
            Dictionary<int, string> new_messages;
            var stored_uidl_list = new Dictionary<int, string>();
            var stored_md5_list = new Dictionary<int, string>();

            InvokeGetStoredMessagesUIDL_MD5(stored_uidl_list, stored_md5_list);

            if (!IsUidlSupported)
            {
                _log.Info("UIDL is not supported! Account '{0}' has been skiped.", Account.EMail);
                return true;
            }

            var email_ids = client.GetUniqueIds();

            new_messages =
                email_ids
                .Where(id => !stored_uidl_list.Values.Contains(id.UniqueId))
                .OrderBy(id => id.Index)
                .ToDictionary(id => id.Index, id => id.UniqueId );


            var quota_error_flag = false;

            if (client.IsConnected)
            {
                if (new_messages.Count == 0)
                    _log.Debug("New messages not found.\r\n");
                else
                {
                    _log.Debug("Found {0} new messages.\r\n", new_messages.Count);

                    if (new_messages.Count > 1)
                    {
                        _log.Debug("Calculating order");

                        try
                        {
                            var first_header = client.RetrieveHeaderObject(new_messages.First().Key);
                            var last_header = client.RetrieveHeaderObject(new_messages.Last().Key);

                            if (first_header.Date < last_header.Date)
                            {
                                _log.Debug("Account '{0}' order is DESC", Account.EMail.Address);
                                new_messages = new_messages
                                    .OrderByDescending(item => item.Key) // This is to ensure that the newest message would be handled primarily.
                                    .ToDictionary(id => id.Key, id => id.Value);
                            }
                            else
                                _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 skip_on_date = Account.BeginDate != MailBoxManager.MIN_BEGIN_DATE;

                    var skip_break_on_date = MailQueueItemSettings.PopUnorderedDomains.Contains(Account.Server.ToLowerInvariant());

                    foreach (var new_message in new_messages)
                    {
                        var has_parse_error = false;
                        
                        try
                        {
                            if (stop_event.WaitOne(0))
                            {
                                break;
                            }

                            if (max_messages_per_session == 0)
                            {
                                _log.Debug("Limit of max messages per session is exceeded!");
                                break;
                            }

                            _log.Debug("Processing new message\tid={0}\t{1}\t",
                                new_message.Key,
                                (IsUidlSupported ? "UIDL: " : "MD5: ") + new_message.Value);

                            if (!client.IsConnected)
                            {
                                _log.Warn("POP3 server is disconnected. Skip another messages.");
                                bad_messages_exist = true;
                                break;
                            }

                            Message message = null;

                            try
                            {
                                message = client.RetrieveMessageObject(new_message.Key);
                            }
                            catch (Exception ex)
                            {
                                if (ex is ParsingException || ex is IndexOutOfRangeException)
                                {
                                    _log.Error("ActiveUp Parse error: trying to save message with 'has_parse_error' flag. Exception:\r\n {0}", ex.ToString());
                                    message = GetPop3MessageAfterParseError(client, new_message.Key);
                                    has_parse_error = true;
                                }
                                else
                                    throw;
                            }

                            UpdateTimeCheckedIfNeeded();

                            if (message.Date < Account.BeginDate && skip_on_date)
                            {
                                if (!skip_break_on_date)
                                {
                                    _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;
                            }

                            var header_md5 = string.Empty;

                            if (IsUidlSupported)
                            {
                                var unique_identifier = string.Format("{0}|{1}|{2}|{3}",
                                                                      message.From.Email,
                                                                      message.Subject,
                                                                      message.DateString,
                                                                      message.MessageId);

                                header_md5 = unique_identifier.GetMd5();

                                if (!message.To.Exists(email =>
                                                       email.Email
                                                            .ToLowerInvariant()
                                                            .Equals(message.From.Email
                                                                           .ToLowerInvariant())))
                                {

                                    var found_message_id = stored_md5_list
                                        .Where(el => el.Value == header_md5)
                                        .Select(el => el.Key)
                                        .FirstOrDefault();

                                    if (found_message_id > 0)
                                    {
                                        InvokeOnUpdateUidl(found_message_id, new_message.Value);
                                        continue; // Skip saving founded message
                                    }
                                }
                            }

                            InvokeOnRetrieve(message,
                                MailFolder.Ids.inbox, 
                                IsUidlSupported ? new_message.Value : "",
                                IsUidlSupported ? header_md5 : new_message.Value, has_parse_error);
                        }
                        catch (IOException io_ex)
                        {
                            if (io_ex.Message.StartsWith("Unable to write data to the transport connection") ||
                                io_ex.Message.StartsWith("Unable to read data from the transport connection"))
                            {
                                _log.Error("ProcessMessages() Account='{0}': {1}",
                                     Account.EMail.Address, io_ex.ToString());

                                max_messages_per_session = 0; //It needed for stop messsages proccessing.
                                bad_messages_exist = true;
                                break;
                            }
                        }
                        catch (MailBoxOutException ex)
                        {
                            _log.Info("ProcessMessages() Tenant={0} User='******' Account='{2}': {3}",
                                Account.TenantId, Account.UserId, Account.EMail.Address, ex.Message);
                            bad_messages_exist = true;
                            break;
                        }
                        catch (TenantQuotaException qex)
                        {
                            _log.Info("Tenant {0} quota exception: {1}", Account.TenantId, qex.Message);
                            quota_error_flag = true;
                        }
                        catch (Exception e)
                        {
                            bad_messages_exist = true;
                            _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, new_message.Key, new_message.Value, e.ToString());
                        }

                        UpdateTimeCheckedIfNeeded();
                        max_messages_per_session--;
                    }
                }
            }
            else
            {
                _log.Debug("POP3 server is disconnected.");
                bad_messages_exist = true;
            }

            InvokeOnDone(quota_error_flag);

            processed_messages_count -= max_messages_per_session;
            return !bad_messages_exist && max_messages_per_session > 0;
        }