配置mail使用SMTP傳送郵件

tlanyan發表於2019-03-04

轉載請註明文章出處:tlanyan.me/config-mail…

前文“PHP回顧之傳送郵件”介紹了郵件中的一些基本概念,今天分享在Linux上使用mail命令通過SMTP對外傳送郵件。

mail、mailx和sendmail

先看一下三者的關係:mailmailx的別名,最初叫nail(與arch linux目前用的S nail基因相同);mail是Heirloom的一個子專案,sendmail是Eric Allman的作品,都是開源專案;mail是使用者代理(客戶端),sendmail是郵件傳輸代理(伺服器);mail預設使用sendmail對外傳送郵件。

總結:mail和mailx是同一個東西,大約類似於發信用的foxmail、outlook等工具,sendmail大約相當於163/qq郵箱的伺服器軟體。

SSL、TLS和STARTTLS

由前文我們知道雲伺服器基本上不允許25埠對外通訊,要對外發郵件只能考慮465和587埠。那麼465和587埠有什麼區別?這要先從SSL、TLS和STARTTLS的區別開始說。

SSL(Secure Socket Layer)是加密傳輸層,TLS(Transport Layer Security)是SSL的繼承者和升級版,提供更好的安全性和效能。SSL有SSL v2、SSL v3兩個版本,目前都不建議使用。TLS有TSL v1.0-v1.3,建議至少使用TLS v1.2。

TLS和STARTTLS兩者關係不大,但更讓人容易產生誤解,原因是名字中都帶有TLS。STARTTLS是升級非安全連線為安全連線的協議,並沒有強制使用加密。當服務端支援時,客戶端和服務端才協商將已經建立的連線升級到SSL或者TLS加密。

接著看465埠和587埠。我們知道25埠剛被設計出來時是用於轉發郵件的,沒有考慮認證、加密等問題。隨著垃圾郵件氾濫、網路安全問題嚴重,MSA、ESMTP/SMTPS等概念和協議被設計出來。1997年465埠被註冊用於加密方式(SMTPS)提交郵件,那時STARTTLS還沒有搗騰出來。1998年STARTLS標準出爐,規定用587埠以STARTTLS方式提交郵件,465埠被吊銷。然而許多客戶端不支援STARTTLS,加上非常多郵件服務提供商都在使用465埠作為加密提交埠,於是465就一直這麼被用到今天。

簡單來說,465埠只支援加密傳輸,不符合網際網路號碼分配結構(The Internet Assigned Numbers Authority,IANA)的標準,但一直被使用和支援;587埠專門被設計用來提交郵件,傳輸可以加密也可以不加密。

配置mail

明白了基本概念,接下來配置mail使用SMTP對外傳送郵件。mail命令的系統級配置檔案是/etc/mail.rc,使用者級別的預設配置檔案是~/.mailrc,也可以通過MAILRC環境變數設定配置檔案路徑。作為普通使用者,我們在本地的~/.mailrc檔案進行配置,SMTP的主要配置如下:

set smtp=smtps://smtp.xxx.com:465   # 這裡填入smtp地址
set smtp-auth=login                 # 認證方式
set smtp-auth-user=user@xxx.com     # 這裡輸入郵箱賬號
set smtp-auth-password=password     # 這裡填入密碼
set ssl-verify=ignore               # 忽略證照警告
set nss-config-dir=/etc/pki/nssdb   # 證照所在目錄
set from=user@xxx.com               # 設定發信人郵箱和暱稱
#set smtp-use-starttls=yes          # STARTTLS時使用
複製程式碼

幾個注意點:

  1. 如果是465埠,需要加上smtps://協議;如果是587埠,不需要加smtps://或者寫smtp://
  2. 如果使用587埠通訊,應當顯示設定smtp-use-starttls
  3. 郵件的來源應當與郵箱相同,或者將發信人姓名寫在郵箱後的括號中。例如:set from=user@xxxx.comset from=user@xxx.com(nickname);如果郵箱與認證的不一致,將出現“smtp-server: 553 Mail from must equal authorized user”的錯誤;
  4. 有些郵件伺服器的587埠不是使用STARTTLS而是SMTPS,此時仍需加上smtps://協議,例如126郵箱。

配置好後,使用mail命令傳送郵件:

echo `郵件內容` | mail -s `郵件標題` 收件人郵箱
#或者:
cat 郵件內容.txt | mail -s `郵件標題` 收件人郵箱
#或者
mail -s `郵件標題` 收件人郵箱 < 郵件內容.txt
複製程式碼

