首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

C# 將 MailMessage 另存為 .eml 檔案(利用反射存取內部 MailWriter)

     編輯:關於.NET

問題背景

.NET 2.0 大幅增強 SmtpClient 發送郵件功能,但缺乏將 MailMessage 直接存為 .eml 檔的公開 API。實際上 SmtpClient.Send 內部會先產生臨時 .eml 再發送,核心在於 internal 類別 System.Net.Mail.MailWriter。

反射實作完整代碼

/// <summary>
/// 將 MailMessage 存為 .eml 檔案
/// </summary>
/// <param name="msg">含內容的 MailMessage</param>
/// <param name="emlFileAbsolutePath">輸出 .eml 完整路徑</param>
static void SaveToEml(MailMessage msg, string emlFileAbsolutePath)
{
    const BindingFlags flags = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy;
    using (MemoryStream ms = new MemoryStream())
    {
        Assembly assembly = typeof(SmtpClient).Assembly;
        Type mailWriterType = assembly.GetType("System.Net.Mail.MailWriter");
        object mailWriter = Activator.CreateInstance(mailWriterType, flags, null, new object[] { ms }, CultureInfo.InvariantCulture);
        msg.GetType().GetMethod("Send", flags).Invoke(msg, new object[] { mailWriter, true });
        File.WriteAllText(emlFileAbsolutePath, Encoding.Default.GetString(ms.ToArray()), Encoding.Default);
    }
}

使用範例

MailMessage msg = new MailMessage();
msg.Subject = "hello, i am deltacat";
msg.From = new MailAddress("deltacat@microsoft.com");
msg.To.Add("zu14.cn@live.cn");
msg.Body = "welcome to www.zu14.cn";
SaveToEml(msg, @"d:\test.eml");

原理說明

  1. SmtpClient.Send 內部呼叫 GetFileMailWriter 建立 MailWriter(包裝 FileStream)。
  2. MailWriter 為 internal,外部不可直接存取。
  3. 透過反射取得 MailWriter 型別、建立實例(傳入 MemoryStream)。
  4. 呼叫 MailMessage 的非公開 Send(MailWriter, bool) 多載,將郵件內容寫入記憶體流。
  5. 最後將 MemoryStream 以預設編碼寫入檔案。

注意事項

  • 依賴 .NET Framework 內部實作細節,版本升級可能失效。
  • 僅適用於 .NET Framework,.NET Core / .NET 5+ 需另尋方案(如 MimeKit)。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved