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

C# 將 MailMessage 另存為本地 .eml 檔案:SmtpClient Pickup 目錄法

     編輯:關於C#

前言

上一篇介紹了透過反射呼叫內部 MailWriter 將 MailMessage 序列化為 EML,雖可行但程式碼複雜且依賴非公開 API。本文發現 SmtpClient 內建一種更簡單的機制:設定 DeliveryMethod = SpecifiedPickupDirectory,郵件不會真正發送,而是直接寫入指定目錄成 .eml 檔。

原理分析

SmtpClient.Send 內部針對 DeliveryMethod 分派:

  • Network:透過 SMTP 協定發送
  • PickupDirectoryFromIis:交給 IIS SMTP 服務拾取(需安裝 IIS)
  • SpecifiedPickupDirectory:直接在 PickupDirectoryLocation 目錄生成 .eml 檔,無任何網路互動

此機制原本設計給 IIS SMTP 服務輪詢拾取,我們借用它來「離線生成 EML」。

最小實作程式碼

using System.Net.Mail;

public void SaveMailAsEml(string pickupFolder)
{
    // 確保目錄存在
    if (!Directory.Exists(pickupFolder))
        Directory.CreateDirectory(pickupFolder);

    using (var smtp = new SmtpClient())
    {
        smtp.EnableSsl = false; // 必須關閉 SSL
        smtp.DeliveryMethod = SmtpDeliveryMethod.SpecifiedPickupDirectory;
        smtp.PickupDirectoryLocation = pickupFolder; // 例如 @"D:\MailDrop\"

        var msg = new MailMessage();
        msg.Subject = "Hello from C#";
        msg.From = new MailAddress("sender@example.com");
        msg.To.Add("recipient@example.com");
        msg.Body = "這是透過 Pickup 目錄生成的 .eml 檔案。";
        msg.IsBodyHtml = false;

        smtp.Send(msg); // 瞬間在 pickupFolder 產生一個 {GUID}.eml
    }
}

優缺點對照

優點缺點
零反射、零內部 API 依賴檔名為隨機 GUID,無法自訂
程式碼極簡,幾行搞定需手動掃描目錄取得最新檔案
自動處理附件、編碼、標頭格式若需精確控制檔名,仍需反射法或自行組裝 MIME
不需安裝/設定 SMTP 服務大量生成時需注意目錄清理

進階:取得剛生成的檔案路徑

public string SaveMailAsEmlAndGetPath(string pickupFolder, MailMessage msg)
{
    // 發送前先記錄目錄現有檔案
    var before = new HashSet<string>(Directory.GetFiles(pickupFolder, "*.eml"), StringComparer.OrdinalIgnoreCase);

    using (var smtp = new SmtpClient())
    {
        smtp.EnableSsl = false;
        smtp.DeliveryMethod = SmtpDeliveryMethod.SpecifiedPickupDirectory;
        smtp.PickupDirectoryLocation = pickupFolder;
        smtp.Send(msg);
    }

    // 發送後比對新增檔案
    var after = Directory.GetFiles(pickupFolder, "*.eml");
    foreach (var f in after)
    {
        if (!before.Contains(f))
            return f; // 回傳新生成的 .eml 完整路徑
    }
    return null;
}

適用場景

  • 郵件內容歸檔/審計
  • 單元測試驗證郵件格式
  • 離線開發環境無 SMTP 伺服器時的除錯
  • 批次產生通知信 .eml 供後續人工審核發送

注意事項

  1. EnableSsl 必須為 false,否則會嘗試 STARTTLS 導致例外
  2. 目錄權限:執行身分需具備寫入權限
  3. .eml 檔案編碼為 UTF-8,可直接用 Outlook/Windows Mail 開啟
  4. 附件會以 Base64 編碼內嵌於 .eml 內

原文出處:cnblogs sjcatsoft

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved