Kann ich eine Outlook (2003/2007) PST-Datei in C # lesen?

70

Ist es möglich, eine .PST-Datei mit C # zu lesen? Ich möchte dies als eigenständige Anwendung tun, nicht als Outlook-Add-In (falls dies möglich ist).

Wenn Sie andere ähnliche SO- Fragen gesehen haben, erwähnen Sie MailNavigator, aber ich möchte dies programmgesteuert in C # tun.

Ich habe mir den Microsoft.Office.Interop.Outlook- Namespace angesehen, aber das scheint nur für Outlook-Addins zu sein. LibPST scheint in der Lage zu sein, PST-Dateien zu lesen, aber dies ist in C (sorry Joel, ich habe C vor dem Abschluss nicht gelernt ).

Jede Hilfe wäre sehr dankbar, danke!

BEARBEITEN:

Vielen Dank für die Antworten! Ich akzeptierte Matthew Rustons Antwort als Antwort, weil sie mich letztendlich zu dem Code führte, den ich suchte. Hier ist ein einfaches Beispiel für meine Arbeit (Sie müssen einen Verweis auf Microsoft.Office.Interop.Outlook hinzufügen):

using System;
using System.Collections.Generic;
using Microsoft.Office.Interop.Outlook;

namespace PSTReader {
    class Program {
        static void Main () {
            try {
                IEnumerable<MailItem> mailItems = readPst(@"C:\temp\PST\Test.pst", "Test PST");
                foreach (MailItem mailItem in mailItems) {
                    Console.WriteLine(mailItem.SenderName + " - " + mailItem.Subject);
                }
            } catch (System.Exception ex) {
                Console.WriteLine(ex.Message);
            }
            Console.ReadLine();
        }

        private static IEnumerable<MailItem> readPst(string pstFilePath, string pstName) {
            List<MailItem> mailItems = new List<MailItem>();
            Application app = new Application();
            NameSpace outlookNs = app.GetNamespace("MAPI");
            // Add PST file (Outlook Data File) to Default Profile
            outlookNs.AddStore(pstFilePath);
            MAPIFolder rootFolder = outlookNs.Stores[pstName].GetRootFolder();
            // Traverse through all folders in the PST file
            // TODO: This is not recursive, refactor
            Folders subFolders = rootFolder.Folders;
            foreach (Folder folder in subFolders) {
                Items items = folder.Items;
                foreach (object item in items) {
                    if (item is MailItem) {
                        MailItem mailItem = item as MailItem;
                        mailItems.Add(mailItem);
                    }
                }
            }
            // Remove PST file from Default Profile
            outlookNs.RemoveStore(rootFolder);
            return mailItems;
        }
    }
}

Hinweis: Bei diesem Code wird davon ausgegangen, dass Outlook installiert und bereits für den aktuellen Benutzer konfiguriert ist. Es wird das Standardprofil verwendet (Sie können das Standardprofil bearbeiten, indem Sie in der Systemsteuerung auf Mail klicken). Eine wesentliche Verbesserung dieses Codes besteht darin, ein temporäres Profil zu erstellen, das anstelle des Standardprofils verwendet wird, und es nach Abschluss zu zerstören.

Andy May
quelle
Ich hatte keine Ahnung, dass die Liste AddStores und Stores überhaupt in der Outlook-API vorhanden ist. Guter Post!
Matthew Ruston
Vermisse ich etwas Warum kann ich nicht auf die Stores-Sammlung von OutlookNS zugreifen? Es ist nicht in Intellisense.
Mike Cole
Haben Sie "using Microsoft.Office.Interop.Outlook" hinzugefügt? in deinem Code?
Andy
Ich habe es getan und ich kann alles andere sehen. Ich kann die Store-Sammlung des Outlook-Namespace einfach nicht sehen. Ich habe gerade an etwas gedacht ... auf welche Version von Microsoft.Office.Interop.Outlook haben Sie verwiesen? Ich benutze 11.
Mike Cole
Sie können auch versuchen, mit Aspose.Network for .NET Nachrichtendateien aus der Outlook PST-Datei zu lesen und zu extrahieren. Bitte besuchen Sie http://www.aspose.com/documentation/.net-components/aspose.network-for-.net/read-outlook-pst-file-and-get-folders-and-subfolders-information.html für Mehr Informationen.
Saqib Razzaq

