今日是JAVAWEB最后一課,JAVAMAIL。E-mail在當(dāng)今的日常生活中已經(jīng)成為人們重要的通信方式之一,在WEB應(yīng)用中E -mail被做為與用戶(hù)通信的最重要方式。如今各大綜合性網(wǎng)站都有提供自己的mail服務(wù),企業(yè)或各其他專(zhuān)業(yè)性網(wǎng)站也有自己的內(nèi)部mail服務(wù)器,天于為工作交流與合作。所以,學(xué)習(xí)E-mail技術(shù)是十分重要的!
一、郵件傳輸協(xié)議:
有使用過(guò)桌面郵件客戶(hù)端的人都知道,關(guān)聯(lián)一個(gè)郵件帳戶(hù),需要設(shè)置它的SMTP郵件發(fā)送服務(wù)器和POP3郵件接收服務(wù)器。
SMTP和POP3協(xié)議到底是什么?(老方的圖片):

1. 實(shí)線部分(lisi@sina.com向wangwu@sohu.com發(fā)送郵件):
使用郵件客戶(hù)端(這里使用的是OutLook,也可以是網(wǎng)頁(yè)郵件客戶(hù)端或其他郵件客戶(hù)端),使用SMTP協(xié)議向sina的郵件服務(wù)器發(fā)送郵件,服務(wù)器檢測(cè)收件人的郵箱地址是sohu的郵件服務(wù)。所以,通過(guò)SMTP協(xié)議轉(zhuǎn)發(fā)給sohu服務(wù)器,sohu服務(wù)器將郵件存儲(chǔ)到存儲(chǔ)設(shè)備中。
2. wangwu@sohu.com,登陸郵件客戶(hù)端。通過(guò)pop3協(xié)議,從POP3服務(wù)器接收自己帳戶(hù)的郵件。POP3從郵件服務(wù)器中讀取郵件發(fā)送給客戶(hù)端。
3. 虛線部分(wangwu@sohu.com向lisi@sina.com發(fā)送郵件)
過(guò)程與上邊的相同。
二、使用windwos的控制臺(tái)發(fā)送郵件(SMTP協(xié)議):
1.注冊(cè)一個(gè)郵件帳戶(hù),比如:test@gmail.com。
2.在運(yùn)行中輸入“cmd”打開(kāi)控制臺(tái)程序。
3.輸入:telnet smtp.google.com 25,回車(chē)。使用windows的telnet程序連接gmail的郵件發(fā)送服務(wù)器,SMTP的默認(rèn)端口為25。
4.輸入:auth login,回車(chē)。登陸。
5.輸入:(test)用戶(hù)名,必須是經(jīng)過(guò)Base64編碼后的文本。
6.輸入:密碼,必須是經(jīng)過(guò)Base64編碼后的文本。
7.輸入:mail from:<test@gmail.com>,回車(chē)。郵件開(kāi)自,這里是自己給自己發(fā)郵件,也可以是其他郵件。
8.輸入:rcpt to:<test@gmail.com>,回車(chē)。郵件發(fā)送到。
9.輸入:Data,回車(chē)。接下來(lái)要輸入郵件內(nèi)容。
10.輸入:郵件內(nèi)容,回車(chē)。
11.輸入:.,回車(chē)。(空行中的點(diǎn),代表內(nèi)容結(jié)束)
12.輸入:quit,回車(chē)。退出!
Ok,郵件發(fā)送成功!
三、使用windows控制臺(tái)接收郵件(POP3協(xié)議):
1.在運(yùn)行中輸入“cmd”打開(kāi)控制臺(tái)程序。
2.輸入:telnet pop3.gmail.com 110,回車(chē)。使用windows的telnet程序連接gmail的郵件接收服務(wù)器,POP3的默認(rèn)端口為110。
3.輸入:user test,回車(chē)。這里的用戶(hù)名不需要Base64編碼。
4.輸入:pass密碼,回車(chē)。這里的密碼不需要Base64編碼。
5.輸入:stat,回車(chē)。顯示郵箱的狀態(tài):郵件的數(shù)量和總大小。
6.輸入:list,回車(chē)。索引列出各郵件,顯示郵件的索引和大小。
7輸入:retr index,回車(chē)。這是最重要的一條命令,顯示批定索引的郵件。
8.輸入:quit,回車(chē)。退出!
OK,郵件接收成功!
四、創(chuàng)建郵件RFC822文檔:
n RFC32文檔規(guī)定了如何編寫(xiě)一封簡(jiǎn)單的郵件:
n 郵件頭和郵件體,兩者使用空行分隔。
n 郵件頭:
u From字段,此處可以隨便填寫(xiě),比如發(fā)送冒充郵件。也有一些郵件服務(wù)器為此進(jìn)行了檢查。
u To字段
u Subject字段,標(biāo)題。
u Cc、bcc字段,抄送和密送。
n 郵件體:郵件內(nèi)容
上邊的這些內(nèi)容可以加在Data輸入之前,進(jìn)行設(shè)置。這樣郵件就可以看到標(biāo)題來(lái)自、以及抄送等內(nèi)容。
Windows的OutLook郵件客戶(hù)端,只能接收使用RFC822規(guī)范創(chuàng)建的郵件,否則查詢(xún)郵件各項(xiàng)參數(shù)和內(nèi)容都為空。
五、創(chuàng)建郵件的MIME協(xié)議:
1.MIME協(xié)議是對(duì)RFC822文檔的升級(jí)和補(bǔ)充,它描述了如何生成一封復(fù)雜郵件。通常我們把MIME協(xié)議描述的郵件稱(chēng)之為MIME郵件,MIME協(xié)議描述的數(shù)據(jù)稱(chēng)之為MIME消息。
2.對(duì)于一封復(fù)雜郵件,如果包含了多個(gè)不同的數(shù)據(jù),MIME協(xié)議規(guī)定了要使用容器對(duì)多段數(shù)據(jù)進(jìn)行分隔,并使用Content-Type頭字段對(duì)數(shù)據(jù)的類(lèi)型、以及多個(gè)數(shù)據(jù)之間的關(guān)系進(jìn)行描述。(查看outlook郵件源文件)
MIME協(xié)議十分經(jīng)典,WEB應(yīng)用中使用的文件上傳正是此協(xié)議!
六、協(xié)議中的字段
1. Content-type字段:
數(shù)據(jù)類(lèi)型 video:
以“主類(lèi)型/子類(lèi)型”的形式出現(xiàn),主類(lèi)型有text、image、audio、video、application、multipart、message等,分別表示文本、圖片、音頻、視頻、應(yīng)用程序、組合結(jié)構(gòu)、消息等。每個(gè)主類(lèi)型下面都有多個(gè)子類(lèi)型,例如text主類(lèi)型包含plain、html、xml、css等子類(lèi)型。
數(shù)據(jù)的關(guān)系:
multipart/mixed、multipart/related、multipart/alternative
2. Content-Disposition頭字段:
Content-Disposition頭字段用于指定郵件閱讀程序處理數(shù)據(jù)內(nèi)容的方式,有inline和attachment兩種標(biāo)準(zhǔn)方式,inline表示直接處理,而attachment表示當(dāng)作附件處理。如果將Content-Disposition設(shè)置為attachment,在其后還可以指定filename屬性,如下所示:
Content-Disposition: attachment; filename=“1.bmp”
上面的MIME頭字段表示MIME消息體的內(nèi)容為郵件附件,附件名“1.bmp”。
3.Content-ID頭字段
Content-ID頭字段用于為“multipart/related”組合消息中的內(nèi)嵌資源指定一個(gè)唯一標(biāo)識(shí)號(hào),在HTML格式的正文中可以使用這個(gè)唯一標(biāo)識(shí)號(hào)來(lái)引用該內(nèi)嵌資源。例如,假設(shè)將一個(gè)表示內(nèi)嵌圖片的MIME消息的Content-ID頭字段設(shè)置為如下形式:
Content-ID: it315logo_gif
那么,在HTML正文中就需要使用如下HTML語(yǔ)句來(lái)引用該圖片資源:
<img src="cid:it315logo_gif">
注意,在引用Content-ID頭字段標(biāo)識(shí)的內(nèi)嵌資源時(shí),要在資源的唯一標(biāo)識(shí)號(hào)前面加上“cid:”,以說(shuō)明要采用唯一標(biāo)識(shí)號(hào)對(duì)資源進(jìn)行引用。
七、發(fā)送最復(fù)雜郵件的程序
下面,我們來(lái)看一個(gè)發(fā)送最復(fù)雜的郵件程序(發(fā)送:文本內(nèi)容、圖片、附件):
import java.util.Properties; import javax.activation.*; import javax.mail.*; import javax.mail.Message.RecipientType; import javax.mail.internet.*; public class MySmtp { public static void main(String[] args) throws Exception { String host = "smtp.google.com"; String from = "test@gmail.com"; String username = "test"; String password = "123456"; // 設(shè)置郵件的參數(shù),根據(jù)參數(shù)生成會(huì)話(huà)。 Properties prop = new Properties(); prop.setProperty("mail.host", host); prop.setProperty("mail.transport.protocol", "smtp"); prop.setProperty("mail.smtp.auth", "true"); Session session = Session.getDefaultInstance(prop); session.setDebug(true); // 獲取郵件內(nèi)容 MimeMessage message = getMessage(from, from); // 連接服務(wù)器,發(fā)送郵件 Transport ts = session.getTransport(); ts.connect(username, password); ts.sendMessage(message, message.getAllRecipients()); ts.close(); } // 此方法生成郵件的內(nèi)容 private static MimeMessage getMessage(String from, String recipient) throws Exception{ MimeMessage message = new MimeMessage(Session .getDefaultInstance(new Properties())); message.setFrom(new InternetAddress(from)); message.setRecipient(RecipientType.TO, new InternetAddress( recipient)); message.setSubject("把這功能學(xué)會(huì)了,就能發(fā)世界上最難的郵件!"); // 郵件中的文本內(nèi)容 MimeBodyPart mbpText = new MimeBodyPart(); mbpText.setContent("我是郵件的內(nèi)容,可以顯示圖片哦!<img src='cdi:test.jpg'>", "text/html;charset=UTF-8"); // 郵件中的圖片 MimeBodyPart mbpImage = new MimeBodyPart(); DataHandler dhImage = new DataHandler(new FileDataSource("C:/test.jpg")); mbpImage.setDataHandler(dhImage); mbpImage.setContentID("test.jpg"); // 郵件中的附件 MimeBodyPart mbpAttmen = new MimeBodyPart(); DataHandler dhAttmen = new DataHandler(new FileDataSource("C:/test.txt")); mbpAttmen.setDataHandler(dhAttmen); // 郵件中在文本內(nèi)容和附件路徑會(huì)出現(xiàn)中文亂碼,所以使用MimeUtility進(jìn)行編碼。 mbpAttmen.setFileName(MimeUtility.encodeText(dhAttmen.getName())); // 將圖片與文本內(nèi)容放到一個(gè)單元里 MimeMultipart mm1 = new MimeMultipart(); mm1.addBodyPart(mbpText); mm1.addBodyPart(mbpImage); // 描述正文和圖片的關(guān)系 mm1.setSubType("related"); // 返回需要將附加與文本和圖片添加到一個(gè)單元里。 // MimeMultipart不能添加MimeMultipart,但可以添加MimeBodyPart。 MimeBodyPart text_img = new MimeBodyPart(); text_img.setContent(mm1); // 將文本、圖片與附件添加到一個(gè)單元里 MimeMultipart mm2 = new MimeMultipart(); mm2.addBodyPart(mbpAttmen); mm2.addBodyPart(text_img); mm2.setSubType("mixed"); // 將內(nèi)容添加到message中 message.setContent(mm2); message.saveChanges(); return message; } } |
參照上面的代碼,來(lái)看一下相關(guān)API的關(guān)系圖(老方的):

l MimeMessage類(lèi)表示整封郵件。
l MimeBodyPart類(lèi)表示郵件的一個(gè)MIME消息。
l MimeMultipart類(lèi)表示由多個(gè)MIME消息組合成的一個(gè)組合MIME消息。
六、三大功能類(lèi)
JavaMail API按其功能劃分通常可分為如下三大類(lèi):
l 創(chuàng)建和解析郵件內(nèi)容:Message類(lèi)是創(chuàng)建和解析郵件的核心API,它的實(shí)例對(duì)象代表一封電子郵件。
l 發(fā)送郵件:Transport類(lèi)是發(fā)送郵件的核心API類(lèi),它的實(shí)例對(duì)象代表實(shí)現(xiàn)了某個(gè)郵件發(fā)送協(xié)議的郵件發(fā)送對(duì)象,例如SMTP協(xié)議。
l 接收郵件:Store類(lèi)是接收郵件的核心API類(lèi),它的實(shí)例對(duì)象代表實(shí)現(xiàn)了某個(gè)郵件接收協(xié)議的郵件接收對(duì)象,例如POP3協(xié)議。
l Session類(lèi)用于定義整個(gè)應(yīng)用程序所需的環(huán)境信息,以及收集客戶(hù)端與郵件服務(wù)器建立網(wǎng)絡(luò)連接的會(huì)話(huà)信息,如郵件服務(wù)器的主機(jī)名、端口號(hào)、采用的郵件發(fā)送和接收協(xié)議等。Session對(duì)象根據(jù)這些信息構(gòu)建用于郵件收發(fā)的Transport和Store對(duì)象,以及為客戶(hù)端創(chuàng)建Message對(duì)象時(shí)提供信息支持。
Ok了!今天下午的時(shí)候終于抽出點(diǎn)時(shí)間大家一起合個(gè)影。今天也是方老師最后一天的課程,大家都十分喜歡他,祝他身體健康,工作愉快!