简体   繁体   English

在C#中将PST转换为多个EML文件

[英]Convert PST into multiple EML files in C#

I need to create an application that parses a PST file and converts the mails into multiple EML files. 我需要创建一个解析PST文件并将邮件转换为多个EML文件的应用程序。 Basically, I need to do the opposite of what's being asked in this question . 基本上,我需要做与此问题相反的事情。

Is there any sample code or guidelines to achieve this feature? 是否有任何示例代码或准则可以实现此功能?

You could use the Outlook Redemption library which is capable of opening PST and extracting messages as .EML (among other formats). 您可以使用Outlook Redemption库,该库能够打开PST并以.EML格式提取消息(包括其他格式)。 Redemption is a COM Object (32 or 64 bit) that can be used in C# without any problem. 兑换是一个COM对象(32或64位),可以毫无问题地在C#中使用。 Here is a Console Application sample code that demonstrates this: 这是一个控制台应用程序示例代码,它演示了这一点:

using System;
using System.IO;
using System.Text;
using Redemption;

namespace DumpPst
{
    class Program
    {
        static void Main(string[] args)
        {
            // extract 'test.pst' in the 'test' folder
            ExtractPst("test.pst", Path.GetFullPath("test"));
        }

        public static void ExtractPst(string pstFilePath, string folderPath)
        {
            if (pstFilePath == null)
                throw new ArgumentNullException("pstFilePath");

            RDOSession session = new RDOSession();
            RDOPstStore store = session.LogonPstStore(pstFilePath);
            ExtractPstFolder(store.RootFolder, folderPath);
        }

        public static void ExtractPstFolder(RDOFolder folder, string folderPath)
        {
            if (folder == null)
                throw new ArgumentNullException("folder");

            if (folderPath == null)
                throw new ArgumentNullException("folderPath");

            if (folder.FolderKind == rdoFolderKind.fkSearch)
                return;

            if (!Directory.Exists(folderPath))
            {
                Directory.CreateDirectory(folderPath);
            }

            foreach(RDOFolder child in folder.Folders)
            {
                ExtractPstFolder(child, Path.Combine(folderPath, ToFileName(child.Name)));
            }

            foreach (var item in folder.Items)
            {
                RDOMail mail = item as RDOMail;
                if (mail == null)
                    continue;

                mail.SaveAs(Path.Combine(folderPath, ToFileName(mail.Subject)) + ".eml", rdoSaveAsType.olRFC822);
            }
        }

      /// <summary>
      /// Converts a text into a valid file name.
      /// </summary>
      /// <param name="fileName">The file name.</param>
      /// <returns>
      /// A valid file name.
      /// </returns>
      public static string ToFileName(string fileName)
      {
          return ToFileName(fileName, null, null);
      }

      /// <summary>
      /// Converts a text into a valid file name.
      /// </summary>
      /// <param name="fileName">The file name.</param>
      /// <param name="reservedNameFormat">The reserved format to use for reserved names. If null '_{0}_' will be used.</param>
      /// <param name="reservedCharFormat">The reserved format to use for reserved characters. If null '_x{0}_' will be used.</param>
      /// <returns>
      /// A valid file name.
      /// </returns>
      public static string ToFileName(string fileName, string reservedNameFormat, string reservedCharFormat)
      {
          if (fileName == null)
              throw new ArgumentNullException("fileName");

          if (string.IsNullOrEmpty(reservedNameFormat))
          {
              reservedNameFormat = "_{0}_";
          }

          if (string.IsNullOrEmpty(reservedCharFormat))
          {
              reservedCharFormat = "_x{0}_";
          }

          if (Array.IndexOf(ReservedFileNames, fileName.ToLowerInvariant()) >= 0 ||
              IsAllDots(fileName))
              return string.Format(reservedNameFormat, fileName);

          char[] invalid = Path.GetInvalidFileNameChars();

          StringBuilder sb = new StringBuilder(fileName.Length);
          foreach (char c in fileName)
          {
              if (Array.IndexOf(invalid, c) >= 0)
              {
                  sb.AppendFormat(reservedCharFormat, (short)c);
              }
              else
              {
                  sb.Append(c);
              }
          }

          string s = sb.ToString();

          // directory limit is 255
          if (s.Length > 254)
          {
              s = s.Substring(0, 254);
          }

          if (string.Equals(s, fileName, StringComparison.Ordinal))
          {
              s = fileName;
          }
          return s;
      }

      private static bool IsAllDots(string fileName)
      {
          foreach (char c in fileName)
          {
              if (c != '.')
                  return false;
          }
          return true;
      }

      private static readonly string[] ReservedFileNames = new[]
      {
          "con", "prn", "aux", "nul",
          "com0", "com1", "com2", "com3", "com4", "com5", "com6", "com7", "com8", "com9",
          "lpt0", "lpt1", "lpt2", "lpt3", "lpt4", "lpt5", "lpt6", "lpt7", "lpt8", "lpt9"
      };
    }
}

You need essentially to do the inverse of what is being asked in that question. 从本质上讲,您需要做的与该问题相反。

  • Load the PST file using Outlook interop (or redemption as above) 使用Outlook互操作加载PST文件(或如上赎回)
  • Enumerate all the files. 枚举所有文件。
  • Use CDO, System.Mail or similar to compose an EML file for each file in the PST. 使用CDO,System.Mail或类似文件为PST中的每个文件编写一个EML文件。

The thing to note is that a PST doesn't contain EML files, it contains MSG files. 需要注意的是,PST不包含EML文件,而是包含MSG文件。 So you will have to do some form of conversion, and you will not get back exactly what was originally sent. 因此,您将必须进行某种形式的转换,而您将无法完全获得最初发送的内容。

See also this question: Are there .NET Framework methods to parse an email (MIME)? 另请参见以下问题: 是否存在.NET Framework方法来解析电子邮件(MIME)?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM