Messaging: Add SMTP Functions, inital tests

This commit is contained in:
Jonathan Jenne 2021-07-26 16:32:06 +02:00
parent 999e2e617b
commit 0f0b517c56
2 changed files with 237 additions and 119 deletions

View File

@ -7,28 +7,34 @@ Public Class frmEmail
Private Email As Email2
Private Sub frmEmail_Load(sender As Object, e As EventArgs) Handles Me.Load
Logconfig = New LogConfig(LogConfig.PathType.Temp)
Logconfig = New LogConfig(LogConfig.PathType.Temp, ProductName:="TestGUI.IMAP")
Logconfig.Debug = True
Email = New Email2(Logconfig)
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim oResult = Email.Test_Login(txtServer.Text, txtUser.Text, txtPassword.Text, Email2.EmailSecurity.SSLTLS)
Using oClient = Email.New_IMAPConnection(txtServer.Text, txtUser.Text, txtPassword.Text, Email2.EmailSecurity.SSL)
Dim oResult = Email.Test_IMAPLogin(oClient, "Inbox")
If oResult = True Then
AddLog($"Connection to {txtServer.Text} successful.")
Else
AddLog($"Connection to {txtServer.Text} failed!")
End If
If oResult = True Then
AddLog($"Connection to {txtServer.Text} successful.")
Else
AddLog($"Connection to {txtServer.Text} failed!")
End If
End Using
End Sub
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
Dim oMessages = Email.Get_Messages(txtServer.Text, txtUser.Text, txtPassword.Text, Email2.EmailSecurity.SSLTLS, "Inbox")
AddLog($"Found {oMessages.Count} Messages!")
For Each oMessage In oMessages
AddLog(oMessage.MessageID)
Next
Using oClient = Email.New_IMAPConnection(txtServer.Text, txtUser.Text, txtPassword.Text, Email2.EmailSecurity.SSL)
Dim oMessages = Email.Get_IMAPMessages(oClient, "Inbox")
AddLog($"Found {oMessages.Count} Messages!")
For Each oMessage In oMessages
AddLog(oMessage.MessageID)
Next
End Using
End Sub
Private Sub AddLog(pMessage)
@ -36,22 +42,24 @@ Public Class frmEmail
End Sub
Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
Dim oMessageId As String = txtMessageID.Text
Dim oMail As IMail = Email.Get_Message(txtServer.Text, txtUser.Text, txtPassword.Text, Email2.EmailSecurity.SSLTLS, oMessageId, "Inbox")
Dim oFilename As String = IO.Path.GetTempFileName
oMail.Save(oFilename)
Using oClient = Email.New_IMAPConnection(txtServer.Text, txtUser.Text, txtPassword.Text, Email2.EmailSecurity.SSL)
Dim oMessageId As String = txtMessageID.Text
Dim oMail As IMail = Email.Get_IMAPMessage(oClient, oMessageId, "Inbox")
Dim oFilename As String = IO.Path.GetTempFileName
oMail.Save(oFilename)
AddLog($"Mail saved to {oFilename}")
AddLog($"Mail saved to {oFilename}")
Dim oEmailTempPath = Email.Remove_AttachmentsFromEmail(oFilename)
Dim oEmailTempPath = Email.Remove_AttachmentsFromEmail(oFilename)
AddLog($"Mail without attachments saved to {oEmailTempPath}")
AddLog($"Mail without attachments saved to {oEmailTempPath}")
Dim oAttachments As List(Of String) = Email.Save_AttachmentsToDisk(oFilename)
Dim oAttachments As List(Of String) = Email.Save_AttachmentsToDisk(oFilename)
For Each oAttachment In oAttachments
AddLog($"Attachmen saved to {oAttachment}")
Next
For Each oAttachment In oAttachments
AddLog($"Attachmen saved to {oAttachment}")
Next
End Using
End Sub
Private Sub ListBox1_SelectedValueChanged(sender As Object, e As EventArgs) Handles ListBox1.SelectedValueChanged

View File