mail命令的選項非常豐富,具體可檢視其文件或這篇文章

多賬戶

如果想切換髮送郵箱怎麼辦?答案是利用配置檔案的account指令或在命令列中指定配置。先看配置檔案中指定,在~/.mailrc中將配置改成如下:

# 126不支援STARTTLS,使用465埠
account 126 {
    set smtp=smtps://smtp.126.com:465
    set smtp-auth=login
    set smtp-auth-user=user@126.com
    set smtp-auth-password=password
    set ssl-verify=ignore
    set nss-config-dir=/etc/pki/nssdb
    set from=password@126.com
}
# QQ郵箱支援STARTTLS,使用587埠
account qq {
    set smtp=smtp://smtp.qq.com:587
    set smtp-auth=login
    set smtp-auth-user=user@qq.com
    set smtp-auth-password=password
    set ssl-verify=ignore
    set nss-config-dir=/etc/pki/nssdb
    set from="user@qq.com(nickname)"
    set smtp-use-starttls=yes
}
複製程式碼

配置檔案中定義了兩個賬戶,傳送郵件時可用-A引數指定發信賬戶:

echo `mail test for 126` | mail -A 126 -s `mail test` user@xxx.com
echo `mail test for qq` | mail -A qq -s `mail test` user@xxx.com
複製程式碼

除了配置檔案,也可以在命令列中用-S引數進行設定。例如:

echo `mail test for command line option` | mail -s `mail test` -S smtp=smtp://smtp.qq.com:587 -S smtp-auth=login -S smtp-auth-user=user@qq.com -S smtp-auth-password=password -S ssl-verify=ignore -S nss-config-dir=/etc/pki/nssdb -S from="user@qq.com(nickname)" -S smtp-use-starttls=yes user@xxx.com
複製程式碼

這種方法比較繁瑣,就是將配置檔案的每一行都作為選項寫在命令中。在程式中呼叫mail命令傳送郵件時可以採取這種方法。

解決警告

雖然郵件能順利傳送,但每次執行都會出現一行警告:“Error in certificate: Peer`s certificate issuer is not recognized.”。這是由於使用加密通訊,但客戶端不能確認證照是否真實。如果我們將配置中的set ssl-verify=ignore改成set ssl-verify=strict,連線將直接中斷而不會繼續發郵件。

要解決這個警告,需要將郵件伺服器的證照加入到信任列表。操作步驟如下:

  1. 獲取郵件伺服器證照:
# 465埠
echo -n "" | openssl s_client -connect smtp.xxx.com:465 | sed -ne `/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p` > xxx.crt

# 587埠
echo -n | openssl s_client -starttls smtp -connect smtp.xxx.com:587 | sed -ne `/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p` > xxx.crt

# 也可以直接在瀏覽器上開啟網頁版,儲存證照為PEM(base64格式)格式然後上傳到伺服器
複製程式碼
  1. 將證照新增到受信任列表:
certutil -A -n `xxxx` -t "P,P,P" -d . -i ./xxx.crt
複製程式碼

上述命令中-A表示新增,-n是nickname,可以隨意取,例如126或qq;-t表示受信任的標籤,可取值是t/c/p三種或者其組合;-d表示證照所在目錄,-i指示證照檔案的位置。

  1. 在配置檔案中更改證照目錄:
# 指向證照檔案目錄
set nss-config-dir=/path/to/cert-dir
複製程式碼

網上許多教程的-t標籤都是"C,,",實踐中發現使用該標籤仍會報錯(gmail的證照是google自己簽發的,用C標籤沒問題,許多博主估計沒試就直接抄來)。通過查閱certutil的用法,使用P標籤順利解決問題。

配置完成後,再使用mail命令傳送郵件,煩人的警告消失不見。

其他

“Unexpected EOF on SMTP connection”,基本上是由於埠只支援SMTPS導致,將協議改成smtps://即可。

參考

  1. heirloom.sourceforge.net/mailx.html
  2. gist.github.com/ilkereroglu…
  3. serverfault.com/questions/4…
  4. www.systutorials.com/docs/linux/…
  5. www.fastmail.com/help/techni…
  6. docs.iredmail.org/enable.smtp…
  7. www.computerhope.com/unix/umailx…
  8. coderwall.com/p/ez1x2w/se…

相關文章