javaMail解析郵件內容和下載附件

介紹一下JavaMail的Message

它對應JavaMail的Message對象,一個Message對象又會有多個子對象如MultiPart對象,更特殊的是整個郵件內容爲一個大的 MultiPart,然而郵件的正文則在嵌套的一個子MultiPart中,如果不瞭解這種組織結構,就可能無法正確獲得郵件的正文。此結構如下圖所示:

郵件Message

 

頭部(主題, 發件人信息等)

MultiPart郵件全部內容, 包含正文和附件

 

正文 MultiPart

 

文本正文 text/plain

 

Content-Type: text/plain;charset="gb2312"

 

HTML網頁格式 text/html

 

Content-Type: text/html;charset="gb2312"

 

 

 

 

附件1

 

Content-Type: application/octet-stream;

       name="String2Java.jpg"

Content-Transfer-Encoding: base64

Content-Disposition: attachment;

       filename="String2Java.jpg"

 

 

附件2

 

Content-Type: application/octet-stream;

       name="FoxmailUpdate.log"

Content-Transfer-Encoding: base64

Content-Disposition: attachment;

       filename="FoxmailUpdate.log"

 

 

 

 附上代碼

package com.zz.mail;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.Properties;
import javax.mail.Address;
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.NoSuchProviderException;
import javax.mail.Part;
import javax.mail.Session;
import javax.mail.Store;
import javax.mail.URLName;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeUtility;
/**
* 郵件接受測試
* 
*/
public class POP3MailReceiverTest {
    public POP3MailReceiverTest() {
        try {
        	 // 1. 設置連接信息, 生成一個 Session
    		Properties props = new Properties();
    		props.setProperty("mail.smtp.host", "smtp.genomics.cn");
    		props.setProperty("mail.smtp.auth", "true");
    		Session session = Session.getDefaultInstance(props);
    		// 2. 獲取 Store 並連接到服務器	
    		//
    		URLName urlname = new URLName("pop3","pop.genomics.cn",110,null,"[email protected]","****");
    		Store store = session.getStore(urlname);
    		store.connect();
        	Folder folder = store.getDefaultFolder();// 默認父目錄
            if (folder == null) {
                System.out.println("服務器不可用");
                return;
            }
          /*
           System.out.println("默認信箱名:" + folder.getName());

           Folder[] folders = folder.list();// 默認目錄列表
           for(int i = 0; i < folders.length; i++) {
        	   System.out.println(folders[0].getName());
           }
            System.out.println("默認目錄下的子目錄數: " + folders.length);
            */
            Folder popFolder = folder.getFolder("INBOX");// 獲取收件箱
            popFolder.open(Folder.READ_WRITE);// 可讀郵件,可以刪郵件的模式打開目錄
            // 4. 列出來收件箱 下所有郵件
            Message[] messages = popFolder.getMessages();
            // 取出來郵件數
            int msgCount = popFolder.getMessageCount();
            System.out.println("共有郵件: " + msgCount + "封");
            // FetchProfile fProfile = new FetchProfile();// 選擇郵件的下載模式,
            // 根據網速選擇不同的模式
            // fProfile.add(FetchProfile.Item.ENVELOPE);
            // folder.fetch(messages, fProfile);// 選擇性的下載郵件
            // 5. 循環處理每個郵件並實現郵件轉爲新聞的功能
            for (int i = 0; i < msgCount; i++) {
            	// 單個郵件
            	System.out.println("第" + i +"郵件開始");
            	mailReceiver(messages[i]);
            	System.out.println("第" + i +"郵件結束");
               //郵件讀取用來校驗
                 messages[i].writeTo(new FileOutputStream("D:/pop3MailReceiver"+ i +".eml"));
            }  
            // 7. 關閉 Folder 會真正刪除郵件, false 不刪除
            popFolder.close(true);
            // 8. 關閉 store, 斷開網絡連接
            store.close();
        } catch (NoSuchProviderException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    
	/**
	 * 解析郵件
	 * 
	 * @param messages 郵件對象
	 * @param i
	 * @return
	 * @throws IOException
	 * @throws MessagingException
	 * @throws FileNotFoundException
	 * @throws UnsupportedEncodingException
	 */
	private void mailReceiver(Message msg)throws Exception{
		// 發件人信息
		Address[] froms = msg.getFrom();
		if(froms != null) {
		    //System.out.println("發件人信息:" + froms[0]);
		    InternetAddress addr = (InternetAddress)froms[0];
		    System.out.println("發件人地址:" + addr.getAddress());
		    System.out.println("發件人顯示名:" + addr.getPersonal());
		}
		System.out.println("郵件主題:" + msg.getSubject());
		// getContent() 是獲取包裹內容, Part相當於外包裝
		Object o = msg.getContent();
		if(o instanceof Multipart) {
			Multipart multipart = (Multipart) o ;
			reMultipart(multipart);
		} else if (o instanceof Part){
			Part part = (Part) o; 
			rePart(part);
		} else {
			System.out.println("類型" + msg.getContentType());
			System.out.println("內容" + msg.getContent());
		}
	}
	
	/**
	 * @param part 解析內容
	 * @throws Exception
	 */
	private void rePart(Part part) throws MessagingException,
			UnsupportedEncodingException, IOException, FileNotFoundException {
		if (part.getDisposition() != null) {
		
			String strFileNmae = MimeUtility.decodeText(part.getFileName()); //MimeUtility.decodeText解決附件名亂碼問題
		    System.out.println("發現附件: " +  MimeUtility.decodeText(part.getFileName()));
		    System.out.println("內容類型: " + MimeUtility.decodeText(part.getContentType()));
		    System.out.println("附件內容:" + part.getContent());
		    InputStream in = part.getInputStream();// 打開附件的輸入流
		    // 讀取附件字節並存儲到文件中
		    java.io.FileOutputStream out = new FileOutputStream(strFileNmae);
		    int data;
		    while((data = in.read()) != -1) {
		        out.write(data);
		    }
		    in.close();
		    out.close();
		} else {
			if(part.getContentType().startsWith("text/plain")) {
				System.out.println("文本內容:" + part.getContent());
			} else {
				//System.out.println("HTML內容:" + part.getContent());
			}
		}
	}
	
	/**
	 * @param multipart // 接卸包裹(含所有郵件內容(包裹+正文+附件))
	 * @throws Exception
	 */
	private void reMultipart(Multipart multipart) throws Exception {
		//System.out.println("郵件共有" + multipart.getCount() + "部分組成");
	    // 依次處理各個部分
	    for (int j = 0, n = multipart.getCount(); j < n; j++) {
	        //System.out.println("處理第" + j + "部分");
	        Part part = multipart.getBodyPart(j);//解包, 取出 MultiPart的各個部分, 每部分可能是郵件內容,
	        // 也可能是另一個小包裹(MultipPart)
	        // 判斷此包裹內容是不是一個小包裹, 一般這一部分是 正文 Content-Type: multipart/alternative
	        if (part.getContent() instanceof Multipart) {
	            Multipart p = (Multipart) part.getContent();// 轉成小包裹
	            //遞歸迭代
	            reMultipart(p);
	        } else {
	        	rePart(part);
	        }
	     }
	}
	
    /**
     * @param args
     */
    public static void main(String[] args) {
        new POP3MailReceiverTest();
    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章