Imports System.Collections.Generic Imports System.IO Imports System.Linq Imports DigitalData.Modules.Base Imports DigitalData.Modules.Database Imports DigitalData.Modules.Interfaces Imports DigitalData.Modules.Logging Namespace ZUGFeRD Public Class FileFunctions Private ReadOnly _logConfig As LogConfig Private ReadOnly _logger As Logger Private ReadOnly _filesystem As FilesystemEx Private ReadOnly _email As ZUGFeRD.EmailFunctions Public Sub New(pLogConfig As LogConfig, pMSSQL As MSSQLServer) _logConfig = pLogConfig _logger = _logConfig.GetLogger() _email = New EmailFunctions(pLogConfig, pMSSQL) _filesystem = New FilesystemEx(pLogConfig) End Sub Public Function CheckFileAge(oFiles As List(Of FileInfo), pMinFileAge As Integer) Return oFiles.Where(Function(f) Now.Subtract(f.CreationTime).Minutes < pMinFileAge).Any() End Function Public Sub MoveFiles( pArgs As WorkerArgs, pMessageId As String, pFiles As List(Of FileInfo), pAttachmentFiles As List(Of FileInfo), pEmbeddedAttachments As List(Of PDFEmbeds.EmbeddedFile), pMoveDirectory As String, pIsSuccess As Boolean) Dim oFinalMoveDirectory As String = pMoveDirectory Dim oDateSubDirectoryName As String = Now.ToString("yyyy\\MM\\dd") Dim oAttachmentDirectory As String = Path.Combine(oFinalMoveDirectory, pArgs.AttachmentsSubDirectory, oDateSubDirectoryName) ' Files will be moved to a subfolder for the current day if they are rejected If Not pIsSuccess Then oFinalMoveDirectory = Path.Combine(oFinalMoveDirectory, oDateSubDirectoryName) End If ' Create directories if they don't exist If Not Directory.Exists(oFinalMoveDirectory) Then Try Directory.CreateDirectory(oFinalMoveDirectory) Catch ex As Exception _logger.Error(ex) End Try End If If Not Directory.Exists(oAttachmentDirectory) And pAttachmentFiles.Count > 0 Then Try Directory.CreateDirectory(oAttachmentDirectory) Catch ex As Exception _logger.Error(ex) End Try End If ' Filter out Attachments from `Files` Dim oInvoiceFiles As List(Of FileInfo) = pFiles.Except(pAttachmentFiles).ToList() ' Move PDF/A Files For Each oFile In oInvoiceFiles Try Dim oFilePath = _filesystem.GetVersionedFilename(Path.Combine(oFinalMoveDirectory, oFile.Name)) _filesystem.MoveTo(oFile.FullName, oFilePath, oFinalMoveDirectory) _logger.Info("File moved to {0}", oFilePath) Catch ex As Exception _logger.Warn("Could not move file {0}", oFile.FullName) _logger.Error(ex) End Try Next ' Move non-PDF/A Email Attachments/Files For Each oFile In pAttachmentFiles Try Dim oFilePath = _filesystem.GetVersionedFilename(Path.Combine(oAttachmentDirectory, oFile.Name)) _filesystem.MoveTo(oFile.FullName, oFilePath, oAttachmentDirectory) _logger.Info("Attachment moved to {0}", oFilePath) Catch ex As Exception _logger.Warn("Could not move attachment {0}", oFile.FullName) _logger.Error(ex) End Try Next ' Write Embedded Files to disk For Each oResult In pEmbeddedAttachments Try Dim oFileName As String = $"{pMessageId}~{oResult.FileName}" Dim oFilePath As String = Path.Combine(oAttachmentDirectory, oFileName) If Not File.Exists(oAttachmentDirectory) Then Directory.CreateDirectory(oAttachmentDirectory) End If System.IO.File.WriteAllBytes(oFilePath, oResult.FileContents) If CheckBytes(oFilePath, oResult.FileContents) = True Then If FileOpenwithError(oFilePath) Then _logger.Info("Embedded Attachment moved to {0}", oFilePath) Else _logger.Info("File is corrupt. Deleting the created file ...") File.Delete(oFilePath) End If Else _logger.Info("File is corrupt (CheckBytes). Deleting the created file ...") File.Delete(oFilePath) End If 'Using oWriter As New FileStream(oFilePath, FileMode.Create) ' oWriter.Write(oResult.FileContents, 0, oResult.FileContents.Length) 'End Using Catch ex As Exception _logger.Warn("Could not save embedded attachment {0}", oResult.FileName) _logger.Error(ex) End Try Next _logger.Info("Finished moving files") End Sub Private Function CheckBytes(oFilePath As String, oFileContents As IEnumerable(Of Byte)) As Boolean Dim savedBytes() As Byte = System.IO.File.ReadAllBytes(oFilePath) If savedBytes.SequenceEqual(oFileContents) Then Return True Else Return False End If End Function Public Function MoveAndRenameEmailToRejected(pArgs As WorkerArgs, pMessageId As String) As EmailData _logger.Info("Moving Mail with MessageId [{0}] to Rejected folder", pMessageId) _logger.Debug("Fetching Email Data") Dim oEmailData = _email.GetEmailDataForMessageId(pMessageId) _logger.Debug("Email Data fetched!") Dim oSource = _email.GetOriginalEmailPath(pArgs.OriginalEmailDirectory, pMessageId) _logger.Debug("Original email path: [{0}]", oSource) If oSource = String.Empty Then _logger.Warn("Original Email for [{0}] could not be found. Exiting.", pMessageId) Return New EmailData() End If Dim oDateSubDirectoryName As String = Now.ToString("yyyy-MM-dd") Dim oDestination As String Dim oRejectedDirectory As String = Path.Combine(pArgs.RejectedEmailDirectory, oDateSubDirectoryName) ' Create the destination directory if it does not exist _logger.Debug("Creating destination directory [{0}]", oRejectedDirectory) If Not Directory.Exists(oRejectedDirectory) Then Try Directory.CreateDirectory(oRejectedDirectory) Catch ex As Exception _logger.Error(ex) End Try End If ' If oEmailData is Nothing, TBEDM_EMAIL_PROFILER_HISTORY for MessageId was not found. ' This only should happen when testing and db-tables are deleted frequently If oEmailData Is Nothing Then oDestination = GetEmailPathWithSubjectAsName(oRejectedDirectory, pMessageId) Else oDestination = GetEmailPathWithSubjectAsName(oRejectedDirectory, StringEx.ConvertTextToSlug(oEmailData.Subject)) End If _logger.Debug("Destination for eml file is {0}", oDestination) Dim oFinalFileName = _filesystem.GetVersionedFilename(oDestination) _logger.Debug("Versioned filename for eml file is {0}", oFinalFileName) If oEmailData Is Nothing Then _logger.Warn("Could not get Email Data from Database. File {0} will not be moved!", oSource) Return New EmailData() End If '--------------------------- Try _logger.Info("Moving email from {0} to {1}", oSource, oFinalFileName) File.Move(oSource, oFinalFileName) oEmailData.Attachment = oFinalFileName Catch ex As Exception _logger.Warn("File {0} could not be moved! Original Filename will be used!", oSource) _logger.Error(ex) oEmailData.Attachment = oSource End Try _logger.Info("Email [{0}] moved to rejected folder!", pMessageId) Return oEmailData End Function Private Function FileOpenwithError(pFilePath As String) As Boolean Try Using fs As FileStream = File.Open(pFilePath, FileMode.Open, FileAccess.Read, FileShare.None) Return True ' Datei kann geöffnet werden End Using Catch ex As IOException _logger.Info("file [{0}] could not be opened! Error IOException: [{1}]", pFilePath, ex.Message) Return False ' Datei ist gesperrt oder existiert nicht Catch ex As Exception _logger.Info("file [{0}] could not be opened! Error: [{1}]", pFilePath, ex.Message) Return False ' Andere Fehler End Try End Function Public Function GetEmailPathWithSubjectAsName(RejectedEmailDirectory As String, UncleanedSubject As String) As String Dim oCleanSubject = String.Join("", UncleanedSubject.Split(Path.GetInvalidPathChars())) Dim oAttachmentDirectory = RejectedEmailDirectory Dim oAttachmentFile = oCleanSubject & ".eml" _logger.Debug("Email Filename is [{0}]", oAttachmentFile) Dim oAttachmentPath = Path.Combine(oAttachmentDirectory, oAttachmentFile) Return oAttachmentPath End Function End Class End Namespace