SMTP 連線
本頁說明 SMTP.SendEmail() 依 port 選擇連線方式、認證條件,以及實際送出的信件格式。
前置檢查
SendEmail()(internal/service/smtp.go:28)在連線前依序檢查,任一失敗即回傳錯誤:
| 檢查 | 錯誤訊息 |
|---|---|
enabled 為 true 且 host 非空 |
SMTP not Enabled or Host is not set |
to 至少一個收件者 |
no user email configured |
host:port 在 5 秒內可建立 TCP 連線 |
failed to connect TCP (...) |
連線方式
graph TB
Probe[TCP 探測 5 秒] --> Plain[smtp.Dial 明文連線]
Plain -->|成功| Port587{port = 587?}
Plain -->|失敗且 port = 465| Implicit[tls.Dial 隱式 TLS]
Plain -->|失敗且其他 port| Fail[回傳錯誤]
Port587 -->|是且伺服器支援| StartTLS[STARTTLS 升級]
Port587 -->|否| Auth
StartTLS --> Auth{username 與 password 皆非空?}
Implicit --> Auth
Auth -->|是| Login[PLAIN 認證]
Auth -->|否| Send
Login --> Send[MAIL FROM / RCPT TO / DATA]
| port | 實際行為 |
|---|---|
465 |
先嘗試明文 SMTP;隱式 TLS 伺服器不會送出明文問候,明文嘗試要等伺服器關閉連線才失敗,之後才改以 tls.Dial 建立隱式 TLS 連線,因此寄信可能延遲 |
587 |
明文連線後,若伺服器宣告 STARTTLS 擴充則升級為 TLS;不支援時以明文繼續 |
其他(如 25) |
只用明文連線,不升級 TLS |
TLS 一律以 host 作為 ServerName 驗證伺服器憑證。
認證
username 與 password 都非空時才執行 smtp.PlainAuth;任一為空則略過認證,適用於內網免認證的轉信伺服器。Go 標準庫的 PLAIN 認證只允許在 TLS 連線或 localhost 上送出,因此在 25 等未加密 port 上設定帳密會認證失敗。
信件格式
| 標頭 | 值 |
|---|---|
| From | config.from |
| To | config.to 以逗號串接 |
| Cc | config.cc;空值時填 config.from |
| Subject | 告警或測試信主旨 |
| Content-Type | text/html; charset=UTF-8 |
RCPT TO 只對 to 清單中的地址送出,Cc 只寫在標頭,見 已知限制。