自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

JavaMail API詳解(下)

開發(fā) 后端
JavaMail API詳解共分為兩部分,本文是其第二部分,重點(diǎn)的講述了如何使用JavaMail API。

五、如何使用JavaMail API
在明確了JavaMail API的核心部分如何工作后,本人將帶領(lǐng)大家學(xué)習(xí)一些使用Java Mail API任務(wù)案例。
1.發(fā)送郵件
在獲得了Session后,建立并填入郵件信息,然后發(fā)送它到郵件服務(wù)器。這便是使用Java Mail API發(fā)送郵件的過程,在發(fā)送郵件之前,我們需要設(shè)置SMTP服務(wù)器:通過設(shè)置Properties的mail.smtp.host屬性。

  1. String host = ...;String from = ...;  
  2. String to = ...;// Get system propertiesProperties props = System.getProperties();  
  3. // Setup mail serverprops.put("mail.smtp.host", host);  
  4. // Get sessionSession session = Session.getDefaultInstance(props, null);  
  5. // Define messageMimeMessage message = new MimeMessage(session);  
  6. message.setFrom(new InternetAddress(from));  
  7. message.addRecipient(Message.RecipientType.TO,       
  8. new InternetAddress(to));message.setSubject("Hello JavaMail");  
  9. message.setText("Welcome to JavaMail");  
  10. // Send messageTransport.send(message); 

由于建立郵件信息和發(fā)送郵件的過程中可能會(huì)拋出異常,所以我們需要將上面的代碼放入到try-catch結(jié)構(gòu)塊中。

2.接收郵件
為了在讀取郵件,我們獲得了session,并且連接到了郵箱的相應(yīng)store,打開相應(yīng)的Folder,然后得到我們想要的郵件,當(dāng)然別忘記了在結(jié)束時(shí)關(guān)閉連接。

  1. String host = ...;String username = ...;  
  2. String password = ...;// Create empty propertiesProperties props = new Properties();  
  3. // Get sessionSession session = Session.getDefaultInstance(props, null);  
  4. // Get the storeStore store = session.getStore("pop3");
  5. store.connect(host, username, password);  
  6. // Get folderFolder folder = store.getFolder("INBOX");  
  7. folder.open(Folder.READ_ONLY);  
  8. // Get directoryMessage message[] = folder.getMessages();  
  9. for (int i=0, n=message.length;   
  10. i": " + message[i].getFrom()[0]       
  11.  + "\t" + message[i].getSubject());}  
  12. // Close connection folder.close(false);  
  13. store.close(); 

上面的代碼所作的是從郵箱中讀取每個(gè)郵件,并且顯示郵件的發(fā)信人地址和主題。從技術(shù)角度講,這里存在著一個(gè)異常的可能:當(dāng)發(fā)信人地址為空時(shí),getFrom()[0]將拋出異常。