Antworten:

29

Die Outlook Interop-Bibliothek ist nicht nur für Add-Ins gedacht. Zum Beispiel könnte es verwendet werden, um eine Konsolen-App zu schreiben, die nur alle Ihre Outlook-Kontakte liest. Ich bin mir ziemlich sicher, dass Sie mit der Standard-Microsoft Outlook Interop-Bibliothek die E-Mails lesen können - obwohl in Outlook wahrscheinlich eine Sicherheitsabfrage ausgelöst wird, durch die der Benutzer klicken muss.

BEARBEITUNGEN : Die tatsächliche Implementierung des E-Mail-Lesens mit Outlook Interop hängt davon ab, was Ihre Definition von "Standalone" bedeutet. Für die Outlook Interop-Bibliothek muss Outlook auf dem Clientcomputer installiert sein, damit es funktioniert.

// Dumps all email in Outlook to console window.
// Prompts user with warning that an application is attempting to read Outlook data.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Outlook = Microsoft.Office.Interop.Outlook;

namespace OutlookEmail
{
class Program
{
    static void Main(string[] args)
    {
        Outlook.Application app = new Outlook.Application();
        Outlook.NameSpace outlookNs = app.GetNamespace("MAPI");
        Outlook.MAPIFolder emailFolder = outlookNs.GetDefaultFolder(Microsoft.Office.Interop.Outlook.OlDefaultFolders.olFolderInbox);

        foreach (Outlook.MailItem item in emailFolder.Items)
        {
            Console.WriteLine(item.SenderEmailAddress + " " + item.Subject + "\n" + item.Body);
        }
        Console.ReadKey();
    }
}
}
Matthew Ruston
quelle
Es ist davon auszugehen, dass Outlook auf dem Computer installiert wird. Ich würde es jedoch vorziehen, wenn Outlook nicht zum Lesen aus der PST-Datei geöffnet sein muss.
Andy
Es muss nicht offen sein. Die Interop-Bibliothek öffnet es einfach im Hintergrund und schließt es, wenn Sie fertig sind.
Matthew Ruston
Ahhh, ok, das hört sich gut an. Ich sehe einige Beispiele, wie man dies zum Lesen von Kontakten und dergleichen verwendet, aber ich bin nur daran interessiert, Nachrichten in einem PST zu lesen, nicht Kontakte von einem Exchange-Server. Wissen Sie oder haben Sie ein Beispiel dafür?
Andy
4
Ich habe in den letzten 10 Minuten ein Codebeispiel in meinem Beitrag. Reicht das als Ausgangspunkt aus?
Matthew Ruston
Danke für das Codebeispiel. Das sieht so aus, als würde es aus der Mailbox gelesen und nicht aus einer PST-Datei, aber ich werde sehen, was ich optimieren kann, um eine PST-Datei zu lesen. Ich werde bald ein Update veröffentlichen.
Andy
6

