protected bool MoveWaybill(string archFileName, string fileName, DataRow drCurrent, BaseDocumentReader documentReader)
        {
            using (var cleaner = new FileCleaner()) {
                var supplierId = Convert.ToUInt32(drCurrent[WaybillSourcesTable.colFirmCode]);
                try {
                    var addresses  = With.Connection(c => documentReader.ParseAddressIds(c, supplierId, archFileName, fileName));
                    var formatFile = documentReader.FormatOutputFile(fileName, drCurrent);

                    cleaner.Watch(fileName);
                    cleaner.Watch(formatFile);

                    foreach (var addressId in addresses)
                    {
                        var log = DocumentReceiveLog.LogNoCommit(supplierId,
                                                                 (uint)addressId,
                                                                 formatFile,
                                                                 _currentDocumentType.DocType,
                                                                 "Получен с нашего FTP");

                        _logger.InfoFormat("WaybillLanSourceHandler: обработка файла {0}", fileName);
                        documentReader.ImportDocument(log, fileName);
                        new WaybillService().Process(new[] { log }.ToList());
                    }
                }
                catch (Exception e) {
                    var message = "Не удалось отформатировать документ.\nОшибка: " + e;
                    _logger.ErrorFormat("WaybillLanSourceHandler: {0}, archfilename {1}, fileName {2}, error {3}", message, archFileName, fileName, e);
                    DocumentReceiveLog.Log(supplierId, null, fileName, _currentDocumentType.DocType, message);
                    return(false);
                }
            }

            return(true);
        }
        protected override void SendUnrecLetter(Mime m, AddressList fromList, EMailSourceHandlerException e)
        {
            try {
                var attachments = m.Attachments.Where(a => !String.IsNullOrEmpty(a.GetFilename())).Aggregate("", (s, a) => s + String.Format("\"{0}\"\r\n", a.GetFilename()));
                var ms          = new MemoryStream(m.ToByteData());
                FailMailSend(m.MainEntity.Subject, fromList.ToAddressListString(),
                             m.MainEntity.To.ToAddressListString(), m.MainEntity.Date, ms, attachments, e.Message);

                DocumentReceiveLog.Log(GetFirmCodeByFromList(fromList), _addressId, null, _currentDocumentType.DocType, String.Format(@"{0}
Тема            : {1}
Отправители     : {2}
Получатели      : {3}
Список вложений :
{4}
",
                                                                                                                                      e.Message,
                                                                                                                                      m.MainEntity.Subject,
                                                                                                                                      fromList.ToAddressListString(),
                                                                                                                                      m.MainEntity.To.ToAddressListString(),
                                                                                                                                      attachments), IMAPHandler.CurrentUID);
            }
            catch (Exception exMatch) {
                _logger.Error("Не удалось отправить нераспознанное письмо", exMatch);
            }
        }
        protected override void ErrorOnMessageProcessing(Mime m, AddressList from, EMailSourceHandlerException e)
        {
            try {
                var subject = e.MailTemplate.Subject;
                var body    = e.MailTemplate.Body;
                var message = e.Message;
                if (String.IsNullOrEmpty(body))
                {
                    SendUnrecLetter(m, from, e);
                    return;
                }

                var attachments = m.Attachments.Where(a => !String.IsNullOrEmpty(a.GetFilename())).Aggregate("", (s, a) => s + String.Format("\"{0}\"\r\n", a.GetFilename()));
                SendErrorLetterToSupplier(e, m);

                if (e is EmailFromUnregistredMail)
                {
                    var mail1 = new RejectedEmail {
                        Comment = message, LogTime = DateTime.Now, From = @from.Mailboxes.First().EmailAddress, Subject = subject
                    };
                    using (var session = ActiveRecordMediator.GetSessionFactoryHolder().GetSessionFactory(typeof(ActiveRecordBase)).OpenSession())
                        using (var transaction = session.BeginTransaction()) {
                            session.Save(mail1);
                            transaction.Commit();
                        }
                }

                var comment = $@"{message}
Отправители     : {@from.ToAddressListString()}
Получатели      : {m.MainEntity.To.ToAddressListString()}
Список вложений :
{attachments}
Тема письма поставщику : {subject}
Тело письма поставщику :
{body}";
                _logger.Warn($"Не удалось разобрать письмо с адреса {@from.ToAddressListString()}", e);
                if (_currentDocumentType != null)
                {
                    DocumentReceiveLog.Log(GetFirmCodeByFromList(@from), _addressId, null, _currentDocumentType.DocType, comment, IMAPHandler.CurrentUID);
                }
            }
            catch (Exception exMatch) {
                _logger.Error("Не удалось отправить нераспознанное письмо", exMatch);
            }
        }
        protected bool ProcessWaybillFile(string inFile, DataRow drCurrent, BaseDocumentReader documentReader)
        {
            //Массив файлов
            var files = new[] { inFile };
            var dir   = inFile + ExtrDirSuffix;

            if (ArchiveHelper.IsArchive(inFile))
            {
                // Получаем файлы, распакованные из архива
                files = Directory.GetFiles(dir, "*.*", SearchOption.AllDirectories);
            }

            if (!Directory.Exists(dir))
            {
                Directory.CreateDirectory(dir);
            }

            try {
                files = documentReader.DivideFiles(dir, files);
            }
            catch (Exception exDivide) {
                var supplierId = Convert.ToUInt32(drCurrent[WaybillSourcesTable.colFirmCode]);
                DocumentReceiveLog.Log(supplierId, null, Path.GetFileName(CurrFileName), _currentDocumentType.DocType, String.Format("Не удалось разделить файлы: {0}", exDivide));
                return(false);
            }

            var processed = false;

            foreach (var file in files)
            {
                if (MoveWaybill(inFile, file, drCurrent, documentReader))
                {
                    processed = true;
                }
            }
            return(processed);
        }
        public override void ProcessData()
        {
            // Заполняем таблицу с данными о поставщиках.
            FillSourcesTable();

            foreach (var row in dtSources.Rows.Cast <DataRow>())
            {
                var supplierId = Convert.ToUInt32(row[WaybillSourcesTable.colFirmCode]);
                drCurrent = row;
                try {
                    _currentDocumentType = null;
                    var clazz = row[WaybillSourcesTable.colReaderClassName].ToString();
                    if (String.IsNullOrEmpty(clazz))
                    {
                        _logger.WarnFormat("Игнорирую источник для поставщика с кодом {0} тк не задан формат разбора имени документа", supplierId);
                        continue;
                    }
                    var documentReader = ReflectionHelper.GetDocumentReader <BaseDocumentReader>(clazz);

                    foreach (var documentType in _documentTypes)
                    {
                        try {
                            _currentDocumentType = documentType;

                            // Получаем список файлов из папки
                            var files = GetFileFromSource(supplierId, documentReader);

                            foreach (var sourceFileName in files)
                            {
                                GetCurrentFile(sourceFileName);
                                if (String.IsNullOrEmpty(CurrFileName))
                                {
                                    continue;
                                }

                                var correctArchive = PriceProcessor.FileHelper.ProcessArchiveIfNeeded(CurrFileName, ExtrDirSuffix);
                                if (correctArchive)
                                {
                                    if (!ProcessWaybillFile(CurrFileName, row, documentReader))
                                    {
                                        using (var mm = new MailMessage(
                                                   Settings.Default.FarmSystemEmail,
                                                   Settings.Default.DocumentFailMail,
                                                   String.Format("{0} ({1})", row[WaybillSourcesTable.colShortName], SourceType),
                                                   String.Format("Код поставщика : {0}\nФирма: {1}\nТип: {2}\nДата: {3}\nПричина: {4}",
                                                                 row[WaybillSourcesTable.colFirmCode],
                                                                 row[SourcesTableColumns.colShortName],
                                                                 _currentDocumentType.GetType().Name,
                                                                 DateTime.Now,
                                                                 "Не удалось сопоставить документ клиентам. Подробнее смотрите в таблице logs.document_logs."))) {
                                            if (!String.IsNullOrEmpty(CurrFileName))
                                            {
                                                mm.Attachments.Add(new Attachment(CurrFileName));
                                            }
                                            var sc = new SmtpClient(Settings.Default.SMTPHost);
                                            sc.Send(mm);
                                        }
                                    }
                                    //После обработки файла удаляем его из папки
                                    if (!String.IsNullOrEmpty(sourceFileName) && File.Exists(sourceFileName))
                                    {
                                        File.Delete(sourceFileName);
                                    }
                                }
                                else
                                {
                                    DocumentReceiveLog.Log(supplierId, null, Path.GetFileName(CurrFileName), documentType.DocType, String.Format("Не удалось распаковать файл '{0}'", Path.GetFileName(CurrFileName)));
                                    //Распаковать файл не удалось, поэтому удаляем его из папки
                                    if (!String.IsNullOrEmpty(sourceFileName) && File.Exists(sourceFileName))
                                    {
                                        File.Delete(sourceFileName);
                                    }
                                }
                                Cleanup();
                            }
                        }
                        catch (Exception e) {
                            //Обрабатываем ошибку в случае обработки одного из типов документов
                            var message = String.Format("Источник : {0}\nТип : {1}", supplierId, documentType.GetType().Name);
                            Log(e, message);
                        }
                    }
                }
                catch (Exception ex) {
                    Log(ex, String.Format("Источник : {0}", supplierId));
                }
            }
        }
        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);
            }
        }