Преобразование нескольких файлов eml в один PST на С#

Мне нужно написать одну функцию, которая будет принимать несколько файлов eml (может быть из одной папки файловой системы) и преобразовывать их в один файл PST.

Является ли это возможным? если да, может ли кто-нибудь предоставить пример кода?

Я предполагаю, что это возможно, потому что есть много коммерческих конвертеров eml в pst, делающих это.


person Ayesha    schedule 12.06.2010    source источник


Ответы (4)


Хотя Outlook может открывать файлы EML, нельзя сделать это программно только с помощью VBA. Поэтому я создал этот макрос VBA, который проходит через некоторую папку и открывает каждый файл EML с помощью SHELL EXEC. Открытие EML-файла в Outlook может занять несколько миллисекунд, поэтому VBA ждет, пока что-нибудь откроется в ActiveInspector. Наконец, это письмо копируется в какую-то выбранную папку, и (в случае успеха) исходный файл EML удаляется.

Этот макрос иногда дает сбой, но вы можете перезапустить макрос в любое время, и он перезапустится с того места, где произошел предыдущий сбой (помните, что все успешно импортированные файлы EML удаляются). Если он продолжает падать после перезапуска, возможно, проблема связана со следующим файлом EML, который будет импортирован. В этом случае вы можете просто удалить проблемный EML.

PS: Иногда вы можете открыть EML самостоятельно, без сбоя Outlook, но, согласно моим тестам, каждый раз, когда файл EML приводил к сбою Outlook, это было что-то неважное, например уведомления о прочтении.

Здесь следует мой код VBA. Если у вас есть какие-либо сомнения или проблемы, дайте мне знать.

'----------------------------------------------------
' Code by Ricardo Drizin (contact info at http://www.drizin.com.br)
'----------------------------------------------------
Private Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Option Explicit

'---------------------------------------------------------------------
' This method closes ActiveInspectors if any.
' All inporting is based on the assumption that the EML
' is opened by shell and we can refer to it through the ActiveInspector
'---------------------------------------------------------------------
Function CloseOpenInspectors() As Boolean
    Dim app As Outlook.Application: Set app = CreateObject("Outlook.Application")
    Dim insp As Outlook.Inspector
    Dim count As Integer
    count = 0
repeat:
    count = count + 1
    Set insp = app.ActiveInspector
    If TypeName(insp) = "Nothing" Then
        CloseOpenInspectors = True
        Exit Function
    End If
    If TypeName(insp.CurrentItem) = "Nothing" Then
        CloseOpenInspectors = True
        Exit Function
    End If
    If (count > 100) Then
        MsgBox "Error. Could not close ActiveInspector. "
        CloseOpenInspectors = False
    End If

    insp.Close (olDiscard)
    GoTo repeat
End Function


'---------------------------------------------------------------------
' This method allows user to choose a Root Folder in Outlook
' All EML files will be imported under this folder
'---------------------------------------------------------------------
Function GetRootFolder() As Outlook.folder
    Dim app As Outlook.Application: Set app = CreateObject("Outlook.Application")
    Dim NS As Outlook.NameSpace: Set NS = app.GetNamespace("MAPI")
    Dim fold As Outlook.folder
    Set fold = NS.PickFolder
    'MsgBox fold.Name
    Set GetRootFolder = fold
End Function

'---------------------------------------------------------------------
' Creates a child folder in Outlook, under root folder.
'---------------------------------------------------------------------
Function GetChildFolder(parentFolder As Outlook.folder, name As String)
    On Error Resume Next
    Dim fold2 As Outlook.folder
    Set fold2 = parentFolder.folders.Item(name)
    If Err.Number Then
        On Error GoTo 0
        Set fold2 = parentFolder.folders.Add(name)
    End If
    On Error GoTo 0
    'MsgBox fold2.Name
    Set GetChildFolder = fold2
End Function

'---------------------------------------------------------------------
' Imports the EML open in the current ActiveInspector
' into the given folder
'---------------------------------------------------------------------
Sub ImportOpenItem(targetFolder As Outlook.folder)
    Dim app As Outlook.Application: Set app = CreateObject("Outlook.Application")
    Dim insp As Outlook.Inspector: Set insp = app.ActiveInspector

    Dim retries As Integer
    retries = 0
    While TypeName(insp) = "Nothing" ' READING PANE should be visible, or else it will not work.
        'MsgWaitObj (1000)
        Sleep (50)
        DoEvents
        Sleep (50)
        Set insp = app.ActiveInspector
        retries = retries + 1
        'If retries > 100 Then
        '    Stop
        'End If
    Wend

    If TypeName(insp) = "Nothing" Then
        MsgBox "Error! Could not find open inspector for importing email."
        Exit Sub
    End If


    Dim m As MailItem, m2 As MailItem, m3 As MailItem
    Set m = insp.CurrentItem
    'MsgBox m.Subject
    Set m2 = m.Copy
    Set m3 = m2.Move(targetFolder)
    m3.Save
    Set m = Nothing
    Set m2 = Nothing
    Set m3 = Nothing
    insp.Close (olDiscard)
    Set insp = Nothing
End Sub


'---------------------------------------------------------------------
' Scans a given folder for *.EML files and import them
' into the given folder.
' Each EML file will be deleted after importing.
'---------------------------------------------------------------------
Sub ImportEMLFromFolder(targetFolder As Outlook.folder, emlFolder As String)
    If Right(emlFolder, 1) <> "\" Then emlFolder = emlFolder & "\"
    Dim firstImport As Boolean: firstImport = True

    Dim file As String
    Dim count As Integer: count = 0
    'MsgBox fold.Items.count
    'Exit Sub
    file = Dir(emlFolder & "*.eml")