Ich habe das Refactoring für Unterordner durchgeführt

    private static IEnumerable<MailItem> readPst(string pstFilePath, string pstName)
    {
        List<MailItem> mailItems = new List<MailItem>();
        Microsoft.Office.Interop.Outlook.Application app = new Microsoft.Office.Interop.Outlook.Application();
        NameSpace outlookNs = app.GetNamespace("MAPI");

        // Add PST file (Outlook Data File) to Default Profile
        outlookNs.AddStore(pstFilePath);

        string storeInfo = null;

        foreach (Store store in outlookNs.Stores)
        {
            storeInfo = store.DisplayName;
            storeInfo = store.FilePath;
            storeInfo = store.StoreID;
        }

        MAPIFolder rootFolder = outlookNs.Stores[pstName].GetRootFolder();

        // Traverse through all folders in the PST file
        Folders subFolders = rootFolder.Folders;

        foreach (Folder folder in subFolders)
        {
            ExtractItems(mailItems, folder);
        }
        // Remove PST file from Default Profile
        outlookNs.RemoveStore(rootFolder);
        return mailItems;
    }

    private static void ExtractItems(List<MailItem> mailItems, Folder folder)
    {
        Items items = folder.Items;

        int itemcount = items.Count;

        foreach (object item in items)
        {
            if (item is MailItem)
            {
                MailItem mailItem = item as MailItem;
                mailItems.Add(mailItem);
            }
        }

        foreach (Folder subfolder in folder.Folders)
        {
            ExtractItems(mailItems, subfolder);
        }
    }
Tom Kidd
quelle
Was ist pstName? Sie übergeben den pstFilePath bereits darin. Warum benötigen Sie pstName?
HoKy22
6

Wie bereits in einer Ihrer verknüpften SO-Fragen erwähnt, würde ich auch die Verwendung der Einlösungsbibliothek empfehlen . Ich verwende es in einer kommerziellen Anwendung, um Outlook-Mails zu verarbeiten und verschiedene Aufgaben damit auszuführen. Es funktioniert einwandfrei und verhindert, dass die lästigen Sicherheitswarnungen angezeigt werden. Es würde bedeuten, COM Interop zu verwenden, aber das sollte kein Problem sein.

In diesem Paket befindet sich eine Bibliothek namens RDO, die die CDO 1.21 ersetzt, mit der Sie direkt auf PST-Dateien zugreifen können. Dann ist es so einfach wie das Schreiben (VB6-Code):

set Session = CreateObject("Redemption.RDOSession")
'open or create a PST store
set Store = Session.LogonPstStore("c:\temp\test.pst")
set Inbox = Store.GetDefaultFolder(6) 'olFolderInbox
MsgBox Inbox.Items.Count
MicSim
quelle
4

Sie können den pstsdk.net: .NET-Port der PST-Dateiformat-SDK- Bibliothek verwenden, die Open Source ist, um PST-Dateien ohne installiertes Outlook zu lesen .

Giorgi
quelle
Keine Downloads auf dieser Seite verfügbar!
Villamejia
Es ist ein Wrapper, kein Port (was wichtig ist, weil es auf diese Weise weniger portabel ist).
sehe
3

Versuchen Sie es mit Pstxy .

Es bietet eine .NET-API zum Lesen der Outlook PST- und OST-Datei, ohne dass Outlook installiert werden muss.

Es gibt eine kostenlose Version zum Extrahieren von E-Mail-Inhalten (Text, HTML und RTF). Die Plus-Version unterstützt auch Anhänge.

neolei
quelle
Das ist so vielversprechend. Es funktioniert in Dotnetcore, wie ich gerade versucht habe. Leider unterstützt es, wie alle anderen Bibliothekslösungen, nicht die neuesten Datenbankformate
siehe
2
@sehe nicht sicher, ob es noch relevant ist, versuchen Sie Pstxy (NetPstExtractor zuvor), es hat eine bessere Unterstützung für das neueste Format.
Neolei
Cool @neolel Ich denke auf diese Weise wird es immer relevant sagen. Vielen Dank, dass Sie die Antwort auf dem neuesten Stand gehalten haben
siehe
2

Für diejenigen, die erwähnen, dass sie die Stores-Kollektion nicht sehen:

Die Stores-Auflistung wurde in Outlook 2007 hinzugefügt. Wenn Sie also eine Interop-Bibliothek verwenden, die aus einer früheren Version erstellt wurde (um versionsunabhängig zu sein - dies ist sehr häufig), werden die Stores aus diesem Grund nicht angezeigt Sammlung.

