diff --git a/Windows/FileDrop.vb b/Windows/FileDrop.vb
new file mode 100644
index 00000000..bb97b8b2
--- /dev/null
+++ b/Windows/FileDrop.vb
@@ -0,0 +1,313 @@
+Imports System.Text
+Imports DigitalData.Modules.Base
+Imports DigitalData.Modules.Logging
+Imports DigitalData.Modules.Language.Utils
+Imports Microsoft.Office.Interop
+Imports System.Windows
+
+Public Class FileDrop
+ Inherits BaseClass
+
+ Public Enum FileFormat
+ OutlookAttachment
+ OutlookMail
+ ThunderbirdAttachment
+ ThunderbirdMail
+ MailWithoutAttachments
+ LocalFile
+ Unknown
+ End Enum
+
+ Public Enum FileSource
+ DragDrop
+ FolderWatch
+ Attachment
+ End Enum
+
+ Public Class DroppedFile
+ Public ReadOnly Property FilePath As String
+ Public Property FileFormat As FileFormat
+ Public Property FileSource As FileSource = FileSource.DragDrop
+
+ Public Sub New(pFilePath As String)
+ FilePath = pFilePath
+ End Sub
+
+ Public Sub New(pFilePath As String, pDropType As String)
+ MyClass.New(pFilePath)
+
+ Select Case pDropType
+ Case "LOCAL_FILE" ' "|DROPFROMFSYSTEM|"
+ FileFormat = FileFormat.LocalFile
+
+ Case "OUTLOOK_ATTACHMENT" ' "|OUTLOOK_ATTACHMENT|"
+ FileFormat = FileFormat.OutlookAttachment
+
+ Case "OUTLOOK_MAIL" ' "|OUTLOOK_MESSAGE|"
+ FileFormat = FileFormat.OutlookMail
+
+ Case "|MSGONLY|"
+ FileFormat = FileFormat.MailWithoutAttachments
+
+ Case "|FW_OUTLOOK_MESSAGE|"
+ FileFormat = FileFormat.OutlookMail
+ FileSource = FileSource.FolderWatch
+
+ Case "|FW_SIMPLEINDEXER|"
+ FileFormat = FileFormat.LocalFile
+ FileSource = FileSource.FolderWatch
+
+ Case "|ATTMNTEXTRACTED|"
+ FileFormat = FileFormat.LocalFile
+ FileSource = FileSource.Attachment
+
+ End Select
+ End Sub
+ End Class
+
+ Public Sub New(pLogConfig As LogConfig)
+ MyBase.New(pLogConfig)
+ End Sub
+
+ Public Function GetFileFormat(pEvent As DragEventArgs) As FileFormat
+ If IsThunderbird(pEvent) Then
+ If IsThunderbirdAttachment(pEvent) Then
+ Return FileFormat.ThunderbirdAttachment
+
+ ElseIf IsThunderbirdMail(pEvent) Then
+ Return FileFormat.ThunderbirdMail
+
+ Else
+ Return FileFormat.Unknown
+ End If
+ End If
+
+ If IsOutlook(pEvent) Then
+ If IsOutlookAttachment(pEvent) Then
+ Return FileFormat.OutlookAttachment
+
+ ElseIf IsOutlookMail(pEvent) Then
+ Return FileFormat.OutlookMail
+
+ Else
+ Return FileFormat.Unknown
+ End If
+ End If
+
+ If IsNormalFile(pEvent) Then
+ Return FileFormat.LocalFile
+
+ Else
+ Return FileFormat.Unknown
+ End If
+ End Function
+
+ Public Function GetFilePaths(pEvent As DragEventArgs) As List(Of DroppedFile)
+ Try
+ Dim oFormat = GetFileFormat(pEvent)
+ Dim oFiles As New List(Of DroppedFile)
+
+ Select Case oFormat
+ Case FileFormat.OutlookAttachment, FileFormat.OutlookMail
+ Dim oFilePaths = GetOutlookFilePath(pEvent)
+
+ For Each oPath In oFilePaths
+ oFiles.Add(New DroppedFile(oPath) With {
+ .FileFormat = oFormat
+ })
+ Next
+
+ Case Else
+ Dim oDroppedFiles As String() = GetFormat(pEvent, "FileDrop")
+
+ If oDroppedFiles IsNot Nothing Then
+ For Each oPath In oDroppedFiles
+ oFiles.Add(New DroppedFile(oPath) With {
+ .FileFormat = oFormat
+ })
+ Next
+ End If
+
+ End Select
+
+ Return oFiles
+
+ Catch ex As Exception
+ Logger.Error(ex)
+ Return Nothing
+
+ End Try
+ End Function
+
+ Private Function GetOutlookFilePath(pEvent As DragEventArgs) As List(Of String)
+ Dim oTempPath As String = IO.Path.GetTempPath()
+ Dim oFileName As String = GetOutlookFileName(pEvent)
+ Dim oFilePath As String = IO.Path.Combine(oTempPath, oFileName)
+ Dim oContentsList As List(Of Byte()) = GetOutlookFileContents_FromInterop(pEvent)
+
+ If oContentsList Is Nothing Then
+ Return Nothing
+ End If
+
+ Dim oPathList As New List(Of String)
+
+ For Each oContents In oContentsList
+ Using oFileStream As IO.FileStream = New IO.FileStream(oFilePath, IO.FileMode.Create)
+ oFileStream.Write(oContents, 0, oContents.Length)
+ oFileStream.Close()
+ End Using
+
+ oPathList.Add(oFilePath)
+ Next
+
+ Return oPathList
+
+ End Function
+
+ Private Function GetOutlookFileName(pEvent As DragEventArgs) As String
+ Dim oFileDescriptorSize = 512
+ Dim oIndex As Integer = 76
+ Dim oBuilder As New StringBuilder()
+
+ Using oStream As IO.MemoryStream = GetFormat(pEvent, "FileGroupDescriptor")
+ Dim oFileGroupDescriptor As Byte() = New Byte(oFileDescriptorSize) {}
+ oStream.Read(oFileGroupDescriptor, 0, oFileDescriptorSize)
+
+ While oFileGroupDescriptor(oIndex) <> 0
+ Dim oChar = Convert.ToChar(oFileGroupDescriptor(oIndex))
+ oBuilder.Append(oChar)
+ oIndex += 1
+ End While
+ End Using
+
+ Return oBuilder.ToString
+ End Function
+
+ Private Function GetOutlookFileContents_FromDragEvent(pEvent As DragEventArgs) As List(Of Byte())
+ Using oStream As IO.MemoryStream = pEvent.Data.GetData("FileContents", True)
+ If oStream Is Nothing Then
+ Return Nothing
+ End If
+
+ Dim oContentLength = Convert.ToInt32(oStream.Length)
+ Dim oContents As Byte() = New Byte(oContentLength) {}
+
+ oStream.Position = 0
+ oStream.Read(oContents, 0, Convert.ToInt32(oContentLength))
+
+ Return New List(Of Byte()) From {oContents}
+ End Using
+ End Function
+
+ Private Function GetOutlookFileContents_FromInterop(pEvent As DragEventArgs) As List(Of Byte())
+ Dim oApp As Outlook.Application
+ Try
+ oApp = New Outlook.Application()
+ Catch ex As Exception
+ Logger.Error(ex)
+ Return Nothing
+ End Try
+
+ Dim oResults As New List(Of Byte())
+ Dim oMailItem As Outlook.MailItem
+ For oIndex As Integer = 1 To oApp.ActiveExplorer.Selection.Count
+ Try
+ oMailItem = oApp.ActiveExplorer.Selection.Item(oIndex)
+
+ Dim oSubject As String = ConvertTextToSlug(oMailItem.Subject)
+ If oSubject = "" Then
+ oSubject = "NO_SUBJECT"
+ End If
+ Logger.Info("Subject Slug: [{0}]", oSubject)
+
+ Dim oFileName As String = $"{oSubject}.msg"
+ Dim oTempPath As String = IO.Path.GetTempPath()
+ Dim oFilePath As String = IO.Path.Combine(oTempPath, oFileName)
+
+ oMailItem.SaveAs(oFilePath)
+
+ Using oFileStream As New IO.FileStream(oFilePath, IO.FileMode.Open)
+
+ Dim oContents As Byte() = New Byte(oFileStream.Length) {}
+ oFileStream.Read(oContents, 0, oFileStream.Length)
+
+ oResults.Add(oContents)
+ End Using
+
+ Try
+ IO.File.Delete(oFilePath)
+ Catch ex As Exception
+ Logger.Warn("Temp file [{0}] could not be deleted!", oFilePath)
+ Logger.Error(ex)
+ End Try
+
+ Return oResults
+ Catch ex As Exception
+ Logger.Error(ex)
+ End Try
+ Next
+ End Function
+
+ Public Function GetFormat(pEvent As DragEventArgs, pFormat As String, pAutoConvert As Boolean) As Object
+ If CheckFor(pEvent, pFormat) Then
+ Dim oValue = pEvent.Data.GetData(pFormat, pAutoConvert)
+ Return oValue
+ Else
+ Return Nothing
+ End If
+ End Function
+
+ Public Function GetFormat(pEvent As DragEventArgs, pFormat As String) As Object
+ Return GetFormat(pEvent, pFormat, False)
+ End Function
+
+ Public Function CheckFor(pEvent As DragEventArgs, pFormat As String, pAutoConvert As Boolean) As Boolean
+ Dim oFormatExists = pEvent.Data.GetDataPresent(pFormat)
+ Logger.Debug("Format exists: [{0}]/[{1}]", pFormat, oFormatExists)
+ Return oFormatExists
+ End Function
+
+ Public Function CheckFor(pEvent As DragEventArgs, pFormat As String) As Boolean
+ Return CheckFor(pEvent, pFormat, False)
+ End Function
+
+ Public Function IsNormalFile(e As DragEventArgs) As Boolean
+ Return CheckFor(e, DataFormats.FileDrop, False)
+ End Function
+
+ Public Function IsOutlook(e As DragEventArgs) As Boolean
+ Return CheckFor(e, "FileGroupDescriptor") AndAlso CheckFor(e, "FileDrop")
+ End Function
+ Public Function IsThunderbird(e As DragEventArgs) As Boolean
+ Return CheckFor(e, "text/x-moz-url") AndAlso CheckFor(e, "FileDrop")
+ End Function
+
+
+#Region "Thunderbird"
+ Private Function IsOutlookMail(e As DragEventArgs) As Boolean
+ Return Not IsOutlookAttachment(e) AndAlso CheckFor(e, "RenPrivateSourceFolder")
+ End Function
+
+ Private Function IsOutlookAttachment(e As DragEventArgs) As Boolean
+ Return IsOutlook(e) AndAlso
+ CheckFor(e, "RenPrivateItem") AndAlso
+ CheckFor(e, "ZoneIdentifier")
+ End Function
+#End Region
+
+#Region "Outlook"
+ Private Function IsThunderbirdMail(e As DragEventArgs) As Boolean
+ Return Not IsThunderbirdAttachment(e)
+ End Function
+
+ Private Function IsThunderbirdAttachment(e As DragEventArgs) As Boolean
+ Return IsThunderbird(e) AndAlso
+ CheckFor(e, "text/x-moz-url-data") AndAlso
+ CheckFor(e, "text/x-moz-url-desc")
+ End Function
+#End Region
+
+
+
+
+End Class
diff --git a/Windows/Windows.vbproj b/Windows/Windows.vbproj
index 92b0b6dd..c5eacc15 100644
--- a/Windows/Windows.vbproj
+++ b/Windows/Windows.vbproj
@@ -83,8 +83,10 @@
Form
+
+
@@ -129,10 +131,47 @@
+
+ {6ea0c51f-c2b1-4462-8198-3de0b32b74f8}
+ Base
+
+
+ {d3c8cfed-d6f6-43a8-9bdf-454145d0352f}
+ Language
+
{903B2D7D-3B80-4BE9-8713-7447B704E1B0}
Logging
+
+
+ {2DF8D04C-5BFA-101B-BDE5-00AA0044DE52}
+ 2
+ 8
+ 0
+ primary
+ False
+ True
+
+
+ {00062FFF-0000-0000-C000-000000000046}
+ 9
+ 6
+ 0
+ primary
+ False
+ True
+
+
+ {00020430-0000-0000-C000-000000000046}
+ 2
+ 0
+ 0
+ primary
+ False
+ True
+
+
\ No newline at end of file