JavaMail接收邮件和发送邮件基本一致,大体上是把Transport换成了Store。不过和发送相比,难点是对接收到的邮件进行解析,不然看起来就跟乱码一样。之所以解析这一块难,就在于一封未知的邮件你不知道它的结构是怎样的,因此需要我们通过判断一步步解析。对于这一点,我也不是很清楚,所以下面我就瞎写一点基础的。


一.首先连接POP3服务器获取邮件

(1)创建Properties对象以及Session对象  

// 创建一个有具体连接信息的Properties对象  
Properties properties = new Properties();
properties.put("mail.store.protocal", protocal);
properties.put("mail.pop3.host", pop3Server);		
		
// 使用Properties对象获得Session对象  
Session session = Session.getInstance(properties);
session.setDebug(false);

 

(2)利用Session对象获得Store对象,并连接pop3服务器

try {
Store store = session.getStore(protocal);
store.connect(pop3Server,username, password);
			
//获取收件箱  
Folder folder = store.getFolder("INBOX");
folder.open(Folder.READ_ONLY);  //以只读权限打开收件箱  
/**
 * Folder.READ_ONLY:表示只读权限。
 * Folder.READ_WRITE:表示可以修改并读取邮件夹中的邮件。
 **/
			
//获取收件箱中的邮件
Message[] messages = folder.getMessages();
System.out.println("总的邮件数目:"+messages.length);
System.out.println("新邮件数目:"+folder.getNewMessageCount());
System.out.println("未读邮件数目:"+folder.getUnreadMessageCount());


(3)对邮件进行一些处理后,然后进行格式化输出

for(int i=0;i<messages.length;i++){
	HandleReceivedMail handleOneMail = new HandleReceivedMail((MimeMessage) messages[i]);
	System.out.println("Message "+ i + " : 主题:"+handleOneMail.getSubject());
	System.out.println("Message "+ i + " : 时间:"+handleOneMail.getSendDate());
	System.out.println("Message "+ i + " : 发件人:"+handleOneMail.getFrom());
//	System.out.println("Message "+ i + " : Message-ID:"+handleOneMail.getMessageID());
	System.out.println("Message "+ i + " : 回执:"+handleOneMail.getReplySign());
	handleOneMail.getMailContent((Part)messages[i]);
	System.out.println("Message "+ i + " : 正文:"+handleOneMail.getBodyText());
	System.out.println("Message "+ i + " : 附件:"+handleOneMail.isContainAttach((Part)messages[i]));
	System.out.println();
}


(4)关闭连接

//关闭连接
folder.close(false);
store.close();


二.对获取到的邮件传入到一个处理类HandleReceivedMail中进行处理

(1)对主题等内容进行解密,防止中文乱码

public String changeEncode(String str){
		try {
			 if (str == null || "".equals(str)) 
		         str = ""; 
			 else
				 str = MimeUtility.decodeText(str); 
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		return str;
	}


(2)获取邮件主题

public String getSubject(){
		String subject = "";
		try {
			subject = changeEncode(mimeMessage.getSubject());
			if(subject == null)
				subject = "";	
			return subject;
		} catch (MessagingException e) {
			e.printStackTrace();
		}
		return null;
	}


(3)获取邮件发送时间

public String getSendDate(){
		try {
			Date sendDate = mimeMessage.getSentDate();
			SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			return dateFormat.format(sendDate);
		} catch (MessagingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}


(4)获取发件人姓名和地址

public String getFrom(){
		try {
			InternetAddress[] address = (InternetAddress[]) mimeMessage.getFrom();
			String person = address[0].getPersonal();  //姓名
			if(person == null)
				person = "";
			String from = address[0].getAddress();  //地址
			if(from == null)
				from = "";
			return person+"["+from+"]";
		} catch (MessagingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		return null;
	}


(5)获取邮件的Message-ID

public String getMessageID(){
		try {
			return mimeMessage.getMessageID();
		} catch (MessagingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}


(6)判断邮件是否需要回执,需要返回“true”,否则返回“false”

	public boolean getReplySign(){
		try {
			String[] reply = mimeMessage.getHeader("Disposition-Notification-To");
			if(reply != null)
				return true;	
		} catch (MessagingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return false;	
	}	


(7)解析邮件

public void getMailContent(Part part){
		try {
			String contentType = part.getContentType();
			int nameIndex = contentType.indexOf("name");
			boolean isContainTextAttach = false;  //判断邮件中是否含有嵌套体
			if(nameIndex != -1)
				isContainTextAttach = true;
			if(part.isMimeType("text/plain") && !isContainTextAttach)
				bodytext.append((String)part.getContent());
			else if(part.isMimeType("text/html") && !isContainTextAttach)
				bodytext.append((String)part.getContent());  //对于HTML格式邮件,可以在前后加上标签<html><head>subject</head><body>bodytext</body></html>,保存为html格式文件(PS:未写)
			else if(part.isMimeType("message/rfc822"))
				getMailContent((Part) part.getContent());
			else if(part.isMimeType("multipart/*")){
				Multipart multipart = (Multipart) part.getContent();
				int count = multipart.getCount();
				for(int i=0;i<count;i++)
					getMailContent(multipart.getBodyPart(i));
			}
			
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}	
	}


(8)正文文本内容

public String getBodyText(){
		return bodytext.toString();
	}


(9)判断是否包含附件

public boolean isContainAttach(Part part){
		boolean attachflag = false;  //是否有附件
		try {
			String contentType = part.getContentType();
			if(part.isMimeType("multipart/*")){
				Multipart multipart = (Multipart) part.getContent();
				for(int i=0;i<multipart.getCount();i++){
					BodyPart bodyPart = multipart.getBodyPart(i);
					String disposition = bodyPart.getDisposition();
					if((disposition != null) && (disposition.equals(Part.ATTACHMENT) || disposition.equals(Part.INLINE)))
						attachflag = true;
					else if(bodyPart.isMimeType("multipart/*"))
						attachflag = isContainAttach((Part)bodyPart);
					else{
						String bodytype = bodyPart.getContentType();
						if(bodytype.toLowerCase().indexOf("application") !=-1)
							attachflag = true;
						if(bodytype.toLowerCase().indexOf("name") !=-1)
							attachflag = true;
					}
					
				}
			}
			else if(part.isMimeType("message/rfc822"))
				attachflag = isContainAttach((Part)part.getContent());
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}		
		return attachflag;	
	}


(10)保存附件到本地

(PS:未写)


三.测试代码

public static void main(String[] args) {
	ReceiveMail receiveMail = new ReceiveMail("pop3.163.com","pop3","youname@163.com","youpassword");
//	ReceiveMail receiveMail = new ReceiveMail("pop.qq.com","pop3","youname@qq.com","youpassword");
		receiveMail.receiveAllMail();
	}

注:1,关于POP3服务器,腾讯的和网易的写法还不一样,一个是:pop.qq.com,一个是:pop3.163.com

    2,QQ邮箱如果短时间内大量连接或者重复连接的话,有可能会抽风,即使代码没问题也连不上,对于这种情况,要么等一会,要么换163或其他邮箱进行测试


附:

1,参考博文:http://xiangzhengyan.iteye.com/blog/85961

2,同样,我练习javamail所写的源代码放在了附件中,需要的可以参考下