Можно ли прочитать PST-файл Outlook (2003/2007) в C #? - PullRequest
63 голосов
/ 23 февраля 2009

Можно ли прочитать файл .PST с помощью C #? Я хотел бы сделать это как отдельное приложение, а не как надстройку Outlook (если это возможно).

Если вы видели другое SO вопросы похожие на это упоминание MailNavigator но я хочу сделать это программно в C #.

Я посмотрел на пространство имен Microsoft.Office.Interop.Outlook , но, похоже, это только для надстроек Outlook. LibPST , кажется, может читать файлы PST, но это на C (извините, Джоэл, я не изучил C до окончания ).

Любая помощь будет принята с благодарностью, спасибо!

РЕДАКТИРОВАТЬ:

Спасибо всем за ответы! Я принял ответ Мэтью Растона как ответ, потому что в конечном итоге он привел меня к коду, который я искал. Вот простой пример того, что я получил для работы (вам нужно будет добавить ссылку на 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;
        }
    }
}

Примечание: Этот код предполагает, что Outlook установлен и уже настроен для текущего пользователя. Он использует профиль по умолчанию (вы можете редактировать профиль по умолчанию, перейдя в раздел «Почта» на панели управления). Одним из основных улучшений в этом коде будет создание временного профиля для использования вместо Default, а затем его уничтожение после завершения.

Ответы [ 13 ]

25 голосов
/ 23 февраля 2009

Библиотека Outlook Interop предназначена не только для надстроек. Например, его можно использовать для написания консольного приложения, которое просто читает все ваши контакты Outlook. Я почти уверен, что стандартная библиотека Microsoft Outlook Interop позволит вам читать почту - хотя, вероятно, она выдаст в Outlook запрос безопасности, через который пользователь должен будет щелкнуть.

РЕДАКТИРОВАТЬ : Фактически реализация чтения почты с помощью Outlook Interop зависит от того, что означает определение «автономный». Для работы Outlook Interop lib на клиентском компьютере должен быть установлен Outlook.

// 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();
    }
}
}
6 голосов
/ 23 февраля 2009

Как уже упоминалось в одном из ваших связанных вопросов SO, я бы также рекомендовал использовать библиотеку Redemption . Я использую его в коммерческом приложении для обработки почты Outlook и выполнения с ними различных задач. Он работает безупречно и предотвращает появление надоедливых предупреждений безопасности. Это будет означать использование COM Interop, но это не должно быть проблемой.

В этом пакете есть библиотека под названием RDO, которая заменяет CDO 1.21, что позволяет напрямую обращаться к файлам PST. Тогда это так же просто, как написать (код 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
5 голосов
/ 29 ноября 2009

Я прошел и сделал рефакторинг для подпапок

    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);
        }
    }
4 голосов
/ 01 апреля 2011

Вы можете использовать pstsdk.net: порт .NET библиотеки SDK формата файлов PST с открытым исходным кодом для чтения файлов PST без Outlook установлен.

2 голосов
/ 03 марта 2015

Другое дополнительное решение: NetPstExtractor

Это API .Net для чтения файла Outlook PST без Outlook установлен.

Демо-версию можно найти здесь.

2 голосов
/ 26 марта 2010

Для тех, кто упоминает, что они не видят коллекцию магазинов:

Коллекция Stores была добавлена ​​в Outlook 2007. Итак, если вы используете библиотеку взаимодействия, созданную из более ранней версии (в попытке быть независимой от версии - это очень часто), то по этой причине вы не будете см. коллекцию магазинов.

Вы можете получить Магазины только одним из следующих способов:

  • Используйте библиотеку взаимодействия для Outlook 2007 (это означает, что ваш код не будет работать для более ранних версий Outlook).
  • Перечислите все папки верхнего уровня с объектной моделью Outlook, извлеките StoreID каждой папки, а затем используйте интерфейсы CDO или MAPI для получения дополнительной информации о каждом хранилище.
  • Перечислите коллекцию InfoStores объекта сеанса CDO, а затем используйте коллекцию полей объекта InfoStore для получения дополнительной информации о каждом хранилище.
  • Или (самый сложный способ) использовать расширенный вызов MAPI (в C ++): IMAPISession :: GetMsgStoresTable.
1 голос
/ 16 февраля 2010

Мы собираемся использовать это, чтобы предоставить решение, которое не зависит от внешнего вида.

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

Это очень дорого, но мы надеемся, что это сократит время разработки и повысит качество.

0 голосов
/ 28 февраля 2018

Действительно полезный код. Если у вас есть pst и вы храните свои сообщения в его корне (без какой-либо директории), то вы можете использовать следующее в методе 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 голосов
/ 14 марта 2011

Я нашел некоторые ресурсы непосредственно от Microsoft, которые могут быть полезны для выполнения этой задачи. Поиск в MSDN показывает следующее.

Обратите внимание, что при добавлении ссылки на Microsoft.Office.Interop.Outlook документация настаивает на том, чтобы вы делали это на вкладке .NET вместо вкладки COM.

0 голосов
/ 03 декабря 2010

Да, с Independentsoft PST .NET можно читать / экспортировать защищенный паролем и зашифрованный файл .pst.

...