轉載請註明文章出處: https://tlanyan.me/config-mai...
前文「PHP回顧之發送郵件」介紹了郵件中的一些基本概念,今天分享在Linux上使用mail
命令經過SMTP對外發送郵件。php
先看一下三者的關係:mail
是mailx
的別名,最初叫nail
(與arch linux目前用的S nail
基因相同);mail
是Heirloom的一個子項目,sendmail
是Eric Allman的做品,都是開源項目;mail
是用戶代理(客戶端),sendmail
是郵件傳輸代理(服務器);mail
默認使用sendmail
對外發送郵件。html
總結:mail和mailx是同一個東西,大約相似於發信用的foxmail、outlook等工具,sendmail大約至關於163/qq郵箱的服務器軟件。linux
由前文咱們知道雲服務器基本上不容許25端口對外通訊,要對外發郵件只能考慮465和587端口。那麼465和587端口有什麼區別?這要先從SSL、TLS和STARTTLS的區別開始說。git
SSL(Secure Socket Layer)是加密傳輸層,TLS(Transport Layer Security)是SSL的繼承者和升級版,提供更好的安全性和性能。SSL有SSL v二、SSL v3兩個版本,目前都不建議使用。TLS有TSL v1.0-v1.3,建議至少使用TLS v1.2。github
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端口專門被設計用來提交郵件,傳輸能夠加密也能夠不加密。bash
明白了基本概念,接下來配置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時使用
幾個注意點:網絡
smtps://
協議;若是是587端口,不須要加smtps://
或者寫smtp://
;smtp-use-starttls
;set from=user@xxxx.com
或set from=user@xxx.com(nickname)
;若是郵箱與認證的不一致,將出現「smtp-server: 553 Mail from must equal authorized user」的錯誤;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
,鏈接將直接中斷而不會繼續發郵件。
要解決這個警告,須要將郵件服務器的證書加入到信任列表。操做步驟以下:
# 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格式)格式而後上傳到服務器
certutil -A -n 'xxxx' -t "P,P,P" -d . -i ./xxx.crt
上述命令中-A表示添加,-n是nickname,能夠隨意取,例如126或qq;-t表示受信任的標籤,可取值是t/c/p三種或者其組合;-d表示證書所在目錄,-i指示證書文件的位置。
# 指向證書文件目錄 set nss-config-dir=/path/to/cert-dir
網上許多教程的-t標籤都是"C,,"
,實踐中發現使用該標籤仍會報錯(gmail的證書是google本身簽發的,用C標籤沒問題,許多博主估計沒試就直接抄來)。經過查閱certutil
的用法,使用P標籤順利解決問題。
配置完成後,再使用mail
命令發送郵件,煩人的警告消失不見。
"Unexpected EOF on SMTP connection",基本上是因爲端口只支持SMTPS致使,將協議改爲smtps://
便可。