/// <summary>
        /// Происходит разбор собственно вложения и сверка его с источниками
        /// </summary>
        private void UnPack(Mime m, ref bool Matched, AddressList FromList, string ShortFileName)
        {
            //Раньше не проверялся весь список From, теперь это делается. Туда же добавляется и Sender
            foreach (var mbFrom in FromList.Mailboxes)
            {
                //Раньше не проверялся весь список TO, теперь это делается
                foreach (var mba in m.MainEntity.To.Mailboxes)
                {
                    var drLS = dtSources.Select(String.Format("(EMailTo = '{0}') and (EMailFrom like '*{1}*')",
                                                              MimeEntityExtentions.GetCorrectEmailAddress(mba.EmailAddress),
                                                              mbFrom.EmailAddress));
                    foreach (DataRow drS in drLS)
                    {
                        if ((drS[SourcesTableColumns.colPriceMask] is String) &&
                            !String.IsNullOrEmpty(drS[SourcesTableColumns.colPriceMask].ToString()))
                        {
                            var priceMask          = (string)drS[SourcesTableColumns.colPriceMask];
                            var priceMaskIsMatched = FileHelper.CheckMask(ShortFileName, priceMask);
                            if (priceMaskIsMatched)
                            {
                                SetCurrentPriceCode(drS);

                                // Пробуем разархивировать
                                var correctArchive = FileHelper.ProcessArchiveIfNeeded(CurrFileName, ExtrDirSuffix, drS["ArchivePassword"].ToString());

                                if (correctArchive)
                                {
                                    string extrFile;
                                    if (ProcessPriceFile(CurrFileName, out extrFile, (ulong)PriceSourceType.EMail))
                                    {
                                        Matched = true;
                                        LogDownloadedPrice((ulong)PriceSourceType.EMail, Path.GetFileName(CurrFileName), extrFile);
                                    }
                                    else
                                    {
                                        LogDownloaderFail((ulong)PriceSourceType.EMail, "Не удалось обработать файл '" +
                                                          Path.GetFileName(CurrFileName) + "'",
                                                          Path.GetFileName(CurrFileName));
                                    }
                                }
                                else
                                {
                                    LogDownloaderFail((ulong)PriceSourceType.EMail, "Не удалось распаковать файл '" +
                                                      Path.GetFileName(CurrFileName) + "'. Файл поврежден",
                                                      Path.GetFileName(CurrFileName));
                                }
                                drS.Delete();
                            }
                        }
                    }
                    dtSources.AcceptChanges();
                }         //foreach (MailboxAddress mba in m.MainEntity.To.Mailboxes)
            }             //foreach (MailboxAddress mbFrom in FromList.Mailboxes)
        }
        protected override void ProcessAttachs(Mime mime, AddressList fromList)
        {
            //Один из аттачментов письма совпал с источником, иначе - письмо не распознано
            bool matched = false;

            /*
             * В накладных письма обрабатываются немного по-другому:
             * письма обрабатываются относительно адреса отправителя
             * и если такой отправитель найден в истониках, то все вложения
             * сохраняются относительно него.
             * Если он не найден, то ничего не делаем.
             */
            if (fromList == null)
            {
                _logger.Info("WaybillEmailSourceHandler: Адрес отправителя пуст");
            }
            if (fromList.Count == 0)
            {
                _logger.Info("WaybillEmailSourceHandler: Адреса в коллекции не обнаружены");
            }
            if (fromList.Mailboxes.Length == 0)
            {
                _logger.Info("WaybillEmailSourceHandler: Список адресов mailboxes пустой");
            }

            foreach (var mbFrom in fromList.Mailboxes)
            {
                var sources = dtSources.Select(String.Format("({0} like '*{1}*')",
                                                             WaybillSourcesTable.colEMailFrom, mbFrom.EmailAddress));
                // Адрес отправителя должен быть только у одного поставщика,
                // если получилось больше, то ищем поставщика, который доступен клиенту,
                // если таких нет или несколько, то это ошибка

                DataRow source;

                if (sources.Length > 1)
                {
                    source = SelectWaybillSourceForClient(sources, _addressId);
                    if (source == null)
                    {
                        _logger.Info(String.Format("WaybillEmailSourceHandler: На адрес \"{0}\"" +
                                                   "назначено несколько поставщиков. Определить какой из них работает с клиентом не удалось", mbFrom.EmailAddress));
                        throw new Exception(String.Format(
                                                "На адрес \"{0}\" назначено несколько поставщиков. Определить какой из них работает с клиентом не удалось", mbFrom.EmailAddress));
                    }
                }
                else if (sources.Length == 0)
                {
                    var addition = dtSources.Rows == null ? "В строках источников находится null" : String.Format("Количество записей в источниках - {0}", dtSources.Rows.Count);
                    _logger.Info(String.Format("WaybillEmailSourceHandler: Не найдено записи в источниках, соответствующей адресу {0}. {1}", mbFrom.EmailAddress, addition));
                    if (dtSources.Rows != null && dtSources.Rows.Count > 0)
                    {
                        var count1 = dtSources.Select(String.Format("({0} like '*{1}*')",
                                                                    WaybillSourcesTable.colEMailFrom, mbFrom.EmailAddress)).Length;
                        var count2 = dtSources.Select(String.Format("({0} like '%{1}%')",
                                                                    WaybillSourcesTable.colEMailFrom, mbFrom.EmailAddress)).Length;
                        _logger.Info(String.Format("WaybillEmailSourceHandler: Делаем попытку выбрать нужные записи иначе: " +
                                                   "количество через * - {0}, через % - {1}, исходное - {2}", count1, count2, sources.Count()));
                    }
                    continue;
                }
                else
                {
                    source = sources.Single();
                }

                var attachments = mime.GetValidAttachements();
                if (!attachments.Any())
                {
                    _logger.Info(String.Format("WaybillEmailSourceHandler: Отсутствуют вложения в письме от адреса {0}", mbFrom.EmailAddress));
                }
                //двойная очистка FileCleaner и Cleanup нужно оставить только одно
                //думаю Cleaner подходит лучше
                using (var cleaner = new FileCleaner()) {
                    var savedFiles = new List <string>();
                    foreach (var entity in attachments)
                    {
                        SaveAttachement(entity);
                        var correctArchive = FileHelper.ProcessArchiveIfNeeded(CurrFileName, ExtrDirSuffix);
                        matched = true;
                        if (!correctArchive)
                        {
                            DocumentReceiveLog.Log(Convert.ToUInt32(source[WaybillSourcesTable.colFirmCode]),
                                                   _addressId,
                                                   Path.GetFileName(CurrFileName),
                                                   _currentDocumentType.DocType,
                                                   "Не удалось распаковать файл",
                                                   IMAPHandler.CurrentUID);
                            Cleanup();
                            continue;
                        }
                        if (ArchiveHelper.IsArchive(CurrFileName))
                        {
                            var files = Directory.GetFiles(CurrFileName + ExtrDirSuffix +
                                                           Path.DirectorySeparatorChar, "*.*", SearchOption.AllDirectories);
                            savedFiles.AddRange(files);
                            cleaner.Watch(files);
                        }
                        else
                        {
                            savedFiles.Add(CurrFileName);
                            cleaner.Watch(CurrFileName);
                        }
                    }
                    var logs = ProcessWaybillFile(savedFiles, source);

                    var service = new WaybillService();
                    service.Process(logs);
                    if (service.Exceptions.Count > 0)
                    {
                        SendErrorLetterToSupplier(service.Exceptions.First(), mime);
                    }
                }
                Cleanup();
                source.Delete();
                dtSources.AcceptChanges();
            }             //foreach (MailboxAddress mbFrom in FromList.Mailboxes)

            if (!matched)
            {
                throw new EmailFromUnregistredMail(
                          "Для данного E-mail не найден источник в таблице documents.waybill_sources",
                          Settings.Default.ResponseDocSubjectTemplateOnUnknownProvider,
                          Settings.Default.ResponseDocBodyTemplateOnUnknownProvider);
            }
        }
        public override void ProcessData()
        {
            //набор строк похожих источников
            FillSourcesTable();
            while (dtSources.Rows.Count > 0)
            {
                DataRow[] drLS          = null;
                var       currentSource = dtSources.Rows[0];
                var       priceSource   = new PriceSource(currentSource);
                if (!IsReadyForDownload(priceSource))
                {
                    currentSource.Delete();
                    dtSources.AcceptChanges();
                    continue;
                }
                try {
                    drLS = GetLikeSources(priceSource);
                    try {
                        CurrFileName = String.Empty;
                        GetFileFromSource(priceSource);
                        priceSource.UpdateLastCheck();
                    }
                    catch (PathSourceHandlerException pathException) {
                        FailedSources.Add(priceSource.PriceItemId);
                        DownloadLogEntity.Log(priceSource.SourceTypeId, priceSource.PriceItemId, pathException.ToString(), pathException.ErrorMessage);
                    }
                    catch (Exception e) {
                        FailedSources.Add(priceSource.PriceItemId);
                        DownloadLogEntity.Log(priceSource.SourceTypeId, priceSource.PriceItemId, e.ToString());
                    }

                    if (!String.IsNullOrEmpty(CurrFileName))
                    {
                        var correctArchive = FileHelper.ProcessArchiveIfNeeded(CurrFileName, ExtrDirSuffix, priceSource.ArchivePassword);
                        foreach (var drS in drLS)
                        {
                            SetCurrentPriceCode(drS);
                            string extractFile = null;
                            try {
                                if (!correctArchive)
                                {
                                    throw new PricePreprocessingException("Не удалось распаковать файл '" + Path.GetFileName(CurrFileName) + "'. Файл поврежден", CurrFileName);
                                }

                                if (!ProcessPriceFile(CurrFileName, out extractFile, priceSource.SourceTypeId))
                                {
                                    throw new PricePreprocessingException("Не удалось обработать файл '" + Path.GetFileName(CurrFileName) + "'", CurrFileName);
                                }

                                LogDownloadedPrice(priceSource.SourceTypeId, Path.GetFileName(CurrFileName), extractFile);
                                FileProcessed();
                            }
                            catch (PricePreprocessingException e) {
                                LogDownloaderFail(priceSource.SourceTypeId, e.Message, e.FileName);
                                FileProcessed();
                            }
                            catch (Exception e) {
                                LogDownloaderFail(priceSource.SourceTypeId, e.Message, extractFile);
                            }
                            finally {
                                drS.Delete();
                            }
                        }
                        Cleanup();
                    }
                    else
                    {
                        foreach (var drDel in drLS)
                        {
                            drDel.Delete();
                        }
                    }
                }
                catch (Exception ex) {
                    var error = String.Empty;
                    if (drLS != null && drLS.Length > 1)
                    {
                        error += String.Join(", ", drLS.Select(r => r[SourcesTableColumns.colPriceCode].ToString()).ToArray());
                        drLS.Each(r => FileHelper.Safe(r.Delete));
                        error = "Источники : " + error;
                    }
                    else
                    {
                        error = String.Format("Источник : {0}", currentSource[SourcesTableColumns.colPriceCode]);
                        FileHelper.Safe(currentSource.Delete);
                    }
                    Log(ex, error);
                }
                finally {
                    FileHelper.Safe(() => dtSources.AcceptChanges());
                }
            }
        }