前兩天想研究下 e-mail 到底是怎么回事衩侥,e-mail 相關(guān)的協(xié)議是怎么定義的失都,于是查了下資料驾锰,并且還通過命令行的 telnet 工具試驗了手動發(fā)送 e-mail磁椒。下面我就把自己探索的一些東西整理下,水平有限杏糙,講不了很深入慎王,感興趣的朋友可以自己再看下相關(guān)資料。
E-mail 相關(guān)協(xié)議
E-mail 的發(fā)送和接收采用不同協(xié)議宏侍!
E-mail 相關(guān)的應用層協(xié)議挺多赖淤,其中使用得比較廣泛的接收 E-mail 的協(xié)議為:POP3、IMAP谅河,發(fā)送 E-mail 的協(xié)議比較統(tǒng)一咱旱,郵件服務器基本都支持 SMTP确丢。
來看一張圖,F(xiàn)oxmail 配置新的郵箱賬戶時的“手動設(shè)置”界面:
從這里可以看到吐限,常見的接收協(xié)議為 POP3鲜侥、IMAP,這個 Exchange 是微軟自己的協(xié)議诸典。
指定接收郵件的服務器的地址和端口描函,如果服務器支持相應的協(xié)議,那么就可以收取你郵箱的郵件狐粱。
而發(fā)送郵箱舀寓,服務器基本都支持 SMTP 協(xié)議,像上圖中配置好 SMTP 服務器的地址脑奠、端口基公,就可以發(fā)送郵件了。
我自己試驗的主要是發(fā)送郵件宋欺,所以就只介紹下 SMTP 協(xié)議轰豆。
SMTP 協(xié)議
其實所有的這些 e-mail 相關(guān)的協(xié)議,都是很久之前定義的齿诞,SMTP 協(xié)議在上個世紀 80 年代就發(fā)布了酸休。而根據(jù)維基百科的資料,HTTP 第一版(HTTP v0.9)是 1991 年發(fā)布的祷杈。所以斑司,應該是 E-mail 相關(guān)的應用更早,HTTP 協(xié)議是不是也從 E-mail 相關(guān)協(xié)議借鑒了許多東西呢但汞,這個我就不知道了宿刮。
不過這些協(xié)議也是與時俱進的,像 POP 協(xié)議目前是 POP3私蕾,IMAP 協(xié)議目前是 IMAP4僵缺,不過貌似都是稱呼 POP3、IMAP踩叭,為啥一個帶版本號磕潮,另一個不帶呢,不清楚了容贝。
從我理解來看自脯,SMTP 協(xié)議一開始并沒有把自己設(shè)計為專門發(fā)送 e-mail,貌似是收發(fā)都有設(shè)計斤富,不過實際應用中都是在發(fā)送 e-mail 時使用 SMTP 協(xié)議膏潮,接收郵件則通常使用 POP3、IMAP满力。這里面應該有很多背景戏罢、歷史吧屋谭。
維基百科對 SMTP 的描述:
SMTP is a connection-oriented, text-based protocol in which a mail sender communicates with a mail receiver by issuing command strings and supplying necessary data over a reliable ordered data stream channel, typically a Transmission Control Protocol (TCP) connection.
經(jīng)過自己通過 SMTP協(xié)議手動發(fā)送 E-mail 的試驗,我印象比較深的就是 SMTP 是基于文本的協(xié)議龟糕,通過文本而非二進制數(shù)據(jù)進行通信,在客戶端與服務器之間進行通信的時候悔耘,有點像是客戶端和服務器在聊天讲岁,只不過要嚴格遵循一套語法,不然誰也不知道對方在說什么衬以。
關(guān)于具體的協(xié)議細節(jié)缓艳,請到參考資料中的鏈接里面瞅瞅吧,我把自己通過 telnet 命令發(fā)送郵件過程和服務器的“對話”貼出來看峻,感受一下阶淘。
通過 telnet 手動發(fā)送郵件
在 CMD 中,通過 telnet 建立連接:telnet smtp.sina.com 25
220 smtp-5-122.smtpsmail.fmail.xd.sinanode.com ESMTP
helo sina
250 smtp-5-122.smtpsmail.fmail.xd.sinanode.com
auth login
334 VXNlcm5hbWU6
dGFuZ2thbmd4aW5nQHNpbmEuY29t
334 UGFzc3dvcmQ6
<base64 編碼的郵箱密碼互妓,省略_>
235 OK Authenticated
mail from:tangkangxing@sina.com
250 ok
rcpt to:xsm_ue@sina.com
250 ok
data
354 End data with <CR><LF>.<CR><LF>
from:tangkangxing@sina.com
to:xsm_ue@sina.com
subject:helloHello, xsm-ue!
** .**
250 ok queue id 7343365767177
quit
221 smtp-5-122.smtpsmail.fmail.xd.sinanode.com
注:以上加粗的是我輸入的內(nèi)容溪窒,其他的是服務器返回的消息。
簡單回顧下我和新浪郵箱服務器的聊天吧:
- 首先我先通過 telnet 打通了電話冯勉,新浪服務器給了我一個回應(220代號的消息)
- 我打了個招呼(helo)
- 需要登錄驗證身份澈蚌,輸入經(jīng)過 base64 編碼的郵箱賬號和密碼
- 然后我告訴新浪郵箱我以哪個郵箱地址,給誰發(fā)送郵件(mail from 和 rcpt to)
- 然后寫郵件灼狰,“信封”內(nèi)容和“信件”內(nèi)容隔一行宛瞄,寫完以約定的單個 "." 的一行表示結(jié)束
- OK,退出(quit)
這里的新浪郵箱是我的發(fā)件郵箱交胚,也是我注冊自己郵箱賬號的地方份汗。也就是說,我登錄自己的郵箱服務器蝴簇,把郵件發(fā)給TA杯活,再由TA轉(zhuǎn)交給收件人的郵箱服務器(在上面的例子里是一樣的,收件人也是新浪郵箱賬號)军熏。
發(fā)件人 -(SMTP)-> 發(fā)件郵箱服務器 --> 收件郵箱服務器 -(POP3/IMAP)-> 收件人
注:我的系統(tǒng)是 Win8轩猩,默認沒有開啟 telnet 功能,在“控制面板”/“程序”/“啟用或關(guān)閉 Windows 功能” 這里勾選上“Telnet 客戶端”就好了荡澎。
通過 Node.js 寫程序發(fā)送郵件
由于咱是程序員嘛均践,所以想看看能不能鼓搗出個小程序來發(fā)郵箱,因為通過 telnet 敲命令來發(fā)送郵件太慢了摩幔,而且登錄的時候還要把用戶名彤委、密碼進行轉(zhuǎn)換(Chrome 瀏覽器在控制臺通過
可以進行轉(zhuǎn)換)太麻煩。
這一部分其實就是查 Node.js 的 API或衡,然后把上面 telnet 的過程再實現(xiàn)一遍焦影,不多說了车遂,感興趣可以去看看:send-mail by luobotang。
我也發(fā)布到了 NPM斯辰,膽子大的朋友可以安裝了試試:
npm install send-mail
var sendMail = require('send-mail')
sendMail({
"host": "smtp.example.com",
"port": 25,
"username": "luobotang@example.com",
"password": "---",
"from": "luobotang <luobotang@example.com>",
"to": "luobotang1 <luobotang@example1.com>; luobotang2 <luobotang@example2.com>",
"subject": "Hello",
"body": "Hello!"
})