.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");
SmtpClient.Send 內部呼叫 GetFileMailWriter 建立 MailWriter(包裝 FileStream)。MailWriter 為 internal,外部不可直接存取。MailWriter 型別、建立實例(傳入 MemoryStream)。MailMessage 的非公開 Send(MailWriter, bool) 多載,將郵件內容寫入記憶體流。MemoryStream 以預設編碼寫入檔案。MimeKit)。