轉(zhuǎn)自:http://book.csdn.net/bookfiles/402/10040214756.shtml
MIME郵件的編碼方式
由于每個ASCII碼字符只占用一個字節(jié)(8個bit位),且最高bit位總為0,即ASCII碼字符中的有真正意義的信息只是后面的7個低bit位,而傳統(tǒng)的SMTP協(xié)議又是基于ASCII碼字符設(shè)計(jì)的,因此,一些基于傳統(tǒng)SMTP協(xié)議設(shè)計(jì)的SMTP服務(wù)器在處理郵件內(nèi)容時(shí)只取出每個字節(jié)中的7個低bit位進(jìn)行處理,而將最高bit位忽略不計(jì)。顯然,這樣的SMTP服務(wù)器在處理包含有非ASCII碼字符的郵件內(nèi)容時(shí),會出現(xiàn)嚴(yán)重的問題,這就限制了郵件中只能出現(xiàn)英文的ASCII碼字符,而不能出現(xiàn)中文字符或二進(jìn)制數(shù)據(jù)。
為了能夠在郵件內(nèi)容中包含中文、圖像或聲音等非ASCII字符的數(shù)據(jù),人們想到了采用某種編碼方式將非ASCII字符的數(shù)據(jù)轉(zhuǎn)換成可打印的ASCII字符后再發(fā)送,郵件閱讀程序則按照相應(yīng)的解碼方式從郵件中還原出原始數(shù)據(jù)即可,比較常用的兩種郵件編碼方式為BASE64和Quoted-printable。后來的擴(kuò)展SMTP協(xié)議允許直接在郵件中傳遞二進(jìn)制數(shù)據(jù),而不用對它們進(jìn)行郵件編碼,人們將這種沒有進(jìn)行郵件編碼的二進(jìn)制數(shù)據(jù)的郵件內(nèi)容稱為8bit編碼,為了與此相區(qū)別,人們將沒有進(jìn)行郵件編碼的純ASCII碼字符的郵件稱為7bit編碼。MIME消息體的郵件編碼方式通過MIME消息頭中的Content- Transfer- Encoding頭字段指定,每種郵件編碼方式的介紹如下:
— 7Bit
指消息體內(nèi)容全部是沒有經(jīng)過編碼的ASCII字符。
— 8Bit
指消息體內(nèi)容是沒有經(jīng)過編碼的原始數(shù)據(jù),且其中包含有非ASCII字符的數(shù)據(jù)。現(xiàn)在的郵件服務(wù)器基本上都支持8Bit編碼,使用支持8Bit編碼的郵件服務(wù)器可以簡化郵件的處理過程。
— BASE64
Base64是將二進(jìn)制數(shù)據(jù)轉(zhuǎn)換成可打印的ASCII字符的一種最常見的編碼方式,它的基本原理是將一組連續(xù)的字節(jié)數(shù)據(jù)按6個bit位進(jìn)行分組,然后對每組數(shù)據(jù)用一個ASCII字符來表示。6個bit位最多能表示26=64個數(shù)值,因此可以使用64個ASCII字符來對應(yīng)這64個數(shù)值,這64個ASCII字符為:
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
其中每個字符表示的數(shù)值就是該字符在上面的排列中的索引號,索引號從0開始編號。假設(shè)在內(nèi)存中有如下三個連續(xù)的字節(jié)數(shù)據(jù):
[0110,0001] [0110,0010] [0110,0011]
將它們按6個bit位進(jìn)行分組后的形式如下:
[0110,00] [01,0110,] [0010,01] [10,0011]
分組后得到了四組數(shù)據(jù),每組數(shù)據(jù)對應(yīng)的十進(jìn)制數(shù)值分別為24、22、9、35,它們分別對應(yīng)Y、W、J、j這四個字符,所以,對[0110,0001] [0110,0010] [0110,0011]這三個字節(jié)的數(shù)據(jù)進(jìn)行BASE64編碼后的結(jié)果是“YWJj”。
BASE64編碼要求把3個8位字節(jié)(即24個bit)的數(shù)據(jù)轉(zhuǎn)化為4個6位字節(jié)(也是24個bit)的數(shù)據(jù),如果原來的8位字節(jié)數(shù)據(jù)的字節(jié)個數(shù)不能被3整除,其余數(shù)只能是1或2,那么如何對余下的1個或2個8位字節(jié)數(shù)據(jù)進(jìn)行處理呢?對于這種情況,仍然按6個bit位對剩余的字節(jié)進(jìn)行分組,在最后不夠6個bit位的內(nèi)容后面添加幾個為0的bit位來湊成6個bit位,例如,如果最后剩下的一個8位字節(jié)的內(nèi)容如下:
[0110,0001]
對它進(jìn)行分組后的結(jié)果如下:
[0110,00] [01,0000]
其中用黑斜體標(biāo)識的0為填充的bit位,所以,最后剩下的這個字節(jié)的BASE64編碼結(jié)果為“YQ”。BASE64編碼還有規(guī)定,如果編碼后的整個結(jié)果文本的字符個數(shù)不是4的整數(shù)倍,那么需要在最后填充“=”字符來湊成4的倍數(shù),所以,在最后這個字節(jié)編碼的結(jié)果后面還要添加兩個“=”字符,即“YQ==”。顯然,如果最后剩下兩個8位字節(jié)的內(nèi)容,它可以被編碼成三個字符,最后還需要添加一個“=”字符。對一大段數(shù)據(jù)進(jìn)行BASE64編碼時(shí),可以在編碼結(jié)果中的適當(dāng)位置加入回車換行,MIME規(guī)范建議BASE64編碼結(jié)果中的每行最多76個字符。
— Quoted-printable
Quoted-printable也是一種將二進(jìn)制數(shù)據(jù)轉(zhuǎn)換成可打印的ASCII字符的編碼方式,它對ASCII字符不進(jìn)行轉(zhuǎn)換,只對非ASCII字符的數(shù)據(jù)進(jìn)行編碼轉(zhuǎn)化。每個非ASCII字符的字節(jié)數(shù)據(jù),都被轉(zhuǎn)換成一個"="號后跟這個字節(jié)的十六進(jìn)制數(shù)據(jù),例如,“ab中國”的Quoted-printable編碼結(jié)果為“ab=d6=d0=b9= fa”。顯然,由于"="號在Quoted-printable編碼中具有的特殊意義,所以,原始數(shù)據(jù)中的"="號字符也需要進(jìn)行編碼轉(zhuǎn)換,用“=3d”表示。
對一大段數(shù)據(jù)進(jìn)行Quoted-printable編碼時(shí),可以在編碼結(jié)果中的適當(dāng)位置加入回車換行,在回車換行前需要額外再加入一個“=”字符,以表示后面的換行是因編碼而造成的軟回車,而非原始數(shù)據(jù)中原有的回車換行。例如,對于下面一段Quoted-printable編碼后的數(shù)據(jù):
=D5=E2=CA=C7=CD=A8=D0=C5=B5=C4=B3=CC=D0=
=F2, =C7=EB=D6=B8=BD=CC!
在第一行末尾的“=”字符和換行,都是由于編碼后生成的。