381 lines
20 KiB
VB.net

Imports Independentsoft.Email
Imports Independentsoft.Email.Imap
Imports Independentsoft.Email.Mime
Imports DigitalData.EMLProfiler.ClassCurrent
Imports DigitalData.Modules.Logging
Imports AE
Imports System.Net
Imports System.Reflection
Imports System.IO
Imports DigitalData.Modules.Database
Public Class clsEmailIMAP
Private Shared Logger As DigitalData.Modules.Logging.Logger
Private Shared LogConfig As DigitalData.Modules.Logging.LogConfig
Private _DB_MSSQL As clsDatabase
Sub New(LogConf As LogConfig, ECMConnectionString As String)
LogConfig = LogConf
Logger = LogConf.GetLogger
_DB_MSSQL = New clsDatabase(LogConf, ECMConnectionString)
End Sub
'Private Shared Sub OnWriteLog(ByVal sender As Object, ByVal e As WriteLogEventArgs)
' Logger.Info(e.Log)
'End Sub
Public Function FetchIMAPMessagesS22(Server As String, Port As Integer, Username As String, Password As String, pInbox As String, Optional IsTest As Boolean = False, Optional DeleteinTest As Boolean = False, Optional MoveMailTo As String = "") As Boolean
Logger.Debug("FetchIMAPMessagesS22 - Connecting to Server {0}:{1} with user {2}", Server, Port, Username)
Try
Logger.Debug("FetchIMAPMessagesS22 - Connecting...")
Using oClient As New S22.Imap.ImapClient(Server, Port, Username, Password, S22.Imap.AuthMethod.Login, True)
If Not oClient.Authed Then
Logger.Warn("FetchIMAPMessagesS22 - Connected to server but authentication failed.")
Return False
End If
Logger.Info($"FetchIMAPMessagesS22 - Fetching unseen MessageIds from Inbox: {pInbox}")
Dim oMessageIds As IEnumerable(Of UInteger) = oClient.Search(S22.Imap.SearchCondition.Unseen, pInbox)
Logger.Info("FetchIMAPMessagesS22 - Found [{0}] messages", oMessageIds.Count)
Logger.Debug("FetchIMAPMessagesS22 - Fetching messages...")
Dim oMessageCountRegular As Integer = 0
Dim oMessageCountWorked As Integer = 0
Dim oLastLog As String
For Each oMessageId As UInteger In oMessageIds
Logger.Debug($"Checking message...")
Dim oMessage = oClient.GetMessage(oMessageId, False, pInbox)
oLastLog = $"Checking message with Subject [{oMessage.Subject}] From [{oMessage.From}]"
Logger.Debug(oLastLog)
Dim oTempPath = Path.GetTempFileName()
Try
Dim oResult = WriteMessageToFile(oMessage, oTempPath)
oLastLog &= $" # Message written to TempPath [{oTempPath}]"
Dim oMessageREFGUID
Dim oMsg As Message
Try
oLastLog &= " # Creating the New Message(oTempPath)"
oMsg = New Message(oTempPath)
oLastLog &= " # Extracting the MessageID"
oMessageREFGUID = oMsg.MessageID
Catch ex As Exception
Logger.Warn($"FetchIMAPMessagesS22 - Could not get a MessageID or create a MailObject - Error: {ex.Message} - Last Debug Log: [{oLastLog}]")
Continue For
End Try
oLastLog &= " # Got the MessageID"
oMessageREFGUID = oMessageREFGUID.Replace(">", "").Replace("<", "")
Dim oCHECKSQL = $"SELECT * FROM TBEMLP_HISTORY WHERE EMAIL_MSGID = '{oMessageREFGUID}'"
Dim oCHECKDT As DataTable = _DB_MSSQL.Return_Datatable(oCHECKSQL)
If Not IsNothing(oCHECKDT) Then
If oCHECKDT.Rows.Count = 0 Then
oMessageCountRegular += 1
CURRENT_WORKMAIL_LIST.Add(oMsg)
oLastLog &= " # Added to CURRENT_WORKMAIL_LIST"
Else
Logger.Info("FetchIMAPMessagesS22 - Message has already been worked! Skipping!")
Logger.Debug($"Message shall be deleted...")
oLastLog &= " # Message shall be deleted..."
oClient.DeleteMessage(oMessageId)
Logger.Debug($"FetchIMAPMessagesS22 - Message has been deleted!")
oLastLog &= " # FetchIMAPMessagesS22 - Message has been deleted!"
Dim oUpd = $"UPDATE TBEMLP_HISTORY SET DATE_DELETED_INBOX = GETDATE() WHERE EMAIL_MSGID = '{oMessageId}'"
_DB_MSSQL.Execute_non_Query(oUpd)
oMessageCountWorked += 1
End If
If IsTest = True Then
Logger.Debug($"FetchIMAPMessagesS22 - IMAP-Test Message#: {oMessageCountRegular} - Msgsubject is: {oMsg.Subject} - MsgMessageID is: {oMessageREFGUID}")
Logger.Debug($"FetchIMAPMessagesS22 - message correctly fetched. Mail has been downloaded to {oTempPath}")
End If
Try
If DeleteinTest = True Then
Logger.Debug($"Message shall be deleted...")
oClient.DeleteMessage(oMessageId,)
Logger.Debug($"FetchIMAPMessagesS22 - Message has been deleted!")
End If
Catch ex As Exception
Logger.Warn("Message could not be deleted: " & ex.Message)
End Try
If MoveMailTo <> String.Empty Then
Try
Logger.Debug($"Moving to [{MoveMailTo}] is active...")
oClient.MoveMessage(oMessageId, MoveMailTo)
Logger.Debug($"FetchIMAPMessagesS22 - successfully moved!")
Catch ex As Exception
Logger.Warn($"FetchIMAPMessagesS22 - Could not move message to folder [{MoveMailTo}] - Error: {ex.Message}")
End Try
End If
End If
Try
If IsTest = False Then
File.Delete(oTempPath)
End If
Catch ex As Exception
End Try
Catch ex As Exception
Logger.Warn($"FetchIMAPMessages - Unexpected Error while working on email: [{ex.Message}] - Last Debug Log: [{oLastLog}]")
End Try
Next
oClient.Expunge()
Logger.Debug("FetchIMAPMessagesS22 - Finished Message-Fetch")
If oMessageCountRegular > 0 Or oMessageCountWorked > 0 Then
Logger.Info($"###############################################")
If oMessageCountRegular > 0 Then
Logger.Info($"Found [{oMessageCountRegular.ToString}] regular messages to work on!")
End If
If oMessageCountWorked > 0 Then
Logger.Info($"Found [{oMessageCountWorked.ToString}] worked messages to work on!")
End If
If IsTest = True Then
Dim omsgtext As String
If oMessageCountRegular > 0 Then
omsgtext = $"Found [{oMessageCountRegular.ToString}] regular Messages to work on!"
End If
If oMessageCountWorked > 0 Then
If omsgtext = String.Empty Then
Logger.Info($"Found [{oMessageCountWorked.ToString}] worked messages to work on!")
Else
omsgtext += vbNewLine & $"Found [{oMessageCountWorked.ToString}] worked messages to work on!"
End If
End If
MsgBox(omsgtext)
End If
Logger.Info($"###############################################")
End If
End Using
Return True
Catch ex As Exception
Logger.Error(ex)
Return False
End Try
End Function
Private Shared Sub OnWriteLog(ByVal sender As Object, ByVal e As WriteLogEventArgs)
Logger.Debug(e.Log)
End Sub
Public Function FetchIMAPMessagesIsoft(Server As String, Port As Integer, Username As String, Password As String, Inbox As String, Optional MoveMailTo As String = "", Optional IsoftLog As String = "", Optional IsTest As Boolean = False, Optional DeleteinTest As Boolean = False)
Try
Logger.Debug(String.Format("Working on IMAP_COLLECT Independentsoft..."))
Dim oClient As New Independentsoft.Email.Imap.ImapClient(Server, Port)
If IsoftLog <> "" And LogConfig.Debug = True Then
Dim iLogger As New Independentsoft.Email.Logger(IsoftLog)
AddHandler iLogger.WriteLog, AddressOf OnWriteLog
oClient.Logger = iLogger
End If
oClient.EnableSsl = True
oClient.ValidateRemoteCertificate = False
Try
oClient.Connect()
Catch ex As Exception
Logger.Warn("Error while oClient.Connec(): " & ex.Message)
Return False
End Try
Try
oClient.Login(Username, Password, AuthenticationType.Login)
Catch ex As Exception
Logger.Warn("Error while loginImap.now trying Ntlm-Auth: " & ex.Message)
Try
oClient.Login(Username, Password, AuthenticationType.Ntlm)
Catch ex1 As Exception
Logger.Error(ex)
Return False
End Try
End Try
Logger.Debug("Logged in...")
oClient.SelectFolder(Inbox)
Dim coSearchCriteria As New SearchCriteria()
coSearchCriteria.All = True
Dim oMessageCountRegular As Integer = 0
Dim oMessageCountWorked As Integer = 0
Dim oUniqueID As Integer() = oClient.Search(coSearchCriteria)
If IsTest = True Then
MsgBox($"{oUniqueID.Count} messages in Postbox! (oUniqueID.Length: {oUniqueID.Length.ToString})")
End If
Dim oFoundMessages As Message() = New Message(oUniqueID.Length - 1) {}
Dim oEnvelopes As Independentsoft.Email.Imap.Envelope() = oClient.ListMessages()
For oCounterEnvelope As Integer = 0 To oEnvelopes.Length - 1
Logger.Debug($"oEnvelopes.Length: {oEnvelopes.Length}")
For oCounterEmailInPostbox As Integer = 0 To oUniqueID.Length - 1
If oEnvelopes(oCounterEnvelope).UniqueID = oUniqueID(oCounterEmailInPostbox) Then
Dim oMimeMessage As Mime.Message = oClient.GetMessage(oEnvelopes(oCounterEnvelope).UniqueID)
If Not IsNothing(oMimeMessage) Then
Dim oMessageID = oMimeMessage.MessageID
oMessageID = oMessageID.Replace(">", "").Replace("<", "")
'oEnvelopes(oCounterEnvelope).UniqueI
Logger.Info($"Isoft: Working on email: MessageID [{oMessageID}] - Subject[{oEnvelopes(oCounterEnvelope).Subject}] - Date [{oEnvelopes(oCounterEnvelope).Date.ToString}]")
Dim oCHECKSQL = $"SELECT * FROM TBEMLP_HISTORY WHERE lower(EMAIL_MSGID) = lower('{oMessageID}')"
Dim oCHECKDT As DataTable = _DB_MSSQL.Return_Datatable(oCHECKSQL)
If Not IsNothing(oCHECKDT) Then
If oCHECKDT.Rows.Count = 0 Then
Logger.Info($"Isoft: Adding email: MessageID [{oMessageID}] - Subject[{oEnvelopes(oCounterEnvelope).Subject}] - Date [{oEnvelopes(oCounterEnvelope).Date.ToString}]")
oMessageCountRegular += 1
CURRENT_WORKMAIL_LIST.Add(oMimeMessage)
Else
Logger.Info($"Isoft: Already existing email with MessageID [{oMessageID}] - Subject[{oEnvelopes(oCounterEnvelope).Subject}] - Date [{oEnvelopes(oCounterEnvelope).Date.ToString}] ")
oMessageCountWorked += 1
Try
oClient.Delete(oEnvelopes(oCounterEnvelope).UniqueID)
Dim oUpd = $"UPDATE TBEMLP_HISTORY SET DATE_DELETED_INBOX = GETDATE(), COMMENT = 'DELETED MESSAGE FROM INBOX (2ndRun ALREADY WORKED)' WHERE lower(EMAIL_MSGID) = lower('{oMessageID}')"
_DB_MSSQL.Execute_non_Query(oUpd)
Catch ex As Exception
Logger.Warn($"Error deleting/Commenting message due to to already worked: {ex.Message}")
End Try
End If
oClient.Store(oEnvelopes(oCounterEnvelope).UniqueID, "+FLAGS", "SEEN")
If MoveMailTo <> String.Empty Then
Try
oClient.AddMessage(MoveMailTo, oMimeMessage)
Catch ex As Exception
Logger.Warn($"Isoft: Could not move message to folder [{MoveMailTo}] - Error: {ex.Message}")
End Try
End If
If oMessageCountRegular = 250 Then
Logger.Warn($"Worked 100 Mails exiting oCounterEmailInPostbox!")
Exit For
End If
End If
End If
End If
Next
Next
oClient.Expunge()
oClient.Disconnect()
If oMessageCountRegular > 0 Or oMessageCountWorked > 0 Then
Logger.Info($"###############################################")
If oMessageCountRegular > 0 Then
Logger.Info($"Isoft: Found [{oMessageCountRegular.ToString}] regular messages to work on!")
End If
If oMessageCountWorked > 0 Then
Logger.Info($"Isoft: Found [{oMessageCountWorked.ToString}] worked messages to work on!")
End If
If IsTest = True Then
Dim omsgtext As String
If oMessageCountRegular > 0 Then
omsgtext = $"Isoft: Found [{oMessageCountRegular.ToString}] regular Messages to work on!"
End If
If oMessageCountWorked > 0 Then
If omsgtext = String.Empty Then
Logger.Info($"Isoft: Found [{oMessageCountWorked.ToString}] worked messages to work on!")
Else
omsgtext += vbNewLine & $"Isoft: Found [{oMessageCountWorked.ToString}] worked messages to work on!"
End If
End If
MsgBox(omsgtext)
End If
Logger.Info($"###############################################")
End If
' Logger.Debug($"{oCount.ToString} messages will be worked..")
Logger.Debug("Isoft: IMAP COLLECT Independentsoft finished!")
Return True
Catch ex As Exception
Logger.Error(ex, "Unexpected Error in IMAP COLLECT Independentsoft:")
Return False
End Try
End Function
Public Function IMAP_Set2Seen(Server As String, Port As Integer, Username As String, Password As String, IsoftLog As String)
Try
Logger.Debug(String.Format("Working on IMAP_Set2Seen Independentsoft..."))
Dim oClient As New Independentsoft.Email.Imap.ImapClient(Server, Port)
If IsoftLog <> "" And LogConfig.Debug = True Then
Dim iLogger As New Independentsoft.Email.Logger(IsoftLog)
AddHandler iLogger.WriteLog, AddressOf OnWriteLog
oClient.Logger = iLogger
End If
oClient.EnableSsl = True
oClient.ValidateRemoteCertificate = False
oClient.Connect()
Try
oClient.Login(Username, Password, AuthenticationType.Login)
Catch ex As Exception
Logger.Warn("Error while loginImap.now trying Ntlm-Auth: " & ex.Message)
Try
oClient.Login(Username, Password, AuthenticationType.Ntlm)
Catch ex1 As Exception
Logger.Error(ex)
Return False
End Try
End Try
Logger.Debug("Logged in...")
oClient.SelectFolder("Inbox")
Dim coSearchCriteria As New SearchCriteria()
coSearchCriteria.Unseen = True
Dim oUniqueID As Integer() = oClient.Search(coSearchCriteria)
Dim oFoundMessages As Message() = New Message(oUniqueID.Length - 1) {}
For i As Integer = 0 To oUniqueID.Length - 1
oFoundMessages(i) = oClient.GetMessage(oUniqueID(i))
If oFoundMessages(i).Subject.ToLower.Contains("seen") Then
Logger.Debug($"Working on unseen email: [{oUniqueID(i)}] Subject:{oFoundMessages(i).Subject} - Date {oFoundMessages(i).Date}")
Dim oEnvelopes1 As Independentsoft.Email.Imap.Envelope() = oClient.ListMessages()
For i1 As Integer = 0 To oEnvelopes1.Length - 1
If oEnvelopes1(i1).UniqueID = oUniqueID(i) Then
Logger.Debug($"Setting email to Unseen!")
oClient.Store(oEnvelopes1(i1).UniqueID, "+FLAGS", "SEEN")
MsgBox("Set to SEEN")
End If
Next
End If
Next
oClient.Expunge()
MsgBox("Expunge done")
oClient.Disconnect()
Logger.Debug("IMAP_Set2Seen finished!")
Return True
Catch ex As Exception
Logger.Error(ex, "Unexpected Error in IMAP_Set2Seen Independentsoft:")
Return False
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 Mail.MailMessage, Filename As String) As Boolean
Dim oAssembly As Assembly = GetType(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(Mail.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
End Class