private ICollection <IWorkflowAction> MapWorkflowPECMailLinkActions(UDSEntityModel model) { if (model.Relations.PECMails == null || !model.Relations.PECMails.Any()) { return(new List <IWorkflowAction>()); } ICollection <IWorkflowAction> workflowActions = new List <IWorkflowAction>(); foreach (UDSPECMail instance in model.Relations.PECMails) { PECMail pecInstance = GetPECMailAsync(instance.IdPECMail).Result; if (pecInstance != null && !pecInstance.Year.HasValue) { workflowActions.Add(new WorkflowActionDocumentUnitLinkModel( new DocumentUnitModel() { UniqueId = model.IdUDS, Number = model.Number.Value.ToString(), Year = model.Year.Value }, new DocumentUnitModel() { UniqueId = instance.UniqueIdPECMail, EntityId = instance.IdPECMail, Environment = (int)DocSuiteWeb.Model.Entities.Commons.DSWEnvironmentType.PECMail })); } } return(workflowActions); }
public Boolean ExistNotification(int idPECMail, String accountName, SMSNotificationType notificationType = SMSNotificationType.PEC) { PECMail pec = null; return(NHibernateSession.QueryOver <SMSNotification>() .JoinAlias(j => j.PECMail, () => pec) .Where(f => f.AccountName == accountName) .And((f) => pec.Id == idPECMail) .SingleOrDefault() != null); }
internal static void AddPECMail(TaskDTO taskDTO, MailDTO mailDTO) { var header = FacadeFactory.Instance.TaskHeaderFacade.GetById(taskDTO.Id.Value); var pecMail = new PECMail(); pecMail.Id = int.Parse(mailDTO.Id); header.AddPECMail(pecMail); FacadeFactory.Instance.TaskHeaderFacade.Update(ref header); }
public async Task <PECMail> UpdatePECMailAsync(PECMail pecMail, string actionType = "") { try { return(await _webApiClient.PutEntityAsync(pecMail, actionType)); } catch (Exception ex) { _logger.WriteError(ex, LogCategories); throw ex; } }
public bool IsEmlArchiviedInBiblos(MailInfo mailInfo) { FileLogger.Info(_loggerName, "Verifica presenza PECMail in biblos."); PECMail pecMail = FacadeFactory.Instance.PECMailFacade.GetById(mailInfo.IDPECMail); BiblosDocumentInfo originalEml = FacadeFactory.Instance.PECMailFacade.GetPecMailContent(pecMail); if (originalEml != null) { string originalEmlChecksum = GetString(originalEml.Checksum); if (originalEmlChecksum.CompareTo(mailInfo.EmlHash) == 0) { return(true); } } return(false); }
public ICollection <SMSNotification> GetByTipology(Int16 IdPECMailBox = Int16.MinValue, SMSNotificationType notificationType = SMSNotificationType.PEC, LogicalStateType logicalState = LogicalStateType.Active) { PECMail pec = null; PECMailBox mailBox = null; IQueryOver <SMSNotification, SMSNotification> expression = NHibernateSession.QueryOver <SMSNotification>(); if (IdPECMailBox != Int16.MinValue) { expression = expression .JoinAlias(x => x.PECMail, () => pec) .JoinAlias(x => x.PECMail.MailBox, () => mailBox) .Where(() => mailBox.Id == IdPECMailBox); } return(expression .Where(f => f.NotificationType == notificationType) .And((f) => f.LogicalState == logicalState) .List <SMSNotification>()); }
protected override IQueryOver <PECMailLog, PECMailLog> MappingProjection(IQueryOver <PECMailLog, PECMailLog> queryOver) { PECMail pec = null; PECMailLogHeader header = null; queryOver .JoinAlias(o => o.Mail, () => pec) .SelectList(list => list .Select(x => x.Id).WithAlias(() => header.Id) .Select(x => x.Description).WithAlias(() => header.Description) .Select(x => x.Type).WithAlias(() => header.Type) .Select(x => x.Date).WithAlias(() => header.Date) .Select(x => x.SystemComputer).WithAlias(() => header.SystemComputer) .Select(x => x.SystemUser).WithAlias(() => header.SystemUser) .Select(x => pec.Id).WithAlias(() => header.MailId) .Select(x => pec.MailSubject).WithAlias(() => header.MailSubject) ) .TransformUsing(Transformers.AliasToBean <PECMailLogHeader>()); return(queryOver); }
private void SaveMail(PECMailBox mailbox, IMail email, PECMail pecMail, string password) { // Upload su cartela Sent if (mailbox.IncomingServerProtocol != IncomingProtocol.Imap || !mailbox.Configuration.UploadSent || string.IsNullOrEmpty(mailbox.Configuration.FolderSent)) { return; } try { using (Imap imap = new Imap()) { imap.ServerCertificateValidate += ServerCertificateValidateHandler; // Utilizzo connessione SSL if (mailbox.IncomingServerUseSsl.HasValue && mailbox.IncomingServerUseSsl.Value) { imap.ConnectSSL(mailbox.IncomingServerName, mailbox.IncomingServerPort.HasValue ? mailbox.IncomingServerPort.Value : 993); } else { imap.Connect(mailbox.IncomingServerName, mailbox.IncomingServerPort.HasValue ? mailbox.IncomingServerPort.Value : 143); } // Utilizzo autenticazione if (!string.IsNullOrEmpty(mailbox.Username) && !string.IsNullOrEmpty(password)) { imap.UseBestLogin(mailbox.Username, password); } imap.UploadMessage(mailbox.Configuration.FolderSent, email); imap.Close(); } } catch (Exception ex) { throw new Exception(string.Format( "Non è stato possibile salvare la PEC {0} / casella {1} - {2} nella cartella della posta inviata ({3}) per un probabile errore di rete o di server PEC.", pecMail.Id, mailbox.Id, mailbox.MailBoxName, mailbox.Configuration.FolderSent), ex); } }
/// <summary> Esegue gli invii per la PECMailBox passata per parametro. </summary> /// <param name="box">PECMailBox in cui cercare i messaggi da spedire.</param> public void Process(PECMailBox box, string password) { FileLogger.Info(_loggerName, string.Format("Avvio ciclo di invio per la casella {0} - {1}", box.Id, box.MailBoxName)); // Gestisco la duplicazione delle PEC marchiate tali GenerateMultiplePecs(box); // Recupero da DB l'elenco delle PEC in uscita non ancora spedite (MailDate NULL). Carcio anche le PEC in stato Processing. bool useStatusProcessing = true; IList <Int32> mail_ids = _factory.PECMailFacade.GetOutgoingMails(box.Id, box.Configuration.MaxSendForSession, useStatusProcessing); FileLogger.Info(_loggerName, string.Format("Trovate {0} PEC da spedire.", mail_ids.Count)); // Eseguo un ciclo sulle PEC da spedire fino al numero massimo di PEC gestibili per sessione di lavoro int successSendMail = 0; int errorSendMail = 0; int counter = 0; for (int index = 0; index < mail_ids.Count && counter < box.Configuration.MaxSendForSession; index++) { if (_cancelRequest()) { FileLogger.Info(_loggerName, "Blocco invio PEC per chiusura modulo invocata dall'utente."); return; } // Avvio watch per verificare quanto ci impiega per singola mail //TODO : da mettere in debug mode Stopwatch watch = Stopwatch.StartNew(); PECMail mail = MailStoreFacade.Factory.PECMailFacade.GetById(mail_ids[index]); if (mail.IsActive != ActiveType.Cast(ActiveType.PECMailActiveType.Active) && mail.IsActive != ActiveType.Cast(ActiveType.PECMailActiveType.Processing)) { FileLogger.Info(_loggerName, string.Format("Errore in lettura pecMail [{0}]. Lo status doveva essere 1. Possibile aggiornamento dati non previsto.", mail.Id)); return; } MailStoreFacade.Factory.TaskHeaderFacade.ActivatePECTaskProcess(mail); mail.IsActive = ActiveType.Cast(ActiveType.PECMailActiveType.Processing); _factory.PECMailFacade.Update(ref mail); FileLogger.Info(_loggerName, string.Format("Inizio processamento PEC [{0}] per invio. - Item #{1}", mail.Id, counter)); // Preparo i dati per l'invio Guid guid = Guid.NewGuid(); String fullName = string.Empty; IMail iMailPec = null; int i = 0; Exception lastException = null; String errorLastSendMail = string.Empty; while (iMailPec == null && i < 5) { // Salvo solamente gli errori dell'ultimo step esecuitivo StringBuilder errorMessage = new StringBuilder(); try { iMailPec = PrepareEmlData(mail, guid, ref fullName, ref errorMessage); if (iMailPec == null) { FileLogger.Error(_loggerName, string.Format("Tentativo di creazione eml {0}/5 saltato per massimo numero di elementi in Temp raggiunto per la PEC [{1}]", i + 1, mail.Id)); } } catch (Exception ex) { string errMsg = string.Format("Errore in fase di inserimento in Biblos per invio della PEC [{0}] - Tentativo {1}/5", mail.Id, i + 1); errorMessage.Append(errMsg); FileLogger.Error(_loggerName, errMsg, ex); lastException = ex; if (_cancelRequest()) { String message = "Blocco invio PEC per chiusura modulo invocata dall'utente a causa di errore in fase di preparazione dati EML."; errorMessage.Append(message); _factory.PECMailLogFacade.Warning(ref mail, message); FileLogger.Info(_loggerName, message); return; } Thread.Sleep(1000 * 30); } finally { errorLastSendMail = errorMessage.ToString(); i++; } } // Ho eseguito operazioni importanti per cui libero la memoria GC.Collect(); // Se a questo punto non sono riuscito ad ottenere un oggetto iMail significa che ci sono problemi su Biblos o su FileSystem, // quindi notifico, blocco e procedo oltre if (iMailPec == null) { String errorResult = string.Format("La PEC {0} della casella {1} - {2} non è stata correttamente inserita in Biblos per 5 volte. La PEC non è stata inviata ed è stata disattivata (isActive = 255) e dovrà essere riattivata previa verifica dell'errore.", mail.Id, box.Id, box.MailBoxName); mail.IsActive = ActiveType.Cast(ActiveType.PECMailActiveType.Error); _factory.PECMailFacade.UpdateOnly(ref mail); _factory.PECMailLogFacade.Error(ref mail, string.Concat(errorResult, errorLastSendMail)); MailStoreFacade.SetPECMailTaskError(mail); throw new Exception(errorResult, lastException); } // Se sono qui significa che tutti i dati su Biblos sono stati memorizzati // Spedisco la PEC via SMTP try { if (SendMail(box, iMailPec, mail, guid, password)) { // Se sono riuscito ad inviare allora salvo su Server via IMAP successSendMail++; try { //Aggiorno l'attributo MailDate per l'archivio di conservazione BiblosDocumentInfo mainInfo = BiblosDocumentInfo.GetDocuments(mail.Location.ConservationServer, mail.IDMailContent).SingleOrDefault(); FileLogger.Info(_loggerName, "Tentativo di aggiornare attributo MailDate"); mainInfo.AddAttribute("MailDate", mail.MailDate.Value.ToString(new CultureInfo("it-IT") { DateTimeFormat = new DateTimeFormatInfo { ShortDatePattern = "dd/MM/yyyy" } }), true); mainInfo.Update("BibloDS"); FileLogger.Info(_loggerName, string.Format("Attributi della PEC con ID {0} aggiornati.", mail.Id)); } catch (Exception ex) { _factory.PECMailLogFacade.Error(ref mail, string.Format("Errore in fase di aggiornamento attributi conservazione: {0}", ex.Message)); _sendMessage(string.Format("Errore in fase di aggiornamento attributi conservazione: {0} - Stacktrace: {1}", ex.Message, _fullStacktrace(ex))); } try { mail.IsActive = ActiveType.Cast(ActiveType.PECMailActiveType.Active); _factory.PECMailFacade.UpdateOnly(ref mail); SaveMail(box, iMailPec, mail, password); } catch (Exception ex) { _factory.PECMailLogFacade.Error(ref mail, string.Format("Errore in fase di salvataggio mail su IMAP: {0}", ex.Message)); _sendMessage(string.Format("Errore in fase di salvataggio mail su IMAP: {0} - Stacktrace: {1}", ex.Message, _fullStacktrace(ex))); } MailStoreFacade.CompletePECMailTask(mail); // Pulisco eventuali dati sporchi rimanenti CleanEmlData(mail.Id, _parameters.TempFolder); } else { errorSendMail++; } } catch (Exception ex) { _factory.PECMailLogFacade.Error(ref mail, string.Format("Errore in fase di invio mail: {0}", ex.Message)); _sendMessage(string.Format("Errore in fase di invio mail: {0} - Stacktrace: {1}", ex.Message, _fullStacktrace(ex))); MailStoreFacade.SetPECMailTaskError(mail); } // Fermo il Watch e registro il LOG watch.Stop(); FileLogger.Info(_loggerName, string.Format("Fine processamento PEC [{0}] per invio. Gestione avvenuta in {1} millisecondi. Item #{2}", mail.Id, watch.ElapsedMilliseconds, counter)); // Procedo con la PEC successiva counter++; // Fermo il thread per non sovraccaricare troppo i sistemi if (_parameters.SendSleep > 0) { Thread.Sleep(1000 * _parameters.SendSleep); } } if (successSendMail > 0) { _factory.PECMailboxLogFacade.InsertLog(ref box, string.Format("PEC Inviate {0} con successo", successSendMail), PECMailBoxLogFacade.PecMailBoxLogType.Sent); } if (errorSendMail > 0) { _factory.PECMailboxLogFacade.InsertLog(ref box, string.Format("Ci sono {0} PecMail da controllare", errorSendMail), PECMailBoxLogFacade.PecMailBoxLogType.SentError); } FileLogger.Info(_loggerName, string.Format("Fine ciclo di invio per la casella {0} - {1}", box.Id, box.MailBoxName)); }
/// <summary> /// Verifica se la mail scaricata utilizzando l'hash md5 dell'intero Eml se questa è già presente nel db, e quindi non deve essere ri-elaborata. /// Allo stesso tempo aggiorna il campo Header Hash calcolato dalla nuova versione della gestione pec nella tabella PecMail per /// poter individuare da subito utilizzando il solo header se si tratta di una mail già processata /// Se la mail esiste lo status viene già portata ad Archivied affinche venga gestito la release con evenutale cancellazione e backup della mail. /// </summary> public SortedList <short, StatisticLog> UpdateHeaderHash(SortedList <short, StatisticLog> statistics, Dictionary <short, string> passwordBoxes) { FileLogger.Info(_loggerName, "Verifica checksum mail scaricate"); try { String[] files = MailInfo.GetInfoFiles(_parameters.DropFolder); List <int> isActiveIn = new List <int> { 0, 1, 2 }; //rimuove o sposta le mail processate MailInfo mailInfo = null; DateTime start, end; foreach (String filename in files) { try { mailInfo = null; start = DateTime.Now; if (_cancelRequest()) { FileLogger.Info(_loggerName, "Chiusura modulo invocata dall'utente."); return(statistics); } mailInfo = MailInfo.Load(filename); if (mailInfo.Status != MailInfo.ProcessStatus.Downloaded) { end = DateTime.Now; if (statistics != null && mailInfo != null && mailInfo.IDPECMailBox > 0 && statistics.Keys.Any(f => f == mailInfo.IDPECMailBox)) { statistics[mailInfo.IDPECMailBox].ElaboratedTime = statistics[mailInfo.IDPECMailBox].ElaboratedTime + (TimeSpan.FromTicks(end.Ticks) - TimeSpan.FromTicks(start.Ticks)); } continue; } //ok, la mail non esiste bisogna processarla if (!MailStoreFacade.Factory.PECMailFacade.ChecksumExists(mailInfo.EmlHash, mailInfo.MailBoxRecipient)) { end = DateTime.Now; if (statistics != null && mailInfo != null && mailInfo.IDPECMailBox > 0 && statistics.Keys.Any(f => f == mailInfo.IDPECMailBox)) { statistics[mailInfo.IDPECMailBox].ElaboratedTime = statistics[mailInfo.IDPECMailBox].ElaboratedTime + (TimeSpan.FromTicks(end.Ticks) - TimeSpan.FromTicks(start.Ticks)); } continue; } //se esiste e mi trovo a questo punto, aggiorno il valore dell'headerChecksum IList <PECMail> results = MailStoreFacade.Factory.PECMailFacade.GetByChecksum(mailInfo.EmlHash, mailInfo.MailBoxRecipient, isActiveIn); foreach (PECMail pecMail in results.Where(item => string.IsNullOrEmpty(item.HeaderChecksum))) { PECMail temp = pecMail; temp.HeaderChecksum = mailInfo.HeaderHash; MailStoreFacade.Factory.PECMailFacade.Update(ref temp); FileLogger.Info(_loggerName, string.Format("HeaderHash aggiornato per la Mail Id:{0}.", temp.Id)); } //Old: Non serve più importare la mail perchè esiste già, verra rimossa nella fase di Release, quindi la segno come archiviata mailInfo.UpdateStatus(MailInfo.ProcessStatus.Archived); mailInfo.Save(); WashOnlinePecNotErased(mailInfo, passwordBoxes[mailInfo.IDPECMailBox]); end = DateTime.Now; if (statistics != null && mailInfo != null && statistics.Keys.Any(f => f == mailInfo.IDPECMailBox)) { statistics[mailInfo.IDPECMailBox].ElaboratedTime = statistics[mailInfo.IDPECMailBox].ElaboratedTime + (TimeSpan.FromTicks(end.Ticks) - TimeSpan.FromTicks(start.Ticks)); } } catch (Exception ex_int) { String pecName = filename; if (mailInfo != null) { pecName = mailInfo.Subject; try { PECMailBox box = MailStoreFacade.Factory.PECMailboxFacade.GetById(mailInfo.IDPECMailBox); MailStoreFacade.Factory.PECMailboxLogFacade.InsertLog(ref box, "ERRORE - Verifica checksum", PECMailBoxLogFacade.PecMailBoxLogType.ErrorEval); } catch (Exception) { } } FileLogger.Error(_loggerName, string.Format("Errore in verifica checksum mail scaricate della mail {0}. Il flusso normale proseguirà con le successive mail.", pecName), ex_int); _sendMessage(string.Format("Errore in verifica checksum mail scaricate della mail {0}. Il flusso normale proseguirà con le successive mail. Exception: {1} - Stacktrace: {2}", pecName, ex_int.Message, _fullStacktrace(ex_int))); } } } catch (Exception ex) { FileLogger.Error(_loggerName, "Errore in verifica checksum mail scaricate.", ex); _sendMessage(string.Format("Errore in verifca checksum mail scaricate. Exception:{0} - Stacktrace: {1}", ex.Message, _fullStacktrace(ex))); } FileLogger.Info(_loggerName, "Fine checksum mail scaricate"); return(statistics); }
/// <summary> /// Questo metodo si occupa di effettuare la bonifica di eventuali eml rimasti in sospeso /// </summary> public void CheckEmlToSend() { FileLogger.Info(_loggerName, "Inizio ciclo di verifica di eventuali EML orfani nella Temp"); // Carico tutte gli EML della cartella Temp String[] emls = Directory.GetFiles(_parameters.TempFolder, "PecToSendId_*"); FileLogger.Info(_loggerName, string.Format("Sono stati trovati {0} EML da analizzare.", emls.Count())); foreach (String emlFullPath in emls) { FileLogger.Info(_loggerName, string.Format("Analisi EML {0}", emlFullPath)); // Verifico se ne frattempo il file fosse già stato analizzato // in tal caso procedo con il prossimo FileInfo checkExistence = new FileInfo(emlFullPath); if (!checkExistence.Exists) { FileLogger.Info(_loggerName, string.Format("Il file {0} non esiste.", emlFullPath)); continue; } FileLogger.Info(_loggerName, string.Format("Il file {0} esiste.", emlFullPath)); // Effettuo il parsing del testo String[] temp = emlFullPath.Split('_'); int pecId = -1; if (!int.TryParse(temp[1], out pecId)) { FileLogger.Error(_loggerName, string.Format("L'EML {0} nel tenativoo di recuori della PEC in uscita sull'host {1} non è stato processato. Verrà ignorato ma il file dovrà essere spostato manualmente.", emlFullPath, Environment.MachineName)); _sendMessage(string.Format("L'EML {0} nel tenativoo di recuori della PEC in uscita sull'host {1} non è stato processato. Verrà ignorato ma il file dovrà essere spostato manualmente.", emlFullPath, Environment.MachineName)); continue; } DateTime elementDateTime = DateTime.ParseExact(temp[4], "yyyyMMdd-HHmm", CultureInfo.InvariantCulture); // Calcolo quanto vecchi sono i file TimeSpan timespan = DateTime.Now - elementDateTime; FileLogger.Info(_loggerName, string.Format("L'elemento è vecchio di {0} minuti.", timespan.TotalMinutes)); // Se gli elementi memorizzati sono più vecchi di 15 minuti non ci provo più e procedo oltre if (timespan.TotalMinutes >= 15) { FileLogger.Warn(_loggerName, string.Format("L'elemento {0} è vecchio di {1} minuti e quindi verrà cancellato.", emlFullPath, timespan.TotalMinutes)); _sendMessage(string.Format("L'elemento {0} è vecchio di {1} minuti e quindi verrà cancellato.", emlFullPath, timespan.TotalMinutes)); File.Delete(emlFullPath); continue; } // Verifico se la PEC è stata archiviata in Biblos PECMail pecMail = _factory.PECMailFacade.GetById((pecId)); if (pecMail != null) { FileLogger.Debug(_loggerName, string.Format("PEC {0} esistente", pecMail.Id)); // Se sono riuscito a caricare la PEC, allora verifico if (pecMail.IDPostacert == Guid.Empty) { FileLogger.Debug(_loggerName, string.Format( "Una precedente memorizzazione su Biblos della PEC {0} non è andata a buon fine. Nuovo tentativo.", pecMail.Id)); // Significa che la memorizzazione in Biblos non è andata a buon fine try { Byte[] dataB = File.ReadAllBytes(emlFullPath); _factory.PECMailFacade.ArchivePostacert(ref pecMail, dataB, "Message.eml"); _factory.PECMailFacade.UpdateNoLastChange(ref pecMail); FileLogger.Debug(_loggerName, string.Format( "Inserimento in Biblos della PEC {0} avvenuto con successo.", pecMail.Id)); } catch (Exception ex) { FileLogger.Error(_loggerName, string.Format("Impossibile salvare su Biblos l'EML {0} per la PEC {1}", emlFullPath, pecMail.Id), ex); _sendMessage(string.Format("Impossibile salvare su Biblos l'EML {0} per la PEC {1} - Stacktrace: {2}", emlFullPath, pecMail.Id, _fullStacktrace(ex))); // Attendo 60 secondi, se si tratta di un problema momentaneo, in 60 secondi potrebbe risolversi Thread.Sleep(1000 * 60); continue; } } // Se sono riuscito ad inserire in Biblos e la PEC non è ancora stata spedita e ancora risulta non attiva allora la riattiva if (pecMail.IDPostacert != Guid.Empty && pecMail.MailDate == null && pecMail.IsActive == ActiveType.Cast(ActiveType.PECMailActiveType.Processed)) { pecMail.IsActive = ActiveType.Cast(ActiveType.PECMailActiveType.Active); _factory.PECMailFacade.UpdateOnly(ref pecMail); FileLogger.Debug(_loggerName, string.Format("PEC {0} riattivata per ritentare invio.", pecMail.Id)); _sendMessage(string.Format("PEC {0} riattivata per ritentare invio.", pecMail.Id)); } CleanEmlData(pecMail.Id, _parameters.TempFolder); } else { FileLogger.Error(_loggerName, string.Format("Errore in fase di gestione EML {0}", emlFullPath)); _sendMessage(string.Format("Errore in fase di verifica di gestione EML {0}", emlFullPath)); CleanEmlData(pecId, _parameters.TempFolder); } } FileLogger.Info(_loggerName, "Fine ciclo di verifica di eventuali EML orfani nella Temp"); }
/// <summary> Spedisce l'email. </summary> /// <param name="mailbox"> MailBox da dove spedire l'email. </param> /// <param name="email"> Email da spedire. </param> /// <param name="pecMail"> PEC da inviare </param> /// <param name="guid"> Guid della mail</param> public bool SendMail(PECMailBox mailbox, IMail email, PECMail pecMail, Guid guid, string password) { // In caso di modalità DEBUG modifico i destinatari con quello di default: if (_parameters.DebugModeEnabled) { // Creo una nuova mail alla quale aggiungo come allegato la mail originale MailBuilder debugBuilder = new MailBuilder(); debugBuilder.From.Add(email.From.First()); debugBuilder.Subject = string.Format("Inoltro messaggio per DEBUG -> {0}", email.Subject); // Crea il corpo del messaggio di default (non è richiesto dall'Interoperabilità) o lo legge da base dati, se indicato debugBuilder.Text = "In allegato la mail che sarebbe stata spedita."; // Aggiungo il destinatario di debug debugBuilder.To.Add(new MailBox(_parameters.PecOutAddressDebugMode, "DEBUG ADDRESS")); // Aggiungo la mail come allegatos debugBuilder.AddAttachment(email); // Sostituisco item con il debugMail email = debugBuilder.Create(); FileLogger.Info(_loggerName, string.Format("Modificato l'indirizzo di invio della PEC con l'indirizzo {0}.", _parameters.PecOutAddressDebugMode)); } // Eseguo in modo atomico il blocco di invio int i = 0; bool sent = false; ISendMessageResult sendResult = null; Exception lastException = null; while (!sent && i < 5) { try { using (Smtp smtp = new Smtp()) { smtp.ServerCertificateValidate += ServerCertificateValidateHandler; // Utilizzo connessione SSL if (mailbox.OutgoingServerUseSsl.HasValue && mailbox.OutgoingServerUseSsl.Value) { smtp.SSLConfiguration.EnabledSslProtocols = System.Security.Authentication.SslProtocols.Tls12; smtp.ConnectSSL(mailbox.OutgoingServerName, mailbox.OutgoingServerPort.HasValue ? mailbox.OutgoingServerPort.Value : 465); } else { smtp.Connect(mailbox.OutgoingServerName, mailbox.OutgoingServerPort.HasValue ? mailbox.OutgoingServerPort.Value : 25); } // Utilizzo autenticazione if (!string.IsNullOrEmpty(mailbox.Username) && !string.IsNullOrEmpty(password)) { smtp.UseBestLogin(mailbox.Username, password); } sendResult = smtp.SendMessage(email); sent = (sendResult.Status == SendMessageStatus.Success); if (!sent) { string errors = string.Empty; if (sendResult.GeneralErrors != null && sendResult.GeneralErrors.Any()) { errors = string.Join(", ", sendResult.GeneralErrors .Select(f => string.Concat("Code: ", f.Code, " - EnhancedStatusCode: ", f.EnhancedStatusCode, " - Message: ", f.Message, " - Status : ", f.Status))); } FileLogger.Error(_loggerName, string.Format("Errore in spedizione PEC {0} / casella {1} - {2}. Stato spedizione: {3} - Errori:{4}.", pecMail.Id, mailbox.Id, mailbox.MailBoxName, sendResult.Status, errors)); } smtp.Close(false); } if (!sent) { continue; } // Aggiorno immediatamente la PEC come spedita in modo da non avere dubbi che la PEC sia stata davvero spedita pecMail.MailDate = DateTime.Now; pecMail.XRiferimentoMessageID = string.Format("<{0}>", guid); _factory.PECMailFacade.UpdateOnly(ref pecMail); Protocol currentProtocol = _factory.PECMailFacade.GetProtocol(pecMail); if (currentProtocol != null && (short)ProtocolKind.FatturePA == currentProtocol.IdProtocolKind) { currentProtocol.IdStatus = (int)ProtocolStatusId.PAInvoiceSent; _factory.ProtocolFacade.UpdateOnly(ref currentProtocol); } } catch (Exception ex) { lastException = ex; // Se mi trovo in questo status è avvenuto un errore in fase di spedizione, per cui posso riprocedere ad inviare FileLogger.Error(_loggerName, string.Format("Non è stato possibile inviare la PEC {0} / casella {1} - {2} per un probabile errore di rete o di server PEC. La procedura verrà ritentata. - Tentativo {3}/5", pecMail.Id, mailbox.Id, mailbox.MailBoxName, i + 1), ex); // Attendo 1 minuto prima di riprovare #if !DEBUG Thread.Sleep(1000 * 30); #endif } finally { // Procedo i++; } } // Se dopo 5 tentativi ancora non ha ricevuto conferma di spedizione allora invio una mail e blocco l'invio if (sent) { _factory.PECMailboxLogFacade.SentMail(ref pecMail); return(true); } // Errori String errorMessages = string.Format("Errori di invio:{0}", Environment.NewLine); errorMessages = sendResult.GeneralErrors.Aggregate(errorMessages, (current, generalError) => current + string.Format("Code:{1} - Message:{2} - Status:{3}{0}", Environment.NewLine, generalError.Code, generalError.Message, generalError.Status)); _factory.PECMailboxLogFacade.SentErrorMail(ref pecMail, new Exception(errorMessages)); pecMail.IsActive = ActiveType.Cast(ActiveType.PECMailActiveType.Error); _factory.PECMailFacade.UpdateOnly(ref pecMail); String errorResult = string.Format("La PEC {0} / casella {1} - {2} non è stata spedita dopo 5 tentativi falliti. \nE' stata pertanto disattivata (isActive = 255) per evitare ulteriori tentativi.", pecMail.Id, mailbox.Id, mailbox.MailBoxName); _factory.PECMailLogFacade.Error(ref pecMail, errorResult); _factory.PECMailLogFacade.Error(ref pecMail, string.Concat(errorResult, errorMessages)); MailStoreFacade.SetPECMailTaskError(pecMail); throw new Exception(errorResult, lastException); }
/// <summary> /// Questo metodo ha il compito di gestire la memorizzazione in Biblos e in DB di una PEC in uscita /// </summary> public IMail PrepareEmlData(PECMail pecMail, Guid guid, ref string fullname, ref StringBuilder sb) { if (fullname == null) { sb.Append("Fullname non settato."); throw new ArgumentNullException("fullname"); } // Verifico sia definita una location, altrimenti non posso caricare gli allegati if (pecMail.Location == null) { pecMail.Location = pecMail.MailBox.Location; _factory.PECMailFacade.UpdateNoLastChange(ref pecMail); } // Salvo l'eml sul disco fullname = GetEmlFullName(_parameters.TempFolder, pecMail.Id, 5); if (!string.IsNullOrEmpty(fullname)) { // Genero l'istanza di IMail da spedire via SMTP IMail simpleMail = GetMailMessage(guid, pecMail); simpleMail.Save(fullname); FileInfo generatedEml = new FileInfo(fullname); FileLogger.Debug(_loggerName, $"Envelope salvato in [{generatedEml.FullName}]. Check: {generatedEml.Exists}"); if (pecMail.IDMailContent.Equals(Guid.Empty)) { PECMail lambdaProblemPec = pecMail; HibernateSessionHelper.TryOrRollback(() => { _factory.PECMailFacade.ArchiveInConservation(ref lambdaProblemPec, Encoding.GetEncoding(1252).GetBytes(generatedEml.FullName), "Message.eml"); // Ulteriore check di coerenza if (lambdaProblemPec.IDMailContent.Equals(Guid.Empty)) { // Significa che l'archiviazione in Conservazione non è avvuta correttamente. // Blocco tutto e lancio eccezione throw new Exception("Non è stato possibile memorizzazione il blob in conservazione. Verificare di avere impostato un archivio di conservazione."); } }, _loggerName, "Impossibile memorizzare la PEC in conservazione. Possibile errore Biblos. Transazione annullata.", true); } // Verifico che già non sia stato fatto if (pecMail.IDPostacert == Guid.Empty) { try { var dataB = File.ReadAllBytes(generatedEml.FullName); _factory.PECMailFacade.ArchivePostacert(ref pecMail, dataB, "Message.eml"); _factory.PECMailFacade.UpdateNoLastChange(ref pecMail); } catch (Exception ex) { if (ex.InnerException != null) { sb.Append(ex.InnerException); } sb.Append(ex.Message); throw new Exception(string.Format("Errore in fase di salvataggio PEC [{0}] su Biblos. Il processo procederà con la prossima PEC fino a 5 tentativi totali", pecMail.Id), ex); } } else { FileLogger.Debug(_loggerName, string.Format("La PEC {0} è già stata memorizzata in Biblos, passo saltato.", pecMail.Id)); } return(simpleMail); } // Se fosse già presente lo lascio lì perchè lo gestirò nella seconda parte del modulo // quindi proseguo con le restanti PEC return(null); }
/// <summary> /// Verifica se la mail scaricata utilizzando l'hash md5 dell'intero Eml se questa è già presente nel db, e quindi non deve essere ri-elaborata. /// Allo stesso tempo aggiorna il campo Header Hash calcolato dalla nuova versione della gestione pec nella tabella PecMail per /// poter individuare da subito utilizzando il solo header se si tratta di una mail già processata /// Se la mail esiste lo status viene già portata ad Archivied affinche venga gestito la release con evenutale cancellazione e backup della mail. /// </summary> public void UpdateHeaderHash() { FileLogger.Info(_loggerName, "Verifica checksum mail scaricate"); try { String[] files = MailInfo.GetInfoFiles(_parameters.DropFolder); List <int> isActiveIn = new List <int> { 0, 1, 2 }; //rimuove o sposta le mail processate MailInfo mailInfo = null; foreach (String filename in files) { try { mailInfo = null; if (_cancelRequest()) { FileLogger.Info(_loggerName, "Chiusura modulo invocata dall'utente."); return; } mailInfo = MailInfo.Load(filename); if (mailInfo.Status != MailInfo.ProcessStatus.Downloaded) { continue; } //ok, la mail non esiste bisogna processarla if (!MailStoreFacade.Factory.PECMailFacade.ChecksumExists(mailInfo.EmlHash, mailInfo.MailBoxRecipient)) { continue; } //se esiste e mi trovo a questo punto, aggiorno il valore dell'headerChecksum IList <PECMail> results = MailStoreFacade.Factory.PECMailFacade.GetByChecksum(mailInfo.EmlHash, mailInfo.MailBoxRecipient, isActiveIn); foreach (PECMail pecMail in results.Where(item => string.IsNullOrEmpty(item.HeaderChecksum))) { PECMail temp = pecMail; temp.HeaderChecksum = mailInfo.HeaderHash; MailStoreFacade.Factory.PECMailFacade.Update(ref temp); FileLogger.Info(_loggerName, string.Format("HeaderHash aggiornato per la Mail Id:{0}.", temp.Id)); } //Old: Non serve più importare la mail perchè esiste già, verra rimossa nella fase di Release, quindi la segno come archiviata mailInfo.UpdateStatus(MailInfo.ProcessStatus.Archived); mailInfo.Save(); WashOnlinePecNotErased(mailInfo); } catch (Exception ex_int) { String pecName = filename; if (mailInfo != null) { pecName = mailInfo.Subject; } FileLogger.Error(_loggerName, string.Format("Errore in verifica checksum mail scaricate della mail {0}. Il flusso normale proseguirà con le successive mail.", pecName), ex_int); _sendMessage(string.Format("Errore in verifica checksum mail scaricate della mail {0}. Il flusso normale proseguirà con le successive mail. Exception: {1} - Stacktrace: {2}", pecName, ex_int.Message, _fullStacktrace(ex_int))); } } } catch (Exception ex) { FileLogger.Error(_loggerName, "Errore in verifica checksum mail scaricate.", ex); _sendMessage(string.Format("Errore in verifca checksum mail scaricate. Exception:{0} - Stacktrace: {1}", ex.Message, _fullStacktrace(ex))); } FileLogger.Info(_loggerName, "Fine checksum mail scaricate"); }
/// <summary> /// Archiviazione dei file generati dalla ProcessFolder. /// Questa funzione racchiude tutte le funzioni di archiviazione su storage della mail (Biblos e DocSuite) /// I file vengono salvati in Biblos secondo la gerarchia indicata nel file ..._index.xml /// Genera il record PecMail e tutte i record di supporto per i file contenuti nella Pec (postacert.eml, daticert.xml, ecc...) /// Genera i record per PecMailAttachments /// </summary> public void ArchiveFiles() { FileLogger.Info(_loggerName, "Avvio archiviazione mail elaborate"); PECMail pecMail = null; int nRetry = MaxRetry; String errMsg = string.Empty; int waitingTime = 30000; try { String[] files = MailInfo.GetInfoFiles(_parameters.DropFolder); foreach (String filename in files) { try { if (_cancelRequest()) { FileLogger.Info(_loggerName, "Chiusura modulo invocata dall'utente."); return; } nRetry = MaxRetry; errMsg = string.Empty; waitingTime = 30000; IterationTracker iterationTracker = new IterationTracker(); while (--nRetry > 0) { IterationDescriptor currentIterationInfo = iterationTracker.AddIteration(); if (_storeFacade.ArchiveMail(_parameters.DropFolder, filename, _parameters.DebugModeEnabled, true, out pecMail, out errMsg, currentIterationInfo)) { FileLogger.Info(_loggerName, string.Format("Archiviazione di MailInfo [{0}] avvenuta con successo, passaggio ad elemento successivo.", filename)); break; } FileLogger.Warn(_loggerName, string.Format("E' avvenuto un errore di archiviazione, potenzialmente temporaneo. Verrà ritentata l'archiviazione altre {0} volte dopo una pausa di {1} sec.", nRetry, waitingTime / 1000)); //Errore di archiviazione, attendo 150 secondi diviso il tentativo prima di riprovare if (nRetry > 0) { #if !DEBUG Thread.Sleep(waitingTime); #endif waitingTime += waitingTime / nRetry; } } iterationTracker.Log(_loggerName); // Se mi trovo qui significa che ho esaurito i tentativi di archiviazione if (nRetry <= 0) { String errorMessage = string.Format("{0} - Eseguiti {1} tentativi di archiviazione senza successo.", errMsg, MaxRetry); if (pecMail != null) { String errorResult = string.Format("La PEC {0} non è stata correttamente inserita ed è stata disattivata (isActive = 255) e dovrà essere riattivata previa verifica dell'errore. {1}", pecMail.Id, errorMessage); pecMail.IsActive = ActiveType.Cast(ActiveType.PECMailActiveType.Error); try { MailStoreFacade.Factory.PECMailFacade.UpdateOnly(ref pecMail); MailStoreFacade.Factory.PECMailLogFacade.Error(ref pecMail, errorResult); } catch (Exception ex) { errorMessage = string.Concat(errorMessage, "\n", ex.Message); } } //throw new ApplicationException(errorMessage); } } catch (Exception ex_int) { FileLogger.Error(_loggerName, string.Format("Errore in archiviazione mail {0}. Il flusso normale proseguirà con le successive mail.", filename), ex_int); _sendMessage(string.Format("Errore in archiviazione mail. Il flusso normale proseguirà con le successive mail.{0}Exception: {1}{0}Stacktrace: {2}", Environment.NewLine, ex_int.Message, _fullStacktrace(ex_int))); } } } catch (Exception ex) { FileLogger.Error(_loggerName, "Errore in archiviazione globale mail.", ex); _sendMessage(string.Format("Errore in archiviazione globale mail.{0}Exception: {1}{0}Stacktrace: {2}", Environment.NewLine, ex.Message, _fullStacktrace(ex))); } FileLogger.Info(_loggerName, "Fine archiviazione mail scaricate e processate"); }
public PECMailRightsUtil(PECMail pecMail, string userName) { CurrentPecMail = pecMail; _userName = userName; _currentUDSRepositoryFacade = new UDSRepositoryFacade(userName); }
private IMail GetMailMessage(Guid guid, PECMail pecMail) { MailBuilder builder = new MailBuilder(); foreach (MailBox mailBox in MailStringToList(pecMail.MailSenders)) { builder.From.Add(mailBox); } foreach (MailBox mailBox in MailStringToList(pecMail.MailRecipients)) { builder.To.Add(mailBox); } foreach (MailBox mailBox in MailStringToList(pecMail.MailRecipientsCc)) { builder.Cc.Add(mailBox); } builder.Subject = string.IsNullOrEmpty(pecMail.MailSubject) ? string.Empty : StringHelper.ReplaceCrLf(pecMail.MailSubject); // Crea il corpo del messaggio di default (non è richiesto dall'Interoperabilità) o lo legge da base dati, se indicato builder.Text = (string.IsNullOrEmpty(pecMail.MailBody)) ? string.Format("Invio protocollo \"{0}\" ({1}/{2})", pecMail.MailSubject, pecMail.Number, pecMail.Year) : pecMail.MailBody; builder.MessageID = guid.ToString(); if (!string.IsNullOrEmpty(pecMail.Segnatura)) { // Estrae la segnatura dalla base dati e la allega alla mail in uscita MimeData xmlSegnatura = builder.AddAttachment(Encoding.GetEncoding(1252).GetBytes(pecMail.Segnatura)); xmlSegnatura.ContentType = new ContentType(MimeType.Text, MimeSubtype.Xml); xmlSegnatura.ContentId = "Segnatura.xml"; xmlSegnatura.FileName = "Segnatura.xml"; } // Estrae i relativi allegati da base dati (documento ed allegati) if ((pecMail.Attachments != null) && (pecMail.Attachments.Count > 0)) { byte[] attachmentByteArray; foreach (PECMailAttachment attachment in pecMail.Attachments) { try { attachmentByteArray = null; string attachmentName = FileHelper.ReplaceUnicode(FileHelper.ConvertUnicodeToAscii(attachment.AttachmentName)); if (pecMail.Location != null && !string.IsNullOrEmpty(pecMail.Location.DocumentServer) && attachment.IDDocument != Guid.Empty) { // Allora utilizzo l'idDocument BiblosDocumentInfo doc = new BiblosDocumentInfo(pecMail.Location.DocumentServer, attachment.IDDocument); attachmentByteArray = doc.Stream; FileLogger.Debug(_loggerName, string.Format("Caricamento allegato {0} della PEC {1} inserito da DSW8 utilizzando l'IDDocument", attachmentName, pecMail.Id)); } else { throw new Exception("L'allegato non contiene nè un idBiblos valido nè uno stream valido e pertanto non può essere inviato."); } MimeData document = builder.AddAttachment(attachmentByteArray); if (attachmentName.EndsWith(FileHelper.EML, StringComparison.InvariantCultureIgnoreCase)) { document.ContentType = new ContentType(MimeType.Message, MimeSubtype.Rfc822); } else { document.ContentType = new ContentType(MimeType.Application, MimeSubtype.OctetStream); } document.ContentId = attachmentName; document.FileName = attachmentName; } catch (Exception ex) { FileLogger.Error(_loggerName, string.Format("Errore in aggiunta allegati alla PECMail [{0}].", pecMail.Id), ex); } } } // Estrae il messaggio di ritorno dalla base dati, se presente e lo allega alla mail in uscita if (pecMail.MessaggioRitornoName != null && pecMail.MessaggioRitornoStream != null) { MimeData messaggioRitornoStream = builder.AddAttachment(Encoding.GetEncoding(1252).GetBytes(pecMail.MessaggioRitornoStream)); messaggioRitornoStream.ContentType = new ContentType(MimeType.Text, MimeSubtype.Xml); messaggioRitornoStream.ContentId = pecMail.MessaggioRitornoStream; messaggioRitornoStream.FileName = pecMail.MessaggioRitornoStream; } if (pecMail.MailPriority.HasValue) { switch (pecMail.MailPriority) { case -1: builder.Priority = MimePriority.NonUrgent; break; case 1: builder.Priority = MimePriority.Urgent; break; default: builder.Priority = MimePriority.Normal; break; } } else { builder.Priority = MimePriority.Normal; } return(builder.Create()); }
private void RecoverEnvelopeAttachments(IEnumerable <PECMailBox> boxes) { var boxName = string.Empty; try { foreach (var box in boxes) { boxName = string.Format("{0} - {1}", box.Id, box.MailBoxName); if (CancelRequest()) { FileLogger.Info(Name, "Chiusura modulo invocata dall'utente."); return; } FileLogger.Info(Name, "Recupero Envelope in corso..."); // Recupero l'elenco delle PEC da riprocessare NHibernatePECMailFinder finder = new NHibernatePECMailFinder { Actives = true, MailDateFrom = !Parameters.RecoverEnvelopeAttachmentStartDate.Equals(default(DateTime)) ? (DateTime?)Parameters.RecoverEnvelopeAttachmentStartDate : null, MailDateTo = !Parameters.RecoverEnvelopeAttachmentEndDate.Equals(default(DateTime)) ? (DateTime?)Parameters.RecoverEnvelopeAttachmentEndDate : null, MailboxIds = new[] { box.Id }, }; List <PECMail> pecMails = finder.DoSearch().Where(pecMail => pecMail.Direction != (short)DocSuiteWeb.Data.PECMailDirection.Outgoing && pecMail.IDMailContent != Guid.Empty && !pecMail.LogEntries.Any(pml => pml.Type.Eq(PECMailLogType.Reprocessed.ToString()))). Take(box.Configuration.MaxReadForSession).ToList(); FileLogger.Info(Name, string.Format("Trovate {0} pec da riprocessare", pecMails.Count)); foreach (PECMail pecMail in pecMails) { PECMail currentPecMail = pecMail; // Recupero la PEC dal server di conservazione BiblosDocumentInfo originalEml = FacadeFactory.Instance.PECMailFacade.GetPecMailContent(currentPecMail); if (originalEml == null) { continue; } BiblosDocumentInfo originalEnvelope = new BiblosDocumentInfo(currentPecMail.Location.DocumentServer, currentPecMail.IDEnvelope); FileLogger.Info(Name, string.Format("Estrazione eml originale GUID_Chain_EML {0} PEC [{1}] da riprocessare - EML name [{2}]", currentPecMail.IDMailContent, currentPecMail.Id, originalEml.Name)); try { Guid originalEnvelopeId = currentPecMail.IDEnvelope; IMail envelope = new MailBuilder().CreateFromEml(originalEml.Stream); FileLogger.Debug(Name, "Generata busta da EML"); envelope.RemoveAttachments(); FileLogger.Debug(Name, "Rimossi allegati con successo, archiviazione in corso..."); MailStoreFacade.Factory.PECMailFacade.ArchiveEnvelope(ref currentPecMail, envelope.Render(), originalEnvelope.Name); MailStoreFacade.Factory.PECMailFacade.UpdateNoLastChange(ref currentPecMail); FileLogger.Info(Name, string.Format( "Aggiornamento Envelope avvenuto correttamente: nuovo GUID_Chain [{0}]", currentPecMail.IDEnvelope)); MailStoreFacade.Factory.PECMailLogFacade.InsertLog(ref currentPecMail, string.Format("Ricalcolata busta: guidPrecedente [{0}] -> guidRicalcolato [{1}]", originalEnvelopeId, currentPecMail.IDEnvelope), PECMailLogType.Reprocessed); } catch (Exception ex) { FileLogger.Error(Name, "Errore in fase di ricalcolo busta.", ex); SendMessage( string.Format("Errore in fase di ricalcolo busta per la PEC {1} - Guid: [{2}].{0}Stacktrace: {3}", Environment.NewLine, pecMail.Id, pecMail.IDEnvelope, FullStacktrace(ex))); } } } } catch (Exception ex) { FileLogger.Error(Name, string.Format("Errore in [RecoverEnvelopeAttachments] - Casella [{0}].", boxName), ex); SendMessage(string.Format("Errore in [RecoverEnvelopeAttachments] - Casella [{0}]. \nErrore: {1} \nStacktrace: {2}", boxName, ex.Message, FullStacktrace(ex))); } finally { // Libero le risorse NHibernateManager.NHibernateSessionManager.Instance.CloseTransactionAndSessions(); GC.Collect(GC.MaxGeneration); } }
/// <summary> /// Archiviazione dei file generati dalla ProcessFolder. /// Questa funzione racchiude tutte le funzioni di archiviazione su storage della mail (Biblos e DocSuite) /// I file vengono salvati in Biblos secondo la gerarchia indicata nel file ..._index.xml /// Genera il record PecMail e tutte i record di supporto per i file contenuti nella Pec (postacert.eml, daticert.xml, ecc...) /// Genera i record per PecMailAttachments /// </summary> public SortedList <short, StatisticLog> ArchiveFiles(SortedList <short, StatisticLog> statistics) { FileLogger.Info(_loggerName, "Avvio archiviazione mail elaborate"); PECMail pecMail = null; int nRetry = MaxRetry; String errMsg = string.Empty; int waitingTime = 30000; try { String[] files = MailInfo.GetInfoFiles(_parameters.DropFolder); DateTime start, end; foreach (String filename in files) { start = DateTime.Now; try { if (_cancelRequest()) { FileLogger.Info(_loggerName, "Chiusura modulo invocata dall'utente."); return(statistics); } nRetry = MaxRetry; errMsg = string.Empty; waitingTime = 30000; IterationTracker iterationTracker = new IterationTracker(); while (--nRetry > 0) { IterationDescriptor currentIterationInfo = iterationTracker.AddIteration(); if (_storeFacade.ArchiveMail(_parameters.DropFolder, filename, _parameters.DebugModeEnabled, true, out pecMail, out errMsg, currentIterationInfo)) { FileLogger.Info(_loggerName, $"Archiviazione di MailInfo [{filename}] avvenuta con successo, passaggio ad elemento successivo."); if (pecMail?.MailBox != null && statistics?.Keys != null && statistics.Keys.Any(f => f == pecMail.MailBox.Id)) { statistics[pecMail.MailBox.Id].PECDone++; } break; } FileLogger.Warn(_loggerName, $"E' avvenuto un errore di archiviazione, potenzialmente temporaneo. Verrà ritentata l'archiviazione altre {nRetry} volte dopo una pausa di {waitingTime / 1000} sec."); //Errore di archiviazione, attendo 150 secondi diviso il tentativo prima di riprovare if (nRetry > 0) { #if !DEBUG System.Threading.Thread.Sleep(waitingTime); #endif waitingTime += waitingTime / nRetry; } } iterationTracker.Log(_loggerName); // Se mi trovo qui significa che ho esaurito i tentativi di archiviazione if (nRetry <= 0) { String errorMessage = $"{errMsg} - Eseguiti {MaxRetry} tentativi di archiviazione senza successo."; if (pecMail != null && pecMail.Id > 0) { String errorResult = $"La PEC {pecMail.Id} non è stata correttamente inserita ed è stata disattivata (isActive = 255) e dovrà essere riattivata previa verifica dell'errore. {errorMessage}"; pecMail.IsActive = ActiveType.Cast(ActiveType.PECMailActiveType.Error); try { MailStoreFacade.Factory.PECMailFacade.UpdateOnly(ref pecMail); MailStoreFacade.Factory.PECMailLogFacade.Error(ref pecMail, errorResult); if (pecMail != null && pecMail.MailBox != null && statistics != null && statistics.Keys != null && statistics.Keys.Any(f => f == pecMail.MailBox.Id)) { statistics[pecMail.MailBox.Id].PECError++; } } catch (Exception ex) { errorMessage = string.Concat(errorMessage, "\n", ex.Message); } } //throw new ApplicationException(errorMessage); } end = DateTime.Now; if (pecMail?.MailBox != null && statistics?.Keys != null && statistics.Keys.Any(f => f == pecMail.MailBox.Id)) { statistics[pecMail.MailBox.Id].ElaboratedTime = statistics[pecMail.MailBox.Id].ElaboratedTime + (TimeSpan.FromTicks(end.Ticks) - TimeSpan.FromTicks(start.Ticks)); } } catch (Exception ex_int) { if (pecMail != null && pecMail.Id > 0) { try { PECMailBox box = MailStoreFacade.Factory.PECMailboxFacade.GetById(pecMail.MailBox.Id); MailStoreFacade.Factory.PECMailboxLogFacade.InsertLog(ref box, "ERRORE - Archiviazione mail", PECMailBoxLogFacade.PecMailBoxLogType.ErrorEval); end = DateTime.Now; if (pecMail != null && pecMail.MailBox != null && statistics != null && statistics.Keys != null && statistics.Keys.Any(f => f == pecMail.MailBox.Id)) { statistics[pecMail.MailBox.Id].ElaboratedTime = statistics[pecMail.MailBox.Id].ElaboratedTime + (TimeSpan.FromTicks(end.Ticks) - TimeSpan.FromTicks(start.Ticks)); statistics[pecMail.MailBox.Id].PECError++; } } catch (Exception ex_log) { FileLogger.Error(_loggerName, string.Format("Errore in archiviazione mail {0} -> logger. Il flusso normale proseguirà con le successive mail.", filename), ex_log); _sendMessage(string.Format("Errore in archiviazione mail -> logger. Il flusso normale proseguirà con le successive mail.{0}Exception: {1}{0}Stacktrace: {2}", Environment.NewLine, ex_log.Message, _fullStacktrace(ex_log))); } } FileLogger.Error(_loggerName, string.Format("Errore in archiviazione mail {0}. Il flusso normale proseguirà con le successive mail.", filename), ex_int); _sendMessage(string.Format("Errore in archiviazione mail. Il flusso normale proseguirà con le successive mail.{0}Exception: {1}{0}Stacktrace: {2}", Environment.NewLine, ex_int.Message, _fullStacktrace(ex_int))); } } } catch (Exception ex) { FileLogger.Error(_loggerName, "Errore in archiviazione globale mail.", ex); _sendMessage(string.Format("Errore in archiviazione globale mail.{0}Exception: {1}{0}Stacktrace: {2}", Environment.NewLine, ex.Message, _fullStacktrace(ex))); } FileLogger.Info(_loggerName, "Fine archiviazione mail scaricate e processate"); return(statistics); }
public async Task ExecuteAsync(ICommandBuildPECMail command) { PECMail pecMail = new PECMail { UniqueId = Guid.NewGuid(), Direction = PECMailDirection.Outgoing, IsActive = DocSuiteWeb.Entity.PECMails.PECMailActiveType.Active, }; PECMailBuildModel pecMailBuildModel = command.ContentType.ContentTypeValue; PECMailModel pecMailModel = pecMailBuildModel.PECMail; IdWorkflowActivity = pecMailBuildModel.IdWorkflowActivity; try { if (RetryPolicyEvaluation != null && !string.IsNullOrEmpty(RetryPolicyEvaluation.ReferenceModel)) { pecMailModel = JsonConvert.DeserializeObject <PECMailModel>(RetryPolicyEvaluation.ReferenceModel, _serializerSettings); } else { RetryPolicyEvaluation = new EvaluationModel(); } #region Creazione Documeti Allegati (Attachments OPTIONAL) if (!RetryPolicyEvaluation.Steps.Any(f => f.Name == "CREATE_ATTACHMENTS") && pecMailModel.Attachments.Any()) { Archive pecMailArchive = _biblosArchives.Single(f => f.Name.Equals(pecMailModel.PECMailBox.Location.ProtocolArchive, StringComparison.InvariantCultureIgnoreCase)); _logger.WriteDebug(new LogMessage($"biblos attachment archive name is {pecMailArchive.Name}"), LogCategories); List <BiblosDS.BiblosDS.Attribute> attachmentAttributes = _biblosClient.Document.GetAttributesDefinition(pecMailArchive.Name); //CREO CATENA IDENTIFICATIVA Guid?attachmentChainId = pecMailModel.IDAttachments; if (!attachmentChainId.HasValue) { attachmentChainId = _biblosClient.Document.CreateDocumentChain(pecMailArchive.Name, new List <AttributeValue>()); pecMailModel.IDAttachments = attachmentChainId; } pecMail.IDAttachments = attachmentChainId.Value; List <AttributeValue> attachmentAttributeValues; Content documentContent; Dictionary <Guid, long> sizes = new Dictionary <Guid, long>(); foreach (DocumentModel attachment in pecMailModel.Attachments.Where(f => !f.DocumentId.HasValue && f.DocumentToStoreId.HasValue)) { attachmentAttributeValues = new List <AttributeValue>() { new AttributeValue() { Attribute = attachmentAttributes.Single(f => f.Name.Equals(AttributeHelper.AttributeName_Filename, StringComparison.InvariantCultureIgnoreCase)), Value = attachment.FileName, }, new AttributeValue() { Attribute = attachmentAttributes.Single(f => f.Name.Equals(AttributeHelper.AttributeName_Signature, StringComparison.InvariantCultureIgnoreCase)), Value = attachment.Segnature, }, }; attachment.ChainId = attachmentChainId; _logger.WriteInfo(new LogMessage($"reading document content {attachment.DocumentToStoreId} ..."), LogCategories); documentContent = RetryingPolicyAction(() => _biblosClient.Document.GetDocumentContentById(attachment.DocumentToStoreId.Value)); //CREO IL DOCUMENTO Document attachmentPECMailDocument = new Document { Archive = pecMailArchive, Content = new Content { Blob = documentContent.Blob }, Name = attachment.FileName, IsVisible = true, AttributeValues = attachmentAttributeValues }; //ASSOCIO IL DOCUMENTO ALLA SUA CATENA DI COMPETENZA attachmentPECMailDocument = _biblosClient.Document.AddDocumentToChain(attachmentPECMailDocument, attachmentChainId, ContentFormat.Binary); _logger.WriteInfo(new LogMessage($"inserted document {attachmentPECMailDocument.IdDocument} in archive {pecMailArchive.IdArchive} with size {documentContent.Blob.LongLength}"), LogCategories); attachment.DocumentId = attachmentPECMailDocument.IdDocument; sizes.Add(attachmentPECMailDocument.IdDocument, documentContent.Blob.LongLength); } //Assegno gli allegati all'entita foreach (DocumentModel attachment in pecMailModel.Attachments.Where(f => f.DocumentId.HasValue)) { PECMailAttachment pecMailAttachment = new PECMailAttachment { IDDocument = attachment.DocumentId, AttachmentName = attachment.FileName, Parent = null, IsMain = false, Size = sizes[attachment.DocumentId.Value] }; pecMail.Attachments.Add(pecMailAttachment); } RetryPolicyEvaluation.Steps.Add(new StepModel() { Name = "CREATE_ATTACHMENTS", LocalReference = JsonConvert.SerializeObject(pecMail, _serializerSettings) }); } else { StepModel pecMailStatus = RetryPolicyEvaluation.Steps.First(f => f.Name == "CREATE_ATTACHMENTS"); pecMail = JsonConvert.DeserializeObject <PECMail>(pecMailStatus.LocalReference); } #endregion #region Creazione PECMail con stato attivo if (!RetryPolicyEvaluation.Steps.Any(f => f.Name == "ENTITY")) { pecMail.InvoiceStatus = !pecMailModel.InvoiceStatus.HasValue || pecMailModel.InvoiceStatus.Value == DocSuiteWeb.Model.Entities.PECMails.InvoiceStatus.None ? default(InvoiceStatus?) : (InvoiceStatus)pecMailModel.InvoiceStatus; pecMail.MailBody = pecMailModel.MailBody; pecMail.MailPriority = pecMailModel.MailPriority.HasValue ? (PECMailPriority)pecMailModel.MailPriority.Value : PECMailPriority.Normal; pecMail.MailRecipients = pecMailModel.MailRecipients; pecMail.MailRecipientsCc = pecMailModel.MailRecipientsCc; pecMail.MailSenders = pecMailModel.MailSenders; pecMail.MailSubject = pecMailModel.MailSubject; pecMail.PECType = null; pecMail.MailType = "invio"; pecMail.SplittedFrom = 0; pecMail.ProcessStatus = 0; pecMail.MultipleType = DocSuiteWeb.Entity.PECMails.PECMailMultipleType.NoSplit; pecMail.IsValidForInterop = false; pecMail.Location = new Location() { EntityShortId = pecMailModel.PECMailBox.Location.IdLocation.Value }; pecMail.PECMailBox = new PECMailBox() { EntityShortId = (short)pecMailModel.PECMailBox.PECMailBoxId.Value }; pecMail.IsActive = DocSuiteWeb.Entity.PECMails.PECMailActiveType.Active; WorkflowActionDocumentUnitLinkModel workflowActionDocumentUnitLinkModel = null; Protocol protocol = null; if ((workflowActionDocumentUnitLinkModel = pecMailBuildModel.WorkflowActions .OfType <WorkflowActionDocumentUnitLinkModel>() .FirstOrDefault(f => f.GetDestinationLink().Environment == (int)DocSuiteWeb.Entity.Commons.DSWEnvironmentType.PECMail)) != null && (protocol = await _webApiClient.GetProtocolAsync(workflowActionDocumentUnitLinkModel.GetReferenced().UniqueId)) != null) { pecMail.Year = protocol.Year; pecMail.Number = protocol.Number; pecMail.DocumentUnit = new DocSuiteWeb.Entity.DocumentUnits.DocumentUnit() { UniqueId = protocol.UniqueId }; pecMail.RecordedInDocSuite = null; } pecMail.WorkflowName = pecMailBuildModel.WorkflowName; pecMail.IdWorkflowActivity = pecMailBuildModel.IdWorkflowActivity; pecMail.WorkflowAutoComplete = pecMailBuildModel.WorkflowAutoComplete; foreach (IWorkflowAction workflowAction in pecMailBuildModel.WorkflowActions) { pecMail.WorkflowActions.Add(workflowAction); } pecMail = await _webApiClient.PostEntityAsync(pecMail); } else { StepModel pecMailStatus = RetryPolicyEvaluation.Steps.First(f => f.Name == "ENTITY"); pecMail = JsonConvert.DeserializeObject <PECMail>(pecMailStatus.LocalReference); } #endregion #region [ EventCompletePECMailBuild ] pecMailBuildModel.PECMail = pecMailModel; IEventCompletePECMailBuild eventCompletePECMailBuild = new EventCompletePECMailBuild(Guid.NewGuid(), pecMailBuildModel.UniqueId, command.TenantName, command.TenantId, command.TenantAOOId, command.Identity, pecMailBuildModel, null); if (!await _webApiClient.PushEventAsync(eventCompletePECMailBuild)) { _logger.WriteError(new LogMessage($"EventCompletePECMailBuild {pecMail.EntityId} has not been sended"), LogCategories); throw new Exception("IEventCompletePECMailBuild not sended"); } _logger.WriteInfo(new LogMessage($"IEventCompletePECMailBuild {eventCompletePECMailBuild.Id} has been sended"), LogCategories); #endregion #region Detach documenti archivio workflow foreach (DocumentModel attachment in pecMailModel.Attachments.Where(f => f.DocumentToStoreId.HasValue)) { _logger.WriteInfo(new LogMessage($"detaching workflow document {attachment.DocumentToStoreId} ..."), LogCategories); RetryingPolicyAction(() => _biblosClient.Document.DocumentDetach(new Document() { IdDocument = attachment.DocumentToStoreId.Value })); } #endregion } catch (Exception ex) { RetryPolicyEvaluation.ReferenceModel = JsonConvert.SerializeObject(pecMailModel, _serializerSettings); _logger.WriteError(ex, LogCategories); throw new ServiceBusEvaluationException(RetryPolicyEvaluation); } }
/// <summary> /// Pulizia dei file generati nel drop folder per consentire l'elaborazione del contenuto della mail e l'archiviazione della stessa /// Inoltre si occupa di spostare le mail con errori e quelle invece archiviate con successo /// Se richiesto elimina la mail dal server e crea un backup su file system /// </summary> /// <param name="dumpFolder"></param> public SortedList <short, StatisticLog> ReleaseFiles(string dumpFolder, SortedList <short, StatisticLog> statistics, Dictionary <short, string> passwordBoxes) { FileLogger.Info(_loggerName, "Avvio pulizia file temporanei e mail archiviate"); try { String[] files = MailInfo.GetInfoFiles(_parameters.DropFolder); MailInfo mailInfo = null; DateTime start, end; //rimuove o sposta le mail processate foreach (String filename in files) { try { mailInfo = null; start = DateTime.Now; if (_cancelRequest()) { FileLogger.Info(_loggerName, "Chiusura modulo invocata dall'utente."); return(statistics); } mailInfo = MailInfo.Load(filename); PECMailBox box = _storeFacade.GetMailBox(mailInfo.IDPECMailBox); ImapClient imapClient = new ImapClient(CreateImapParams(box, passwordBoxes[box.Id])); //ERRORE DI ELABORAZIONE if (mailInfo.HasError()) { //invia warnings PECMail pecMail = mailInfo.IDPECMail > 0 ? _storeFacade.GetMail(mailInfo.IDPECMail) : null; if (pecMail != null && pecMail.Id > 0) { IList <PECMailLog> logs = MailStoreFacade.Factory.PECMailLogFacade.GetByPec(pecMail); if (logs.Count > 0) { foreach (PECMailLog pecMailLog in logs.Where(pecMailLog => pecMailLog.Type == PECMailLogType.Warning.ToString() || pecMailLog.Type == PECMailLogType.Error.ToString())) { _sendMessage(string.Format("PEC[{0}] {1}: {2}", pecMail.Id, pecMailLog.Type, pecMailLog.Description)); } } } //se indicato sposta in cartella di errore if (mailInfo.Client == MailInfo.ClientType.Imap && !string.IsNullOrEmpty(box.Configuration.MoveErrorToFolder)) { imapClient.MoveByUid(long.Parse(mailInfo.MailUID), box.Configuration.MoveErrorToFolder); FileLogger.Warn(_loggerName, string.Format("Mail Uid:{0} 'SPOSTATA SU CARTELLA:{1}' nel Server {2} [{3}]", mailInfo.MailUID, box.Configuration.MoveErrorToFolder, box.MailBoxName, box.IncomingServerName)); } //se indicato una cartella di errore sposta la mail scaricata e i relativi file if (!string.IsNullOrEmpty(_parameters.ErrorFolder)) { mailInfo.MoveFiles(_parameters.DropFolder, _parameters.ErrorFolder); } } //ELABORATA CON SUCCESSO if (mailInfo.Status == MailInfo.ProcessStatus.Archived) { // Verifico se è stata richiesta la cancellazione dal server if (box.Configuration.DeleteMailFromServer.GetValueOrDefault(false)) { //esegui backup prima della cancellazione if (!string.IsNullOrEmpty(_parameters.DumpFolder)) { BackupToFolder(mailInfo, box, dumpFolder); if (!_parameters.DebugModeEnabled) { DeleteFromServer(mailInfo, box, passwordBoxes[box.Id]); } else { FileLogger.Info(_loggerName, "Cancellazione da server non effettuata per modalità debug attiva."); } } else { throw new Exception("Impossibile effettuare il backup prima della cancellazione da server a causa della mancanza del parametro \"DumpFolder\""); } } else { //nel caso di connessione Imap if (mailInfo.Client == MailInfo.ClientType.Imap) { if (box.Configuration.MarkAsRead && !_parameters.DebugModeEnabled) { imapClient.MarkMessageSeen(long.Parse(mailInfo.MailUID)); FileLogger.Info(_loggerName, string.Format("Mail Uid:{0} 'IMPOSTATA COME LETTA' nel Server {1} [{2}]", mailInfo.MailUID, box.MailBoxName, box.IncomingServerName)); } if (!string.IsNullOrEmpty(box.Configuration.MoveToFolder) && !_parameters.DebugModeEnabled) { imapClient.MoveByUid(long.Parse(mailInfo.MailUID), box.Configuration.MoveToFolder); FileLogger.Info(_loggerName, string.Format("Mail Uid:{0} 'SPOSTATA SU CARTELLA:{1}' nel Server {2} [{3}]", mailInfo.MailUID, box.Configuration.MoveToFolder, box.MailBoxName, box.IncomingServerName)); } } } //Se tutto è andato a buon fine allora procedo a svuotare la cartella di drop FileLogger.Debug(_loggerName, "Cancellazione file elaborati in DropFolder"); mailInfo.RemoveFiles(_parameters.DropFolder); } end = DateTime.Now; if (mailInfo != null && statistics != null && statistics.Keys != null && statistics.Keys.Any(f => f == mailInfo.IDPECMailBox)) { statistics[mailInfo.IDPECMailBox].ElaboratedTime = statistics[mailInfo.IDPECMailBox].ElaboratedTime + (TimeSpan.FromTicks(end.Ticks) - TimeSpan.FromTicks(start.Ticks)); } } catch (Exception ex_int) { String pecName = filename; if (mailInfo != null) { pecName = mailInfo.Subject; try { PECMailBox box = MailStoreFacade.Factory.PECMailboxFacade.GetById(mailInfo.IDPECMailBox); MailStoreFacade.Factory.PECMailboxLogFacade.InsertLog(ref box, "ERRORE - Pulizia EML", PECMailBoxLogFacade.PecMailBoxLogType.ErrorEval); } catch (Exception) { } } FileLogger.Error(_loggerName, string.Format("Errore in pulizia file temporanei e mail archiviate della mail {0}. Il flusso normale proseguirà con le successive mail.", pecName), ex_int); _sendMessage(string.Format("Errore in pulizia file temporanei e mail archiviate della mail {0}. Il flusso normale proseguirà con le successive mail. Exception: {1} - Stacktrace: {2}", pecName, ex_int.Message, _fullStacktrace(ex_int))); } } } catch (Exception ex) { FileLogger.Error(_loggerName, "Errore pulizia file temporanei e mail archiviate.", ex); _sendMessage(string.Format("Errore pulizia file temporanei e mail archiviate.{0}Exception: {1}{0}Stacktrace: {2}", Environment.NewLine, ex.Message, _fullStacktrace(ex))); } FileLogger.Info(_loggerName, "Fine pulizia file temporanei e mail archiviate"); return(statistics); }