471 lines
16 KiB
VB.net
471 lines
16 KiB
VB.net
Imports System.IO
|
|
Imports DigitalData.Modules.Logging
|
|
Imports DigitalData.Modules.Filesystem
|
|
Imports Limilabs.Mail
|
|
Imports Limilabs.Mail.MIME
|
|
Imports Limilabs.Mail.MSG
|
|
Imports Limilabs.Client.IMAP
|
|
Imports Limilabs.Client.SMTP
|
|
Imports Limilabs.Client
|
|
|
|
Public Class Email2
|
|
Private ReadOnly Logger As Logger
|
|
Private ReadOnly LoggerMail As Logger
|
|
Private ReadOnly LogConfig As LogConfig
|
|
Private ReadOnly FileEx As Filesystem.File
|
|
Private ReadOnly MailBuilder As New MailBuilder()
|
|
Private ReadOnly TempFiles As New List(Of String)
|
|
|
|
Private DisableExcessiveLogging As Boolean = False
|
|
|
|
Public Sub New(pLogConfig As LogConfig)
|
|
LogConfig = pLogConfig
|
|
Logger = pLogConfig.GetLogger()
|
|
LoggerMail = pLogConfig.GetLogger("Limilabs.Mail")
|
|
FileEx = New Filesystem.File(pLogConfig)
|
|
|
|
' Turn on internal Mail.dll logging
|
|
Limilabs.Mail.Log.Enabled = True
|
|
|
|
AddHandler Limilabs.Mail.Log.WriteLine, AddressOf ProcessMailLog
|
|
End Sub
|
|
|
|
Public Enum EmailSecurity
|
|
SSL
|
|
START_TLS
|
|
End Enum
|
|
|
|
Private Sub ProcessMailLog(pMessage As String)
|
|
If DisableExcessiveLogging = False Then
|
|
LoggerMail.Debug(pMessage)
|
|
End If
|
|
End Sub
|
|
|
|
Public Function New_SMTPConnection(pSMTP As Smtp, pServer As String, pUsername As String, pPassword As String, pSecurity As EmailSecurity, Optional pPort As Integer = 0) As Smtp
|
|
Try
|
|
Logger.Info("Connecting to SMTP server [{0}:{1}] with user [{2}]", pServer, pPort, pUsername)
|
|
|
|
Dim oPort As Integer
|
|
If pPort = 0 Then
|
|
If pSecurity = EmailSecurity.SSL Then
|
|
oPort = Smtp.DefaultSSLPort
|
|
|
|
Else
|
|
oPort = Smtp.DefaultPort
|
|
|
|
End If
|
|
|
|
Else
|
|
oPort = pPort
|
|
|
|
End If
|
|
Logger.Debug("Using Port [{0}] for connection", oPort)
|
|
|
|
If pSecurity = EmailSecurity.SSL Then
|
|
Logger.Debug("Using SSL/TLS as Security Option")
|
|
pSMTP.ConnectSSL(pServer, oPort)
|
|
Else
|
|
Logger.Debug("Using STARTTLS as Security Option")
|
|
pSMTP.Connect(pServer, oPort)
|
|
pSMTP.StartTLS()
|
|
End If
|
|
Logger.Debug("Connection to SMTP Server [{0}] established!", pServer)
|
|
|
|
Logger.Debug("Logging in with user [{0}]", pUsername)
|
|
pSMTP.UseBestLogin(pUsername, pPassword)
|
|
|
|
Return pSMTP
|
|
|
|
Catch ex As Exception
|
|
Logger.Warn("Could not connect to server [{0}] with user [{1}]", pServer, pUsername)
|
|
Logger.Error(ex)
|
|
Return pSMTP
|
|
|
|
End Try
|
|
End Function
|
|
|
|
Public Function New_IMAPConnection(pServer As String, pUsername As String, pPassword As String, pSecurity As EmailSecurity, Optional pPort As Integer = 0) As Imap
|
|
Try
|
|
Logger.Info("Connecting to IMAP server [{0}:{1}] with user [{2}]", pServer, pPort, pUsername)
|
|
|
|
Dim oIMAP As New Imap()
|
|
Dim oPort As Integer
|
|
If pPort = 0 Then
|
|
If pSecurity = EmailSecurity.SSL Then
|
|
oPort = Imap.DefaultSSLPort
|
|
|
|
Else
|
|
oPort = Imap.DefaultPort
|
|
|
|
End If
|
|
|
|
Else
|
|
oPort = pPort
|
|
|
|
End If
|
|
Logger.Debug("Using Port [{0}] for connection", oPort)
|
|
|
|
If pSecurity = EmailSecurity.SSL Then
|
|
Logger.Debug("Using SSL/TLS as Security Option")
|
|
oIMAP.ConnectSSL(pServer, oPort)
|
|
Else
|
|
Logger.Debug("Using STARTTLS as Security Option")
|
|
oIMAP.Connect(pServer, oPort)
|
|
oIMAP.StartTLS()
|
|
End If
|
|
Logger.Debug("Connection to IMAP Server [{0}] established!", pServer)
|
|
|
|
Logger.Debug("Logging in with user [{0}]", pUsername)
|
|
oIMAP.UseBestLogin(pUsername, pPassword)
|
|
|
|
Return oIMAP
|
|
|
|
Catch ex As Exception
|
|
Logger.Warn("Could not connect to server [{0}] with user [{1}]", pServer, pUsername)
|
|
Logger.Error(ex)
|
|
Throw ex
|
|
|
|
End Try
|
|
End Function
|
|
|
|
Public Function Test_IMAPLogin(pClient As Imap, Optional pFolder As String = "Inbox") As Boolean
|
|
Logger.Info("Testing Login to IMAP Server")
|
|
|
|
Try
|
|
Logger.Debug("Fetching Inbox")
|
|
Dim oStatus As FolderStatus = pClient.SelectInbox()
|
|
|
|
Logger.Debug("Test succeeded!")
|
|
|
|
Return True
|
|
Catch ex As Exception
|
|
Logger.Warn("Login failed for IMAP server!")
|
|
Logger.Error(ex)
|
|
|
|
Return False
|
|
End Try
|
|
End Function
|
|
|
|
Public Function Test_SMTPLogin(pClient As Smtp) As Boolean
|
|
Logger.Info("Testing Login to IMAP Server")
|
|
|
|
Try
|
|
Dim oExtensions = pClient.SupportedExtensions()
|
|
Dim oExtensionArray = oExtensions.Select(Function(ex) ex.ToString).ToArray
|
|
Logger.Debug("Supported Extensions: ")
|
|
Logger.Debug(String.Join(", ", oExtensionArray))
|
|
Logger.Debug("Test succeeded!")
|
|
|
|
Return True
|
|
Catch ex As Exception
|
|
Logger.Warn("Login failed for SMTP server!")
|
|
Logger.Error(ex)
|
|
|
|
Return False
|
|
End Try
|
|
End Function
|
|
|
|
Public Function Get_IMAPMessages(pClient As Imap, Optional pFolder As String = "Inbox") As List(Of IMail)
|
|
Logger.Info("Fetching Messages in Folder [{0}]", pFolder)
|
|
Dim oMails As New List(Of IMail)
|
|
|
|
Try
|
|
Logger.Debug("Fetching Folder [{0}]", pFolder)
|
|
Dim oStatus As FolderStatus = pClient.Select(pFolder)
|
|
|
|
Logger.Debug("Fetching Unseen UUIDs")
|
|
|
|
DisableExcessiveLogging = True
|
|
Dim oUUIDs As List(Of Long) = pClient.Search(Flag.Unseen)
|
|
DisableExcessiveLogging = False
|
|
|
|
Logger.Debug("Fetching Unseen Mails")
|
|
For Each oUUID As Long In oUUIDs
|
|
DisableExcessiveLogging = True
|
|
Dim oEmlFile As Byte() = pClient.GetMessageByUID(oUUID)
|
|
DisableExcessiveLogging = False
|
|
|
|
Dim oEmail As IMail = MailBuilder.CreateFromEml(oEmlFile)
|
|
oMails.Add(oEmail)
|
|
|
|
Next
|
|
|
|
Logger.Debug("Emails fetched!")
|
|
|
|
Return oMails
|
|
|
|
Catch ex As Exception
|
|
Logger.Warn("Fetching messages for folder [{0}] failed!", pFolder)
|
|
Logger.Error(ex)
|
|
Return New List(Of IMail)
|
|
|
|
End Try
|
|
End Function
|
|
|
|
Public Function Get_IMAPMessage(pClient As Imap, pMessageId As String, Optional pFolder As String = "Inbox") As IMail
|
|
Logger.Info("Fetching Message [{0}]", pMessageId)
|
|
|
|
Dim oMail As IMail = Nothing
|
|
|
|
Try
|
|
Logger.Debug("Fetching Folder [{0}]", pFolder)
|
|
Dim oStatus As FolderStatus = pClient.Select(pFolder)
|
|
|
|
Logger.Debug("Fetching UUIDs")
|
|
Dim oUUIDs As List(Of Long) = pClient.Search(Flag.All)
|
|
Logger.Debug("Fetching Mails")
|
|
|
|
DisableExcessiveLogging = True
|
|
Dim oInfos As List(Of MessageInfo) = pClient.GetMessageInfoByUID(oUUIDs)
|
|
DisableExcessiveLogging = False
|
|
|
|
Dim oMailInfo = oInfos.Where(Function(i) i.Envelope.MessageID = pMessageId).FirstOrDefault()
|
|
|
|
If oMailInfo IsNot Nothing Then
|
|
DisableExcessiveLogging = True
|
|
Dim oMailData As Byte() = pClient.GetMessageByUID(oMailInfo.UID)
|
|
DisableExcessiveLogging = False
|
|
oMail = MailBuilder.CreateFromEml(oMailData)
|
|
End If
|
|
|
|
Logger.Debug("Email fetched!")
|
|
|
|
Return oMail
|
|
|
|
Catch ex As Exception
|
|
Logger.Warn("Fetching message with MessageID [{0}] failed!", pMessageId)
|
|
Logger.Error(ex)
|
|
|
|
Return Nothing
|
|
|
|
End Try
|
|
End Function
|
|
|
|
Public Function Send_SMTPMessage(pClient As Smtp, pSender As String, pReceiver As String, pSubject As String, pBody As String) As Boolean
|
|
Logger.Info("Sending Message with Subject [{0}]", pSubject)
|
|
|
|
Try
|
|
Dim oBuilder As New MailBuilder()
|
|
oBuilder.From.Add(New Headers.MailBox(pSender))
|
|
oBuilder.To.Add(New Headers.MailBox(pReceiver))
|
|
oBuilder.Subject = pSubject
|
|
oBuilder.Text = pBody
|
|
|
|
Dim oMail As IMail = oBuilder.Create()
|
|
Dim oResult As ISendMessageResult = pClient.SendMessage(oMail)
|
|
|
|
If oResult.Status = SendMessageStatus.Success Then
|
|
Logger.Debug("Message sent successful!")
|
|
Return True
|
|
|
|
Else
|
|
Logger.Warn("Message sending failed. Status: [{0}]", oResult.Status)
|
|
Return False
|
|
|
|
End If
|
|
|
|
Catch ex As Exception
|
|
Logger.Warn("Message sending failed.")
|
|
Logger.Error(ex)
|
|
Return False
|
|
|
|
End Try
|
|
End Function
|
|
|
|
''' <summary>
|
|
''' Loads an eml file from disk and returns the IMail representation of it
|
|
''' </summary>
|
|
''' <param name="pFileName">Path to the eml file</param>
|
|
''' <returns>The IMail object</returns>
|
|
Public Function Load_Email(pFileName As String) As IMail
|
|
Dim oFileName As String = MaybeConvert_MsgToEml(pFileName)
|
|
Return MailBuilder.CreateFromEmlFile(oFileName)
|
|
End Function
|
|
|
|
''' <summary>
|
|
''' Removes all attachments from an EML file and saves it to a temporary file.
|
|
''' </summary>
|
|
''' <param name="pFileName">The EML file to process.</param>
|
|
''' <param name="pSuffix">The optional suffix to add to the original filename.</param>
|
|
''' <returns>The path of the new EML without attachments.</returns>
|
|
Public Function Remove_AttachmentsFromEmail(pFileName As String, Optional pSuffix As String = "") As String
|
|
Try
|
|
' Convert possible msg file to eml
|
|
Dim oEmlPath As String = MaybeConvert_MsgToEml(pFileName)
|
|
|
|
' Clean and version new path
|
|
Dim oTempPath As String = Path.Combine(Path.GetTempPath(), Add_FilenameSuffix(oEmlPath, pSuffix, ".eml"))
|
|
Dim oCleanedPath As String = FileEx.GetCleanPath(oTempPath)
|
|
Dim oVersionedPath As String = FileEx.GetVersionedFilename(oCleanedPath)
|
|
|
|
' Load eml file
|
|
Dim oMail = MailBuilder.CreateFromEmlFile(oEmlPath)
|
|
|
|
' Remove attachments and save
|
|
oMail.RemoveAttachments()
|
|
oMail.Save(oVersionedPath)
|
|
|
|
Return oVersionedPath
|
|
Catch ex As Exception
|
|
Logger.Error(ex)
|
|
|
|
Return Nothing
|
|
End Try
|
|
End Function
|
|
|
|
Public Function Save_AttachmentsToDisk(pFileName As String) As List(Of String)
|
|
Try
|
|
Dim oAttachmentPaths As New List(Of String)
|
|
Dim oEmlFile As String = MaybeConvert_MsgToEml(pFileName)
|
|
Dim oMail = MailBuilder.CreateFromEmlFile(oEmlFile)
|
|
Dim oTempPath As String = IO.Path.GetTempPath()
|
|
|
|
If oMail.Attachments.Count = 0 Then
|
|
Return New List(Of String)
|
|
End If
|
|
|
|
For Each oAttachment As MimeData In oMail.Attachments
|
|
Dim oPath As String = IO.Path.Combine(oTempPath, oAttachment.SafeFileName)
|
|
Dim oVersionedPath As String = FileEx.GetVersionedFilename(oPath)
|
|
|
|
oAttachment.Save(oVersionedPath)
|
|
oAttachmentPaths.Add(oVersionedPath)
|
|
TempFiles.Add(oVersionedPath)
|
|
Next
|
|
|
|
Return oAttachmentPaths
|
|
Catch ex As Exception
|
|
Logger.Error(ex)
|
|
|
|
Return New List(Of String)
|
|
End Try
|
|
End Function
|
|
|
|
Public Sub Clear_TempFiles()
|
|
Logger.Info("Cleaning [{0}] email temp files", TempFiles.Count)
|
|
For Each oFile In TempFiles
|
|
Try
|
|
IO.File.Delete(oFile)
|
|
Catch ex As Exception
|
|
Logger.Warn("Could not clean temp file [{0}]", oFile)
|
|
Logger.Error(ex)
|
|
End Try
|
|
Next
|
|
End Sub
|
|
|
|
Public Function Get_MessageSender(Mail As IMail) As String
|
|
Try
|
|
Dim oAddress = Mail.From.First()
|
|
|
|
If oAddress Is Nothing Then
|
|
Logger.Warn("Could not get MessageSender from Mail [{0}]", Mail.MessageID)
|
|
Return Nothing
|
|
End If
|
|
|
|
Return oAddress.Address
|
|
|
|
Catch ex As Exception
|
|
Logger.Warn("Could not get MessageSender from Mail [{0}]", Mail.MessageID)
|
|
Logger.Error(ex)
|
|
Return Nothing
|
|
|
|
End Try
|
|
End Function
|
|
|
|
Public Function Get_MessageReceiver(Mail As IMail) As String
|
|
Try
|
|
Dim oAddress = Mail.To.FirstOrDefault()
|
|
|
|
If oAddress Is Nothing Then
|
|
Logger.Warn("Could not get MessageReceiver from Mail [{0}]", Mail.MessageID)
|
|
Return Nothing
|
|
End If
|
|
|
|
Dim oMailBox = oAddress.GetMailboxes().First()
|
|
|
|
If oMailBox Is Nothing Then
|
|
Logger.Warn("Could not get MessageReceiver from Mail [{0}]", Mail.MessageID)
|
|
Return Nothing
|
|
End If
|
|
|
|
Return oMailBox.Address
|
|
|
|
Catch ex As Exception
|
|
Logger.Error(ex)
|
|
Return Nothing
|
|
|
|
End Try
|
|
End Function
|
|
|
|
Public Function Convert_ToEml(pFilePath As String) As String
|
|
Return MaybeConvert_MsgToEml(pFilePath)
|
|
End Function
|
|
|
|
Private Function MaybeConvert_MsgToEml(pEmailFilePath As String) As String
|
|
Dim oInfo As New FileInfo(pEmailFilePath)
|
|
|
|
If oInfo.Extension.ToUpper = ".EML" Then
|
|
Return pEmailFilePath
|
|
|
|
ElseIf oInfo.Extension.ToUpper = ".MSG" Then
|
|
Return DoConvertMsgToEmlFile(pEmailFilePath)
|
|
|
|
Else
|
|
Return Nothing
|
|
|
|
End If
|
|
End Function
|
|
|
|
Private Function DoConvertMsgToEmlFile(pMsgFile As String) As String
|
|
Try
|
|
Logger.Debug("Converting Msg file to Eml: [{0}]", pMsgFile?.ToString)
|
|
|
|
Dim oTempPath As String = IO.Path.GetTempPath()
|
|
Dim oFileNameWithoutExtension = Path.GetFileNameWithoutExtension(pMsgFile)
|
|
Dim oFileNameWithoutInvalidChars = Language.Utils.RemoveInvalidCharacters(oFileNameWithoutExtension)
|
|
Dim oEmlPath As String = IO.Path.Combine(oTempPath, $"{oFileNameWithoutInvalidChars}.eml")
|
|
Dim oVersionedPath As String = FileEx.GetVersionedFilename(oEmlPath)
|
|
|
|
Logger.Debug("New Path for Eml file: [{0}]", oVersionedPath)
|
|
|
|
Using oConverter As New MsgConverter(pMsgFile)
|
|
Logger.Debug("Converter created")
|
|
Dim oEmail As IMail = oConverter.CreateMessage()
|
|
Logger.Debug("Message created")
|
|
Dim oData As Byte() = oEmail.Render()
|
|
Logger.Debug("Message rendered")
|
|
|
|
oEmail.Save(oVersionedPath)
|
|
Logger.Debug("Message saved")
|
|
End Using
|
|
|
|
Logger.Info("Msg File successfully converted to Eml: [{0}]", oVersionedPath)
|
|
TempFiles.Add(oVersionedPath)
|
|
Return oVersionedPath
|
|
|
|
Catch ex As Exception
|
|
Logger.Warn("Converting Msg to Eml file failed!")
|
|
Logger.Error(ex)
|
|
|
|
Return Nothing
|
|
End Try
|
|
End Function
|
|
|
|
Private Function Add_FilenameSuffix(pFilename As String, pSuffix As String, Optional pExtension As String = Nothing)
|
|
Dim oFileInfo As New FileInfo(pFilename)
|
|
Dim oExtension As String = oFileInfo.Extension
|
|
|
|
If pExtension IsNot Nothing Then
|
|
If pExtension.StartsWith(".") = False Then
|
|
oExtension = $".{pExtension}"
|
|
Else
|
|
oExtension = pExtension
|
|
End If
|
|
End If
|
|
|
|
Dim oFileNameWithoutExtension = Path.GetFileNameWithoutExtension(pFilename)
|
|
|
|
Return $"{oFileNameWithoutExtension}{pSuffix}{oExtension}"
|
|
End Function
|
|
End Class
|