web-dev-qa-db-fra.com

Puis-je lire un fichier PST Outlook (2003/2007) en C #?

Est-il possible de lire un fichier .PST en utilisant C #? Je voudrais faire ceci en tant qu'application autonome, pas en tant que complément Outlook (si cela est possible). 

Si j'ai vu autreSOquestionssimilaire à cette mention MailNavigator mais je cherche à le faire par programme en C #.

J'ai regardé le Microsoft.Office.Interop.Outlook namespace mais cela semble être juste pour les compléments Outlook. LibPST semble être capable de lire les fichiers PST, mais c'est en C (désolé Joel, je n'ai pas appris C avant d'obtenir mon diplôme ).

Toute aide serait grandement appréciée, merci!

MODIFIER: 

Merci à tous pour les réponses! J'ai accepté la réponse de Matthew Ruston, car elle m'a finalement conduit au code que je cherchais. Voici un exemple simple de mon travail (vous devrez ajouter une référence à Microsoft.Office.Interop.Outlook):

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;
        }
    }
}

Remarque: Ce code suppose que Outlook est installé et déjà configuré pour l'utilisateur actuel. Il utilise le profil par défaut (vous pouvez modifier le profil par défaut en accédant à Mail dans le Panneau de configuration). ce code consisterait à créer un profil temporaire à utiliser à la place du profil par défaut, puis à le détruire une fois terminé.

63
Andy May

La bibliothèque Outlook Interop n'est pas uniquement destinée aux add-ins. Par exemple, il pourrait être utilisé pour écrire une application console qui lit uniquement tous vos contacts Outlook. Je suis à peu près sûr que la bibliothèque standard Microsoft Outlook Interop vous permettra de lire le courrier, même si elle lancera probablement une invite de sécurité dans Outlook sur laquelle l'utilisateur devra cliquer.

&EACUTE;DITE: La mise en œuvre de la lecture du courrier à l'aide d'Outlook Interop dépend de la définition donnée par "autonome". Outlook Interop lib nécessite que Outlook soit installé sur la machine cliente pour fonctionner.

// 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();
    }
}
}
25
Matthew Ruston

Comme déjà mentionné dans l'une de vos questions liées SO, je vous recommanderais également d'utiliser la bibliothèque Redemption . Je l'utilise dans une application commerciale pour traiter des mails Outlook et effectuer diverses tâches avec eux. Cela fonctionne parfaitement et empêche l'affichage des alertes de sécurité gênantes. Cela impliquerait l'utilisation de COM Interop, mais cela ne devrait pas être un problème.

RDO contient une bibliothèque qui remplace le CDO 1.21, qui vous permet d’accéder directement aux fichiers PST. Alors c'est aussi simple que d'écrire (code VB6):

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
6
MicSim

Je suis allé et ai fait le refactoring pour les sous-dossiers

    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);
        }
    }
5
Tom Kidd

Vous pouvez utiliser pstsdk.net: port .NET du format de fichier PST SDK library, qui est une source ouverte, pour lire le fichier pst sans Outlook installé.

4
Giorgi

Une autre solution optionnelle: NetPstExtractor

Ceci est une API .Net pour lire le fichier Outlook PST sans Outlook installé.

Vous pouvez trouver la version démo ici.

2
neolei

Pour ceux qui mentionnent ne pas voir la collection Stores:

La collection Stores a été ajoutée à Outlook 2007. Par conséquent, si vous utilisez une bibliothèque interop créée à partir d'une version antérieure (dans le but d'être indépendante de la version - cela est très courant), vous ne verrez donc pas la bibliothèque collection.

Vos seules options pour obtenir les magasins sont les suivantes:

  • Utilisez une bibliothèque d'interopérabilité pour Outlook 2007 (cela signifie que votre code ne fonctionnera pas pour les versions antérieures d'Outlook).
  • Énumérez tous les dossiers de niveau supérieur avec le modèle d'objet Outlook, extrayez le StoreID de chaque dossier, puis utilisez les interfaces CDO ou MAPI pour obtenir plus d'informations sur chaque magasin.
  • Énumérez la collection InfoStores d'objet de session CDO, puis utilisez la collection de champs d'objet InfoStore afin d'obtenir plus d'informations sur chaque magasin.
  • Ou (le plus difficile) utilisez l'appel MAPI étendu (en C++): IMAPISession :: GetMsgStoresTable. 
2
Ryan Farley

Nous allons utiliser cela pour fournir une solution qui ne repose pas sur Outlook. 

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

C'est très coûteux, mais nous espérons que cela réduira le temps de développement et augmentera la qualité.

1
Chris Barry

J'ai trouvé des ressources directement auprès de Microsoft qui pourraient être utiles pour mener à bien cette tâche. Une recherche sur MSDN révèle les éléments suivants.

Notez que lorsque vous ajoutez une référence à Microsoft.Office.Interop.Outlook, la documentation insiste pour que vous le fassiez via l'onglet .NET au lieu de l'onglet COM.

0
HappyNomad

L'API MAPI est ce que vous recherchez. Malheureusement, il n’est pas disponible en .Net, je crains donc que vous n’ayez à recourir à un code non géré.

Un rapide Google révèle plusieurs enveloppes disponibles, peut-être qu’elles fonctionnent pour vous?

Cela pourrait également être utile: http://www.wischik.com/lu/programmer/mapi_utils.html

0
Gerrie Schenck

This .NET connecteur pour Outlook peut vous aider à démarrer.

0
Chris Ballance

Code vraiment utile. Si vous avez pst et stockez vos messages à la racine (sans répertoire), vous pouvez utiliser les éléments suivants dans la méthode readPst:

 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);
      }
 }
0
Moises Quintero Orea

Oui, avec Independentsoft PST .NET, il est possible de lire/exporter un fichier .pst protégé par mot de passe et crypté.

0
AlanSB