Jobs/ZUGFeRD: Handle Errors while moving files, send mail when unhandled exceptions occur.

This commit is contained in:
Jonathan Jenne 2021-05-10 14:30:05 +02:00
parent 2ae4c9a555
commit 0771d5af28
4 changed files with 96 additions and 40 deletions

View File

@ -1,5 +1,5 @@
Public Class EmailData Public Class EmailData
Public Attachment As String Public Attachment As String = ""
Public Subject As String Public Subject As String
Public From As String Public From As String
End Class End Class

View File

@ -27,7 +27,7 @@ Public Class EmailFunctions
Dim oJobId = RandomValue(1, 10000) Dim oJobId = RandomValue(1, 10000)
Dim oReference = MessageId Dim oReference = MessageId
Dim oEmailTo = "" Dim oEmailTo = ""
Dim oSubject = EmailStrings.EMAIL_SUBJECT Dim oSubject = EmailStrings.EMAIL_SUBJECT_REJECTED
Dim oAccountId = 1 Dim oAccountId = 1
Dim oCreatedWho = "ZUGFeRD Service" Dim oCreatedWho = "ZUGFeRD Service"
Dim oFinalBodyText = String.Format(EmailStrings.EMAIL_WRAPPING_TEXT, BodyText) Dim oFinalBodyText = String.Format(EmailStrings.EMAIL_WRAPPING_TEXT, BodyText)
@ -63,7 +63,7 @@ Public Class EmailFunctions
_logger.Error(ex) _logger.Error(ex)
End Try End Try
End Sub End Sub
Public Sub AddToEmailQueueMSSQL(MessageId As String, BodyText As String, pEmailData As EmailData, SourceProcedure As String, pEmailAccountId As Integer, Transaction As SqlTransaction) Public Sub AddToEmailQueueMSSQL(MessageId As String, BodyText As String, pEmailData As EmailData, SourceProcedure As String, pEmailAccountId As Integer)
If pEmailData Is Nothing Then If pEmailData Is Nothing Then
_logger.Warn("EmailData is empty. Email will not be sent!") _logger.Warn("EmailData is empty. Email will not be sent!")
Exit Sub Exit Sub
@ -73,7 +73,7 @@ Public Class EmailFunctions
Dim oJobId = RandomValue(1, 10000) Dim oJobId = RandomValue(1, 10000)
Dim oReference = MessageId Dim oReference = MessageId
Dim oEmailTo = "" Dim oEmailTo = ""
Dim oSubject = EmailStrings.EMAIL_SUBJECT Dim oSubject = EmailStrings.EMAIL_SUBJECT_REJECTED
Dim oCreatedWho = "ZUGFeRD Service" Dim oCreatedWho = "ZUGFeRD Service"
Dim oFinalBodyText = String.Format(EmailStrings.EMAIL_WRAPPING_TEXT, BodyText) Dim oFinalBodyText = String.Format(EmailStrings.EMAIL_WRAPPING_TEXT, BodyText)
@ -98,7 +98,7 @@ Public Class EmailFunctions
_logger.Debug("Subject: {0}", oSubject) _logger.Debug("Subject: {0}", oSubject)
_logger.Debug("Body {0}", oFinalBodyText) _logger.Debug("Body {0}", oFinalBodyText)
Dim osql = $"Select MAX(GUID) FROM TBEMLP_HISTORY WHERE EMAIL_MSGID = '{MessageId}'" Dim osql = $"Select MAX(GUID) FROM TBEMLP_HISTORY WHERE EMAIL_MSGID = '{MessageId}'"
Dim oHistoryID = _mssql.GetScalarValue(osql, Transaction) Dim oHistoryID = _mssql.GetScalarValue(osql)
'osql = $"select * from TBEMLP_EMAIL_OUT where REFERENCE_ID = {oHistoryID} and EMAIL_ADRESS = '{oEmailTo}' and EMAIL_SUBJ = '{oSubject}'" 'osql = $"select * from TBEMLP_EMAIL_OUT where REFERENCE_ID = {oHistoryID} and EMAIL_ADRESS = '{oEmailTo}' and EMAIL_SUBJ = '{oSubject}'"
@ -129,7 +129,7 @@ Public Class EmailFunctions
,'{SourceProcedure}' ,'{SourceProcedure}'
,'{oCreatedWho}' ,'{oCreatedWho}'
,'{oAttachment}')" ,'{oAttachment}')"
_mssql.ExecuteNonQuery(oInsert, Transaction) _mssql.ExecuteNonQuery(oInsert)
Else Else
'If oDTResult.Rows.Count = 0 Then 'If oDTResult.Rows.Count = 0 Then
' _logger.Debug("Email has already been sent!!") ' _logger.Debug("Email has already been sent!!")

