2021-07-19 16:42:29 +02:00

560 lines
26 KiB
VB.net

Imports Independentsoft.Email
Imports Independentsoft.Email.Pop3
Imports Independentsoft.Email.Mime
Imports Independentsoft.Email.Imap
Imports System.Net.Mail
Imports System.Net
Imports System.Reflection
Imports System.IO
Public Class Email
Private ReadOnly _logger As Logging.Logger
Private ReadOnly _logConfig As Logging.LogConfig
Public Err_Message As String
Public _msg_Send As Boolean
Public Sub New(LogConfig As Logging.LogConfig)
_logger = LogConfig.GetLogger()
_logConfig = LogConfig
End Sub
''' <summary>
''' Tests connection to a given IMAP Server by connecting and doing a simple message query.
''' </summary>
''' <param name="Server">IP-Address or Domainname of Server</param>
''' <param name="Port">IMAP-Port</param>
''' <param name="Username">IMAP-Username</param>
''' <param name="Password">IMAP-Password</param>
''' <param name="Folder">The folder to fetch messages from. Defaults to `Inbox`</param>
''' <returns>True if connection and query were successful. False otherwise.</returns>
Public Function TestIMAPLogin(Server As String, Port As Integer, Username As String, Password As String, Optional Folder As String = "Inbox") As Boolean
_logger.Debug("Testing Login to Server {0}:{1} with user {2}", Server, Port, Username)
Try
_logger.Debug("Connecting...")
Using oClient As New S22.Imap.ImapClient(Server, Port, Username, Password, S22.Imap.AuthMethod.Login, True)
If Not oClient.Authed Then
_logger.Warn("Connected to server but authentication failed.")
Return False
End If
_logger.Debug("Connection successful")
_logger.Debug("Fetching MessageIds..")
Dim oMessageIds As IEnumerable(Of UInteger) = oClient.Search(S22.Imap.SearchCondition.Unseen, Folder)
_logger.Debug("Found {0} messages", oMessageIds.Count)
_logger.Debug("Fetching messages...")
Dim oMessages As IEnumerable(Of MailMessage) = oClient.GetMessages(oMessageIds, False, Folder)
_logger.Debug("Messages fetched")
oClient.Dispose()
Return True
End Using
Catch ex As Exception
_logger.Error(ex)
Return False
End Try
End Function
''' <summary>
''' Connects to an IMAP Server with the given credentials and
''' fetches emails from the given folder.
''' Results can be filtered with `SearchCondition`
''' </summary>
''' <param name="Server">IP-Address or Domainname of Server</param>
''' <param name="Port">IMAP-Port</param>
''' <param name="Username">IMAP-Username</param>
''' <param name="Password">IMAP-Password</param>
''' <param name="Folder">The folder to fetch messages from</param>
''' <param name="SearchCondition">Filter the search command. Defaults to `All`</param>
''' <returns>A list of Independentsoft.Email.Mime.Message objects</returns>
Public Function FetchIMAPMessages(Server As String, Port As Integer, Username As String, Password As String, Folder As String) As List(Of Message) ', Optional SearchCondition As S22.Imap.SearchCondition = S22.Imap.SearchCondition.All
Dim oMessages As New List(Of Message)
_logger.Debug("Connecting to Server {0}:{1} with user {2}", Server, Port, Username)
Try
_logger.Debug("Connecting...")
Using oClient As New S22.Imap.ImapClient(Server, Port, Username, Password, S22.Imap.AuthMethod.Login, True)
If Not oClient.Authed Then
_logger.Warn("Connected to server but authentication failed.")
Return Nothing
End If
_logger.Debug("Connection successful")
_logger.Debug("Fetching MessageIds..")
Dim oMessageIds As IEnumerable(Of UInteger) = oClient.Search(S22.Imap.SearchCondition.Unseen, Folder)
_logger.Debug("Found {0} messages", oMessageIds.Count)
_logger.Debug("Fetching messages...")
' Since this needs to return a list of IndependentSoft Message objects,
' we 'convert' the .NET MailMessage objects that are fetched from the server
' by writing them temporarily to disk as an eml file and then reading them back into a Message object.
' This approach uses an unintended use of internal .NET APIs and may break in the future.
For Each oMessageId As UInteger In oMessageIds
Dim oMessage = oClient.GetMessage(oMessageId, False, Folder)
Dim oTempPath = Path.GetTempFileName()
Dim oResult = WriteMessageToFile(oMessage, oTempPath)
Dim oMsg As New Message(oTempPath)
oMessages.Add(oMsg)
Try
File.Delete(oTempPath)
Catch ex As Exception
_logger.Error(ex)
_logger.Warn("Temp file could not be deleted")
End Try
Next
_logger.Debug("{0} Messages fetched", oMessages.Count)
End Using
Return oMessages
Catch ex As Exception
_logger.Error(ex)
Return Nothing
End Try
End Function
''' <summary>
''' Uses a private API from MailWriter to write a MailMessage to disk.
''' May break in future versions of .NET
''' </summary>
Public Function WriteMessageToFile(Message As MailMessage, Filename As String) As Boolean
Dim oAssembly As Assembly = GetType(System.Net.Mail.SmtpClient).Assembly
Dim oMailWriterType As Type = oAssembly.[GetType]("System.Net.Mail.MailWriter")
Try
Using oStream As New FileStream(Filename, FileMode.Create)
Dim oMailWriterConstructor As ConstructorInfo = oMailWriterType.GetConstructor(
BindingFlags.Instance Or BindingFlags.NonPublic, Nothing, New Type() {GetType(Stream)}, Nothing
)
Dim oMailWriter As Object = oMailWriterConstructor.Invoke(New Object() {oStream})
Dim sendMethod As MethodInfo = GetType(MailMessage).GetMethod("Send", BindingFlags.Instance Or BindingFlags.NonPublic)
sendMethod.Invoke(Message, BindingFlags.Instance Or BindingFlags.NonPublic, Nothing, {oMailWriter, True, True}, Nothing)
End Using
Return True
Catch ex As Exception
Return Nothing
End Try
End Function
Public Function IMAP_COLLECT(INBOXNAME As String, MYMAIL_SERVER As String, MYMAIL_PORT As Integer, MYMAIL_USER As String, MYMAIL_USER_PW As String)
Try
Dim oMAIL_LIST As New ArrayList()
_logger.Info(String.Format("Working on IMAP_COLLECT..."))
Dim oClient As New ImapClient(MYMAIL_SERVER, MYMAIL_PORT)
oClient.Connect()
oClient.Login(MYMAIL_USER, MYMAIL_USER_PW)
oClient.SelectFolder("Inbox")
Dim oEnvelopes As Envelope() = oClient.ListMessages()
For i As Integer = 0 To oEnvelopes.Length - 1
If Not IsNothing(oEnvelopes(i).Subject) Then
'If envelopes(i).Subject.ToString.ToUpper.Contains("[PROCESSMANAGER]") Or envelopes(i).Subject.ToString.ToUpper.Contains("[ADDI]") Then
_logger.Info($"Working on email: UniqueID: {oEnvelopes(i).UniqueID} - Subject:{oEnvelopes(i).Subject} - Date {oEnvelopes(i).Date.ToString}")
Dim message As Mime.Message = oClient.GetMessage(oEnvelopes(i).UniqueID)
If Not IsNothing(message) Then
oMAIL_LIST.Add(message)
End If
'End If
End If
Next
oClient.Disconnect()
_logger.Debug("IMAP_COLLECT finished!")
Return oMAIL_LIST
Catch ex As Exception
_logger.Error(ex, "Unexpected Error in IMAP COLLECT:")
Return Nothing
End Try
End Function
Public Function TEST_IMAP_COLLECT(INBOXNAME As String, MYMAIL_SERVER As String, MYMAIL_PORT As Integer, MYMAIL_USER As String, MYMAIL_USER_PW As String)
Try
_logger.Info(String.Format("Working on TEST_IMAP_COLLECT....."))
Dim oClient As New ImapClient(MYMAIL_SERVER, MYMAIL_PORT)
oClient.Connect()
oClient.Login(MYMAIL_USER, MYMAIL_USER_PW)
oClient.SelectFolder(INBOXNAME)
Dim oEnvelopes As Envelope() = oClient.ListMessages()
For i As Integer = 0 To oEnvelopes.Length - 1
If Not IsNothing(oEnvelopes(i).Subject) Then
'If envelopes(i).Subject.ToString.ToUpper.Contains("[PROCESSMANAGER]") Or envelopes(i).Subject.ToString.ToUpper.Contains("[ADDI]") Then
MsgBox($"Working on email: UniqueID: {oEnvelopes(i).UniqueID} - Subject:{oEnvelopes(i).Subject} - Date {oEnvelopes(i).Date.ToString}")
Dim message As Mime.Message = oClient.GetMessage(oEnvelopes(i).UniqueID)
End If
Next
oClient.Disconnect()
_logger.Info("TEST_IMAP_COLLECT finished!")
Return True
Catch ex As Exception
_logger.Error(ex, "Unexpected Error in TEST_IMAP_COLLECT:")
Return False
End Try
End Function
Public Function POP3_COLLECT(MYMAIL_SERVER As String, MYMAIL_PORT As Integer, MYMAIL_USER As String, MYMAIL_USER_PW As String)
Try
Dim oMAIL_LIST As New ArrayList()
_logger.Debug(String.Format("Working on POP3_COLLECT....."))
Dim oClient As New Pop3Client(MYMAIL_SERVER, MYMAIL_PORT)
oClient.ValidateRemoteCertificate = False
oClient.Connect()
_logger.Debug(String.Format("..connected!"))
oClient.Login(MYMAIL_USER, MYMAIL_USER_PW)
Dim oMessageInfo As MessageInfo() = oClient.List()
For i As Integer = 0 To oMessageInfo.Length - 1
Dim message As Message = oClient.GetMessage(oMessageInfo(i).Index)
oMAIL_LIST.Add(message)
Try
_logger.Debug(String.Format("Message [{0}] added", message.Subject))
Catch ex As Exception
End Try
Next
oClient.Disconnect()
_logger.Debug(String.Format(" POP3_COLLECT finished!"))
Return oMAIL_LIST
Catch ex As Exception
_logger.Error(ex)
Return Nothing
End Try
End Function
Public Function TEST_POP3_COLLECT(MYMAIL_SERVER As String, MYMAIL_PORT As Integer, MYMAIL_USER As String, MYMAIL_USER_PW As String) As Boolean
Try
_logger.Debug(String.Format("Working on TEST_POP3_COLLECT..."))
Dim oClient As New Pop3Client(MYMAIL_SERVER, MYMAIL_PORT)
oClient.ValidateRemoteCertificate = False
oClient.Connect()
_logger.Debug(String.Format("..connected!"))
oClient.Login(MYMAIL_USER, MYMAIL_USER_PW)
Dim messageInfo As MessageInfo() = oClient.List()
For i As Integer = 0 To messageInfo.Length - 1
Dim message As Message = oClient.GetMessage(messageInfo(i).Index)
MsgBox(String.Format("Message [{0}] added", message.Subject))
Next
oClient.Disconnect()
MsgBox(String.Format("TEST_POP3_COLLECT finished!"))
Return True
Catch ex As Exception
_logger.Error(ex)
Return False
End Try
End Function
Public Function NewEmail(mailto As String, mailSubject As String, mailBody As String,
mailfrom As String, mailsmtp As String, mailport As Integer, mailUser As String, mailPW As String,
AUTH_TYPE As String, SENDER_INSTANCE As String, Optional attachmentString As String = "", Optional Test As Boolean = False)
Dim myClient As Net.Mail.SmtpClient
Dim myMesssage As New MailMessage
Try
Dim oError As Boolean = False
Dim oReceipiants As String()
If mailto.Contains(";") Then
oReceipiants = mailto.Split(";")
Else
ReDim Preserve oReceipiants(0)
oReceipiants(0) = mailto
End If
For Each oMailReceipiant As String In oReceipiants
_logger.Debug($"oMailReceipiant [{oMailReceipiant}]")
_logger.Debug($"mailsmtp [{mailsmtp}]")
Try
myClient = New Net.Mail.SmtpClient(mailsmtp, mailport)
Catch ex As Exception
_logger.Warn($"Could not create SMTP-Client: [{ex.Message}]")
Return False
End Try
myClient.DeliveryMethod = SmtpDeliveryMethod.Network
myClient.Port = mailport
_logger.Debug($"mailport [{mailport}]")
If AUTH_TYPE = "SSL" Then
_logger.Debug("SSL = true")
myClient.EnableSsl = True
Else
_logger.Debug("SSL = false")
myClient.EnableSsl = False
End If
_logger.Debug($"mailUser [{mailUser}]")
myClient.Credentials = New NetworkCredential(mailUser, mailPW)
myClient.UseDefaultCredentials = False
If Test = True Then
myMesssage.Body = $"This is the body (text will be replaced within profile)! <br> mailsmtp: {mailsmtp} <br> mailport: {mailport} <br> mailUser: {mailUser} <br> mailPW: XXXX <br> AUTH_TYPE: {AUTH_TYPE}"
Else
myMesssage.Body = mailBody
End If
_logger.Debug($"mailBody [{mailBody}]")
'mymesssage.IsBodyHtml = True
Dim htmlView As AlternateView = AlternateView.CreateAlternateViewFromString(myMesssage.Body)
htmlView.ContentType = New System.Net.Mime.ContentType("text/html")
myMesssage.AlternateViews.Add(htmlView)
_logger.Debug($"attachmentString [{attachmentString}]")
If attachmentString <> "" Then
_logger.Info($"Attachment Path is: {attachmentString}")
Dim oAttachment As New System.Net.Mail.Attachment(attachmentString)
'If attment.ToLower.EndsWith("pdf") Then
' oAttachment.ContentType = New Independentsoft.Email.Mime.ContentType("application", "pdf")
'ElseIf attment.ToLower.EndsWith("jpg") Then
' oAttachment.ContentType = New Independentsoft.Email.Mime.ContentType("application", "jpg")
'ElseIf attment.ToLower.EndsWith("docx") Then
' oAttachment.ContentType = New Independentsoft.Email.Mime.ContentType("application", "MS-word")
'End If
myMesssage.Attachments.Add(oAttachment)
Else
_logger.Debug("No Attachment.")
End If
_logger.Debug($"mailfrom [{mailfrom}]")
myMesssage.From = New MailAddress(mailfrom)
_logger.Debug($"mailSubject [{mailSubject}]")
myMesssage.Subject = mailSubject
myMesssage.To.Add(New MailAddress(oMailReceipiant))
_logger.Debug($"Now Sending mail...")
myClient.Send(myMesssage)
_logger.Debug($"Mail has been sent!")
_logger.Info("Message to " & oMailReceipiant & " has been send.")
Next
If oError = False Then
Return True
Else
Return False
End If
Catch ex As Exception
_logger.Error(ex)
Try
_logger.Info("Unexpected error in Sending smtp-Mail: ")
If Not IsNothing(myClient) Then
_logger.Info($"myClient.Host: {myClient.Host.ToString}")
_logger.Info($"myClient.Port: {myClient.Port.ToString}")
_logger.Info($"myClient.EnableSsl: {myClient.EnableSsl.ToString}")
End If
If Not IsNothing(myMesssage) Then
_logger.Info($"myMesssage.Subject: {myMesssage.Subject.ToString}")
_logger.Info($"myMesssage.Body: {myMesssage.Body.ToString}")
_logger.Info($"myMesssage.From: {myMesssage.From.ToString}")
End If
Catch e1x As Exception
End Try
Return False
End Try
End Function
Public Function New_EmailISoft(ByVal mailSubject As String, ByVal mailBody As String, mailto As String,
from_mailaddress As String, from_name As String, mailsmtp As String, mailport As Integer, mailUser As String, mailPW As String,
AUTH_TYPE As String, SENDER_INSTANCE As String, Optional attment As String = "")
Try
Err_Message = ""
_msg_Send = False
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12
_logger.Debug($"in Email_Send_Independentsoft..")
Dim empfaenger As String()
If mailto.Contains(";") Then
empfaenger = mailto.Split(";")
Else
ReDim Preserve empfaenger(0)
empfaenger(0) = mailto
End If
Dim _error As Boolean = False
'Für jeden Empfänger eine Neue Mail erzeugen
For Each _mailempfaenger As String In empfaenger
_logger.Debug($"Working on email for {_mailempfaenger}..")
Try
Dim oMessage As New Message()
oMessage.From = New Mailbox(from_mailaddress, from_name)
oMessage.[To].Add(New Mailbox(_mailempfaenger))
oMessage.Subject = mailSubject
_logger.Debug($"Message created..")
Dim textBodyPart As New BodyPart()
textBodyPart.ContentType = New ContentType("text", "html", "utf-8")
textBodyPart.ContentTransferEncoding = ContentTransferEncoding.QuotedPrintable
textBodyPart.Body = mailBody
oMessage.BodyParts.Add(textBodyPart)
If attment <> String.Empty Then
If System.IO.File.Exists(attment) Then
Dim attachment1 As New Independentsoft.Email.Mime.Attachment(attment)
If attment.ToLower.EndsWith("pdf") Then
attachment1.ContentType = New ContentType("application", "pdf")
ElseIf attment.ToLower.EndsWith("jpg") Then
attachment1.ContentType = New ContentType("application", "jpg")
ElseIf attment.ToLower.EndsWith("docx") Then
attachment1.ContentType = New ContentType("application", "MS-word")
End If
oMessage.BodyParts.Add(attachment1)
Else
_logger.Warn($"Attachment {attment.ToString} is not existing!")
End If
End If
Dim client As Independentsoft.Email.Smtp.SmtpClient
Try
client = New Independentsoft.Email.Smtp.SmtpClient(mailsmtp, mailport)
Catch ex As Exception
_logger.Warn("clsEmail.Create Client: " & ex.Message)
_error = True
Continue For
End Try
Try
client.Connect()
Catch ex As Exception
_logger.Warn("clsEmail.Client.Connect1: " & ex.Message)
_logger.Debug("Error in ClientConnect - but still trying to send")
_error = True
' Continue For
End Try
_logger.Debug("Connected to Client!")
If AUTH_TYPE = "SSL" Then
client.EnableSsl = True
'client.ValidateRemoteCertificate = True
_logger.Debug("Authentification via SSL.")
ElseIf AUTH_TYPE = "TLS" Then
' client.ValidateRemoteCertificate = False
client.StartTls()
client.EnableSsl = False
_logger.Debug("Authentification via TLS. SSL disabled")
Else
client.EnableSsl = False
_logger.Debug("Authentification NONE. SSL disabled")
End If
Try
client.Connect()
Catch ex As Exception
_logger.Warn("clsEmail.Client.Connect: " & ex.Message)
Err_Message = "clsEmail.Client.Connect: " & ex.Message
_error = True
' Continue For
End Try
Try
If mailsmtp.Contains("office365.com") Then
client.Login(mailUser, mailPW, AuthenticationType.None)
Else
client.Login(mailUser, mailPW)
End If
_logger.Debug("Logged in!")
Catch ex As Exception
Try
If mailsmtp.Contains("office365.com") Then
client.Login(mailUser, mailPW, AuthenticationType.Login)
Else
client.Login(mailUser, mailPW, AuthenticationType.Anonymous)
End If
Catch ex1 As Exception
Try
client.Login(mailUser, mailPW, AuthenticationType.Login)
Catch ex2 As Exception
_logger.Warn("clsEmail.Client.Login: " & ex.Message)
_error = True
client.Disconnect()
Continue For
End Try
End Try
End Try
Try
client.Send(oMessage)
_logger.Info("Message to " & _mailempfaenger & " has been send.")
_msg_Send = True
_error = False
Catch ex As Exception
_logger.Warn("clsEmail.Client.Send: " & ex.Message)
Err_Message = ex.Message
_error = True
client.Disconnect()
Continue For
End Try
client.Disconnect()
Catch ex As Exception
Err_Message = ex.Message
If _msg_Send = True Then
_logger.Info($"Error Closing Connection [{ex.Message}]")
Else
_logger.Error(ex)
End If
_error = True
End Try
Next
If _error = True Then
Return False
Else
Return True
End If
Catch ex As Exception
_logger.Error(ex)
Err_Message = ex.Message
Return False
End Try
End Function
Public Function DELETE_EMAIL(POLLTYPE As String, msgid As String, MYMAIL_SERVER As String, MYMAIL_PORT As Integer, MYMAIL_USER As String, MYMAIL_USER_PW As String)
Try
If POLLTYPE = "POP" Then
Dim oClient As New Pop3Client(MYMAIL_SERVER, MYMAIL_PORT)
oClient.ValidateRemoteCertificate = False
oClient.Connect()
oClient.Login(MYMAIL_USER, MYMAIL_USER_PW)
Dim oMessageInfo As MessageInfo() = oClient.List()
For i As Integer = 0 To oMessageInfo.Length - 1
Dim message As Message = oClient.GetMessage(oMessageInfo(i).Index)
If message.MessageID = msgid Then
oClient.Delete(oMessageInfo(i).Index)
_logger.Info(String.Format("Message [{0}] was deleted!", message.Subject))
Exit For
End If
Next
oClient.Disconnect()
Return True
ElseIf POLLTYPE = "IMAP" Then
Dim oIMAPClient As New ImapClient(MYMAIL_SERVER, MYMAIL_PORT)
oIMAPClient.ValidateRemoteCertificate = False
oIMAPClient.Connect()
oIMAPClient.Login(MYMAIL_USER, MYMAIL_USER_PW)
oIMAPClient.SelectFolder("Inbox")
Dim envelopes As Envelope() = oIMAPClient.ListMessages()
For i As Integer = 0 To envelopes.Length - 1
If envelopes(i).MessageID = msgid Then
oIMAPClient.Delete(envelopes(i).UniqueID) 'mark as deleted
End If
Next
oIMAPClient.Expunge() 'delete messages marked as deleted
oIMAPClient.Disconnect()
Return True
End If
Catch ex As Exception
_logger.Error(ex)
'clsLogger.Add("Unexpected Error in DELETE_EMAIL: " & ex.Message)
Return False
End Try
End Function
End Class