Можно ли прочитать PST-файл Outlook (2003/2007) в C#?
Можно ли прочитать файл.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 ответов
Библиотека 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();
}
}
}
Я прошел и сделал рефакторинг для подпапок
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);
}
}
Как уже упоминалось в одном из ваших связанных вопросов 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
Вы можете использовать pstsdk.net: порт.NET библиотеки SDK формата файла PST, который является открытым исходным кодом для чтения файла pst без установленного Outlook.
Другое дополнительное решение: NetPstExtractor
Это API.Net для чтения файла Outlook PST без установленного Outlook.
Вы можете найти демо-версию здесь.
Для тех, кто упоминает, что они не видят коллекцию магазинов:
Коллекция Stores была добавлена в Outlook 2007. Итак, если вы используете библиотеку взаимодействия, созданную из более ранней версии (в попытке быть независимой от версии - это очень часто), то по этой причине вы не увидите Stores коллекция.
Ваши единственные варианты получить магазины - это выполнить одно из следующих действий:
- Используйте библиотеку взаимодействия для Outlook 2007 (это означает, что ваш код не будет работать для более ранних версий Outlook).
- Перечислите все папки верхнего уровня с объектной моделью Outlook, извлеките StoreID каждой папки, а затем используйте интерфейсы CDO или MAPI для получения дополнительной информации о каждом хранилище.
- Перечислите коллекцию InfoStores объекта сеанса CDO, а затем используйте коллекцию полей объекта InfoStore, чтобы получить больше информации о каждом хранилище.
- Или (самый сложный способ) использовать расширенный вызов MAPI (в C++): IMAPISession::GetMsgStoresTable.
Мы собираемся использовать это, чтобы предоставить решение, которое не зависит от внешнего вида.
http://www.independentsoft.de/pst/index.html
Это очень дорого, но мы надеемся, что это сократит время разработки и повысит качество.
Я нашел некоторые ресурсы непосредственно от Microsoft, которые могут быть полезны для выполнения этой задачи. Поиск в MSDN показывает следующее.
- Как использовать библиотеку объектов Microsoft Outlook для извлечения сообщения из папки "Входящие" с помощью Visual C#
- Как использовать библиотеку объектов Microsoft Outlook для получения встречи с помощью Visual C#
Обратите внимание, что когда вы добавляете ссылку на Microsoft.Office.Interop.Outlook, документация настаивает на том, что вы делаете это через вкладку.NET вместо вкладки COM.
MAPI API - это то, что вы ищете. К сожалению, он недоступен в.Net, поэтому, боюсь, вам придется прибегать к вызову неуправляемого кода.
Быстрый Google показывает несколько доступных упаковщиков, может быть, они работают для вас?
Это также может быть полезно: http://www.wischik.com/lu/programmer/mapi_utils.html
Действительно полезный код. Если у вас есть 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);
}
}
Да, с Independentsoft PST .NET можно читать / экспортировать защищенный паролем и зашифрованный файл.pst.
Этот соединитель.NET для Outlook может помочь вам начать работу.
Да, вы можете использовать MS Access, а затем либо импортировать свой pst-контент, либо просто связать его (медленно!).