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.Error(ex) 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.Error(ex) 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.Error(ex) 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.Error(ex) 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.Error(ex) 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.Error(ex) 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.Error(ex) 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) 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.Error(ex) 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.Warn("Unexpected Error in IMAP_Set2Seen Independentsoft") Logger.Error(ex) Return False End Try End Function ''' ''' Uses a private API from MailWriter to write a MailMessage to disk. ''' May break in future versions of .NET ''' 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 Logger.Error(ex) Return Nothing End Try End Function End Class