在.Net中將MailMessage儲存為本地eml檔案(轉)

iDotNetSpace發表於2010-11-02

最近因故需要用.Net(C#)將郵件資訊儲存為本地eml檔案,看起來是個費勁的活:首先得讀懂MIME協議(RFC 2045~2049),然後寫程式碼。還好,以前有朋友也有過這樣的需求,並有現成解決方案,呵呵:System.Net.Mail名稱空間裡已經實現了MailWriter,只不知道為啥沒有公開而已。

用Xenocode Fox 2007(Community Edition)載入System.dll,找到System.Net.Mail.SmtpClient類,可看到其Send(MailMessage)方法中有這麼兩句程式碼:

MailWriter writer;

writer = GetFileMailWriter(PickupDirectoryLocation);

我們來看看GetFileMailWriter方法:

internal MailWriter GetFileMailWriter (string pickupDirectory)
{
  string path;
  ...

  do
  {
    Guid guid1 = Guid.NewGuid();
    string path2 = guid1.ToString() + ".eml";
    path = Path.Combine(pickupDirectory, path2);
  }
  while (File.Exists(path));
  return new MailWriter(new FileStream(path, FileMode.CreateNew));
}

再往深裡看便可知:MailWriter直接將MailMessage內容寫成了“.eml”檔案,而且是按MIME協議寫入的,Yeah!

那接下來要做的就是用上MailWriter這個內部(internal)類,當然這是很簡單的事:

public static byte[] MailMessageToArray(MailMessage msg)
{
    const BindingFlags flags = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy;
    using (var ms = new MemoryStream())
    {
        var assembly = typeof (System.Net.Mail.SmtpClient).Assembly;
        var writerType = assembly.GetType("System.Net.Mail.MailWriter");
        var writer = Activator.CreateInstance(writerType, flags, null, new object[] {ms},
                                              CultureInfo.InvariantCulture);
        msg.GetType().GetMethod("Send", flags).Invoke(msg, new[] {writer, true});
        return ms.ToArray();
    }
}

如果我們使用的是C#3.0以後的版本,還可以為MailMessage新增擴充套件方法,這樣使用起來更為自然。程式碼如下:

//定義擴充套件方法

public static class MailMessageExtend
{
    public static byte[] ToArray(this MailMessage msg)
    {
        const BindingFlags flags = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy;
        using (var ms = new MemoryStream())
        {
            var assembly = typeof(System.Net.Mail.SmtpClient).Assembly;
            var writerType = assembly.GetType("System.Net.Mail.MailWriter");
            var writer = Activator.CreateInstance(writerType, flags, null, new object[] { ms },
                                                  CultureInfo.InvariantCulture);
            msg.GetType().GetMethod("Send", flags).Invoke(msg, new[] { writer, true });
            return ms.ToArray();
        }
    }

}

//呼叫

private void button1_Click(object sender, EventArgs e)
{
    var msg = new MailMessage();
    ...
    var content = msg.ToArray();
    ...
}

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/12639172/viewspace-677249/,如需轉載,請註明出處,否則將追究法律責任。

相關文章