View File

@ -1,14 +1,28 @@
Public Class EmailStrings Public Class EmailStrings
Public Const EMAIL_WRAPPING_TEXT = "<html><body style=''font-family:""Arial"";font-size:10.0pt''>Sehr geehrte Damen und Herren,<br> Public Const EMAIL_WRAPPING_TEXT = "<html><body style=''font-family:""Arial"";font-size:10.0pt''>Sehr geehrte Damen und Herren,<br>
das WISAG-Portal zur Verarbeitung der Eingangsrechnungen im ZUGFeRD-Format konnte die von Ihnen gesandte Rechnung das WISAG-Portal zur Verarbeitung der Eingangsrechnungen im ZUGFeRD-Format konnte die von Ihnen gesandte Rechnung
leider nicht verarbeiten! <br><br> Grund: {0}<p>Bitte prüfen Sie die Datei und nehmen Sie bei Bedarf mit uns Kontakt auf.<p> leider nicht verarbeiten! <br><br> Grund: {0}<p>Bitte prüfen Sie die Datei und nehmen Sie bei Bedarf mit uns Kontakt auf.<p>
Vielen Dank für Ihr Verständnis.<br>Mit freundlichen Grüßen<br>Ihre IT-Abteilung</body></html>" Vielen Dank für Ihr Verständnis.<br>Mit freundlichen Grüßen<br>Ihre IT-Abteilung</body></html>"
Public Const EMAIL_SUBJECT = "WISAG ZUGFeRD Portal: Beleg abgelehnt"
Public Const EMAIL_SUBJECT_REJECTED = "WISAG ZUGFeRD Portal: Beleg abgelehnt"
Public Const EMAIL_SUBJECT_EXCEPTION = "WISAG ZUGFeRD Portal: Unbehandelte Ausnahme"
Public Const EMAIL_UNHANDLED_EXCEPTION = """
<p>Beim Verarbeiten der Datei mit der Message ID '{0}' ist ein schwerer Fehler aufgetreten.</p>
<p>Fehlerbeschreibung: {1}</p>
<pre>{2}</pre>
"""
Public Const EMAIL_MISSINGPROPERTIES_1 = "<p>Die angehängte Datei entspricht nicht dem WISAG ZUGFeRD-Format: {0}</p>" Public Const EMAIL_MISSINGPROPERTIES_1 = "<p>Die angehängte Datei entspricht nicht dem WISAG ZUGFeRD-Format: {0}</p>"
Public Const EMAIL_MISSINGPROPERTIES_2 = "<p>Die folgenden Eigenschaften wurden als ERFORDERLICH eingestuft, wurden aber nicht gefunden:<p/>" Public Const EMAIL_MISSINGPROPERTIES_2 = "<p>Die folgenden Eigenschaften wurden als ERFORDERLICH eingestuft, wurden aber nicht gefunden:<p/>"
Public Const EMAIL_MD5_ERROR = "<p>Die von Ihnen gesendete Rechnung wurde bereits von unserem System verarbeitet.</p>" Public Const EMAIL_MD5_ERROR = "<p>Die von Ihnen gesendete Rechnung wurde bereits von unserem System verarbeitet.</p>"
Public Const EMAIL_TOO_MUCH_FERDS = "<p>Ihre Email enthielt mehr als ein ZUGFeRD-Dokument.</p>" Public Const EMAIL_TOO_MUCH_FERDS = "<p>Ihre Email enthielt mehr als ein ZUGFeRD-Dokument.</p>"
Public Const EMAIL_NO_FERDS = "<p>Ihre Email enthielt keine ZUGFeRD-Dokumente.</p>" Public Const EMAIL_NO_FERDS = "<p>Ihre Email enthielt keine ZUGFeRD-Dokumente.</p>"
Public Const EMAIL_INVALID_DOCUMENT = """ Public Const EMAIL_INVALID_DOCUMENT = """
<p>Ihre Email enthielt ein ZUGFeRD Dokument, welches aber inkorrekt formatiert wurde.</p> <p>Ihre Email enthielt ein ZUGFeRD Dokument, welches aber inkorrekt formatiert wurde.</p>
<p>Mögliche Gründe für ein inkorrektes Format:<ul> <p>Mögliche Gründe für ein inkorrektes Format:<ul>

