diff --git a/Config/Config.vbproj b/Config/Config.vbproj index 46911980..9739d4f1 100644 --- a/Config/Config.vbproj +++ b/Config/Config.vbproj @@ -50,10 +50,6 @@ ..\Base\bin\Debug\DigitalData.Modules.Base.dll - - False - bin\Debug\DigitalData.Modules.Config.dll - ..\Database\bin\Debug\DigitalData.Modules.Database.dll diff --git a/Interfaces/Interfaces.vbproj b/Interfaces/Interfaces.vbproj index 487a76b9..bee80b74 100644 --- a/Interfaces/Interfaces.vbproj +++ b/Interfaces/Interfaces.vbproj @@ -64,68 +64,68 @@ ..\packages\DocumentFormat.OpenXml.Framework.3.2.0\lib\net46\DocumentFormat.OpenXml.Framework.dll - - ..\packages\GdPicture.14.3.3\lib\net462\GdPicture.NET.14.dll + + ..\packages\GdPicture.14.3.18\lib\net462\GdPicture.NET.14.dll - - ..\packages\GdPicture.14.3.3\lib\net462\GdPicture.NET.14.barcode.1d.writer.dll + + ..\packages\GdPicture.14.3.18\lib\net462\GdPicture.NET.14.barcode.1d.writer.dll - - ..\packages\GdPicture.14.3.3\lib\net462\GdPicture.NET.14.barcode.2d.writer.dll + + ..\packages\GdPicture.14.3.18\lib\net462\GdPicture.NET.14.barcode.2d.writer.dll - - ..\packages\GdPicture.14.3.3\lib\net462\GdPicture.NET.14.CAD.dll + + ..\packages\GdPicture.14.3.18\lib\net462\GdPicture.NET.14.CAD.dll - - ..\packages\GdPicture.14.3.3\lib\net462\GdPicture.NET.14.CAD.DWG.dll + + ..\packages\GdPicture.14.3.18\lib\net462\GdPicture.NET.14.CAD.DWG.dll - - ..\packages\GdPicture.14.3.3\lib\net462\GdPicture.NET.14.Common.dll + + ..\packages\GdPicture.14.3.18\lib\net462\GdPicture.NET.14.Common.dll - - ..\packages\GdPicture.14.3.3\lib\net462\GdPicture.NET.14.Document.dll + + ..\packages\GdPicture.14.3.18\lib\net462\GdPicture.NET.14.Document.dll - - ..\packages\GdPicture.14.3.3\lib\net462\GdPicture.NET.14.Email.dll + + ..\packages\GdPicture.14.3.18\lib\net462\GdPicture.NET.14.Email.dll - - ..\packages\GdPicture.14.3.3\lib\net462\GdPicture.NET.14.HTML.dll + + ..\packages\GdPicture.14.3.18\lib\net462\GdPicture.NET.14.HTML.dll - - ..\packages\GdPicture.14.3.3\lib\net462\GdPicture.NET.14.Imaging.dll + + ..\packages\GdPicture.14.3.18\lib\net462\GdPicture.NET.14.Imaging.dll - - ..\packages\GdPicture.14.3.3\lib\net462\GdPicture.NET.14.Imaging.Formats.dll + + ..\packages\GdPicture.14.3.18\lib\net462\GdPicture.NET.14.Imaging.Formats.dll - - ..\packages\GdPicture.14.3.3\lib\net462\GdPicture.NET.14.Imaging.Formats.Conversion.dll + + ..\packages\GdPicture.14.3.18\lib\net462\GdPicture.NET.14.Imaging.Formats.Conversion.dll - - ..\packages\GdPicture.14.3.3\lib\net462\GdPicture.NET.14.Imaging.Rendering.dll + + ..\packages\GdPicture.14.3.18\lib\net462\GdPicture.NET.14.Imaging.Rendering.dll - - ..\packages\GdPicture.14.3.3\lib\net462\GdPicture.NET.14.MSOfficeBinary.dll + + ..\packages\GdPicture.14.3.18\lib\net462\GdPicture.NET.14.MSOfficeBinary.dll - - ..\packages\GdPicture.14.3.3\lib\net462\GdPicture.NET.14.OpenDocument.dll + + ..\packages\GdPicture.14.3.18\lib\net462\GdPicture.NET.14.OpenDocument.dll - - ..\packages\GdPicture.14.3.3\lib\net462\GdPicture.NET.14.OpenXML.dll + + ..\packages\GdPicture.14.3.18\lib\net462\GdPicture.NET.14.OpenXML.dll - - ..\packages\GdPicture.14.3.3\lib\net462\GdPicture.NET.14.OpenXML.Templating.dll + + ..\packages\GdPicture.14.3.18\lib\net462\GdPicture.NET.14.OpenXML.Templating.dll - - ..\packages\GdPicture.14.3.3\lib\net462\GdPicture.NET.14.PDF.dll + + ..\packages\GdPicture.14.3.18\lib\net462\GdPicture.NET.14.PDF.dll - - ..\packages\GdPicture.14.3.3\lib\net462\GdPicture.NET.14.RTF.dll + + ..\packages\GdPicture.14.3.18\lib\net462\GdPicture.NET.14.RTF.dll - - ..\packages\GdPicture.14.3.3\lib\net462\GdPicture.NET.14.SVG.dll + + ..\packages\GdPicture.14.3.18\lib\net462\GdPicture.NET.14.SVG.dll - ..\packages\GdPicture.14.3.3\lib\net462\GdPicture.NET.14.wia.gateway.dll + ..\packages\GdPicture.14.3.18\lib\net462\GdPicture.NET.14.wia.gateway.dll True @@ -303,11 +303,11 @@ powershell.exe -command "& { &'$(SolutionDir)copy-binary.ps1' '$(TargetPath)' '$(TargetFileName)' '$(ConfigurationName)' '$(ProjectName)' }" - + Dieses Projekt verweist auf mindestens ein NuGet-Paket, das auf diesem Computer fehlt. Verwenden Sie die Wiederherstellung von NuGet-Paketen, um die fehlenden Dateien herunterzuladen. Weitere Informationen finden Sie unter "http://go.microsoft.com/fwlink/?LinkID=322105". Die fehlende Datei ist "{0}". - + \ No newline at end of file diff --git a/Interfaces/ZUGFeRDInterface.vb b/Interfaces/ZUGFeRDInterface.vb index cdcb3eb2..b3e91f65 100644 --- a/Interfaces/ZUGFeRDInterface.vb +++ b/Interfaces/ZUGFeRDInterface.vb @@ -281,16 +281,21 @@ Public Class ZUGFeRDInterface ''' ''' ''' The embedded xml data as an XPath document - Public Function ValidateZUGFeRDFileWithGDPicture(pPath As String) As ZugferdResult + Public Function ValidateZUGFeRDFileWithGDPicture(pPath As String, Optional Validate As Boolean = False) As ZugferdResult Dim oEmbedExtractor = New PDFEmbeds(_logConfig) Try ' Extract XML attachments only! Dim oFiles = oEmbedExtractor.Extract(pPath, New List(Of String) From {"xml"}) + If Validate Then + Return _Validator.ValidateZUGFeRDDocument(HandleEmbeddedFiles(oFiles)) + Else + ' Attachments are in this case the files that are embedded into a pdf file, + ' like for example the zugferd-invoice.xml file + Return HandleEmbeddedFiles(oFiles) + End If + - ' Attachments are in this case the files that are embedded into a pdf file, - ' like for example the zugferd-invoice.xml file - Return HandleEmbeddedFiles(oFiles) Catch ex As ZUGFeRDExecption ' Don't log ZUGFeRD Exceptions here, they should be handled by the calling code. diff --git a/Interfaces/packages.config b/Interfaces/packages.config index 18dc42d5..65fdd9b8 100644 --- a/Interfaces/packages.config +++ b/Interfaces/packages.config @@ -3,8 +3,8 @@ - - + + diff --git a/Jobs/App.config b/Jobs/App.config index 6f0dcee6..c6e56df2 100644 --- a/Jobs/App.config +++ b/Jobs/App.config @@ -47,6 +47,10 @@ + + + + diff --git a/Jobs/Jobs.vbproj b/Jobs/Jobs.vbproj index 3fe8cbd1..90c9a98b 100644 --- a/Jobs/Jobs.vbproj +++ b/Jobs/Jobs.vbproj @@ -134,68 +134,68 @@ ..\packages\FirebirdSql.Data.FirebirdClient.7.5.0\lib\net452\FirebirdSql.Data.FirebirdClient.dll - - ..\packages\GdPicture.14.3.19\lib\net462\GdPicture.NET.14.dll + + ..\packages\GdPicture.14.3.18\lib\net462\GdPicture.NET.14.dll - - ..\packages\GdPicture.14.3.19\lib\net462\GdPicture.NET.14.barcode.1d.writer.dll + + ..\packages\GdPicture.14.3.18\lib\net462\GdPicture.NET.14.barcode.1d.writer.dll - - ..\packages\GdPicture.14.3.19\lib\net462\GdPicture.NET.14.barcode.2d.writer.dll + + ..\packages\GdPicture.14.3.18\lib\net462\GdPicture.NET.14.barcode.2d.writer.dll - - ..\packages\GdPicture.14.3.19\lib\net462\GdPicture.NET.14.CAD.dll + + ..\packages\GdPicture.14.3.18\lib\net462\GdPicture.NET.14.CAD.dll - - ..\packages\GdPicture.14.3.19\lib\net462\GdPicture.NET.14.CAD.DWG.dll + + ..\packages\GdPicture.14.3.18\lib\net462\GdPicture.NET.14.CAD.DWG.dll - - ..\packages\GdPicture.14.3.19\lib\net462\GdPicture.NET.14.Common.dll + + ..\packages\GdPicture.14.3.18\lib\net462\GdPicture.NET.14.Common.dll - - ..\packages\GdPicture.14.3.19\lib\net462\GdPicture.NET.14.Document.dll + + ..\packages\GdPicture.14.3.18\lib\net462\GdPicture.NET.14.Document.dll - - ..\packages\GdPicture.14.3.19\lib\net462\GdPicture.NET.14.Email.dll + + ..\packages\GdPicture.14.3.18\lib\net462\GdPicture.NET.14.Email.dll - - ..\packages\GdPicture.14.3.19\lib\net462\GdPicture.NET.14.HTML.dll + + ..\packages\GdPicture.14.3.18\lib\net462\GdPicture.NET.14.HTML.dll - - ..\packages\GdPicture.14.3.19\lib\net462\GdPicture.NET.14.Imaging.dll + + ..\packages\GdPicture.14.3.18\lib\net462\GdPicture.NET.14.Imaging.dll - - ..\packages\GdPicture.14.3.19\lib\net462\GdPicture.NET.14.Imaging.Formats.dll + + ..\packages\GdPicture.14.3.18\lib\net462\GdPicture.NET.14.Imaging.Formats.dll - - ..\packages\GdPicture.14.3.19\lib\net462\GdPicture.NET.14.Imaging.Formats.Conversion.dll + + ..\packages\GdPicture.14.3.18\lib\net462\GdPicture.NET.14.Imaging.Formats.Conversion.dll - - ..\packages\GdPicture.14.3.19\lib\net462\GdPicture.NET.14.Imaging.Rendering.dll + + ..\packages\GdPicture.14.3.18\lib\net462\GdPicture.NET.14.Imaging.Rendering.dll - - ..\packages\GdPicture.14.3.19\lib\net462\GdPicture.NET.14.MSOfficeBinary.dll + + ..\packages\GdPicture.14.3.18\lib\net462\GdPicture.NET.14.MSOfficeBinary.dll - - ..\packages\GdPicture.14.3.19\lib\net462\GdPicture.NET.14.OpenDocument.dll + + ..\packages\GdPicture.14.3.18\lib\net462\GdPicture.NET.14.OpenDocument.dll - - ..\packages\GdPicture.14.3.19\lib\net462\GdPicture.NET.14.OpenXML.dll + + ..\packages\GdPicture.14.3.18\lib\net462\GdPicture.NET.14.OpenXML.dll - - ..\packages\GdPicture.14.3.19\lib\net462\GdPicture.NET.14.OpenXML.Templating.dll + + ..\packages\GdPicture.14.3.18\lib\net462\GdPicture.NET.14.OpenXML.Templating.dll - - ..\packages\GdPicture.14.3.19\lib\net462\GdPicture.NET.14.PDF.dll + + ..\packages\GdPicture.14.3.18\lib\net462\GdPicture.NET.14.PDF.dll - - ..\packages\GdPicture.14.3.19\lib\net462\GdPicture.NET.14.RTF.dll + + ..\packages\GdPicture.14.3.18\lib\net462\GdPicture.NET.14.RTF.dll - - ..\packages\GdPicture.14.3.19\lib\net462\GdPicture.NET.14.SVG.dll + + ..\packages\GdPicture.14.3.18\lib\net462\GdPicture.NET.14.SVG.dll - ..\packages\GdPicture.14.3.19\lib\net462\GdPicture.NET.14.wia.gateway.dll + ..\packages\GdPicture.14.3.18\lib\net462\GdPicture.NET.14.wia.gateway.dll True @@ -285,11 +285,11 @@ powershell.exe -command "& { &'$(SolutionDir)copy-binary.ps1' '$(TargetPath)' '$(TargetFileName)' '$(ConfigurationName)' '$(ProjectName)' }" - + Dieses Projekt verweist auf mindestens ein NuGet-Paket, das auf diesem Computer fehlt. Verwenden Sie die Wiederherstellung von NuGet-Paketen, um die fehlenden Dateien herunterzuladen. Weitere Informationen finden Sie unter "http://go.microsoft.com/fwlink/?LinkID=322105". Die fehlende Datei ist "{0}". - + \ No newline at end of file diff --git a/Jobs/packages.config b/Jobs/packages.config index 5ce66aaf..cd4b8e35 100644 --- a/Jobs/packages.config +++ b/Jobs/packages.config @@ -4,8 +4,8 @@ - - + + diff --git a/Messaging/Mail/MailSession.vb b/Messaging/Mail/MailSession.vb index 902669ff..5c8f6c38 100644 --- a/Messaging/Mail/MailSession.vb +++ b/Messaging/Mail/MailSession.vb @@ -1,4 +1,5 @@ -Imports System.Net.Security +Imports System.IdentityModel.Tokens +Imports System.Net.Security Imports DigitalData.Modules.Base Imports DigitalData.Modules.Logging Imports Limilabs.Client @@ -11,7 +12,6 @@ Namespace Mail Inherits BaseClass Public ReadOnly Client As ClientBase - Public ReadOnly OAuth2 As OAuth2 Public Const AUTH_SSL = "SSL" Public Const AUTH_STARTTLS = "STARTTLS" @@ -19,9 +19,7 @@ Namespace Mail Public Const AUTH_NONE = "NONE" Public Const AUTH_OAUTH2 = "OAUTH2" - Private Const SMTP_IGNORED_ERRORS As SslPolicyErrors = - SslPolicyErrors.RemoteCertificateChainErrors Or ' self-signed - SslPolicyErrors.RemoteCertificateNameMismatch ' name mismatch + Private Const SMTP_IGNORED_ERRORS As SslPolicyErrors = SslPolicyErrors.RemoteCertificateChainErrors Or SslPolicyErrors.RemoteCertificateNameMismatch Private _Session As SessionInfo @@ -56,7 +54,7 @@ Namespace Mail Public Property EnableTls1_1 As Boolean = False Public Property EnableTls1_2 As Boolean = False - ' Not available in .NET 4.6.2 + ' Not available in .NET4.6.2 'Public Property EnableTls1_3 As Boolean = False End Class @@ -71,12 +69,12 @@ Namespace Mail ''' Public Function ConnectToServerWithBasicAuth(pServer As String, pPort As Integer, pUser As String, pPassword As String, pAuthType As String, pOptions As MailSessionOptions) As SessionInfo Dim oSession = New SessionInfo With { - .Server = pServer, - .Port = pPort, - .User = pUser, - .Password = pPassword, - .AuthType = pAuthType - } + .Server = pServer, + .Port = pPort, + .User = pUser, + .Password = pPassword, + .AuthType = pAuthType + } Logger.Debug("Connecting to Server..") Logger.Debug("Server: [{0}]", oSession.Server) @@ -92,17 +90,23 @@ Namespace Mail End Function Public Function ConnectToServerWithO365OAuth(pUser As String, pClientId As String, pTenantId As String, pClientSecret As String, pOptions As MailSessionOptions) As SessionInfo + ' Choose server/port based on the client type + Dim server As String = If(TypeOf Client Is Smtp, "smtp.office365.com", OAuth2.O365_SERVER) + Dim port As Integer = If(TypeOf Client Is Imap, 993, If(TypeOf Client Is Smtp, 587, 993)) + Dim oSession = New SessionInfo With { - .Server = OAuth2.O365_SERVER, - .ClientId = pClientId, - .ClientSecret = pClientSecret, - .TenantId = pTenantId, - .User = pUser, - .AuthType = AUTH_OAUTH2 - } + .Server = server, + .Port = port, + .ClientId = pClientId, + .ClientSecret = pClientSecret, + .TenantId = pTenantId, + .User = pUser, + .AuthType = AUTH_OAUTH2 + } Logger.Debug("Connecting to Server..") Logger.Debug("Server: [{0}]", oSession.Server) + Logger.Debug("Port: [{0}]", oSession.Port) Logger.Debug("User: [{0}]", oSession.User) Logger.Debug("ClientId: [{0}]", oSession.ClientId) Logger.Debug("TenantId: [{0}]", oSession.TenantId) @@ -120,61 +124,52 @@ Namespace Mail If pOptions.EnableDefault Then Logger.Debug("Enabling Default TLS Version") - Client.SSLConfiguration.EnabledSslProtocols = Security.Authentication.SslProtocols.Default + Client.SSLConfiguration.EnabledSslProtocols = System.Security.Authentication.SslProtocols.Default Else Logger.Debug("Disabling Default TLS Version") - Client.SSLConfiguration.EnabledSslProtocols = Security.Authentication.SslProtocols.None + Client.SSLConfiguration.EnabledSslProtocols = System.Security.Authentication.SslProtocols.None End If ' Set TLS Version manually if requested If pOptions.EnableTls1_1 Then - Logger.Debug("Enabling TLS Version 1.1") - Client.SSLConfiguration.EnabledSslProtocols = Client.SSLConfiguration.EnabledSslProtocols Or Security.Authentication.SslProtocols.Tls11 + Logger.Debug("Enabling TLS Version1.1") + Client.SSLConfiguration.EnabledSslProtocols = Client.SSLConfiguration.EnabledSslProtocols Or System.Security.Authentication.SslProtocols.Tls11 End If If pOptions.EnableTls1_2 Then - Logger.Debug("Enabling TLS Version 1.2") - Client.SSLConfiguration.EnabledSslProtocols = Client.SSLConfiguration.EnabledSslProtocols Or Security.Authentication.SslProtocols.Tls12 + Logger.Debug("Enabling TLS Version1.2") + Client.SSLConfiguration.EnabledSslProtocols = Client.SSLConfiguration.EnabledSslProtocols Or System.Security.Authentication.SslProtocols.Tls12 End If - ' This is not available in .NET 4.6.2, only in .NET 4.7/4.8 - 'If pOptions.EnableTls1_3 Then - ' Logger.Debug("Enabling TLS Version 1.3") - ' oSession.SSLConfiguration.EnabledSslProtocols = oSession.SSLConfiguration.EnabledSslProtocols Or Security.Authentication.SslProtocols.Tls13 - 'End If - Logger.Debug("Enabled Encryption Protocols: [{0}]", Client.SSLConfiguration.EnabledSslProtocols) If pSession.AuthType = AUTH_OAUTH2 Then Try If TypeOf Client Is Imap Then - Dim oClient As Imap = Client + Dim oClient As Imap = DirectCast(Client, Imap) + Logger.Debug("Connecting with [OAuth2/IMAP/ConnectSSL] on [{0}/{1}]", pSession.Server, If(pSession.Port > 0, pSession.Port, 993)) + oClient.ConnectSSL(pSession.Server) ', If(pSession.Port > 0, pSession.Port, 993) - Logger.Debug("Connecting with [OAuth2/ConnectSSL] on [{0}]", pSession.Server) - oClient.ConnectSSL(pSession.Server) - Else - Throw New ApplicationException("Only OAuth2 for IMAP is not yet supported!") + ElseIf TypeOf Client Is Smtp Then + Dim s As Smtp = DirectCast(Client, Smtp) + Logger.Debug("Connecting with [OAuth2/SMTP/STARTTLS] on [{0}/{1}]", pSession.Server, If(pSession.Port > 0, pSession.Port, 587)) + s.Connect(pSession.Server, If(pSession.Port > 0, pSession.Port, 587)) + s.StartTLS() End If Catch ex As Exception Logger.Warn("Unexpected Error in ConnectToServer with Auth type OAuth2!") Logger.Error(ex) - Session.Error = ex - Return Session + pSession.Error = ex + Return pSession End Try ElseIf pSession.AuthType = AUTH_SSL Then Try - ' Port 465 ist der SMTP-SSL-Port, wird bei der WISAG verwendet, aber veraltet - ' Port 993 ist der IMAP-SSL-Port, zum Abholen der Mails - If pSession.Port = 465 Or pSession.Port = 993 Then - Logger.Debug("Connecting with [SSL/ConnectSSL] on [{0}/{1}]", pSession.Server, pSession.Port) - Client.ConnectSSL(pSession.Server, pSession.Port) - Else - Logger.Debug("Connecting with [SSL/Connect] on [{0}/{1}]", pSession.Server, pSession.Port) - Client.Connect(pSession.Server, pSession.Port) - End If + ' SSL: always connect with SSL immediately + Logger.Debug("Connecting with [SSL/ConnectSSL] on [{0}/{1}]", pSession.Server, pSession.Port) + Client.ConnectSSL(pSession.Server, pSession.Port) Logger.Debug("Connection (AUTH_SSL) Successful!") Catch ex As Exception @@ -182,21 +177,32 @@ Namespace Mail Logger.Warn($"Error-message: {ex.Message}") Logger.Error(ex) - Session.Error = ex - Return Session + pSession.Error = ex + Return pSession End Try - ElseIf Session.AuthType = AUTH_SSLTLS Or Session.AuthType = AUTH_STARTTLS Then + ElseIf pSession.AuthType = AUTH_SSLTLS Then Try - If pSession.Port = 993 Then - Logger.Debug("Connecting with [STARTTLS/ConnectSSL] on [{0}/{1}]", pSession.Server, pSession.Port) - Client.ConnectSSL(pSession.Server, pSession.Port) - Else - Logger.Debug("Connecting with [STARTTLS/Connect] on [{0}/{1}]", pSession.Server, pSession.Port) - Client.Connect(pSession.Server, pSession.Port) - End If - Logger.Debug("Connection (AUTH_SSLTLS or AUTH_STARTTLS) Successful!") + ' SSL/TLS: same as SSL, explicit branch for clarity + Logger.Debug("Connecting with [SSL/TLS/ConnectSSL] on [{0}/{1}]", pSession.Server, pSession.Port) + Client.ConnectSSL(pSession.Server, pSession.Port) + Logger.Debug("Connection (AUTH_SSLTLS) Successful!") + + Catch ex As Exception + Logger.Warn("Unexpected Error in ConnectToServer with Auth type SSL/TLS!") + Logger.Error(ex) + + pSession.Error = ex + Return pSession + End Try + + ElseIf pSession.AuthType = AUTH_STARTTLS Then + + Try + ' STARTTLS: connect plain and then upgrade + Logger.Debug("Connecting with [STARTTLS/Connect] on [{0}/{1}]", pSession.Server, pSession.Port) + Client.Connect(pSession.Server, pSession.Port) Dim oSupportsSTARTTLS As Boolean = SupportsSTARTTLS(Client) Logger.Debug("Server supports STARTTLS: [{0}]", oSupportsSTARTTLS) @@ -205,8 +211,7 @@ Namespace Mail DoSTARTTLS(Client) Logger.Debug("STARTTLS Successful!") Else - Logger.Debug("Server does not support STARTTLS. Enabling TLS1.2 instead.") - Client.SSLConfiguration.EnabledSslProtocols = Security.Authentication.SslProtocols.Tls12 + Throw New ApplicationException("Server does not support STARTTLS on this endpoint.") End If Catch ex As Exception @@ -219,11 +224,11 @@ Namespace Mail Else Try - Logger.Debug("Auth type [{0}]. Using PLAINTEXT connection.", Session.AuthType) + Logger.Debug("Auth type [{0}]. Using PLAINTEXT connection.", pSession.AuthType) Client.Connect(pSession.Server, pSession.Port, useSSL:=False) Catch ex As Exception - Logger.Warn("Unexpected Error in ConnectToServer with Auth type [{0}]!", Session.AuthType) + Logger.Warn("Unexpected Error in ConnectToServer with Auth type [{0}]!", pSession.AuthType) Logger.Error(ex) pSession.Error = ex @@ -237,8 +242,7 @@ Namespace Mail Logger.Info("Logging in with user [{0}] and Auth Type [{1}]", pSession.User, pSession.AuthType) If pSession.AuthType = AUTH_OAUTH2 Then - ' SessionInfo.Password will be the access token that was obtained - ' in the OAuth2 flow before + ' Use OAuth2 token DoUseBestLogin_OAuth2(Client, pSession) Else DoUseBestLogin_BasicAuth(Client, pSession.User, pSession.Password) @@ -293,7 +297,7 @@ Namespace Mail End If End Function - Private Function SupportsSTARTTLS(pClient As ClientBase) + Private Function SupportsSTARTTLS(pClient As ClientBase) As Boolean If TypeOf pClient Is Smtp Then Return DirectCast(pClient, Smtp).SupportedExtensions.Contains(SmtpExtension.StartTLS) ElseIf TypeOf pClient Is Imap Then @@ -329,16 +333,61 @@ Namespace Mail Private Sub DoUseBestLogin_OAuth2(pClient As ClientBase, pSession As SessionInfo) Logger.Debug("Logging in with O365 OAuth2") - If TypeOf pClient Is Imap Then - Dim oOAuth = New OAuth2(LogConfig, pSession.TenantId, pSession.ClientId, pSession.ClientSecret) - Dim oAccessToken = oOAuth.GetAccessToken() + Dim oOAuth = New OAuth2(LogConfig, pSession.TenantId, pSession.ClientId, pSession.ClientSecret) + Dim oAccessToken = oOAuth.GetAccessToken() - DirectCast(pClient, Imap).LoginOAUTH2(pSession.User, oAccessToken) + ' Diagnose token shape (delegated vs app-only) + Try + Dim parts = oAccessToken.Split("."c) + If parts.Length = 3 Then + Dim payloadJson = System.Text.Encoding.UTF8.GetString(Convert.FromBase64String(PadBase64(parts(1)))) + If payloadJson.Contains("""scp""") Then + Logger.Debug("OAuth2 token contains 'scp' (delegated) – IMAP App-only erwartet 'roles'.") + ElseIf payloadJson.Contains("""roles""") Then + Logger.Debug("OAuth2 token contains 'roles' (application permissions).") + Else + Logger.Debug("OAuth2 token payload hat weder 'scp' noch 'roles'.") + End If + End If + Catch ex As Exception + Logger.Debug("Token-Payload konnte nicht gelesen werden: {0}", ex.Message) + End Try + + If TypeOf pClient Is Imap Then + Dim i = DirectCast(pClient, Imap) + + ' Login mit Hilfsmethode; bei Abbruch explizit SASL XOAUTH2 probieren + Try + ' Direkt versuchen, falls die verwendete Version LoginOAUTH2 unterstützt. + i.LoginOAUTH2(pSession.User, oAccessToken) + Catch ex As Exception + Logger.Warn("LoginOAUTH2 (IMAP) fehlgeschlagen: {0}", ex.Message) + Throw + End Try + ElseIf TypeOf pClient Is Smtp Then + Dim s = DirectCast(pClient, Smtp) + Try + s.LoginOAUTH2(pSession.User, oAccessToken) + Catch ex As Exception + Logger.Warn("LoginOAUTH2 (SMTP) fehlgeschlagen: {0}", ex.Message) + Throw + End Try Else Logger.Error("Unknown session type: [{0}]", pClient.GetType.ToString) End If End Sub + Private Shared Function PadBase64(input As String) As String + ' Normalize Base64 URL-safe and pad to multiple of 4 + If input Is Nothing Then Return String.Empty + Dim normalized As String = input.Replace("-", "+").Replace("_", "/") + Dim remainder As Integer = normalized.Length Mod 4 + If remainder > 0 Then + normalized &= New String("="c, 4 - remainder) + End If + Return normalized + End Function + Private Sub DoSTARTTLS(pClient As ClientBase) If TypeOf pClient Is Smtp Then DirectCast(pClient, Smtp).StartTLS() diff --git a/Messaging/Mail/OAuth2.vb b/Messaging/Mail/OAuth2.vb index 46ba0361..b43b89fc 100644 --- a/Messaging/Mail/OAuth2.vb +++ b/Messaging/Mail/OAuth2.vb @@ -1,58 +1,96 @@ Imports DigitalData.Modules.Base Imports DigitalData.Modules.Logging -Imports DigitalData.Modules.Messaging.Mail.MailSession -Imports Limilabs.Client.IMAP Imports Microsoft.Identity.Client -Public Class OAuth2 - Inherits BaseClass +Namespace Mail + Public Class OAuth2 + Inherits BaseClass - Private ReadOnly TenantId As String - Private ReadOnly ClientId As String - Private ReadOnly ClientSecret As String + Private ReadOnly _tenantId As String + Private ReadOnly _clientId As String + Private ReadOnly _clientSecret As String - Public Const O365_SCOPE = "https://outlook.office365.com/.default" - Public Const O365_SERVER = "outlook.office365.com" + Public Const O365_SERVER As String = "outlook.office365.com" + Public Const O365_SCOPE As String = "https://outlook.office365.com/.default" + Public Const O365_AUTHORITY_PREFIX As String = "https://login.microsoftonline.com/" - Private _AccessToken As String - Public ReadOnly Property AccessToken - Get - Return _AccessToken - End Get - End Property + Public Sub New(pLogConfig As LogConfig, tenantId As String, clientId As String, clientSecret As String) + MyBase.New(pLogConfig) + _tenantId = tenantId + _clientId = clientId + _clientSecret = clientSecret + End Sub - Public Sub New(pLogConfig As LogConfig, pTenantId As String, pClientId As String, pClientSecret As String) - MyBase.New(pLogConfig) - TenantId = pTenantId - ClientId = pClientId - ClientSecret = pClientSecret - End Sub + Public Function GetAccessToken() As String + ' input hardening and better diagnostics + Dim tenantId = If(_tenantId, String.Empty).Trim() + Dim clientId = If(_clientId, String.Empty).Trim() + Dim clientSecret = If(_clientSecret, String.Empty).Trim() - Public Function GetAccessToken() As String - Logger.Debug("Fetching Access Token..") + If String.IsNullOrWhiteSpace(tenantId) Then + Logger.Error("OAuth2: tenantId is empty.") + Throw New ArgumentException("tenantId is empty") + End If + If String.IsNullOrWhiteSpace(clientId) Then + Logger.Error("OAuth2: clientId is empty.") + Throw New ArgumentException("clientId is empty") + End If + If String.IsNullOrWhiteSpace(clientSecret) Then + Logger.Error("OAuth2: clientSecret is empty.") + Throw New ArgumentException("clientSecret is empty") + End If - Try - ' Create the application, which is defined in - ' Microsoft.Identity.Client - Dim oApp = ConfidentialClientApplicationBuilder. - Create(ClientId). - WithTenantId(TenantId). - WithClientSecret(ClientSecret). - Build() + ' common misconfiguration: using the Secret ID (GUID) instead of the Secret VALUE + Dim tmpGuid As Guid + If Guid.TryParse(clientSecret, tmpGuid) Then + Logger.Error("OAuth2: clientSecret looks like a GUID (likely the secret ID). Use the secret VALUE instead.") + Throw New ApplicationException("Invalid client secret: looks like Secret ID (GUID), not the secret value.") + End If - ' Request an access token - Dim oScopes = New List(Of String) From {O365_SCOPE} - Dim oResult = oApp. - AcquireTokenForClient(oScopes). - ExecuteAsync().Result + Try + Dim authority = O365_AUTHORITY_PREFIX & tenantId - Logger.Debug("Access Token fetched.") + Dim app = ConfidentialClientApplicationBuilder.Create(clientId). + WithClientSecret(clientSecret). + WithAuthority(authority). + Build() - Return oResult.AccessToken - Catch ex As Exception - Logger.Warn("Could not request access token!") - Logger.Error(ex) - Return Nothing - End Try - End Function -End Class + Dim scopes = New String() {O365_SCOPE} + Dim result = app.AcquireTokenForClient(scopes).ExecuteAsync().GetAwaiter().GetResult() + + Logger.Info("OAuth2 token acquired for tenant {0}. ExpiresOn={1:u}", tenantId, result.ExpiresOn.UtcDateTime) + Return result.AccessToken + Catch ex As MsalServiceException + ' richer diagnostics without depending on specific MSAL version members + Logger.Error("MSAL service error. Code={0}. Message={1}", ex.ErrorCode, ex.Message) + + ' Try to log StatusCode, ResponseBody if available (via reflection to avoid version dependency) + Try + Dim t = GetType(MsalServiceException) + Dim scProp = t.GetProperty("StatusCode") + If scProp IsNot Nothing Then + Dim sc = scProp.GetValue(ex, Nothing) + If sc IsNot Nothing Then Logger.Error("MSAL StatusCode={0}", sc) + End If + Dim rbProp = t.GetProperty("ResponseBody") + If rbProp IsNot Nothing Then + Dim rb = rbProp.GetValue(ex, Nothing) + If rb IsNot Nothing Then Logger.Error("MSAL ResponseBody={0}", rb) + End If + Dim ciProp = t.GetProperty("Claims") + If ciProp IsNot Nothing Then + Dim claims = ciProp.GetValue(ex, Nothing) + If claims IsNot Nothing AndAlso claims.ToString().Length > 0 Then Logger.Error("MSAL Claims={0}", claims) + End If + Catch + ' ignore reflection diagnostics failures + End Try + + Throw + Catch ex As Exception + Logger.Error(ex) + Throw + End Try + End Function + End Class +End Namespace diff --git a/Messaging/Messaging.vbproj b/Messaging/Messaging.vbproj index 8bdcfa87..77dd232b 100644 --- a/Messaging/Messaging.vbproj +++ b/Messaging/Messaging.vbproj @@ -1,4 +1,4 @@ - + @@ -47,9 +47,9 @@ ..\packages\DigitalData.Modules.Logging.2.6.5\lib\net462\DigitalData.Modules.Logging.dll - - P:\Visual Studio Projekte\Bibliotheken\Limilabs\Mail.dll\Mail.dll - False + + False + P:\Projekte DIGITAL DATA\DIGITAL DATA - Entwicklung\DLL_Bibliotheken\Limilabs\Mail.dll diff --git a/Messaging/My Project/AssemblyInfo.vb b/Messaging/My Project/AssemblyInfo.vb index 8446c67f..df394fb7 100644 --- a/Messaging/My Project/AssemblyInfo.vb +++ b/Messaging/My Project/AssemblyInfo.vb @@ -31,5 +31,5 @@ Imports System.Runtime.InteropServices ' übernehmen, indem Sie "*" eingeben: ' - - + + diff --git a/ZooFlow/ZooFlow.vbproj b/ZooFlow/ZooFlow.vbproj index 76ca9968..be801c79 100644 --- a/ZooFlow/ZooFlow.vbproj +++ b/ZooFlow/ZooFlow.vbproj @@ -44,6 +44,18 @@ On + + ..\Database\bin\Debug\DigitalData.Modules.Database.dll + + + P:\Projekte DIGITAL DATA\DIGITAL DATA - Entwicklung\DLL_Bibliotheken\Digital Data\DD_Modules\DigitalData.Modules.EDMI.API.dll + + + ..\Logging\bin\Debug\DigitalData.Modules.Logging.dll + + + ..\Windows\bin\Debug\DigitalData.Modules.Windows.dll + ..\packages\NLog.5.0.5\lib\net46\NLog.dll @@ -123,24 +135,6 @@ - - - {eaf0ea75-5fa7-485d-89c7-b2d843b03a96} - Database - - - {25017513-0d97-49d3-98d7-ba76d9b251b0} - EDMI.API - - - {903b2d7d-3b80-4be9-8713-7447b704e1b0} - Logging - - - {5EFAEF9B-90B9-4F05-9F70-F79AD77FFF86} - Windows - - powershell.exe -command "& { &'$(SolutionDir)copy-binary.ps1' '$(TargetPath)' '$(TargetFileName)' '$(ConfigurationName)' '$(ProjectName)' }"