要想各種郵件處理程序能識(shí)別我們所寫的電子郵件,能從我們所書寫的電子郵件中分析和提取出發(fā)件人,收件人,郵件主題和郵件內(nèi)容以及附件等信息,那么我們所寫的電子郵件必須要遵循一定的格式要求,正如我們上一篇博客 手工體驗(yàn)smtp和pop3協(xié)議,我們?cè)诎l(fā)送郵件時(shí)有固定的寫法。而這種郵件內(nèi)容的基本格式和具體細(xì)節(jié)分別是由 rfc822 文檔和 mime 協(xié)議定義的。
1、rfc822 郵件格式
英文參考文檔如下:https://tools.ietf.org/html/rfc822
rfc822 文檔中定義的文件格式包括兩個(gè)部分:郵件頭和郵件體。在上一篇博客,我們通過smtp服務(wù)發(fā)送一封郵件,然后用pop3服務(wù)器接收。郵件接收內(nèi)容如下圖紅色框所顯示:
這上面顯示的不全,我這里將其內(nèi)容整理出來,并在每行左邊加上標(biāo)號(hào):
1 received: from smtpbg5.qq.com (unknown [183.60.61.230])
by mx6 (coremail) with smtp id omcowacxv+ssf99zd5fqag--.5570s3;
thu, 12 oct 2017 22:41:48 +0800 (cst)
2 dkim-signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=qq.com; s=s201512;
t=1507819308; bh=n2xk6iu/bt0tcntodutsq3tkyxbttoi08rt+hjuxmbc=;
h=from:to:subject:mime-version:content-type:content-transfer-encoding:date:message-id;
b=lzbtxaww0+hb1bglkkcqlueu4bvvomxdp3uztkq3ycijt5ypu4fke0m5rrrpcxf0d
w0/pqajrqtughltmpjoudi5adwjfrfkoc1z0+ltaaraozfde5hmnq0hxqstna+ibjc
gmvezcomikvm5qklycz/1lwd5mbj90ykkns3sl08=
3 x-qq-feat: gf8h89u9tnwrjwdyipphyegibbvtgumwr4i/ntv6mwr6yoyfiwpupvj+bcsjz
taz24njms/p1d8bxg7lyvzrcpmpqv7jdw3akjtclrss9xe29fxwsejyk5qld1cmiuhhf9po
1hmwwkizx8q6smehiwr+t/du8sprvhvue4ty5kmpeww967qaazgta5hcnrtgajhzrciumvx
r+k4/ny7i+wwnenotfht4ly4k1ne+vd7vnjblhh674hej2csoseebw7x/leesq6m=
4 x-qq-ssf: 0001000000000010000000000000007
5 x-has-attach: no
6 x-qq-business-origin: 2
7 x-originating-ip: 113.57.253.69
8 x-qq-style:
9 x-qq-mid: webmail4t1507819307t4823829
10 from: "=?iso-8859-1?b?mtezmjgwmzk1mq==?=" <>
11 to: "=?iso-8859-1?b?mtgynzeynju3mzi=?=" <>
12 subject: hello world
13 mime-version: 1.0
14 content-type: multipart/alternative;
boundary="----=_nextpart_59df7f2b_08cb07d0_339f08f2"
15 content-transfer-encoding: 8bit
16 date: thu, 12 oct 2017 22:41:47 +0800
17 x-priority: 3
18 message-id: <[email protected]>
19 x-qq-mime: tcmime 1.0 by tencent
20 x-mailer: qqmail 2.x
21 x-qq-mailer: qqmail 2.x
22 x-qq-sendsize: 520
23 received: from qq.com (unknown [10.137.130.92])
by smtp.qq.com (esmtp) with smtp
id ; thu, 12 oct 2017 22:41:47 +0800 (cst)
24 feedback-id: webmail:qq.com:bgweb:bgweb4
25 x-cm-transid:omcowacxv+ssf99zd5fqag--.5570s3
26 authentication-results: mx6; spf=pass ; dki
m=pass
27 x-coremail-antispam: 1uf129kbjdun29kb7zkaujuuuuu529edanixcx71uuuuu7v73
vfw2agmfu7bjvjm3aalaj3ubiyctniwievja73ujifytuyvj4rwlvtduuuu
28 this is a multi-part message in mime format.
29 content-type: text/plain;
charset="iso-8859-1"
30 content-transfer-encoding: base64
31 pgrpdj48c3bhbibzdhlszt0izm9udc1myw1pbhk6icdsdwnpzgegr3jhbmrljywgvmvyzgfu
yswgj01py3jvc29mdcbzyuhlasc7igxpbmutagvpz2h0oiaymy44chg7ij5uaglziglzihro
zsbmaxjzdcblbwfpbcbzzw50igj5ighhbmqgdxnpbmcgdghlifnnvfagchjvdg9jb2w8l3nw
yw4+pc9kaxy+
上面便是 rfc822 所定義的郵件格式,從第 1 行到第 30 行都是郵件頭,第 31 行是郵件體(經(jīng)過base64加密過了,有興趣的大家可以解碼看看)。而郵件頭和郵件體之間以一個(gè)空行間隔,郵件頭部分是由多個(gè)頭字段和字段內(nèi)容組成,分別表示收件人,發(fā)件人,發(fā)件時(shí)間,主題等信息。還有一些信息是對(duì)應(yīng)的smtp服務(wù)器在郵件傳遞過程中所加上的,我們知道現(xiàn)實(shí)生活中的郵局在處理郵件時(shí),通常都會(huì)在信封上加上郵戳,表示這封郵件在什么時(shí)候經(jīng)過了哪個(gè)郵局哪個(gè)部門處理,我們上個(gè)例子是qq郵箱發(fā)給163郵箱的。而smtp服務(wù)器按從下往上的方式添加信息,即先添加的字段位于后添加字段的后面。所以qq的smtp服務(wù)器會(huì)先添加頭字段,但是添加的字段會(huì)在163的smtp服務(wù)器添加字段的下面,另外 pop3服務(wù)器也會(huì)自己添加一些字段。
每一個(gè)郵件頭以“字段名:字段值”的格式出現(xiàn),即每一行郵件頭的內(nèi)容依次由字段名、冒號(hào)、空格、字段值、回車換行符組成。rfc822文檔中定義了多個(gè)標(biāo)準(zhǔn)的郵件頭字段,每一個(gè)郵件頭字段表示一種特定的信息。郵件頭中也可以包含自定義的頭字段,這種自定義的頭字段通常是某個(gè)組織或機(jī)構(gòu)內(nèi)部專用的。下面是對(duì)一些主要的郵件頭字段的解釋:
我們從上可以知道,rfc822文檔存在兩個(gè)問題:
①、定義了郵件內(nèi)容的主體結(jié)構(gòu)和各種郵件頭字段的詳細(xì)細(xì)節(jié),但是,它沒有定義郵件體的格式,rfc822文檔定義的郵件體部分通常都只能用于表述一段普通的文本,而無法表達(dá)出圖片、聲音等二進(jìn)制數(shù)據(jù)。
②、smtp服務(wù)器在接收郵件內(nèi)容時(shí),當(dāng)接收到只有一個(gè)“.”字符的單獨(dú)行時(shí),就會(huì)認(rèn)為郵件內(nèi)容已經(jīng)結(jié)束,如果一封郵件正文中正好有內(nèi)容僅為一個(gè)“.”字符的單獨(dú)行,smtp服務(wù)器就會(huì)丟棄掉該行后面的內(nèi)容,從而導(dǎo)致信息丟失。
上面兩個(gè)問題是致命的,當(dāng)今的電子郵件,人們希望在電子郵件中嵌入圖片、聲音、動(dòng)畫和附件。但是,由于圖片和聲音等內(nèi)容是非ascii碼的二進(jìn)制數(shù)據(jù),而rfc822郵件格式只適合用來表達(dá)純文本的郵件內(nèi)容,所以,要使用rfc822郵件格式發(fā)送這些非ascii碼的二進(jìn)制數(shù)據(jù)時(shí),必須先采用某種編碼方式將它們“編碼”成可打印的ascii字符后再作為rfc822郵件格式的內(nèi)容。郵件閱讀程序在讀取到這種經(jīng)過編碼處理的郵件后,再按照相應(yīng)的解碼方式解碼出原始的二進(jìn)制數(shù)據(jù),這樣就可以借助rfc822郵件格式來傳遞多媒體數(shù)據(jù)了。這種做法需要解決一下兩個(gè)技術(shù)問題:
一、郵件閱讀程序如何知道郵件中嵌入的原始二進(jìn)制數(shù)據(jù)所采用的編碼方式;
二、郵件閱讀程序如何知道每個(gè)嵌入的圖像或其他資源在整個(gè)郵件內(nèi)容中的起止位置。
為了解決上面兩個(gè)問題,人們后來專門為此定義了mime(multipurpose internet mail extension,多用途internet郵件擴(kuò)展)協(xié)議。
2、mime協(xié)議
mime協(xié)議用于定義復(fù)雜郵件體的格式,它可以表達(dá)多段平行的文本內(nèi)容和非文本的郵件內(nèi)容,例如,在郵件體中內(nèi)嵌的圖像數(shù)據(jù)和郵件附件等。另外,mime協(xié)議的數(shù)據(jù)格式也可以避免郵件內(nèi)容在傳輸過程中發(fā)生信息丟失。mime協(xié)議不是對(duì)rfc822郵件格式的升級(jí)和替代,而是基于rfc822郵件格式的擴(kuò)展應(yīng)用。一言以蔽之,rfc822定義了郵件內(nèi)容的格式和郵件頭字段的詳細(xì)細(xì)節(jié),mime協(xié)議則是定義了如何在郵件體部分表達(dá)出的豐富多樣的數(shù)據(jù)內(nèi)容。
一個(gè)采用了mime協(xié)議的電子郵件就叫做mime郵件,mime郵件在rfc822文檔中定義的郵件頭字段的基礎(chǔ)上,擴(kuò)充了一些自己專用的郵件頭字段,例如,使用mime-version頭字段指定mime協(xié)議的版本,使用content-type頭字段指定郵件體的mime類型,使用content-transfer-encoding頭字段指定編碼方法,如下所示:
1
2
3
|
mime-version: 1.0 content-type:multipart/mixed;boundary= "----=_nextpart_000_0050_01c" |
其中,“multipart/mixed”部分說明郵件體中包含有多段數(shù)據(jù),每段數(shù)據(jù)之間使用boundary屬性中指定的字符文本作為分隔標(biāo)識(shí)符。另外,mime郵件也擴(kuò)展了rfc822文檔中已經(jīng)定義了的郵件頭字段的內(nèi)涵,例如,定義了subject頭字段中的值內(nèi)容的格式,以便通過編碼的方式讓郵件主題中也可以使用非ascii碼的字符。subject頭字段中的值嵌套在一對(duì)“=?”和“?=”標(biāo)記符之間,標(biāo)記符之間的內(nèi)容由三部分組成:郵件主題的原始內(nèi)容的字符集、當(dāng)前采用的編碼方式、編碼后的結(jié)果,這三部分之間使用“?”進(jìn)行分隔。
3、總結(jié)
這篇博客,帶上前面兩篇博客,我們就將郵件的收發(fā)基本原理講了一下。那么有人會(huì)問,實(shí)際項(xiàng)目中我們也需要考慮郵件的底層實(shí)現(xiàn)協(xié)議嗎?答案是不用的,比如 sun 公司(現(xiàn)在已經(jīng)被orcal收購(gòu)了)開發(fā)的javamail api 就是為方便java開發(fā)人員在應(yīng)用程序中實(shí)現(xiàn)郵件接收和發(fā)送功能而提供的一套標(biāo)準(zhǔn)開發(fā)包,屏蔽了底層的郵件實(shí)現(xiàn)協(xié)議,那么下一篇博客我們就來用javamail 實(shí)現(xiàn)郵件收發(fā)功能。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持服務(wù)器之家。
原文鏈接:http://www.cnblogs.com/ysocean/p/7663695.html