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

Java 網路基礎:基於 Socket 手寫 SMTP 客戶端發送郵件

     編輯:Java 相關知識

SMTP (Simple Mail Transfer Protocol) 是郵件傳輸的核心協議。本例拋棄 JavaMail,直接使用 Socket 連接埠 25,手動發送 HELO, MAIL FROM, RCPT TO, DATA 等指令完成郵件發送,是理解「郵件如何送達」的最直觀教學案例。

SMTP 會話流程圖解

C: HELO theWorld              // 問候,宣告客戶端身分
S: 250 OK
C: MAIL FROM: <>            // 寄件者(空地址常被拒收)
S: 250 OK
C: RCPT TO: recipient@domain.com  // 收件者
S: 250 OK
C: DATA                       // 開始資料傳輸
S: 354 Start mail input
C: Subject: Test Mail         // 郵件主旨 (Header 一部分)
C: From: sender <>          // 寄件者顯示名
C:                            // 空行分隔 Header 與 Body
C: 這是郵件正文內容...
C: .                          // 單獨一行 "." 結束資料
S: 250 OK queued
C: QUIT                       // 結束會話
S: 221 Bye

程式碼核心實作

Socket s = new Socket(mailServer, 25);
BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream(), "8859_1"));
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(s.getOutputStream(), "8859_1"));

// 封裝發送指令並讀取回應
void send(BufferedReader in, BufferedWriter out, String cmd) {
    out.write(cmd + "\n");
    out.flush();
    System.out.println("C: " + cmd);
    String reply = in.readLine();
    System.out.println("S: " + reply);
}

// 主流程
send(in, out, "HELO theWorld");
send(in, out, "MAIL FROM: <>");
send(in, out, "RCPT TO: " + recipient);
send(in, out, "DATA");
send(out, "Subject: 測試郵件"); // 僅寫入不讀回應
send(out, "From: sender <>");
send(out, "\n"); // 空行
send(out, "郵件正文內容...");
send(out, "\n.\n"); // 結束標記
send(in, out, "QUIT");
s.close();

關鍵技術細節

  • 編碼選擇:SMTP 早期規範 (RFC 821) 規定 7-bit ASCII,傳統用 ISO-8859-1 (Latin-1) 傳輸。現代郵件內容含中文需配合 MIME 編碼 (Base64/Quoted-Printable) 在 Header/Body 中標註 charset,本例未處理編碼,中文可能亂碼。
  • 指令與資料流區分:HELO/MAIL/RCPT/DATA/QUIT 是指令,需讀取伺服器回應碼;DATA 後的 Header/Body 是資料流,不逐行讀取回應,直到發送 .\n 才讀取最終回應。程式碼透過重載 send(BufferedWriter out, String) 區分兩種模式。
  • 反垃圾郵件機制:現代 SMTP 伺服器普遍要求:
    • 認證:AUTH LOGIN/PLAIN (Base64 編碼帳密)
    • 有效寄件域:MAIL FROM 必須為真實可驗證域名
    • SPF/DKIM/DMARC:DNS 記錄驗證發送授權與完整性
    • 加密傳輸:STARTTLS (587) 或 SMTPS (465)
    本例無認證、空寄件者,實測極大概率被主流郵箱 (Gmail, Outlook, 企業郵) 拒收。

教學價值與實戰差距

此程式碼極佳地展示了 SMTP 協議狀態機本質,但距離生產可用尚遠。實戰建議:

  1. 直接使用 JavaMail 或 Apache Commons Email,已封裝完整協議細節、MIME 編碼、SSL/TLS、認證、重試。
  2. 若必須手寫,參考 RFC 5321 完整實作指令語法、回應碼處理、錯誤重試、流量控制。
  3. 考慮引入 專用郵件佇列服務 (如 Postfix, Sendmail, 或雲端 SendGrid/Amazon SES API) 解耦業務邏輯與發送可靠性。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved