Outlook PST 邮件提取






4.83/5 (9投票s)
将 Microsoft Outlook 消息从 PST 文件提取到文件夹结构中
引言
最终,可能会出现我们需要将 Outlook PST(个人存储文件)转换为存储在我们硬盘上,以 Outlook .msg 文件形式存在,而不是存储在 PST 文件本身中的时候。也许您的公司禁止使用 PST 文件,或者它已经失控。将消息从 PST 文件移动到硬盘上,也可能使我们获得更好的搜索能力,使用 Windows 搜索。本文将快速向您展示如何将电子邮件消息从 PST 文件移动到您的硬盘上。
背景
为了在 .NET 应用程序中处理 Outlook,我们需要一个名为 MAPI 的接口。MAPI 代表消息应用程序编程接口,由 Microsoft 为 Outlook 编程提供。使用 MAPI,我们可以访问 PST 文件中存在的类似 收件箱、草稿箱、已发送邮件 等文件夹。我们甚至可以创建会话和命名空间来从 Outlook 或,例如,从 PST 文件中获取项目。目前,MAPI 是 Microsoft 提供的唯一命名空间,用于提取 PST 文件。有关 MAPI 的更多信息,我建议新手访问相关的 MSDN 文章。
Using the Code
开始
- 打开 Visual Studio 并创建一个新的控制台应用程序。
- 当控制台应用程序准备好后,假设您已安装 Outlook(这是本文的必要条件),您需要添加对 Microsoft.Office.Interop.Outlook.dll 程序集的引用(我的程序集位于 C:\Program Files (x86)\Microsoft Visual Studio 10.0\Visual Studio Tools for Office\PIA\Office14)。
- 复制/粘贴以下代码并执行它。
该代码将提示您提供一个文件路径以写入主项目,然后选择一个已添加到您的 Outlook 实例的 PST 文件,递归地迭代所有文件夹和子文件夹,最后将每个 mailItem 提取到定义的根文件夹中。
或者,如果您更喜欢选择一个断开连接的 PST 文件,您可以更新代码以使用 AddStore
/RemoveStore
方法手动添加和删除 PST 文件,并为它定义一个路径。其余代码基本相同。
using System;
using Microsoft.Office.Interop.Outlook;
using System.Text.RegularExpressions;
namespace PSTMover
{
class Program
{
/// <summary>
/// Starting method for console app.
/// </summary>
/// <param name="args">The arguments.</param>
static void Main(string[] args)
{
Console.WriteLine("Enter folder path to write
PST Mail Items to (i.e. c:\\temp\\Email): ");
String OutputRootPath = Console.ReadLine();
if (System.IO.Directory.Exists(OutputRootPath) == false)
return;
WritePSTFilesToFolder(OutputRootPath);
}
/// <summary>
/// Writes the PST files to folder.
/// </summary>
/// <param name="PSTPath">The PST path.</param>
/// <param name="OutputPath">The output path.</param>
private static void WritePSTFilesToFolder(String OutputPath)
{
Application app = new Application();
NameSpace outlookNs = app.GetNamespace("MAPI");
MAPIFolder RootFolder = outlookNs.PickFolder();
if(RootFolder!=null) //It may be NULL if you press the Cancel button
// Traverse through all folders in the PST file
foreach (MAPIFolder SubFolder in RootFolder.Folders)
{
Iterate(SubFolder, OutputPath);
}
}
/// <summary>
/// Iterates and recurses the specified root folder.
/// </summary>
/// <param name="rootFolder">The root folder.</param>
/// <param name="OutputPath">The output path.</param>
private static void Iterate(MAPIFolder RootFolder, String OutputPath)
{
//First, write any email items that may exist at root folder level
OutputPath = OutputPath + RemoveFileNameSpecialChars(RootFolder.Name) + @"\";
WriteEmails(RootFolder, OutputPath);
//Recurse Subfolders
foreach (MAPIFolder SubFolder in RootFolder.Folders)
{
Iterate(SubFolder, OutputPath);
}
}
/// <summary>
/// Writes the emails to the folder
/// </summary>
/// <param name="Folder">The folder.</param>
/// <param name="OutputPath">The output path.</param>
private static void WriteEmails(MAPIFolder Folder, String OutputPath)
{
Items items = Folder.Items;
foreach (object item in items)
{
if (item is MailItem)
{
// Retrieve the Object into MailItem
MailItem mailItem = item as MailItem;
Console.WriteLine("Saving message {0} .... into {1}", mailItem.Subject, OutputPath);
// Save the message to disk in MSG format
if (System.IO.Directory.Exists(OutputPath) == false)
{
System.IO.Directory.CreateDirectory(OutputPath);
}
try
{
String Subject = mailItem.Subject;
if (Subject == null)
Subject = "NULL";
String FilePathName = OutputPath + RemoveFileNameSpecialChars
(Subject.Replace('\u0009'.ToString(), "")) + ".msg"; //removes tab chars
mailItem.SaveAs(FilePathName, OlSaveAsType.olMSG);
System.IO.File.SetCreationTime(FilePathName, mailItem.ReceivedTime);
System.IO.File.SetLastWriteTime(FilePathName, mailItem.ReceivedTime);
}
catch (System.Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
}
/// <summary>
/// Returns a string after removing characters that are NOT:
/// alphanumeric, space, dash, apostrophe, period or comma
/// </summary>
/// <param name="FileName">original file name</param>
/// <returns>String</returns>
public static String RemoveFileNameSpecialChars(string FileName)
{
Regex regex = new Regex(@"[\w\s-'.,]");
String validName = FileName;
//identify invalid chars and replace those within the FileName string
for (int i = 0; i < FileName.Length; i++)
{
Boolean matched = regex.IsMatch(FileName[i].ToString());
if (matched == false)
{
validName = validName.Replace(FileName[i].ToString(), "");
}
}
return validName;
}
}
}
历史
- 2016年3月30日 -- 初始版本