View File

@ -24,6 +24,8 @@ Public Class ImportZUGFeRDFiles
Private Const DIRECTORY_DONT_MOVE = "DIRECTORY_DONT_MOVE" Private Const DIRECTORY_DONT_MOVE = "DIRECTORY_DONT_MOVE"
Private Const EXCEPTION_MAIL_ADDRESS = "info-flow@digitaldata.works"
' List of allowed extensions for PDF/A Attachments ' List of allowed extensions for PDF/A Attachments
' This list should not contain xml so the zugferd xml file will be filtered out ' This list should not contain xml so the zugferd xml file will be filtered out
Private ReadOnly AllowedExtensions As List(Of String) = New List(Of String) From {"docx", "doc", "pdf", "xls", "xlsx", "ppt", "pptx", "txt"} Private ReadOnly AllowedExtensions As List(Of String) = New List(Of String) From {"docx", "doc", "pdf", "xls", "xlsx", "ppt", "pptx", "txt"}
@ -159,7 +161,12 @@ Public Class ImportZUGFeRDFiles
Dim oFBTransaction As FbTransaction = oFBConnection.BeginTransaction() Dim oFBTransaction As FbTransaction = oFBConnection.BeginTransaction()
Dim oSQLConnection As SqlConnection = _mssql.GetConnection() Dim oSQLConnection As SqlConnection = _mssql.GetConnection()
Dim oSQLTransaction As SqlTransaction = oSQLConnection.BeginTransaction() Dim oSQLTransaction As SqlTransaction = oSQLConnection?.BeginTransaction()
If oSQLConnection Is Nothing Then
_logger.Warn("SQL Connection was not set. No INSERTs for MSSQL Server will be performed!")
oArgs.InsertIntoSQLServer = False
End If
' Count the amount of ZUGFeRD files ' Count the amount of ZUGFeRD files
Dim oZUGFeRDCount As Integer = 0 Dim oZUGFeRDCount As Integer = 0
@ -352,7 +359,7 @@ Public Class ImportZUGFeRDFiles
Dim oBody = EmailStrings.EMAIL_MD5_ERROR Dim oBody = EmailStrings.EMAIL_MD5_ERROR
Dim oEmailData = MoveAndRenameEmailToRejected(oArgs, oMessageId) Dim oEmailData = MoveAndRenameEmailToRejected(oArgs, oMessageId)
_email.AddToEmailQueueMSSQL(oMessageId, oBody, oEmailData, "MD5HashException", _EmailOutAccountId, oSQLTransaction) _email.AddToEmailQueueMSSQL(oMessageId, oBody, oEmailData, "MD5HashException", _EmailOutAccountId)
AddRejectedState(oMessageId, "MD5HashException", "Die gesendete Rechnung wurde bereits verarbeitet!", "", oSQLTransaction) AddRejectedState(oMessageId, "MD5HashException", "Die gesendete Rechnung wurde bereits verarbeitet!", "", oSQLTransaction)
Catch ex As InvalidFerdException Catch ex As InvalidFerdException
@ -364,7 +371,7 @@ Public Class ImportZUGFeRDFiles
Dim oBody = EmailStrings.EMAIL_INVALID_DOCUMENT Dim oBody = EmailStrings.EMAIL_INVALID_DOCUMENT
Dim oEmailData = MoveAndRenameEmailToRejected(oArgs, oMessageId) Dim oEmailData = MoveAndRenameEmailToRejected(oArgs, oMessageId)
_email.AddToEmailQueueMSSQL(oMessageId, oBody, oEmailData, "InvalidFerdException", _EmailOutAccountId, oSQLTransaction) _email.AddToEmailQueueMSSQL(oMessageId, oBody, oEmailData, "InvalidFerdException", _EmailOutAccountId)
AddRejectedState(oMessageId, "InvalidFerdException", "Inkorrekte Formate", "", oSQLTransaction) AddRejectedState(oMessageId, "InvalidFerdException", "Inkorrekte Formate", "", oSQLTransaction)
Catch ex As TooMuchFerdsException Catch ex As TooMuchFerdsException
@ -376,7 +383,7 @@ Public Class ImportZUGFeRDFiles
Dim oBody = EmailStrings.EMAIL_TOO_MUCH_FERDS Dim oBody = EmailStrings.EMAIL_TOO_MUCH_FERDS
Dim oEmailData = MoveAndRenameEmailToRejected(oArgs, oMessageId) Dim oEmailData = MoveAndRenameEmailToRejected(oArgs, oMessageId)
_email.AddToEmailQueueMSSQL(oMessageId, oBody, oEmailData, "TooMuchFerdsException", _EmailOutAccountId, oSQLTransaction) _email.AddToEmailQueueMSSQL(oMessageId, oBody, oEmailData, "TooMuchFerdsException", _EmailOutAccountId)
AddRejectedState(oMessageId, "TooMuchFerdsException", "Email enthielt mehr als ein ZUGFeRD-Dokument", "", oSQLTransaction) AddRejectedState(oMessageId, "TooMuchFerdsException", "Email enthielt mehr als ein ZUGFeRD-Dokument", "", oSQLTransaction)
Catch ex As NoFerdsException Catch ex As NoFerdsException
@ -388,7 +395,7 @@ Public Class ImportZUGFeRDFiles
Dim oBody = EmailStrings.EMAIL_NO_FERDS Dim oBody = EmailStrings.EMAIL_NO_FERDS
Dim oEmailData = MoveAndRenameEmailToRejected(oArgs, oMessageId) Dim oEmailData = MoveAndRenameEmailToRejected(oArgs, oMessageId)
_email.AddToEmailQueueMSSQL(oMessageId, oBody, oEmailData, "NoFerdsException", _EmailOutAccountId, oSQLTransaction) _email.AddToEmailQueueMSSQL(oMessageId, oBody, oEmailData, "NoFerdsException", _EmailOutAccountId)
AddRejectedState(oMessageId, "NoFerdsException", " Email enthielt keine ZUGFeRD-Dokumente", "", oSQLTransaction) AddRejectedState(oMessageId, "NoFerdsException", " Email enthielt keine ZUGFeRD-Dokumente", "", oSQLTransaction)
Catch ex As MissingValueException Catch ex As MissingValueException
@ -404,13 +411,21 @@ Public Class ImportZUGFeRDFiles
Dim oBody = CreateBodyForMissingProperties(ex.File.Name, oMissingProperties) Dim oBody = CreateBodyForMissingProperties(ex.File.Name, oMissingProperties)
Dim oEmailData = MoveAndRenameEmailToRejected(oArgs, oMessageId) Dim oEmailData = MoveAndRenameEmailToRejected(oArgs, oMessageId)
_email.AddToEmailQueueMSSQL(oMessageId, oBody, oEmailData, "MissingValueException", _EmailOutAccountId, oSQLTransaction) _email.AddToEmailQueueMSSQL(oMessageId, oBody, oEmailData, "MissingValueException", _EmailOutAccountId)
AddRejectedState(oMessageId, "MissingValueException", "Es fehlten ZugferdSpezifikationen", oMessage, oSQLTransaction) AddRejectedState(oMessageId, "MissingValueException", "Es fehlten ZugferdSpezifikationen", oMessage, oSQLTransaction)
Catch ex As OutOfMemoryException Catch ex As OutOfMemoryException
_logger.Warn("OutOfMemory Error occurred: {0}", ex.Message) _logger.Warn("OutOfMemory Error occurred: {0}", ex.Message)
_logger.Error(ex) _logger.Error(ex)
' Send Email to Digital Data
Dim oBody = CreateBodyForUnhandledException(oMessageId, ex)
Dim oEmailData As New EmailData With {
.From = EXCEPTION_MAIL_ADDRESS,
.Subject = $"OutOfMemoryException im ZUGFeRD-Parser @ {oMessageId}"
}
_email.AddToEmailQueueMSSQL(oMessageId, oBody, oEmailData, "OutOfMemoryException", _EmailOutAccountId)
' Rollback Firebird ' Rollback Firebird
oFBTransaction.Rollback() oFBTransaction.Rollback()
@ -423,6 +438,14 @@ Public Class ImportZUGFeRDFiles
_logger.Warn("Unknown Error occurred: {0}", ex.Message) _logger.Warn("Unknown Error occurred: {0}", ex.Message)
_logger.Error(ex) _logger.Error(ex)
' Send Email to Digital Data
Dim oBody = CreateBodyForUnhandledException(oMessageId, ex)
Dim oEmailData As New EmailData With {
.From = EXCEPTION_MAIL_ADDRESS,
.Subject = $"UnhandledException im ZUGFeRD-Parser @ {oMessageId}"
}
_email.AddToEmailQueueMSSQL(oMessageId, oBody, oEmailData, "UnhandledException", _EmailOutAccountId)
' Rollback Firebird ' Rollback Firebird
oFBTransaction.Rollback() oFBTransaction.Rollback()
@ -432,6 +455,31 @@ Public Class ImportZUGFeRDFiles
oMoveDirectory = DIRECTORY_DONT_MOVE oMoveDirectory = DIRECTORY_DONT_MOVE
Finally Finally
Try
' If an application error occurred, dont move files so they will be processed again later
If oMoveDirectory = DIRECTORY_DONT_MOVE Then
_logger.Info("Application Error occurred. Files for message Id {0} will not be moved.", oMessageId)
Else
' Move all files of the current group
MoveFiles(oArgs, oMessageId, oFileGroupFiles, oEmailAttachmentFiles, oEmbeddedAttachmentFiles, oMoveDirectory, oIsSuccess)
End If
_logger.Info("Finished processing file group {0}", oMessageId)
Catch ex As Exception
' Send Email to Digital Data
Dim oBody = CreateBodyForUnhandledException(oMessageId, ex)
Dim oEmailData As New EmailData With {
.From = EXCEPTION_MAIL_ADDRESS,
.Subject = $"FileMoveException im ZUGFeRD-Parser @ {oMessageId}"
}
_email.AddToEmailQueueMSSQL(oMessageId, oBody, oEmailData, "FileMoveException", _EmailOutAccountId)
_logger.Warn("Could not move files!")
_logger.Error(ex)
Throw ex
Finally
_logger.EndBlock()
End Try
Try Try
' If everything went OK, finally commit all changes to the Database ' If everything went OK, finally commit all changes to the Database
' ================================================================== ' ==================================================================
@ -454,23 +502,6 @@ Public Class ImportZUGFeRDFiles
_logger.Error(ex) _logger.Error(ex)
_logger.Warn("Database Connections were not closed successfully.") _logger.Warn("Database Connections were not closed successfully.")
End Try End Try
Try
' If an application error occurred, dont move files so they will be processed again later
If oMoveDirectory = DIRECTORY_DONT_MOVE Then
_logger.Info("Application Error occurred. Files for message Id {0} will not be moved.", oMessageId)
Else
' Move all files of the current group
MoveFiles(oArgs, oMessageId, oFileGroupFiles, oEmailAttachmentFiles, oEmbeddedAttachmentFiles, oMoveDirectory, oIsSuccess)
End If
_logger.Info("Finished processing file group {0}", oMessageId)
Catch ex As Exception
_logger.Warn("Could not move files!")
_logger.Error(ex)
Throw ex
Finally
_logger.EndBlock()
End Try
End Try End Try
Next Next
End If End If
@ -524,12 +555,11 @@ Public Class ImportZUGFeRDFiles
' Move PDF/A Files ' Move PDF/A Files
For Each oFile In oInvoiceFiles For Each oFile In oInvoiceFiles
Try Try
Dim oFileName = _filesystem.GetVersionedFilename(Path.Combine(oFinalMoveDirectory, oFile.Name)) Dim oFilePath = _filesystem.GetVersionedFilename(Path.Combine(oFinalMoveDirectory, oFile.Name))
_filesystem.MoveTo(oFile.FullName, oFileName, oFinalMoveDirectory) _filesystem.MoveTo(oFile.FullName, oFilePath, oFinalMoveDirectory)
_logger.Info("Finished processing file {0}", oFile.Name) _logger.Info("File moved to {0}", oFilePath)
_logger.Info("File moved to {0}", oFileName)
Catch ex As Exception Catch ex As Exception
_logger.Warn("Could not move file {0}", oFile.FullName) _logger.Warn("Could not move file {0}", oFile.FullName)
_logger.Error(ex) _logger.Error(ex)
@ -539,12 +569,10 @@ Public Class ImportZUGFeRDFiles
' Move non-PDF/A Email Attachments/Files ' Move non-PDF/A Email Attachments/Files
For Each oFile In AttachmentFiles For Each oFile In AttachmentFiles
Try Try
Dim oFileName = _filesystem.GetVersionedFilename(Path.Combine(oAttachmentDirectory, oFile.Name)) Dim oFilePath = _filesystem.GetVersionedFilename(Path.Combine(oAttachmentDirectory, oFile.Name))
_filesystem.MoveTo(oFile.FullName, oFileName, oAttachmentDirectory) _filesystem.MoveTo(oFile.FullName, oFilePath, oAttachmentDirectory)
_logger.Info("Attachment moved to {0}", oFilePath)
_logger.Info("Finished processing file {0}", oFile.Name)
_logger.Info("Attachment moved to {0}", oFileName)
Catch ex As Exception Catch ex As Exception
_logger.Warn("Could not move attachment {0}", oFile.FullName) _logger.Warn("Could not move attachment {0}", oFile.FullName)
_logger.Error(ex) _logger.Error(ex)
@ -557,18 +585,25 @@ Public Class ImportZUGFeRDFiles
Dim oFileName As String = $"{MessageId}~{oResult.FileName}" Dim oFileName As String = $"{MessageId}~{oResult.FileName}"
Dim oFilePath As String = Path.Combine(oAttachmentDirectory, oFileName) Dim oFilePath As String = Path.Combine(oAttachmentDirectory, oFileName)
If Not File.Exists(oAttachmentDirectory) Then
Directory.CreateDirectory(oAttachmentDirectory)
End If
Using oWriter As New FileStream(oFilePath, FileMode.Create) Using oWriter As New FileStream(oFilePath, FileMode.Create)
oWriter.Write(oResult.FileContents, 0, oResult.FileContents.Length) oWriter.Write(oResult.FileContents, 0, oResult.FileContents.Length)
_logger.Info("Embedded Attachment moved to {0}", oFilePath)
End Using End Using
Catch ex As Exception Catch ex As Exception
_logger.Warn("Could not save embedded attachment {0}", oResult.FileName) _logger.Warn("Could not save embedded attachment {0}", oResult.FileName)
_logger.Error(ex) _logger.Error(ex)
End Try End Try
Next Next
_logger.Info("Finished moving files")
End Sub End Sub
Private Function CreateBodyForMissingProperties(OriginalFilename As String, MissingProperties As List(Of String)) Private Function CreateBodyForMissingProperties(OriginalFilename As String, MissingProperties As List(Of String)) As String
Dim oBody = String.Format(EmailStrings.EMAIL_MISSINGPROPERTIES_1, OriginalFilename) Dim oBody = String.Format(EmailStrings.EMAIL_MISSINGPROPERTIES_1, OriginalFilename)
If MissingProperties.Count > 0 Then If MissingProperties.Count > 0 Then
@ -583,6 +618,13 @@ Public Class ImportZUGFeRDFiles
Return oBody Return oBody
End Function End Function
Private Function CreateBodyForUnhandledException(MessageId As String, Exception As Exception) As String
Dim oBody = String.Format(EmailStrings.EMAIL_UNHANDLED_EXCEPTION, MessageId, Exception.Message, Exception.StackTrace)
Return oBody
End Function
Private Function CreateMD5(ByVal Filename As String) As String Private Function CreateMD5(ByVal Filename As String) As String
Try Try
Dim oMD5 As New MD5CryptoServiceProvider Dim oMD5 As New MD5CryptoServiceProvider