一、JavaMail API簡(jiǎn)介 JavaMail API是讀取、撰寫、發(fā)送電子信息的可選包。 可用它來建立如Eudora、Foxmail、MS Outlook Express一般的郵件用戶代理程序(Mail
User Agent,簡(jiǎn)稱MUA,而非郵件傳輸代理MTA)。 從另外一個(gè)角度來看,我們這些電子郵件用戶日常用MUA程序來讀寫郵件,而MUA依賴著MTA處理郵件的遞送。 二、相關(guān)協(xié)議一覽 不依賴于協(xié)議的方式發(fā)送接收電子信息,只依賴特定協(xié)議SMTP、POP、IMAP、MIME、NNTP協(xié)議。 1.SMTP(遞送郵件機(jī)制) 簡(jiǎn)單郵件傳輸協(xié)議 SMTP服務(wù)器將郵件轉(zhuǎn)發(fā)到接收者的SMTP服務(wù)器,直至最后被接收者通過POP或者IMAP協(xié)議獲取。 2.POP(獲取郵件機(jī)制) 郵局協(xié)議,目前為第3個(gè)版本POP3 3.IMAP(多目錄共享) 接收信息的高級(jí)協(xié)議,目前版本為第4版IMAP4 接收新信息,將這些信息遞送給用戶,維護(hù)每個(gè)用戶的多個(gè)目錄。 4.MIME 郵件擴(kuò)展內(nèi)容格式:信息格式、附件格式等等 5.NNTP mail.jar文件添加到CLASSPATH中 2.安裝JavaBeans Activation Framework 從http://java./products/javabeans/glasgow/jaf.html下載JavaBeans Activation Framework activation.jar文件添加到CLASSPATH中 四、初次認(rèn)識(shí)JavaMail API 1.了解我們的JavaMail環(huán)境 A.縱覽JavaMail核心類結(jié)構(gòu) JavaMail.jar文件的一些核心類:Session、Message、Address、Authenticator、Transport、Store、Folder。 以及javax.mail.internet包中還有一些常用的子類。 B.Session(郵件會(huì)話) 進(jìn)行收發(fā)郵件的工作都是基于這個(gè)會(huì)話的。 Session對(duì)象利用了java.util.Properties對(duì)象獲得了郵件服務(wù)器、用戶名、密碼信息和整個(gè)應(yīng)用程序都要使用到的共享信息。 Properties props = new Properties();或者 Properties props = new Properties();從上面的兩個(gè)例子中不難發(fā)現(xiàn),第二個(gè)參數(shù)都是null,這是因?yàn)樵谏厦娴睦又胁]有使用到郵件授權(quán)(參考E) C.Message 建立了Session對(duì)象后,便可以被發(fā)送的構(gòu)造信息體Message抽象類 使用javax.mail.internet.MimeMessage這個(gè)子類,該類是使用MIME類型、MIME信息頭的郵箱信息。 信息頭只能使用US-ASCII字符 Message message = new MimeMessage(session); message.setContent("Hello", "text/plain");//非文本信息內(nèi)容 message.setText("Hello");//純文本信息內(nèi)容 message.setSubject("First");//設(shè)置郵件主題 message.setSentDate(Date);//設(shè)置郵件發(fā)送日期 D.Address 建立了Session和Message對(duì)象后,使用郵件地址Address抽象類 使用javax.mail.internet.InternetAddress這個(gè)子類。通過傳入郵件地址的字符串 Address address = new InternetAddress("kuangye89757@163.com"); //郵件地址 Address address = new InternetAddress("president@whitehouse.gov", "George Bush"); //帶名字的郵件地址 message.setFrom(address);//設(shè)置發(fā)信人 message.setReplyTo(address);//同上 message.addFrom(Address[] address);//添加多個(gè)發(fā)信人 message.addRecipient(type, address)//設(shè)置收信人 Message.RecipientType.TO//收信人 Message.RecipientType.CC//抄送人 Message.RecipientType.BCC//暗送人 E.Authenticator授權(quán)者類 使用Authenticator抽象類必須實(shí)現(xiàn)getPasswordAuthentication()方法(用于存儲(chǔ)認(rèn)證時(shí)要用到的用戶名、密碼)。 并且要在Session中進(jìn)行注冊(cè),使Session能夠了解在認(rèn)證時(shí)該使用哪個(gè)類。 Properties props = new Properties(); Authenticator auth = new MyAuthenticator(); Session session = Session.getDefaultInstance(props, auth); /** * 自定義郵件授權(quán)類 * @return * @throws IOException */ public class MyAuthenticator extends Authenticator { public PasswordAuthentication getPasswordAuthentication(String param) { String username; String password; StringTokenizer st = new StringTokenizer(param, ","); username = st.nextToken(); password = st.nextToken(); return new PasswordAuthentication(username, password); } } F.Transport 發(fā)送信息時(shí)使用Transport抽象類(實(shí)現(xiàn)了SMTP) Transport.send(MimeMessage message); 或者一般用法 當(dāng)然,方法是多樣的。我們也可由Session獲得相應(yīng)協(xié)議對(duì)應(yīng)的Transport實(shí)例。并通過傳遞用戶名、密碼、郵件服務(wù)器主機(jī)名等參數(shù)建立與郵件服務(wù)器的連接,并使用sendMessage()方法將信息發(fā)送,最后關(guān)閉連接: session.setDebug(true);//監(jiān)控郵件發(fā)送過程 message.saveChanges(); //保存文件 Transport transport = session.getTransport("smtp");//獲取實(shí)現(xiàn)了SMTP協(xié)議的Transport類 transport.connect(host, username, password);//連接服務(wù)器 transport.sendMessage(message, message.getAllRecipients());//發(fā)送郵件給所有收件人 transport.close();//關(guān)閉連接 G.Store(存儲(chǔ)郵件的服務(wù)器)和Folder(目錄對(duì)象) Store store = session.getStore("pop3"); store.connect(host, username, password); Folder folder = store.getFolder("INBOX");//POP3協(xié)議只有一個(gè)名為INBOX的Folder有效 folder.open(Folder.READ_ONLY);//只讀方式打開 Message message[] = folder.getMessages();//獲得郵件 System.out.println(((MimeMessage)message).getContent());//郵件內(nèi)容(不包含郵件頭) System.out.println(((MimeMessage)message).writeTo());//郵件內(nèi)容(含郵件頭) folder.close(true);//若刪除郵件則及時(shí)更新Folder,關(guān)閉 store.close();//關(guān)閉 五、使用JavaMail API 1.發(fā)送郵件 在獲得了Session后,建立并填入郵件信息,在發(fā)送郵件之前,我們需要設(shè)置SMTP服務(wù)器:通過設(shè)置Properties的mail.smtp.host屬性 mail配置文件.properties String server=xx.xx.xx.xx(服務(wù)器) authUser=XXX authPasswd=xxxxxx /** * 獲得配置文件信息 * @return * @throws IOException */ private static Properties getProp() throws IOException{ //獲得文件存儲(chǔ)路徑 ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); InputStream inputStream = classLoader.getResourceAsStream("mail配置文件.properties"); Properties prop = new Properties(); prop.load(inputStream); return prop; } private String from = ...;//發(fā)件人 private String to = ...;//收件人 //獲取郵件發(fā)送服務(wù)器及驗(yàn)證用戶名和密碼 Properties props=getProp(); props.put("mail.smtp.host", host); //獲取Session會(huì)話 Session session = Session.getDefaultInstance(props, null); //創(chuàng)建MIMEMessage Message message = new MimeMessage(session); message.setFrom(new InternetAddress(from)); message.addRecipient(Message.RecipientType.TO, new InternetAddress(to)); message.setSubject("Hello JavaMail"); message.setText("Welcome to JavaMail"); //發(fā)送郵件 message.saveChanges(); Transport transport = session.getTransport("smtp"); transport.connect(props.getProperty(“server”), props.getProperty(“authUser”), props.getProperty(“authPasswd”)); transport.sendMessage(message, message.getAllRecipients()); transport.close(); 2.接收郵件 Session session = Session.getDefaultInstance(props, null); Store store = session.getStore("pop3"); store.connect(props.getProperty(“server”), props.getProperty(“authUser”), props.getProperty(“authPasswd”)); Folder folder = store.getFolder("INBOX"); folder.open(Folder.READ_ONLY); Message message[] = folder.getMessages(); for (int i=0, n=message.length; i<n; i++) { System.out.println(i + ": " + message[i].getFrom()[0] + " " + message[i].getSubject()); } folder.close(false); store.close(); 3.刪除郵件和標(biāo)志 Flags類的內(nèi)部類Flag中預(yù)定義了一些標(biāo)志:(POP協(xié)議不支持) 如:Flags.Flag.DELETED 通過訪問一個(gè)已經(jīng)打開的Folder對(duì)象的getPermanetFlags()方法,它將返回當(dāng)前被支持的Flags類對(duì)象。 刪除郵件時(shí),我們可以設(shè)置郵件的DELETED標(biāo)志: if(Message.isSet(Flags.Flag.DELETED)){ folder.open(Folder.READ_WRITE); message.setFlag(Flags.Flag.DELETED, true);//刪除郵件 folder.close(true); } 4.回復(fù)郵件 MimeMessage reply = (MimeMessage)message.reply(false);//不發(fā)送給發(fā)件人 reply.setFrom(new InternetAddress("president@whitehouse.gov")); reply.setText("Thanks"); Transport.send(reply);//回復(fù)郵件 6.轉(zhuǎn)發(fā)郵件 轉(zhuǎn)發(fā)郵件的過程不如前面的回復(fù)郵件那樣簡(jiǎn)單,它將建立一個(gè)轉(zhuǎn)發(fā)郵件,這并非一個(gè)方法就能做到。 每個(gè)郵件是由多個(gè)部分(郵件體MimeBodyPart類對(duì)象)組成 這些郵件體包含MimeMultiPart類對(duì)象 復(fù)制一個(gè)郵件內(nèi)容到另一個(gè)郵件的方法是復(fù)制它的DataHandler(數(shù)據(jù)處理者) Message forward = new MimeMessage(session); forward.setSubject("Fwd: " + message.getSubject()); forward.setFrom(new InternetAddress(from)); forward.addRecipient(Message.RecipientType.TO, new InternetAddress(to)); forward.setContent(multipart);//這里的多媒體對(duì)象通過下列方式獲得 Transport.send(forward);//轉(zhuǎn)發(fā)郵件 //創(chuàng)建郵件體對(duì)象 BodyPart messageBodyPart = new MimeBodyPart(); messageBodyPart.setContent(“內(nèi)容”,"text/plain;charset=GB2312"); messageBodyPart.setDataHandler(message.getDataHandler());//從郵件中獲取DataHandler //創(chuàng)建多媒體對(duì)象 Multipart multipart = new MimeMultipart(); multipart.addBodyPart(messageBodyPart); 7.使用附件 A.發(fā)送帶有附件的郵件建立一個(gè)完整郵件的各個(gè)郵件體部分: 第一個(gè)部分:郵件內(nèi)容文字 第二個(gè)部分:具有DataHandler的附件 1.若文件作為附件發(fā)送建立FileDataSource類型的附件數(shù)據(jù)源對(duì)象 2.若URL作為附件發(fā)送建立URLDataSource類型的附件數(shù)據(jù)源對(duì)象 Message message = new MimeMessage(session); message.setFrom(new InternetAddress(from)); message.addRecipient(Message.RecipientType.TO, new InternetAddress(to)); message.setSubject("Hello JavaMail Attachment"); //第一部分(內(nèi)容) BodyPart messageBodyPart1 = new MimeBodyPart(); messageBodyPart1.setText("Pardon Ideas"); //第二部分(文件附件) BodyPart messageBodyPart2 = new MimeBodyPart(); DataSource source = new FileDataSource(filename); messageBodyPart2.setDataHandler(new DataHandler(source)); messageBodyPart2.setFileName(filename); Multipart multipart = new MimeMultipart(); multipart.addBodyPart(messageBodyPart1);//裝填第一部分 multipart.addBodyPart(messageBodyPart2);//裝填第二部分 message.setContent(multipart); Transport.send(message);//發(fā)送帶有附件的文件 使用servlet實(shí)現(xiàn)發(fā)送帶有附件的郵件注意提交頁(yè)面form中對(duì)編碼類型的設(shè)置應(yīng)為multipart/form-data <form enctype="multipart/form-data" method=post action="/myservlet"> <input type="file" NAME="thefile"> <input type="submit" VALUE="Upload"> </form> B.讀取郵件中的附件 讀取郵件中帶有附件的郵件是多部分組成的,我們必須處理每一個(gè)部分獲得郵件的內(nèi)容和附件 BodyPart類提供了getDisposition()方法獲得郵件體的部署類型 該部分是附件時(shí)返回Part.ATTACHMENT或Part.INLINE //獲取郵件中的多媒體 Multipart mp = (Multipart)message.getContent(); //循環(huán)遍歷多媒體,并獲取郵件體各部分 for (int i=0, n=multipart.getCount(); i<n; i++) { Part part = multipart.getBodyPart(i)); //獲得郵件體的部署類型 String disposition = part.getDisposition(); if ((disposition != null) && ((disposition.equals(Part.ATTACHMENT) || (disposition.equals(Part.INLINE))) { saveFile(part.getFileName(), part.getInputStream()); }else if (disposition == null) { MimeBodyPart mbp = (MimeBodyPart)part; if (mbp.isMimeType("text/plain")) { //解析過程 } else { //其他解析過程 } } } 8.處理HTML郵件 A.發(fā)送HTML郵件 設(shè)置郵件內(nèi)容為html代碼,并設(shè)置內(nèi)容類型為text/html即可: String htmlText = "<H1>Hello</H1>" + "<img src="http://www./images/logo.gif">"; message.setContent(htmlText, "text/html")); 請(qǐng)注意: 在接收郵件時(shí),因?yàn)镴avaMail API郵件內(nèi)容視為二進(jìn)制流。必須使用JEditorPane if (message.getContentType().equals("text/html")) { String content = (String)message.getContent(); JFrame frame = new JFrame(); JEditorPane text = new JEditorPane("text/html", content); text.setEditable(false); JScrollPane pane = new JScrollPane(text); frame.getContentPane().add(pane); frame.setSize(300, 300); frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); frame.show(); } B.在郵件中包含圖片 將HTML中用到的圖片作為郵件附件并使用特殊的cid URL作為圖片的引用(Content-ID頭的引用) 通過設(shè)置圖片附件郵件體部分的header中Content-ID為一個(gè)隨機(jī)字符串, 并在HTML中img的src標(biāo)記中設(shè)置為該字符串來完成了圖片附件與HTML的關(guān)聯(lián)。 String file = ...; Message message = new MimeMessage(session); message.setSubject("Embedded Image"); message.setFrom(new InternetAddress(from)); message.addRecipient(Message.RecipientType.TO, new InternetAddress(to)); // 創(chuàng)建郵件體HTML部分 BodyPart messageBodyPart1 = new MimeBodyPart(); String htmlText = "<H1>Hello</H1>" + "<img src="cid:memememe">"; messageBodyPart1.setContent(htmlText, "text/html"); //創(chuàng)建郵件體img部分 BodyPart messageBodyPart2 = new MimeBodyPart(); DataSource fds = new FileDataSource(file); messageBodyPart2.setDataHandler(new DataHandler(fds)); messageBodyPart2.setHeader("Content-ID","<memememe>"); 9.在郵件中搜索短語(yǔ) JavaMail API提供了過濾器機(jī)制,它被用來建立搜索短語(yǔ)。 使用javax.mail.search包中的SearchTerm抽象類來定義,在定義后我們便可以使用Folder的Search()方法查找郵件: 下面有22個(gè)不同的類(繼承了SearchTerm類)供我們使用: AND
terms 、OR terms 、NOT terms 、SENT DATE terms、CONTENT terms 、HEADER terms 實(shí)例:在Folder中搜索郵件主題含有“ADV”字符串或者發(fā)信人地址為friend@public.com的郵件。 SearchTerm st = new OrTerm(new SubjectTerm("ADV:"), new FromStringTerm("friend@public.com"));
|
|