Ihre einzige Möglichkeit, die Stores zu erhalten, besteht darin, eine der folgenden Aktionen auszuführen:

  • Verwenden Sie eine Interop-Bibliothek für Outlook 2007 (dies bedeutet, dass Ihr Code für frühere Versionen von Outlook nicht funktioniert).
  • Listen Sie alle Ordner der obersten Ebene mit dem Outlook-Objektmodell auf, extrahieren Sie die StoreID jedes Ordners und verwenden Sie dann CDO- oder MAPI-Schnittstellen, um weitere Informationen zu jedem Store zu erhalten.
  • Führen Sie die InfoStores-Auflistung des CDO-Sitzungsobjekts auf und verwenden Sie dann die Feldauflistung des InfoStore-Objekts, um weitere Informationen zu jedem Geschäft zu erhalten.
  • Oder (am schwierigsten) verwenden Sie einen erweiterten MAPI-Aufruf (in C ++): IMAPISession :: GetMsgStoresTable.
Ryan Farley
quelle
1

Wir werden dies nutzen, um eine Lösung bereitzustellen, die nicht auf Outlook basiert.

http://www.independentsoft.de/pst/index.html

Es ist sehr teuer, aber wir hoffen, dass dies die Entwicklungszeit verkürzt und die Qualität erhöht.

Chris Barry
quelle
+1 für diesen Vorschlag (es ist das, was ich verwendet habe). Technischer Support auch sehr reaktionsschnell.
Mittag und
1

Ich habe einige Ressourcen direkt von Microsoft gefunden, die für die Ausführung dieser Aufgabe hilfreich sein können. Eine Suche in MSDN zeigt Folgendes.

Beachten Sie, dass beim Hinzufügen eines Verweises auf Microsoft.Office.Interop.Outlook in der Dokumentation darauf bestanden wird, dass Sie dies über die Registerkarte .NET anstelle der Registerkarte COM tun.

HappyNomad
quelle
0

Die MAPI-API ist genau das, wonach Sie suchen. Leider ist es in .Net nicht verfügbar, daher müssen Sie leider nicht verwalteten Code aufrufen.

Ein kurzer Blick auf Google zeigt, dass mehrere Wrapper verfügbar sind. Vielleicht funktionieren sie für Sie?

Dies kann auch hilfreich sein: http://www.wischik.com/lu/programmer/mapi_utils.html

Gerrie Schenck
quelle
0

Mit diesem .NET-Connector für Outlook können Sie möglicherweise loslegen.

Chris Ballance
quelle
0

Ja, mit Independentsoft PST .NET ist es möglich, passwortgeschützte und verschlüsselte PST-Dateien zu lesen / exportieren.

AlanSB
quelle
0

Wirklich nützlicher Code. Wenn Sie pst haben und Ihre Nachrichten im Stammverzeichnis (ohne Verzeichnis) speichern, können Sie in der Methode readPst Folgendes verwenden:

 MAPIFolder rootFolder = outlookNs.Stores[pstName].GetRootFolder();
 Items items = rootFolder.Items;
 foreach (object item in items)
 {
      if (item is MailItem)
      {
           MailItem mailItem = item as MailItem;
           mailItems.Add(mailItem);
      }
 }
Moises Quintero Orea
quelle
-1

Ja, Sie können MS Access verwenden und dann entweder Ihren PST-Inhalt importieren oder ihn einfach verknüpfen (langsam!).

Lorenzo
quelle
Entschuldigung, ich sehe nicht, wie dies meine Frage zum Lesen einer PST-Datei in C # beantwortet. Bitte erläutern sie noch weiter.
Andy
Oh ja, tut mir leid, ich habe den C # -Teil vergessen, aber wenn Sie den Zugriff von C # aus steuern können, können Sie trotzdem diesen Weg gehen. Ungetestet!
Lorenzo