@ -1,168 +1,238 @@
Imports DigitalData.Modules.Logging
Imports System.IO
Imports DigitalData.Modules.Logging
Imports DigitalData.Modules.Filesystem
Imports Limilabs.Mail
Imports Limilabs.Client.IMAP
Imports Limilabs.Mail.MIME
Imports System.IO
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 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
SSLTLS
STARTTLS
SSL
START_TLS
End Enum
Private Function Get_PortForSecurityOption(pSecurity As EmailSecurity) As Integer
If pSecurity = EmailSecurity.STARTTLS Then
Return 143
Else ' EmailSecurity.SSL
Return 993
Private Sub ProcessMailLog(pMessage As String)
If DisableExcessiveLogging = False Then
LoggerMail.Debug(pMessage)
End If
End Function
End Sub
Private Function New_Connection(pIMAP As Imap, pServer As String, pUsername As String, pPassword As String, pPort As Integer, pSecurity As EmailSecurity) As Boolean
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.Debug("Connecting to IMAP server [{0}]", pServer)
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
Dim oPort As Integer = pPort
If oPort = 0 Then
oPort = Get_PortForSecurityOption(pSecurity)
End If
Logger.Debug("Using Port [{0}] for connection", oPort)
If pSecurity = EmailSecurity.STARTTLS Then
Logger.Debug("Using STARTTLS as Security Option")
pIMAP.Connect(pServer, oPort)
pIMAP.StartTLS()
Else
If pSecurity = EmailSecurity.SSL Then
Logger.Debug("Using SSL/TLS as Security Option")
pIMAP.ConnectSSL(pServer, oPort)
pSMTP.ConnectSSL(pServer, oPort)
Else
Logger.Debug("Using STARTTLS as Security Option")
pSMTP.Connect(pServer, oPort)
pSMTP.StartTLS()
End If
Logger.Debug("Connection to IMAP Server [{0}] established!", pServer)
Logger.Debug("Connection to SMTP Server [{0}] established!", pServer)
Logger.Debug("Logging in with user [{0}]", pUsername)
pIMAP.UseBestLogin(pUsername, pPassword)
pSMTP.UseBestLogin(pUsername, pPassword)
Return True
Return pSMTP
Catch ex As Exception
Logger.Warn("Could not connect to server [{0}] with user [{1}]", pServer, pUsername)
Logger.Error(ex)
Return False
Return pSMTP
End Try
End Function
Public Function Test_Login(pServer As String, pUsername As String, pPassword As String, pSecurity As EmailSecurity, Optional pFolder As String = "Inbox", Optional pPort As Integer = 0) As Boolean
Logger.Debug("Testing Login to Server [{0}:{1}] with user [{2}]", pServer, pPort, pUsername)
Public Function New_IMAPConnection(pServer As String, pUsername As String, pPassword As String, pSecurity As EmailSecurity, Optional pPort As Integer = 0) As Imap
Try
Using oClient As New Imap()
If New_Connection(oClient, pServer, pUsername, pPassword, pPort, pSecurity) Then
Logger.Debug("Fetching Inbox")
Dim oStatus As FolderStatus = oClient.SelectInbox()
Logger.Info("Connecting to IMAP server [{0}:{1}] with user [{2}]", pServer, pPort, pUsername)
Logger.Debug("Test finished!")
oClient.Close()
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
End Using
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 server [{0}:{1}] with user [{2}]!", pServer, pPort, pUsername)
Logger.Warn("Login failed for IMAP server!")
Logger.Error(ex)
Return False
End Try
End Function
Public Function Get_Messages(pServer As String, pUsername As String, pPassword As String, pSecurity As EmailSecurity, Optional pFolder As String = "Inbox", Optional pPort As Integer = 0) As List(Of IMail)
Logger.Debug("Fetching Messages from Server [{0}:{1}] with user [{2}]", pServer, pPort, pUsername)
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
Using oClient As New Imap()
If New_Connection(oClient, pServer, pUsername, pPassword, pPort, pSecurity) Then
Logger.Debug("Fetching Folder [{0}]", pFolder)
Dim oStatus As FolderStatus = oClient.Select(pFolder)
Logger.Debug("Fetching Folder [{0}]", pFolder)
Dim oStatus As FolderStatus = pClient.Select(pFolder)
Logger.Debug("Fetching Unseen UUIDs")
Dim oUUIDs As List(Of Long) = oClient.Search(Flag.Unseen)
Dim oMailBuilder As New MailBuilder()
Logger.Debug("Fetching Unseen UUIDs")
Logger.Debug("Fetching Unseen Mails")
For Each oUUID As Long In oUUIDs
Dim oEmlFile As Byte() = oClient.GetMessageByUID(oUUID)
Dim oEmail As IMail = oMailBuilder.CreateFromEml(oEmlFile)
oMails.Add(oEmail)
DisableExcessiveLogging = True
Dim oUUIDs As List(Of Long) = pClient.Search(Flag.Unseen)
DisableExcessiveLogging = False
Next
Logger.Debug("Fetching Unseen Mails")
For Each oUUID As Long In oUUIDs
DisableExcessiveLogging = True
Dim oEmlFile As Byte() = pClient.GetMessageByUID(oUUID)
DisableExcessiveLogging = False
Logger.Debug("Emails fetched!")
oClient.Close()
Dim oEmail As IMail = MailBuilder.CreateFromEml(oEmlFile)
oMails.Add(oEmail)
End If
Next
End Using
Logger.Debug("Emails fetched!")
Return oMails
Catch ex As Exception
Logger.Warn("Login failed for server [{0}:{1}] with user [{2}]!", pServer, pPort, pUsername)
Logger.Warn("Fetching messages for folder [{0}] failed!", pFolder)
Logger.Error(ex)
Return New List(Of IMail)
End Try
End Function
Public Function Get_Message(pServer As String, pUsername As String, pPassword As String, pSecurity As EmailSecurity, pMessageId As String, Optional pFolder As String = "Inbox", Optional pPort As Integer = 0) As IMail
Logger.Debug("Fetching Message [{0}] from Server [{1}:{2}] with user [{3}]", pMessageId, pServer, pPort, pUsername)
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
Using oClient As New Imap()
If New_Connection(oClient, pServer, pUsername, pPassword, pPort, pSecurity) Then
Logger.Debug("Fetching Folder [{0}]", pFolder)
Dim oStatus As FolderStatus = oClient.Select(pFolder)
Logger.Debug("Fetching Folder [{0}]", pFolder)
Dim oStatus As FolderStatus = pClient.Select(pFolder)
Logger.Debug("Fetching UUIDs")
Dim oUUIDs As List(Of Long) = oClient.Search(Flag.All)
Logger.Debug("Fetching Mails")
Dim oInfos As List(Of MessageInfo) = oClient.GetMessageInfoByUID(oUUIDs)
Logger.Debug("Fetching UUIDs")
Dim oUUIDs As List(Of Long) = pClient.Search(Flag.All)
Logger.Debug("Fetching Mails")
Dim oMailInfo = oInfos.Where(Function(i) i.Envelope.MessageID = pMessageId).FirstOrDefault()
DisableExcessiveLogging = True
Dim oInfos As List(Of MessageInfo) = pClient.GetMessageInfoByUID(oUUIDs)
DisableExcessiveLogging = False
If oMailInfo IsNot Nothing Then
Dim oMailData As Byte() = oClient.GetMessageByUID(oMailInfo.UID)
oMail = MailBuilder.CreateFromEml(oMailData)
End If
Dim oMailInfo = oInfos.Where(Function(i) i.Envelope.MessageID = pMessageId).FirstOrDefault()
Logger.Debug("Emails fetched!")
oClient.Close()
If oMailInfo IsNot Nothing Then
DisableExcessiveLogging = True
Dim oMailData As Byte() = pClient.GetMessageByUID(oMailInfo.UID)
DisableExcessiveLogging = False
oMail = MailBuilder.CreateFromEml(oMailData)
End If
End If
End Using
Logger.Debug("Email fetched!")
Return oMail
Catch ex As Exception
Logger.Warn("Login failed for server [{0}:{1}] with user [{2}]!", pServer, pPort, pUsername)
Logger.Warn("Fetching message with MessageID [{0}] failed!", pMessageId)
Logger.Error(ex)
Return Nothing
@ -170,15 +240,54 @@ Public Class Email2
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>
''' 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
Dim oTempFileName As String = Path.Combine(Path.GetTempPath(), AddFilenameSuffix(pFileName, pSuffix))
Dim oTempPath As String = Path.Combine(Path.GetTempPath(), Add_FilenameSuffix(pFileName, pSuffix))
Dim oCleanedPath As String = FileEx.GetCleanFilename(oTempPath)
Dim oVersionedPath As String = FileEx.GetVersionedFilename(oCleanedPath)
Dim oMail = MailBuilder.CreateFromEmlFile(pFileName)
oMail.RemoveAttachments()
oMail.Save(oTempFileName)
oMail.Save(oVersionedPath)
Return oTempFileName
Return oVersionedPath
Catch ex As Exception
Logger.Error(ex)
@ -186,6 +295,10 @@ Public Class Email2
End Try
End Function
Public Function Load_Email(pFileName As String) As IMail
Return MailBuilder.CreateFromEmlFile(pFileName)
End Function
Public Function Save_AttachmentsToDisk(pFileName As String) As List(Of String)
Try
Dim oAttachmentPaths As New List(Of String)
@ -212,7 +325,7 @@ Public Class Email2
End Try
End Function
Public Function ConvertMsgToEml(pEmailFileName As String) As String
Public Function Convert_MsgToEml(pEmailFileName As String) As String
Dim oInfo As New FileInfo(pEmailFileName)
If oInfo.Extension.ToUpper = ".EML" Then
@ -229,38 +342,35 @@ Public Class Email2
Private Function DoConvertMsgToEmlFile(pMsgFile As String) As String
Try
Dim oTempPath As String = IO.Path.GetTempPath()
Dim oFileNameWithoutExtension = Path.GetFileNameWithoutExtension(pMsgFile)
Dim oEmlPath As String = $"{oFileNameWithoutExtension}.eml"
Dim oEmlPath As String = IO.Path.Combine(oTempPath, $"{oFileNameWithoutExtension}.eml")
Dim oVersionedPath As String = FileEx.GetVersionedFilename(oEmlPath)
Using oConverter As New MsgConverter(pMsgFile)
Dim oEmail As IMail = oConverter.CreateMessage()
Dim oData As Byte() = oEmail.Render()
oEmail.Save(oEmlPath)
oEmail.Save(oVersionedPath)
End Using
Return oEmlPath
Return oVersionedPath
Catch ex As Exception
Return Nothing
Logger.Warn("Converting Msg to Eml file failed!")
Logger.Error(ex)
Return Nothing
End Try
End Function
Private Function GetTempFileNameWithExtension(pExtension As String) As String
Dim oTempFileName As String = IO.Path.GetTempFileName()
Dim oInfo As New IO.FileInfo(oTempFileName)
Dim oExtension As String = IIf(pExtension.StartsWith("."), pExtension, $".{pExtension}")
Dim oNewFileName = IO.Path.Combine(oInfo.DirectoryName, oInfo.Name.Replace(oInfo.Extension, oExtension))
Return oNewFileName
End Function
Private Function AddFilenameSuffix(pFilename As String, pSuffix As String)
Private Function Add_FilenameSuffix(pFilename As String, pSuffix As String)
Dim oFileInfo As New FileInfo(pFilename)
Dim oExtension As String = oFileInfo.Extension
Dim oFileNameWithoutExtension = Path.GetFileNameWithoutExtension(pFilename)
Return $"{oFileNameWithoutExtension}{pSuffix}{oExtension}"
End Function
End Class