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; } } }
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; }