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

C# SMTP 郵件發送庫完整實現:支援認證、附件、HTML、編碼修正版

     編輯:關於C語言

前言

.NET Framework 早期 System.Web.Mail 功能受限,System.Net.Mail (2.0+) 雖強大但理解底層 SMTP 協議、處理特殊編碼、附件邊界仍有學習價值。本文呈現一個純 Socket 實現的 SMTP 客戶端類別 SmtpMail,支援:SMTP AUTH (LOGIN)、多收件人、HTML/純文本、Base64 編碼主題/附件名/正文、多部分 MIME、附件傳輸、優先級、詳細日誌/錯誤碼對照。代碼經過實戰驗證,修正了 1.0 版中文內容丟失、亂碼、附件損壞等問題。

核心類別結構


namespace Lion.Web.Mail
{
    public class SmtpMail
    {
        // 設定屬性
        public string Charset { get; set; } = "GB2312"; // 郵件編碼
        public string From { get; set; }                // 發件人郵箱
        public string FromName { get; set; }            // 發件人顯示名
        public string RecipientName { get; set; }       // 收件人顯示名
        public string MailDomain { set { /* 解析 server:port@user:pass */ } }
        public int MailDomainPort { set { /* port */ } }
        public string MailServerUserName { set { /* user + 啟用 ESmtp */ } }
        public string MailServerPassWord { set { /* pass */ } }
        public string Priority { set { /* High/Normal/Low -> 1/3/5 */ } }
        public bool Html { get; set; }                  // 是否 HTML
        public string Subject { get; set; }
        public string Body { get; set; }
        public int RecipientMaxNum { set { /* 最大收件人數 */ } }

        // 唯讀屬性
        public string ErrorMessage { get; private set; }
        public string Logs { get; private set; } // SMTP 交互日誌

        // 方法
        public void AddAttachment(params string[] filePaths) { /* ... */ }
        public bool AddRecipient(params string[] emails) { /* ... */ }
        public bool Send() { /* 核心發送流程 */ }
        public bool Send(string smtpServer) { /* 便捷重載 */ }
        public bool Send(string smtpServer, string from, string fromName, 
                         string to, string toName, bool html, string subject, string body) { /* 全參數重載 */ }
    }
}

核心發送流程

  1. TCP 連線:TcpClient.Connect(server, port) → NetworkStream
  2. 問候/驗證:
    • 非認證:HELO server
    • 認證:EHLO server → AUTH LOGIN → Base64(user) → Base64(pass)
  3. 信封命令:MAIL FROM:<from> → 多個 RCPT TO:<to>
  4. 資料傳輸:DATA → MIME 完整郵件內容 → .\r\n 結束
  5. 結束:QUIT

MIME 郵件構建關鍵點(修正重點)


// 邊界字串:HTML 有附件 vs 無附件、純文本有附件 用不同前綴區分
string boundary = Html 
    ? "=====001_Dragon520636771063_=====" 
    : "=====001_Dragon303406132050_=====";

// 主題/附件名/顯示名 Base64 編碼:= ?charset?B?base64?=
string EncodeHeader(string text, string charset) {
    return "=?" + charset.ToUpper() + "?B?" + Convert.ToBase64String(Encoding.GetEncoding(charset).GetBytes(text)) + "?=";
}

// 正文/附件內容 Base64 編碼
string EncodeBody(string text, string charset) {
    return Convert.ToBase64String(Encoding.GetEncoding(charset).GetBytes(text));
}

// 附件檔案讀取 Base64
string GetFileBase64(string path) {
    byte[] bytes = File.ReadAllBytes(path);
    return Convert.ToBase64String(bytes);
}

關鍵修正(vs 1.0 版)

問題原因修正
163 郵箱文本模式內容消失MIME 結構錯誤,純文本部分未正確封裝統一使用 multipart/alternative (HTML) 或 multipart/mixed (含附件) 結構,明確 Content-Transfer-Encoding: base64
Outlook 收到亂碼尾隨Base64 解碼邊界處理錯誤,行尾未換行每行 76 字符換行(MIME 標準),附件結束雙換行
新郵箱 (126.com) 亂碼Charset 未正確聲明/編碼不匹配全鏈路指定 charset=GB2312 (或 UTF-8),Header/Body 一致
附件打開內容錯亂附件 Content-Type 錯誤、Base64 編碼錯誤附件用 application/octet-stream,檔案名同樣 Base64 編碼於 Header

使用範例


var mail = new SmtpMail {
    Charset = "UTF-8",          // 建議現代環境用 UTF-8
    From = "sender@domain.com",
    FromName = "發件人名稱",
    RecipientName = "收件人名稱",
    Html = true,
    Subject = "測試郵件",
    Body = "

HTML 內容

支援中文

", Priority = "High" }; mail.MailDomain = "user:pass@smtp.domain.com:25"; // 或分開設定 mail.AddRecipient("to1@domain.com", "to2@domain.com"); mail.AddAttachment(@"C:\report.pdf", @"C:\image.png"); if (mail.Send()) { Console.WriteLine("發送成功"); } else { Console.WriteLine("失敗: " + mail.ErrorMessage); Console.WriteLine("日誌: " + mail.Logs); }

SMTP 回應碼對照表(內建)


// 成功碼
220 服務就緒
250 操作完成
251 非本地用戶,將轉發
354 開始輸入郵件內容
221 關閉連線
334 驗證挑戰 (Base64)
235 驗證成功

// 錯誤碼 (部分)
500 語法錯誤
501 參數錯誤
503 需要認證
550 郵箱不可用/不存在
553 郵箱名格式錯誤
530 需要認證
421 服務未就緒
450/451/452 暫時失敗

注意事項與最佳實踐

  • 編碼選擇:新系統強烈建議 UTF-8;舊系統相容才用 GB2312/Big5
  • 附件大小:SMTP 伺服器通常限制 10~50MB,大檔案請用雲存儲連結
  • SSL/TLS:本實現為明文/STARTTLS 前;生產環境 465/587 埠需 SslStream 包裝 NetworkStream
  • 發信頻率:避免觸發反垃圾郵件限流,批量發送加延遲、分散 IP
  • 錯誤處理:ErrorMessage 含人類可讀說明,Logs 含完整 SMTP 對話,除錯必備
  • 現代替代:.NET Core/5+ 請直接用 MailKit (跨平台、支援 OAuth2、IMAP/POP3/SMTP 全協議)

總結

手寫 SMTP 客戶端是理解郵件協議、MIME 結構、Base64 編碼、TCP 通訊的最佳練習。本 SmtpMail 類別修正了實戰中常見的中文編碼、附件邊界、多部分結構問題,展示了協議級開發的嚴謹性。雖然生產環境推薦成熟庫,但掌握底層細節能在排查郵件發送疑難雜症時游刃有餘。

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