Posted on 2009-05-31 01:03
啥都寫點(diǎn) 閱讀(7892)
評(píng)論(6) 編輯 收藏 所屬分類:
J2SE
關(guān)鍵技術(shù):
- javax.mail.Store:該類實(shí)現(xiàn)特定郵件協(xié)議(如POP3)上的讀、寫、監(jiān)視、查找等操作。通過它的getFolder方法打開一個(gè)javax.mail.Folder。
- javax.mail.Folder:該類用于描述郵件的分級(jí)組織,如收件箱、草稿箱。它的open方法打開分級(jí)組織,close方法關(guān)閉分級(jí)組織,getMessages方法獲得分級(jí)組織中的郵件,getNewMessageCount方法獲得分級(jí)組織中新郵件的數(shù)量,getUnreadMessageCount方法獲得分級(jí)組織中未讀郵件的數(shù)量
- 根據(jù)MimeMessage的getFrom和getRecipients方法獲得郵件的發(fā)件人和收件人地址列表,得到的是InternetAddress數(shù)組,根據(jù)InternetAddress的getAddress方法獲得郵件地址,根據(jù)InternetAddress的getPersonal方法獲得郵件地址的個(gè)人信息。
- MimeMessage的getSubject、getSentDate、getMessageID方法獲得郵件的主題、發(fā)送日期和郵件的ID(表示郵件)。
- 通過MimeMessage的getContent方法獲得郵件的內(nèi)容,如果郵件是MIME郵件,那么得到的是一個(gè)Multipart的對(duì)象,如果是一共普通的文本郵件,那么得到的是BodyPart對(duì)象。Multipart可以包含多個(gè)BodyPart,而BodyPart本身又可以是Multipart。BodyPart的MimeType類型為“multipart/*”時(shí),表示它是一個(gè)Mutipart。
- 但一個(gè)BodyPart的disposition屬性等于Part.ATTACHMENT或者Part.INLINE常量時(shí),表示它帶有附件。通過BodyPart的getInputStream方法可以獲得附件的輸入流。
package book.email;
import java.io.File;
import java.util.Properties;
/**
* 收郵件的基本信息
*/
public class MailReceiverInfo {
// 郵件服務(wù)器的IP、端口和協(xié)議
private String mailServerHost;
private String mailServerPort = "110";
private String protocal = "pop3";
// 登陸郵件服務(wù)器的用戶名和密碼
private String userName;
private String password;
// 保存郵件的路徑
private String attachmentDir = "C:/temp/";
private String emailDir = "C:/temp/";
private String emailFileSuffix = ".eml";
// 是否需要身份驗(yàn)證
private boolean validate = true;
/**
* 獲得郵件會(huì)話屬性
*/
public Properties getProperties(){
Properties p = new Properties();
p.put("mail.pop3.host", this.mailServerHost);
p.put("mail.pop3.port", this.mailServerPort);
p.put("mail.pop3.auth", validate ? "true" : "false");
return p;
}
public String getProtocal() {
return protocal;
}
public void setProtocal(String protocal) {
this.protocal = protocal;
}
public String getAttachmentDir() {
return attachmentDir;
}
public void setAttachmentDir(String attachmentDir) {
if (!attachmentDir.endsWith(File.separator)){
attachmentDir = attachmentDir + File.separator;
}
this.attachmentDir = attachmentDir;
}
public String getEmailDir() {
return emailDir;
}
public void setEmailDir(String emailDir) {
if (!emailDir.endsWith(File.separator)){
emailDir = emailDir + File.separator;
}
this.emailDir = emailDir;
}
public String getEmailFileSuffix() {
return emailFileSuffix;
}
public void setEmailFileSuffix(String emailFileSuffix) {
if (!emailFileSuffix.startsWith(".")){
emailFileSuffix = "." + emailFileSuffix;
}
this.emailFileSuffix = emailFileSuffix;
}
public String getMailServerHost() {
return mailServerHost;
}
public void setMailServerHost(String mailServerHost) {
this.mailServerHost = mailServerHost;
}
public String getMailServerPort() {
return mailServerPort;
}
public void setMailServerPort(String mailServerPort) {
this.mailServerPort = mailServerPort;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public boolean isValidate() {
return validate;
}
public void setValidate(boolean validate) {
this.validate = validate;
}
}
package book.email;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;
import java.util.Date;
import javax.mail.BodyPart;
import javax.mail.Flags;
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.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeUtility;
/**
* 郵件接收器,目前支持pop3協(xié)議。
* 能夠接收文本、HTML和帶有附件的郵件
*/
public class MailReceiver {
// 收郵件的參數(shù)配置
private MailReceiverInfo receiverInfo;
// 與郵件服務(wù)器連接后得到的郵箱
private Store store;
// 收件箱
private Folder folder;
// 收件箱中的郵件消息
private Message[] messages;
// 當(dāng)前正在處理的郵件消息
private Message currentMessage;
private String currentEmailFileName;
public MailReceiver(MailReceiverInfo receiverInfo) {
this.receiverInfo = receiverInfo;
}
/**
* 收郵件
*/
public void receiveAllMail() throws Exception{
if (this.receiverInfo == null){
throw new Exception("必須提供接收郵件的參數(shù)!");
}
// 連接到服務(wù)器
if (this.connectToServer()) {
// 打開收件箱
if (this.openInBoxFolder()) {
// 獲取所有郵件
this.getAllMail();
this.closeConnection();
} else {
throw new Exception("打開收件箱失?。?/span>");
}
} else {
throw new Exception("連接郵件服務(wù)器失??!");
}
}
/**
* 登陸郵件服務(wù)器
*/
private boolean connectToServer() {
// 判斷是否需要身份認(rèn)證
MyAuthenticator authenticator = null;
if (this.receiverInfo.isValidate()) {
// 如果需要身份認(rèn)證,則創(chuàng)建一個(gè)密碼驗(yàn)證器
authenticator = new MyAuthenticator(this.receiverInfo.getUserName(),
this.receiverInfo.getPassword());
}
//創(chuàng)建session
Session session = Session.getInstance(this.receiverInfo
.getProperties(), authenticator);
//創(chuàng)建store,建立連接
try {
this.store = session.getStore(this.receiverInfo.getProtocal());
} catch (NoSuchProviderException e) {
System.out.println("連接服務(wù)器失??!");
return false;
}
System.out.println("connecting");
try {
this.store.connect();
} catch (MessagingException e) {
System.out.println("連接服務(wù)器失敗!");
return false;
}
System.out.println("連接服務(wù)器成功");
return true;
}
/**
* 打開收件箱
*/
private boolean openInBoxFolder() {
try {
this.folder = store.getFolder("INBOX");
// 只讀
folder.open(Folder.READ_ONLY);
return true;
} catch (MessagingException e) {
System.err.println("打開收件箱失??!");
}
return false;
}
/**
* 斷開與郵件服務(wù)器的連接
*/
private boolean closeConnection() {
try {
if (this.folder.isOpen()) {
this.folder.close(true);
}
this.store.close();
System.out.println("成功關(guān)閉與郵件服務(wù)器的連接!");
return true;
} catch (Exception e) {
System.out.println("關(guān)閉和郵件服務(wù)器之間連接時(shí)出錯(cuò)!");
}
return false;
}
/**
* 獲取messages中的所有郵件
* @throws MessagingException
*/
private void getAllMail() throws MessagingException {
//從郵件文件夾獲取郵件信息
this.messages = this.folder.getMessages();
System.out.println("總的郵件數(shù)目:" + messages.length);
System.out.println("新郵件數(shù)目:" + this.getNewMessageCount());
System.out.println("未讀郵件數(shù)目:" + this.getUnreadMessageCount());
//將要下載的郵件的數(shù)量。
int mailArrayLength = this.getMessageCount();
System.out.println("一共有郵件" + mailArrayLength + "封");
int errorCounter = 0; //郵件下載出錯(cuò)計(jì)數(shù)器
int successCounter = 0;
for (int index = 0; index < mailArrayLength; index++) {
try {
this.currentMessage = (messages[index]); //設(shè)置當(dāng)前message
System.out.println("正在獲取第" + index + "封郵件
");
this.showMailBasicInfo();
getMail(); //獲取當(dāng)前message
System.out.println("成功獲取第" + index + "封郵件");
successCounter++;
} catch (Throwable e) {
errorCounter++;
System.err.println("下載第" + index + "封郵件時(shí)出錯(cuò)");
}
}
System.out.println("------------------");
System.out.println("成功下載了" + successCounter + "封郵件");
System.out.println("失敗下載了" + errorCounter + "封郵件");
System.out.println("------------------");
}
/**
* 顯示郵件的基本信息
*/
private void showMailBasicInfo() throws Exception{
showMailBasicInfo(this.currentMessage);
}
private void showMailBasicInfo(Message message) throws Exception {
System.out.println("-------- 郵件ID:" + this.getMessageId()
+ " ---------");
System.out.println("From:" + this.getFrom());
System.out.println("To:" + this.getTOAddress());
System.out.println("CC:" + this.getCCAddress());
System.out.println("BCC:" + this.getBCCAddress());
System.out.println("Subject:" + this.getSubject());
System.out.println("發(fā)送時(shí)間::" + this.getSentDate());
System.out.println("是新郵件?" + this.isNew());
System.out.println("要求回執(zhí)?" + this.getReplySign());
System.out.println("包含附件?" + this.isContainAttach());
System.out.println("------------------------------");
}
/**
* 獲得郵件的收件人,抄送,和密送的地址和姓名,根據(jù)所傳遞的參數(shù)的不同
* "to"----收件人 "cc"---抄送人地址 "bcc"---密送人地址
*/
private String getTOAddress() throws Exception {
return getMailAddress("TO", this.currentMessage);
}
private String getCCAddress() throws Exception {
return getMailAddress("CC", this.currentMessage);
}
private String getBCCAddress() throws Exception {
return getMailAddress("BCC", this.currentMessage);
}
/**
* 獲得郵件地址
* @param type 類型,如收件人、抄送人、密送人
* @param mimeMessage 郵件消息
* @return
* @throws Exception
*/
private String getMailAddress(String type, Message mimeMessage)
throws Exception {
String mailaddr = "";
String addtype = type.toUpperCase();
InternetAddress[] address = null;
if (addtype.equals("TO") || addtype.equals("CC")
|| addtype.equals("BCC")) {
if (addtype.equals("TO")) {
address = (InternetAddress[]) mimeMessage
.getRecipients(Message.RecipientType.TO);
} else if (addtype.equals("CC")) {
address = (InternetAddress[]) mimeMessage
.getRecipients(Message.RecipientType.CC);
} else {
address = (InternetAddress[]) mimeMessage
.getRecipients(Message.RecipientType.BCC);
}
if (address != null) {
for (int i = 0; i < address.length; i++) {
// 先獲取郵件地址
String email = address[i].getAddress();
if (email == null){
email = "";
}else {
email = MimeUtility.decodeText(email);
}
// 再取得個(gè)人描述信息
String personal = address[i].getPersonal();
if (personal == null){
personal = "";
} else {
personal = MimeUtility.decodeText(personal);
}
// 將個(gè)人描述信息與郵件地址連起來
String compositeto = personal + "<" + email + ">";
// 多個(gè)地址時(shí),用逗號(hào)分開
mailaddr += "," + compositeto;
}
mailaddr = mailaddr.substring(1);
}
} else {
throw new Exception("錯(cuò)誤的地址類型!!");
}
return mailaddr;
}
/**
* 獲得發(fā)件人的地址和姓名
* @throws Exception
*/
private String getFrom() throws Exception {
return getFrom(this.currentMessage);
}
private String getFrom(Message mimeMessage) throws Exception {
InternetAddress[] address = (InternetAddress[]) mimeMessage.getFrom();
// 獲得發(fā)件人的郵箱
String from = address[0].getAddress();
if (from == null){
from = "";
}
// 獲得發(fā)件人的描述信息
String personal = address[0].getPersonal();
if (personal == null){
personal = "";
}
// 拼成發(fā)件人完整信息
String fromaddr = personal + "<" + from + ">";
return fromaddr;
}
/**
* 獲取messages中message的數(shù)量
* @return
*/
private int getMessageCount() {
return this.messages.length;
}
/**
* 獲得收件箱中新郵件的數(shù)量
* @return
* @throws MessagingException
*/
private int getNewMessageCount() throws MessagingException {
return this.folder.getNewMessageCount();
}
/**
* 獲得收件箱中未讀郵件的數(shù)量
* @return
* @throws MessagingException
*/
private int getUnreadMessageCount() throws MessagingException {
return this.folder.getUnreadMessageCount();
}
/**
* 獲得郵件主題
*/
private String getSubject() throws MessagingException {
return getSubject(this.currentMessage);
}
private String getSubject(Message mimeMessage) throws MessagingException {
String subject = "";
try {
// 將郵件主題解碼
subject = MimeUtility.decodeText(mimeMessage.getSubject());
if (subject == null){
subject = "";
}
} catch (Exception exce) {
}
return subject;
}
/**
* 獲得郵件發(fā)送日期
*/
private Date getSentDate() throws Exception {
return getSentDate(this.currentMessage);
}
private Date getSentDate(Message mimeMessage) throws Exception {
return mimeMessage.getSentDate();
}
/**
* 判斷此郵件是否需要回執(zhí),如果需要回執(zhí)返回"true",否則返回"false"
*/
private boolean getReplySign() throws MessagingException {
return getReplySign(this.currentMessage);
}
private boolean getReplySign(Message mimeMessage) throws MessagingException {
boolean replysign = false;
String needreply[] = mimeMessage
.getHeader("Disposition-Notification-To");
if (needreply != null) {
replysign = true;
}
return replysign;
}
/**
* 獲得此郵件的Message-ID
*/
private String getMessageId() throws MessagingException {
return getMessageId(this.currentMessage);
}
private String getMessageId(Message mimeMessage) throws MessagingException {
return ((MimeMessage) mimeMessage).getMessageID();
}
/**
* 判斷此郵件是否已讀,如果未讀返回返回false,反之返回true
*/
private boolean isNew() throws MessagingException {
return isNew(this.currentMessage);
}
private boolean isNew(Message mimeMessage) throws MessagingException {
boolean isnew = false;
Flags flags = mimeMessage.getFlags();
Flags.Flag[] flag = flags.getSystemFlags();
for (int i = 0; i < flag.length; i++) {
if (flag[i] == Flags.Flag.SEEN) {
isnew = true;
break;
}
}
return isnew;
}
/**
* 判斷此郵件是否包含附件
*/
private boolean isContainAttach() throws Exception {
return isContainAttach(this.currentMessage);
}
private boolean isContainAttach(Part part) throws Exception {
boolean attachflag = false;
if (part.isMimeType("multipart/*")) {
// 如果郵件體包含多部分
Multipart mp = (Multipart) part.getContent();
// 遍歷每部分
for (int i = 0; i < mp.getCount(); i++) {
// 獲得每部分的主體
BodyPart bodyPart = mp.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 contype = bodyPart.getContentType();
if (contype.toLowerCase().indexOf("application") != -1){
attachflag = true;
}
if (contype.toLowerCase().indexOf("name") != -1){
attachflag = true;
}
}
}
} else if (part.isMimeType("message/rfc822")) {
attachflag = isContainAttach((Part) part.getContent());
}
return attachflag;
}
/**
* 獲得當(dāng)前郵件
*/
private void getMail() throws Exception {
try {
this.saveMessageAsFile(currentMessage);
this.parseMessage(currentMessage);
} catch (IOException e) {
throw new IOException("保存郵件出錯(cuò),檢查保存路徑");
} catch (MessagingException e) {
throw new MessagingException("郵件轉(zhuǎn)換出錯(cuò)");
} catch (Exception e) {
e.printStackTrace();
throw new Exception("未知錯(cuò)誤");
}
}
/**
* 保存郵件源文件
*/
private void saveMessageAsFile(Message message) {
try {
// 將郵件的ID中尖括號(hào)中的部分做為郵件的文件名
String oriFileName = getInfoBetweenBrackets(this.getMessageId(message)
.toString());
//設(shè)置文件后綴名。若是附件則設(shè)法取得其文件后綴名作為將要保存文件的后綴名,
//若是正文部分則用.htm做后綴名
String emlName = oriFileName;
String fileNameWidthExtension = this.receiverInfo.getEmailDir()
+ oriFileName + this.receiverInfo.getEmailFileSuffix();
File storeFile = new File(fileNameWidthExtension);
for (int i = 0; storeFile.exists(); i++) {
emlName = oriFileName + i;
fileNameWidthExtension = this.receiverInfo.getEmailDir()
+ emlName + this.receiverInfo.getEmailFileSuffix();
storeFile = new File(fileNameWidthExtension);
}
this.currentEmailFileName = emlName;
System.out.println("郵件消息的存儲(chǔ)路徑: " + fileNameWidthExtension);
// 將郵件消息的內(nèi)容寫入ByteArrayOutputStream流中
ByteArrayOutputStream baos = new ByteArrayOutputStream();
message.writeTo(baos);
// 讀取郵件消息流中的數(shù)據(jù)
StringReader in = new StringReader(baos.toString());
// 存儲(chǔ)到文件
saveFile(fileNameWidthExtension, in);
} catch (MessagingException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
/*
* 解析郵件
*/
private void parseMessage(Message message) throws IOException,
MessagingException {
Object content = message.getContent();
// 處理多部分郵件
if (content instanceof Multipart) {
handleMultipart((Multipart) content);
} else {
handlePart(message);
}
}
/*
* 解析Multipart
*/
private void handleMultipart(Multipart multipart) throws MessagingException,
IOException {
for (int i = 0, n = multipart.getCount(); i < n; i++) {
handlePart(multipart.getBodyPart(i));
}
}
/*
* 解析指定part,從中提取文件
*/
private void handlePart(Part part) throws MessagingException, IOException {
String disposition = part.getDisposition();
String contentType = part.getContentType();
String fileNameWidthExtension = "";
// 獲得郵件的內(nèi)容輸入流
InputStreamReader sbis = new InputStreamReader(part.getInputStream());
// 沒有附件的情況
if (disposition == null) {
if ((contentType.length() >= 10)
&& (contentType.toLowerCase().substring(0, 10)
.equals("text/plain"))) {
fileNameWidthExtension = this.receiverInfo.getAttachmentDir()
+ this.currentEmailFileName + ".txt";
} else if ((contentType.length() >= 9) // Check if html
&& (contentType.toLowerCase().substring(0, 9)
.equals("text/html"))) {
fileNameWidthExtension = this.receiverInfo.getAttachmentDir()
+ this.currentEmailFileName + ".html";
} else if ((contentType.length() >= 9) // Check if html
&& (contentType.toLowerCase().substring(0, 9)
.equals("image/gif"))) {
fileNameWidthExtension = this.receiverInfo.getAttachmentDir()
+ this.currentEmailFileName + ".gif";
} else if ((contentType.length() >= 11)
&& contentType.toLowerCase().substring(0, 11).equals(
"multipart/*")) {
// System.out.println("multipart body: " + contentType);
handleMultipart((Multipart) part.getContent());
} else { // Unknown type
// System.out.println("Other body: " + contentType);
fileNameWidthExtension = this.receiverInfo.getAttachmentDir()
+ this.currentEmailFileName + ".txt";
}
// 存儲(chǔ)內(nèi)容文件
System.out.println("保存郵件內(nèi)容到:" + fileNameWidthExtension);
saveFile(fileNameWidthExtension, sbis);
return;
}
// 各種有附件的情況
String name = "";
if (disposition.equalsIgnoreCase(Part.ATTACHMENT)) {
name = getFileName(part);
// System.out.println("Attachment: " + name + " : "
// + contentType);
fileNameWidthExtension = this.receiverInfo.getAttachmentDir() + name;
} else if (disposition.equalsIgnoreCase(Part.INLINE)) {
name = getFileName(part);
// System.out.println("Inline: " + name + " : "
// + contentType);
fileNameWidthExtension = this.receiverInfo.getAttachmentDir() + name;
} else {
// System.out.println("Other: " + disposition);
}
// 存儲(chǔ)各類附件
if (!fileNameWidthExtension.equals("")) {
System.out.println("保存郵件附件到:" + fileNameWidthExtension);
saveFile(fileNameWidthExtension, sbis);
}
}
private String getFileName(Part part) throws MessagingException,
UnsupportedEncodingException {
String fileName = part.getFileName();
fileName = MimeUtility.decodeText(fileName);
String name = fileName;
if (fileName != null) {
int index = fileName.lastIndexOf("/");
if (index != -1) {
name = fileName.substring(index + 1);
}
}
return name;
}
/**
* 保存文件內(nèi)容
* @param fileName 文件名
* @param input 輸入流
* @throws IOException
*/
private void saveFile(String fileName, Reader input) throws IOException {
// 為了放置文件名重名,在重名的文件名后面天上數(shù)字
File file = new File(fileName);
// 先取得文件名的后綴
int lastDot = fileName.lastIndexOf(".");
String extension = fileName.substring(lastDot);
fileName = fileName.substring(0, lastDot);
for (int i = 0; file.exists(); i++) {
// 如果文件重名,則添加i
file = new File(fileName + i + extension);
}
// 從輸入流中讀取數(shù)據(jù),寫入文件輸出流
FileWriter fos = new FileWriter(file);
BufferedWriter bos = new BufferedWriter(fos);
BufferedReader bis = new BufferedReader(input);
int aByte;
while ((aByte = bis.read()) != -1) {
bos.write(aByte);
}
// 關(guān)閉流
bos.flush();
bos.close();
bis.close();
}
/**
* 獲得尖括號(hào)之間的字符
* @param str
* @return
* @throws Exception
*/
private String getInfoBetweenBrackets(String str) throws Exception {
int i, j; //用于標(biāo)識(shí)字符串中的"<"和">"的位置
if (str == null) {
str = "error";
return str;
}
i = str.lastIndexOf("<");
j = str.lastIndexOf(">");
if (i != -1 && j != -1){
str = str.substring(i + 1, j);
}
return str;
}
public static void main(String[] args) throws Exception {
MailReceiverInfo receiverInfo = new MailReceiverInfo();
receiverInfo.setMailServerHost("pop.163.com");
receiverInfo.setMailServerPort("110");
receiverInfo.setValidate(true);
receiverInfo.setUserName("***");
receiverInfo.setPassword("***");
receiverInfo.setAttachmentDir("C:/temp/mail/");
receiverInfo.setEmailDir("C:/temp/mail/");
MailReceiver receiver = new MailReceiver(receiverInfo);
receiver.receiveAllMail();
}
}
--
學(xué)海無涯