下面的代碼片斷有效的說明了如何讀取郵件內(nèi)容,在顯示每個(gè)郵件發(fā)信人和主題后,將出現(xiàn)用戶提示從而得到用戶是否讀取該郵件的確認(rèn),如果輸入YES的話,我們可用Message.writeTo(java.io.OutputStream os)方法將郵件內(nèi)容輸出到控制臺(tái)上,關(guān)于Message.writeTo()的具體用法請看JavaMail API。

  1. BufferedReader reader = new BufferedReader (    new InputStreamReader(System.in));  
  2. // Get directoryMessage message[] = folder.getMessages();  
  3. for (int i=0, n=message.length; i
  4. {    System.out.println(i + ": " + message[i].getFrom()[0]        
  5.  + "\t" + message[i].getSubject());      
  6. System.out.println("Do you want to read message? " +      "[YES to read/QUIT to end]");    
  7. String line = reader.readLine();      
  8. if ("YES".equals(line)) {      message[i].writeTo(System.out);    }   
  9. else if ("QUIT".equals(line)) {      break;    }} 


3.刪除郵件和標(biāo)志
設(shè)置與message相關(guān)的Flags是刪除郵件的常用方法。這些Flags表示了一些系統(tǒng)定義和用戶定義的不同狀態(tài)。在Flags類的內(nèi)部類Flag中預(yù)定義了一些標(biāo)志:

  1. Flags.Flag.ANSWERED  
  2. Flags.Flag.DELETED  
  3. Flags.Flag.DRAFT  
  4. Flags.Flag.FLAGGED  
  5. Flags.Flag.RECENT  
  6. Flags.Flag.SEEN  
  7. Flags.Flag.USER 

但需要在使用時(shí)注意的:標(biāo)志存在并非意味著這個(gè)標(biāo)志被所有的郵件服務(wù)器所支持。例如,對于刪除郵件的操作,POP協(xié)議不支持上面的任何一個(gè)。所以要確定哪些標(biāo)志是被支持的——通過訪問一個(gè)已經(jīng)打開的Folder對象的getPermanetFlags()方法,它將返回當(dāng)前被支持的Flags類對象。
刪除郵件時(shí),我們可以設(shè)置郵件的DELETED標(biāo)志:

  1. message.setFlag(Flags.Flag.DELETED, true);  
  2. 但是首先要采用READ_WRITE的方式打開Folder:  
  3. folder.open(Folder.READ_WRITE);  

在對郵件進(jìn)行刪除操作后關(guān)閉Folder時(shí),需要傳遞一個(gè)true作為對刪除郵件的擦除確認(rèn)。

folder.close(true);

Folder類中另一種用于刪除郵件的方法expunge()也同樣可刪除郵件,但是它并不為sun提供的POP3實(shí)現(xiàn)支持,而其它第三方提供的POP3實(shí)現(xiàn)支持或者并不支持這種方法。
另外,介紹一種檢查某個(gè)標(biāo)志是否被設(shè)置的方法:Message.isSet(Flags.Flag flag)方法,其中參數(shù)為被檢查的標(biāo)志。

4.郵件認(rèn)證
我們在前面已經(jīng)學(xué)會(huì)了如何使用Authenticator類來代替直接使用用戶名和密碼這兩字符串作為Session.getDefaultInstance()或者Session.getInstance()方法的參數(shù)。在前面的小試牛刀后,現(xiàn)在我們將了解到全面認(rèn)識一下郵件認(rèn)證。
我們在此取代了直接使用郵件服務(wù)器主機(jī)名、用戶名、密碼這三個(gè)字符串作為連接到POP3 Store的方式,使用存儲(chǔ)了郵件服務(wù)器主機(jī)名信息的屬性文件,并在獲得Session時(shí)傳入自定義的Authenticator實(shí)例:

  1. // Setup propertiesProperties props = System.getProperties();  
  2. props.put("mail.pop3.host", host);  
  3. // Setup authentication, get sessionAuthenticator auth = new PopupAuthenticator();  
  4. Session session = Session.getDefaultInstance(props, auth);  
  5. // Get the storeStore store = session.getStore("pop3");  
  6. store.connect(); 

PopupAuthenticator類繼承了抽象類Authenticator,并且通過重載Authenticator類的getPasswordAuthentication()方法返回PasswordAuthentication類對象。而getPasswordAuthentication()方法的參數(shù)param是以逗號分割的用戶名、密碼組成的字符串。

  1. import javax.mail.*;  
  2. import java.util.*;  
  3. public class PopupAuthenticator extends Authenticator   
  4. {    public PasswordAuthentication getPasswordAuthentication(String param)   
  5. {      String username, password;        
  6. StringTokenizer st = new StringTokenizer(param, ",");        
  7. username = st.nextToken();        
  8. password = st.nextToken();        
  9. return new PasswordAuthentication(username, password);    }} 


5.回復(fù)郵件
回復(fù)郵件的方法很簡單:使用Message類的reply()方法,通過配置回復(fù)郵件的收件人地址和主題(如果沒有提供主題的話,系統(tǒng)將默認(rèn)將“Re:”作為郵件的主體),這里不需要設(shè)置任何的郵件內(nèi)容,只要復(fù)制發(fā)信人或者reply-to到新的收件人。而reply()方法中的boolean參數(shù)表示是否將郵件回復(fù)給發(fā)送者(參數(shù)值為false),或是恢復(fù)給所有人(參數(shù)值為true)。
補(bǔ)充一下,reply-to地址需要在發(fā)信時(shí)使用setReplyTo()方法設(shè)置。

  1. MimeMessage reply = (MimeMessage)message.reply(false);  
  2. reply.setFrom(new InternetAddress("president@whitehouse.gov"));  
  3. reply.setText("Thanks");  
  4. Transport.send(reply); 

6.轉(zhuǎn)發(fā)郵件
轉(zhuǎn)發(fā)郵件的過程不如前面的回復(fù)郵件那樣簡單,它將建立一個(gè)轉(zhuǎn)發(fā)郵件,這并非一個(gè)方法就能做到。
每個(gè)郵件是由多個(gè)部分組成,每個(gè)部分稱為一個(gè)郵件體部分,是一個(gè)BodyPart類對象,對于MIME類型郵件來講就是MimeBodyPart類對象。這些郵件體包含在成為Multipart的容器中對于MIME類型郵件來講就是MimeMultiPart類對象。在轉(zhuǎn)發(fā)郵件時(shí),我們建立一個(gè)文字郵件體部分和一個(gè)被轉(zhuǎn)發(fā)的文字郵件體部分,然后將這兩個(gè)郵件體放到一個(gè)Multipart中。說明一下,復(fù)制一個(gè)郵件內(nèi)容到另一個(gè)郵件的方法是僅復(fù)制它的DataHandler(數(shù)據(jù)處理者)即可。這是由JavaBeans Activation Framework定義的一個(gè)類,它提供了對郵件內(nèi)容的操作命令的訪問、管理了郵件內(nèi)容操作,是不同的數(shù)據(jù)源和數(shù)據(jù)格式之間的一致性接口。

  1. // Create the message to forwardMessage forward = new MimeMessage(session);  
  2. // Fill in headerforward.setSubject("Fwd: " + message.getSubject());  
  3. forward.setFrom(new InternetAddress(from));  
  4. forward.addRecipient(Message.RecipientType.TO,     new InternetAddress(to));  
  5. // Create your new message partBodyPart messageBodyPart = new MimeBodyPart();messageBodyPart.setText
  6. (    "Here you go with the original message:\n\n");  
  7. // Create a multi-part to combine the partsMultipart multipart = new MimeMultipart();  
  8. multipart.addBodyPart(messageBodyPart);  
  9. // Create and fill part for the forwarded contentmessageBodyPart = new MimeBodyPart();  
  10. messageBodyPart.setDataHandler(message.getDataHandler());  
  11. // Add part to multi partmultipart.addBodyPart(messageBodyPart);  
  12. // Associate multi-part with messageforward.setContent(multipart);  
  13. // Send messageTransport.send(forward); 

7.使用附件
附件作為與郵件相關(guān)的資源經(jīng)常以文本、表格、圖片等格式出現(xiàn),如流行的郵件客戶端一樣,我們可以用JavaMail API從郵件中獲取附件或是發(fā)送帶有附件的郵件。

A.發(fā)送帶有附件的郵件
發(fā)送帶有附件的郵件的過程有些類似轉(zhuǎn)發(fā)郵件,我們需要建立一個(gè)完整郵件的各個(gè)郵件體部分,在第一個(gè)部分(即我們的郵件內(nèi)容文字)后,增加一個(gè)具有DataHandler的附件而不是在轉(zhuǎn)發(fā)郵件時(shí)那樣復(fù)制第一個(gè)部分的DataHandler。

如果我們將文件作為附件發(fā)送,那么要建立FileDataSource類型的對象作為附件數(shù)據(jù)源;如果從URL讀取數(shù)據(jù)作為附件發(fā)送,那么將要建立URLDataSource類型的對象作為附件數(shù)據(jù)源。

然后將這個(gè)數(shù)據(jù)源(FileDataSource或是URLDataSource)對象作為DataHandler類構(gòu)造方法的參數(shù)傳入,從而建立一個(gè)DataHandler對象作為數(shù)據(jù)源的DataHandler。

接著將這個(gè)DataHandler設(shè)置為郵件體部分的DataHandler。這樣就完成了郵件體與附件之間的關(guān)聯(lián)工作,下面的工作就是BodyPart的setFileName()方法設(shè)置附件名為原文件名。

最后將兩個(gè)郵件體放入到Multipart中,設(shè)置郵件內(nèi)容為這個(gè)容器Multipart,發(fā)送郵件。

  1. // Define messageMessage message = new MimeMessage(session);  
  2. message.setFrom(new InternetAddress(from));  
  3. message.addRecipient(Message.RecipientType.TO,       
  4. new InternetAddress(to));message.setSubject("Hello JavaMail Attachment");  
  5. // Create the message part BodyPart messageBodyPart = new MimeBodyPart();  
  6. // Fill the messagemessageBodyPart.setText("Pardon Ideas");  
  7. Multipart multipart = new MimeMultipart();  
  8. multipart.addBodyPart(messageBodyPart);  
  9. // Part two is attachmentmessageBodyPart = new MimeBodyPart();  
  10. DataSource source = new FileDataSource(filename);  
  11. messageBodyPart.setDataHandler(new DataHandler(source));  
  12. messageBodyPart.setFileName(filename);multipart.addBodyPart(messageBodyPart);  
  13. // Put parts in messagemessage.setContent(multipart);  
  14. // Send the messageTransport.send(message); 

如果我們使用servlet實(shí)現(xiàn)發(fā)送帶有附件的郵件,則必須上傳附件給servlet,這時(shí)需要注意提交頁面form中對編碼類型的設(shè)置應(yīng)為multipart/form-data。

method=post action="/myservlet">    

B.讀取郵件中的附件
讀取郵件中的附件的過程要比發(fā)送它的過程復(fù)雜一點(diǎn)。因?yàn)閹в懈郊泥]件是多部分組成的,我們必須處理每一個(gè)部分獲得郵件的內(nèi)容和附件。
但是如何辨別郵件信息內(nèi)容和附件呢?Sun在Part類(BodyPart類實(shí)現(xiàn)的接口類)中提供了getDisposition()方法讓開發(fā)者獲得郵件體部分的部署類型,當(dāng)該部分是附件時(shí),其返回之將是Part.ATTACHMENT。但附件也可以沒有部署類型的方式存在或者部署類型為Part.INLINE,無論部署類型為Part.ATTACHMENT還是Part.INLINE,我們都能把該郵件體部分導(dǎo)出保存。

  1. Multipart mp = (Multipart)message.getContent();  
  2. for (int i=0, n=multipart.getCount(); 
  3. i{    Part part = multipart.getBodyPart(i));      
  4. String disposition = part.getDisposition();      
  5. if ((disposition != null) &&           
  6. ((disposition.equals(Part.ATTACHMENT) ||            
  7. (disposition.equals(Part.INLINE)))   
  8. { saveFile(part.getFileName(), part.getInputStream());    }} 

下列代碼中使用了saveFile方法是自定義的方法,它根據(jù)附件的文件名建立一個(gè)文件,如果本地磁盤上存在名為附件的文件,那么將在文件名后增加數(shù)字表示區(qū)別。然后從郵件體中讀取數(shù)據(jù)寫入到本地文件中(代碼省略)。

  1. // from saveFile()File file = new File(filename);  
  2. for (int i=0; file.exists(); i++)   
  3. {    file = new File(filename+i);} 

以上是郵件體部分被正確設(shè)置的簡單例子,如果郵件體部分的部署類型為null,那么我們通過獲得郵件體部分的MIME類型來判斷其類型作相應(yīng)的處理,代碼結(jié)構(gòu)框架如下:

  1. if (disposition == null)   
  2. {    // Check if plain    MimeBodyPart mbp = (MimeBodyPart)part;      
  3. if (mbp.isMimeType("text/plain"))   
  4. {      // Handle plain    } else   
  5. {      // Special non-attachment cases here of         
  6. // image/gif, text/html, ...    }...} 

8.處理HTML郵件
前面的例子中發(fā)送的郵件都是以文本為內(nèi)容的(除了附件),下面將介紹如何接收和發(fā)送基于HTML的郵件。
A.發(fā)送HTML郵件
假如我們需要發(fā)送一個(gè)HTML文件作為郵件內(nèi)容,并使郵件客戶端在讀取郵件時(shí)獲取相關(guān)的圖片或者文字的話,只要設(shè)置郵件內(nèi)容為html代碼,并設(shè)置內(nèi)容類型為text/html即可:

  1. String htmlText = "

    Hello

    "
     + 
    ";  
  2. message.setContent(htmlText, "text/html")); 

請注意:這里的圖片并不是在郵件中內(nèi)嵌的,而是在URL中定義的。郵件接收者只有在線時(shí)才能看到。
在接收郵件時(shí),如果我們使用JavaMail API接收郵件的話是無法實(shí)現(xiàn)以HTML方式顯示郵件內(nèi)容的。因?yàn)镴avaMail API郵件內(nèi)容視為二進(jìn)制流。所以要顯示HTML內(nèi)容的郵件,我們必須使用JEditorPane或者第三方HTML展現(xiàn)組件。

以下代碼顯示了如何使用JEditorPane顯示郵件內(nèi)容:

  1. if (message.getContentType().equals("text/html"))   
  2. {    String content = (String)message.getContent();      
  3. JFrame frame = new JFrame();      
  4. JEditorPane text = new JEditorPane("text/html", content);      
  5. text.setEditable(false);      
  6. JScrollPane pane = new JScrollPane(text);      
  7. frame.getContentPane().add(pane);      
  8. frame.setSize(300300);      
  9. frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);      
  10. frame.show();} 

B.在郵件中包含圖片
如果我們在郵件中使用HTML作為內(nèi)容,那么最好將HTML中使用的圖片作為郵件的一部分,這樣無論是否在線都會(huì)正確的顯示HTML中的圖片。處理方法就是將HTML中用到的圖片作為郵件附件并使用特殊的cid URL作為圖片的引用,這個(gè)cid就是對圖片附件的Content-ID頭的引用。
處理內(nèi)嵌圖片就像向郵件中添加附件一樣,不同之處在于我們必須通過設(shè)置圖片附件所在的郵件體部分的header中Content-ID為一個(gè)隨機(jī)字符串,并在HTML中img的src標(biāo)記中設(shè)置為該字符串。這樣就完成了圖片附件與HTML的關(guān)聯(lián)。

  1. String file = ...;  
  2. // Create the messageMessage message = new MimeMessage(session);  
  3. // Fill its headersmessage.setSubject("Embedded Image");  
  4. message.setFrom(new InternetAddress(from));  
  5. message.addRecipient(Message.RecipientType.TO,       
  6. new InternetAddress(to));  
  7. // Create your new message partBodyPart messageBodyPart = new MimeBodyPart();  
  8. String htmlText = "

    Hello

    "
     + ";
  9. messageBodyPart.setContent(htmlText, "text/html");  
  10. // Create a related multi-part to combine the partsMimeMultipart multipart = new MimeMultipart("related");
  11. multipart.addBodyPart(messageBodyPart);  
  12. // Create part for the imagemessageBodyPart = new MimeBodyPart();  
  13. // Fetch the image and associate to partDataSource fds = new FileDataSource(file);  
  14. messageBodyPart.setDataHandler(new DataHandler(fds));  
  15. messageBodyPart.setHeader("Content-ID","");  
  16. // Add part to multi-partmultipart.addBodyPart(messageBodyPart);  
  17. // Associate multi-part with messagemessage.setContent(multipart); 


9.在郵件中搜索短語
JavaMail API提供了過濾器機(jī)制,它被用來建立搜索短語。這個(gè)短語由javax.mail.search包中的SearchTerm抽象類來定義,在定義后我們便可以使用Folder的Search()方法在Folder中查找郵件:

SearchTerm st = ...;Message[] msgs = folder.search(st);

下面有22個(gè)不同的類(繼承了SearchTerm類)供我們使用:

  1. AND terms (class AndTerm)  
  2. OR terms (class OrTerm)  
  3. NOT terms (class NotTerm)  
  4. SENT DATE terms (class SentDateTerm)  
  5. CONTENT terms (class BodyTerm)  
  6. HEADER terms (FromTerm / FromStringTerm, RecipientTerm / RecipientStringTerm, SubjectTerm, etc.)  

使用這些類定義的斷語集合,我們可以構(gòu)造一個(gè)邏輯表達(dá)式,并在Folder中進(jìn)行搜索。下面是一個(gè)實(shí)例:在Folder中搜索郵件主題含有“ADV”字符串或者發(fā)信人地址為friend@public.com的郵件。

  1. SearchTerm st =     new Or
  2. Term(      new SubjectTerm("ADV:"),         
  3. new FromStringTerm("friend@public.com"));  
  4. Message[] msgs = folder.search(st); 


 

 

【編輯推薦】

  1. 對Java編程思想的忠告
  2. 和我共同了解Java是什么
  3. 著名的Java論壇和網(wǎng)站
  4. 2009年十大Java技術(shù)解決方案
  5. 2008最值得學(xué)習(xí)的五種JAVA技術(shù)
責(zé)任編輯:仲衡 來源: 百度博客
相關(guān)推薦

2009-06-16 09:41:00

2011-12-23 09:28:31

Java

2011-12-07 14:57:44

JavaNIO

2010-05-25 12:41:19

Subversion

2012-03-07 14:37:03

JavaJavaMail

2009-08-03 13:13:52

C#調(diào)用Outlook

2009-06-16 09:06:37

JavaMailJSP

2009-01-16 15:37:34

Oracle數(shù)據(jù)庫API

2022-04-21 09:00:00

API安全密鑰

2014-08-28 10:16:17

HTML5

2009-06-12 16:05:47

JBoss配置

2021-01-14 07:53:09

Linuxlsof 命令

2009-11-11 10:24:10

linuxecho命令詳解

2009-11-30 09:56:16

2013-07-29 14:50:43

API

2020-11-05 10:40:18

ActiveMQ

2023-08-28 08:00:46

2024-06-26 00:22:35

2009-11-13 09:24:58

JPA 2.0Criteria AP

2011-03-01 15:02:54

Qt
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號