repeat:
    If file = "" Then
        'MsgBox "Finished importing EML files. Total = " & count
        Debug.Print "Finished importing EML files. Total = " & count
        Exit Sub
    End If
    count = count + 1

    Debug.Print "Importing... " & file & " - " & emlFolder
    Shell ("explorer """ & emlFolder & file & """")
    'If firstImport Then Stop
    firstImport = False
    Sleep (50)
    On Error GoTo nextfile
    Call ImportOpenItem(targetFolder)
    Call Kill(emlFolder & file)
nextfile:
    On Error GoTo 0
    Sleep (50)

    file = Dir()
    GoTo repeat
End Sub

'---------------------------------------------------------------------
' Main method.
' User chooses an Outlook root Folder, and a Windows Explorer root folder.
' All EML files inside this folder and in immediate subfolders will be imported.
'---------------------------------------------------------------------
Sub ImportAllEMLSubfolders()
    Call CloseOpenInspectors

    MsgBox "Choose a root folder for importing "
    Dim rootOutlookFolder As Outlook.folder
    Set rootOutlookFolder = GetRootFolder()
    If rootOutlookFolder Is Nothing Then Exit Sub

    Dim rootWindowsFolder As String
    rootWindowsFolder = "D:\Outlook Express EMLs folder"
    rootWindowsFolder = InputBox("Choose a windows folder where you have your EML files", , rootWindowsFolder)
    If IsNull(rootWindowsFolder) Or IsEmpty(rootWindowsFolder) Or rootWindowsFolder = "" Then Exit Sub
    If Right(rootWindowsFolder, 1) <> "\" Then rootWindowsFolder = rootWindowsFolder & "\"

    Dim subFolders As New Collection

    Dim subFolder As String
    subFolder = Dir(rootWindowsFolder, vbDirectory)
repeat:
    If subFolder = "." Or subFolder = ".." Then GoTo nextdir
    If (GetAttr(rootWindowsFolder & subFolder) And vbDirectory) = 0 Then GoTo nextdir
    subFolders.Add (subFolder)
nextdir:
    subFolder = Dir()
    If subFolder <> "" Then GoTo repeat

Dim outlookFolder As Outlook.folder

' Importing main folder
Call ImportEMLFromFolder(rootOutlookFolder, rootWindowsFolder)

' Importing subfolders
While subFolders.count
    subFolder = subFolders.Item(1)
    subFolders.Remove (1)
    Set outlookFolder = GetChildFolder(rootOutlookFolder, subFolder)
    Debug.Print "Importing " & rootWindowsFolder & subFolder & " into Outlook folder " & outlookFolder.name & "..."
    Call ImportEMLFromFolder(outlookFolder, rootWindowsFolder & subFolder)
Wend
    Debug.Print "Finished"

End Sub
person drizin    schedule 17.11.2015

Вполне возможно, что это проще или лучше, но одним из способов, вероятно, будет использование Interop для автоматизации Outlook. Возможно, есть какая-то возможность использовать встроенные функции Импорта Outlook, и это будет первое, что я попытаюсь найти. Предполагая, что это невозможно, вы все равно сможете сделать это, прочитав файлы eml в своем приложении, а затем создав почтовые элементы через Interop.

Обычно файлы eml представляют собой просто текстовые файлы в формате MIME, так что это просто вопрос их чтения в виде текстовых файлов и их анализа. Вот одна статья о синтаксическом анализе MIME из C#, а в противном случае просто выполните поиск " POP3 C#», и вы найдете другие статьи об этом.

Затем вы используете Outlook Interop из пространства имен Microsoft.Office.Interop.Outlook, как описано здесь.

Я бы предположил, что вам, возможно, придется сначала создать объект Application, затем использовать его для получения объекта Store (я думаю, что каждый файл PST будет одним Store), а затем Folder, а затем найти какой-то способ создать MailItem, используя данные, которые вы проанализировали из файла eml.

В этой статье описывается использование автоматизации Outlook для создания контактов и встреч и наверное может быть полезно.

person Hans Olsson    schedule 12.06.2010

Для этого вы можете использовать Redemption. Что-то в духе:

  set Session = CreateObject("Redemption.RDOSession")
  Session.LogonPstStore("c:\temp\test.pst")
  set Folder = Session.GetDefaultFolder(olFolderInbox)
  set Msg = Folder.Items.Add("IPM.Note")
  Msg.Sent = true
  Msg.Import("c:\temp\test.eml", 1024)
  Msg.Save
person Dmitry Streblechenko    schedule 22.04.2013
comment
Есть ли бесплатный API? - person Mahesha999; 23.06.2014
comment
Вы можете использовать встроенный конвертер Outlook IConverterSession (только для C++ или Delphi) — см. msdn.microsoft.com/en-us/library/office/. Или вы можете проанализировать файлы EML в своем коде и использовать объектную модель Outlook и задавать свойства по одному. - person Dmitry Streblechenko; 23.06.2014

Вы можете найти спецификации формата файла pst здесь. Но я предполагаю, что вы потратите некоторое время на то, чтобы собрать все вместе, чтобы создать парсер eml->pst самостоятельно. Но это должно быть возможно.

person Mikael Svenson    schedule 12.06.2010