引言:html
JavaMai下載地址l jar包:http://java.sun.com/products/javamail/downloads/index.htmljava
此篇是緊隨上篇文章而封裝出來的,閱讀本篇章建議先閱讀上一篇 -->javamail模擬郵箱功能獲取郵件內容-中級實戰篇【內容|附件下載方法】(javamail API電子郵件實例)數組
在上一篇中,講解了郵件獲取內容的兩個方法(HTML和附件),簡單介紹了郵件發送和內容獲取的相同和不一樣之處,而且引入了新類-->javax.mail.Store:容器類。同時對SMTP和POP3協議對應的大體功能進行說明。
服務器
本章節未來演示javamail的郵件回覆功能,原本覺得API會提供一個自動封裝好的方法來供調用,找了很久,併網上查閱了很多資料,原來根本都沒有實現回覆功能,API只有一個方法:reply(Boolean)方法,來提示郵件回覆時的收件人信息,但這個方法有點雞肋,他僅在發送郵件的時候,除非你指明瞭回覆時的郵件地址,才能回去到,而且在回覆郵件時,徹底能夠新增收件人。session
思路:app
既然API沒有給咱們直接回復的方法,那就發揮咱們自強不息的精神吧(吼吼),那麼該怎麼回覆一封郵件呢?ide
看完思路總結,立馬清晰了,原來郵件回覆就是郵件查看和發送的合體!post
做前感悟:學習
代碼真的是寫的越多,錯的越多,功能越多,就會發現模塊是否可以靈活運轉。杯具不斷在上演(有悲劇才能陪襯喜劇嘛),從第一章節至今,不斷的在對模塊進行拆分,以便對功能細化和簡單化,可是仍是不夠,看過上一篇的朋友會發現,在郵件接收業務類裏面,咱們把郵件的接收和讀取|內容的提取封裝在了一個方法裏面,當初沒有感受到不妥,可是用在回覆裏面就露出馬腳了,當你想獲取郵件的時候,你用不到郵件查看業務類的方法,由於他把查看和內容提取耦合在一塊兒,不能簡單的提取出你想要的郵件。因此,此次在新增回覆方法的同時,對郵件獲取業務類進行拆分,拆分爲獲取郵件,和郵件內容的提取兩大部分,這樣在以後若是有要獲取郵件的時候就能共用到它的部分代碼。測試
示例結構:
本篇示例代碼分了5類(把前一章節的獲取業務類進行拆分,而且新增回覆業務類,其他3類沒有變更)
實例代碼演示:
**************複製此五個類可直接跑測試**************註釋部分我儘量詳細講解每一個方法的做用**************
EmailEntity 類 (有複製以前章節的可忽略此類)
package com.cplatform.movie.back.javamail; import javax.mail.Authenticator; import javax.mail.PasswordAuthentication; /** * 郵件基礎實體類 * @author liuyt * @date 2014-10-24 下午2:12:10 */ public class EmailEntity extends Authenticator { /** * 用戶名(登陸郵箱) */ protected static String username; /** * 密碼 */ protected static String password; /** * 初始化郵箱地址和密碼 * @param username 郵箱 * @param password 密碼 */ public EmailEntity(String username, String password) { EmailEntity.username = "這裏填寫發件箱地址"; EmailEntity.password = "這裏填寫發件箱密碼"; } /** * 重寫自我檢驗方法 */ @Override protected PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication(username, password); } String getPassword() { return password; } String getUsername() { return username; } public void setPassword(String password) { EmailEntity.password = password; } public void setUsername(String username) { EmailEntity.username = username; } }
EmailServiceEnity 類 (有複製以前章節的可忽略此類)
package com.cplatform.movie.back.javamail; import java.io.UnsupportedEncodingException; import java.util.Properties; import javax.mail.Message; import javax.mail.MessagingException; import javax.mail.NoSuchProviderException; import javax.mail.Session; import javax.mail.Transport; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeMessage; import com.cplatform.movie.back.javamail.SimpleEmailFunction.MyAuthenricator; /** * 郵件服務支持類 * @author liuyt * @date 2014-10-24 下午2:11:38 */ public class EmailServiceEnity extends EmailEntity{ // java.util.propertis 類 private transient Properties props; // 一個郵件會話 private transient Session session; // 郵件消息 private transient MimeMessage message; // 郵件傳輸對象 private Transport transport; // 郵件發送內容 private String content; // 郵件內容格式 private final String CONTENT_TYPE_HTML = "text/html;charset=utf-8"; // 端口號 private final static String MAIL_PORT = "25"; // 郵箱協議常量 public static final String MAIL_PROTOCOL_SMTP = "smtp"; public static final String MAIL_PROTOCOL_POP3 = "pop3"; // 郵箱所使用的協議 private String mailProtocol; // 郵箱服務器列表 private String hostPort; //////////////////分//////////////////界/////////////////////線///////////////////////////// /** * 實參構造 * @param mailToaddress 收件人地址,多個以逗號隔開 * @param content 郵件內容 * @throws MessagingException * @throws UnsupportedEncodingException */ public EmailServiceEnity(String mailToaddress, String content, String mailProtocol) throws UnsupportedEncodingException, MessagingException { super(username, password); this.setMailProtocol(mailProtocol); this.setHostPort(mailProtocol +"."+ username.split("@")[1]); this.content = content; this.session = this.initSession(); this.message = this.initMessage(this.getSession(), mailToaddress); // 這裏須要對協議進行判斷,SMTP:爲發送協議(初始化Transport) POP3:則爲接收協議(只能初始化Store,在接收郵件章節用到) if(this.getMailProtocol().equals(MAIL_PROTOCOL_SMTP)){ this.transport = this.initTransport(this.getSession()); } } /** * 初始化perps文件 * @return */ public Properties initPrope() { // 初始化props文件 props = new Properties(); props.setProperty("mail.transport.protocol", this.getMailProtocol());//發送郵件協議 props.put("mail.smtp.auth", "true"); //須要驗證 props.put("mail.smtp.host", this.getHostPort()); //服務器地址 return props; } /** * 初始化session會話 * @return */ public Session initSession() { session = Session.getInstance(this.initPrope(),new MyAuthenricator(username, password)); session.setDebug(true); return session; } /** * 初始化Message消息 * @param session * @return * @throws MessagingException * @throws UnsupportedEncodingException */ public MimeMessage initMessage(Session session, String mailToaddress) throws MessagingException, UnsupportedEncodingException { message = new MimeMessage(session); // 設置發件人地址 message.setFrom(new InternetAddress(username, "要顯示的發件人名稱")); // 設置郵件主題 message.setSubject("主題:默認主題"); // 設置郵件發送內容和內容的content-type message.setContent(content.toString(),this.CONTENT_TYPE_HTML); // 設置郵件接收人地址 if(mailToaddress.trim().length() > 0) { String [] address = mailToaddress.split(","); for(int i=0; i<address.length; i++) { // addRecipient(該方法爲添加收件人列表,參數一爲類型:TO-收件人,CC-抄送,參數二爲一個郵件地址) message.addRecipient(Message.RecipientType.TO, new InternetAddress(address[i].trim())); // 下面方法爲傳遞一個收件地址字符串 (兩者方法任選其一便可) message.addRecipients(Message.RecipientType.CC, address[i].trim()); } } return message; } /** * 初始化Transport * @param session * @return * @throws NoSuchProviderException */ public Transport initTransport(Session session) throws NoSuchProviderException { transport = session.getTransport(); return transport; } /***************** 提供必要的get set方法支持 ************飄逸的分割線****************/ public Session getSession() { return session; } public void setSession(Session session) { this.session = session; } public MimeMessage getMessage() { return message; } public void setMessage(MimeMessage message) { this.message = message; } public Properties getProps() { return props; } public String getContentTypeHtml() { return CONTENT_TYPE_HTML; } public static String getMailPort() { return MAIL_PORT; } public String getHostPort() { return hostPort; } public void setHostPort(String hostPort) { this.hostPort = hostPort; } public Transport getTransport() { return transport; } public void setTransport(Transport transport) { this.transport = transport; } public void setProps(Properties props) { this.props = props; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } public String getCONTENT_TYPE_HTML() { return CONTENT_TYPE_HTML; } public static String getMailProtocolSmtp() { return MAIL_PROTOCOL_SMTP; } public static String getMailProtocolPop3() { return MAIL_PROTOCOL_POP3; } public String getMailProtocol() { return mailProtocol; } public void setMailProtocol(String mailProtocol) { this.mailProtocol = mailProtocol; } }
SendEmailService 類 (有複製以前章節的可忽略此類)
package com.cplatform.movie.back.javamail; import java.io.File; import java.io.UnsupportedEncodingException; import javax.activation.DataHandler; import javax.activation.FileDataSource; import javax.mail.BodyPart; import javax.mail.Message; import javax.mail.MessagingException; import javax.mail.Multipart; import javax.mail.internet.MimeBodyPart; import javax.mail.internet.MimeMultipart; import com.sun.xml.internal.messaging.saaj.packaging.mime.internet.MimeUtility; /** * 郵件發送業務類 * @author liuyt * @date 2014-10-26 上午11:17:45 */ public class SendEmailService { private EmailServiceEnity serviceEnity; /** * 發送HTML內容郵件 (包括TEXT格式) * @throws MessagingException */ public void sendHtmlOrText() throws MessagingException { this.send(); } /** * 附件發送 * @param file java.io.File * @param fileName 附件名 * @throws MessagingException * @throws UnsupportedEncodingException */ public void sendFile(File file, String fileName) throws MessagingException, UnsupportedEncodingException { // 得到Message實例 Message message = serviceEnity.getMessage(); // 建立multipart容器用來容納bodyPart(部件) Multipart multipart = new MimeMultipart(); /** * 建立一個BodyPart內容報文 * 每一個消息都有多個部分組成,每一個部分是一個BodyPart報文部分,多個BodyPart部分又同時組成一個Multipart的容器 */ BodyPart messageBodyPart = new MimeBodyPart(); // 設置該報文的內容 messageBodyPart.setContent(serviceEnity.getContent(),serviceEnity.getCONTENT_TYPE_HTML()); // 添加bodyPart報文部分到multiPart容器 multipart.addBodyPart(messageBodyPart); // 建立一個附件報文 messageBodyPart = new MimeBodyPart(); // 文件源 FileDataSource fds = new FileDataSource(file); // 設置郵件的內含附件 (設置數據源爲復件) messageBodyPart.setDataHandler(new DataHandler(fds)); // 設置附件的文件名,需進行編碼,不然文件名會亂碼 messageBodyPart.setFileName(MimeUtility.encodeText(fileName)); // 添加到容器 multipart.addBodyPart(messageBodyPart); // 添加報文容器到消息實例 message.setContent(multipart); // 發送消息 this.send(); } /** * 發送 * 推薦使用方法一,由於方法二若是收件人爲多個的話,會爲每一個人都打開一個Transport通道再關閉 * 而方法一在發送過程當中一直保持鏈接一般,全部操做完成後才關閉 * @throws MessagingException */ public void send() throws MessagingException { Message message = serviceEnity.getMessage(); // 方法一 serviceEnity.getTransport().connect(); serviceEnity.getTransport().sendMessage(message, message.getAllRecipients()); serviceEnity.getTransport().close(); // 方法二 // Transport.send(this.getMessage()); } // main 方法測試 public static void main(String[] args) { SendEmailService service; EmailServiceEnity enity; // 多個收件人中間以逗號間隔 String mailToaddress = "418874847@qq.com,12450374@qq.com"; // 正文(內容)部分 String content = "點擊進入» <a href='http://www.cnblogs.com/liuyitian'>劉一天的博客</a>"; try { service = new SendEmailService(); enity = new EmailServiceEnity(mailToaddress, content, EmailServiceEnity.MAIL_PROTOCOL_SMTP); service.setServiceEnity(enity); service.sendHtmlOrText(); // 測試HTML文本 /** * 切勿使用同一個EmailServiceEnity實例來發送不一樣內容,若有須要就再初始化一個新實例(不然附件發送失敗且亂碼) * 由於每一個實例在發送完郵件後就會關閉Transport */ enity = new EmailServiceEnity(mailToaddress, content, EmailServiceEnity.MAIL_PROTOCOL_SMTP); service.setServiceEnity(enity); // 傳入一個絕對位置的文件路徑 File file = new File("d:/data/adimg/20141022/09/ad_20141022094708943.jpg"); service.sendFile(file,"測試附件發送.jpg"); // 測試復件發送 } catch (UnsupportedEncodingException e1) { e1.printStackTrace(); } catch (MessagingException e1) { e1.printStackTrace(); } } public EmailServiceEnity getServiceEnity() { return serviceEnity; } public void setServiceEnity(EmailServiceEnity serviceEnity) { this.serviceEnity = serviceEnity; } }
LookEmailService 類 (有功能的細分操做)
package com.cplatform.movie.back.javamail; import java.io.DataInputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.UnsupportedEncodingException; import javax.mail.BodyPart; import javax.mail.Folder; import javax.mail.Message; import javax.mail.MessagingException; import javax.mail.Multipart; import javax.mail.Store; import javax.mail.internet.MimeUtility; /** * 查看|接收郵件業務類 * @author liuyt * @date 2014-10-24 下午2:04:48 */ public class LookEmailService { private transient EmailServiceEnity emailService; private transient Folder folder; private transient Store store; // 初始化對象時附帶初始化必要參數 public LookEmailService() throws UnsupportedEncodingException, MessagingException { this.initStoreAndFolder(); } // 主方法,這裏演示單個郵件的內容讀取和附件下載 public void lookEmail() throws MessagingException, IOException, InterruptedException { // 得到郵件 Message[] messages = this.getAllMessage(); // 方法一,獲得所有郵件數組 Message message = this.getMessageByIndex(messages.length); // 方法二 System.out.println("郵件接收時間:"+message.getSentDate()); System.out.println("郵件發送者:"+message.getFrom()[0]); System.out.println("郵件主題:"+message.getSubject()); System.out.println("郵件內容:"+message.getContent()); // 內存地址 System.out.println("***********************飄逸的分割線*****************************"); /** * 判斷內容是否由多部件組成 */ if(!message.getContentType().contains("multipart/")) { return; } // 獲得郵件的Multipart(內容總部件--【包涵附件】) Multipart multipart = (Multipart) message.getContent(); int count = multipart.getCount(); // 部件個數 for(int i=0; i<count; i++) { // 單個部件 注意:單個部件有可能又爲一個Multipart,層層嵌套 BodyPart part = multipart.getBodyPart(i); // 單個部件類型 String type = part.getContentType().split(";")[0]; /** * 類型衆多,逐一判斷,其中TEXT、HTML類型能夠直接用字符串接收,其他接收爲內存地址 * 可能不全,若有沒判斷住的,請本身打印查看類型,在新增判斷 */ if(type.equals("multipart/alternative")) { // HTML (文本和超文本組合) System.out.println("超文本:" + part.getContent().toString()); }else if(type.equals("text/plain")) { // 純文本 System.out.println("純文本:" + part.getContent().toString()); }else if(type.equals("text/html")){ // HTML標籤元素 System.out.println("HTML元素:" + part.getContent().toString()); }else if(type.equals("multipart/related")){ // 內嵌資源 (包涵文本和超文本組合) System.out.println("內嵌資源:" + part.getContent().toString()); }else if(type.contains("application/")) { // 應用附件 (zip、xls、docx等) System.out.println("應用文件:" + part.getContent().toString()); }else if(type.contains("image/")) { // 圖片附件 (jpg、gpeg、gif等) System.out.println("圖片文件:" + part.getContent().toString()); } /*****************************************獲取郵件內容方法***************************************************/ /** * 附件下載 * 這裏針對image圖片類型附件作下載操做,其餘類型附件同理 */ if(type.contains("image/")) { // 打開附件的輸入流 DataInputStream in = new DataInputStream(part.getInputStream()); // 一個文件輸出流 FileOutputStream out = null; // 獲取附件名 String fileName = part.getFileName(); // 文件名解碼 fileName = MimeUtility.decodeText(fileName); // 根據附件名建立一個File文件 File file = new File("d:/data/" + fileName); // 查看是否有當前文件 Boolean b = file.exists(); if(!b) { out = new FileOutputStream(file); int data; // 循環讀寫 while((data=in.read()) != -1) { out.write(data); } System.out.println("附件:【" + fileName + "】下載完畢,保存路徑爲:" + file.getPath()); } // 關流 if(in != null) { in.close(); } if(out != null) { out.close(); } } /** * 獲取超文本複合內容 * 他本是又是一個Multipart容器 * 此時郵件會分爲TEXT(純文本)正文和HTML正文(HTML標籤元素) */ if(type.equals("multipart/alternative")) { Multipart m = (Multipart) part.getContent(); for (int k=0; k<m.getCount(); k++) { if(m.getBodyPart(k).getContentType().startsWith("text/plain")) { // 處理文本正文 System.out.println("TEXT文本內容:"+"\n" + m.getBodyPart(k).getContent().toString().trim()+"\n"); } else { // 處理 HTML 正文 System.out.println("HTML文本內容:"+"\n" + m.getBodyPart(k).getContent()+"\n"); } } } } /** * 最後千萬別忘記了關閉 */ folder.close(false); // false爲不更新郵件,true爲更新,通常在刪除郵件後使用 store.close(); } /** * 返回一個指定條目的郵件 * @return * @throws MessagingException */ public Message getMessageByIndex(int index) throws MessagingException { return folder.getMessage(index); } /** * 返回郵箱全部郵件 * @param args * @throws MessagingException */ public Message[] getAllMessage() throws MessagingException { return folder.getMessages(); } /** * 返回指定區間(起始條目和結束條目)的郵件 * @param args * @throws MessagingException */ public Message[] getMessageBySpace(int start, int end) throws MessagingException { return folder.getMessages(start, end); } /** * 初始化Store鏈接和獲取Folder郵件夾 * @throws MessagingException * @throws UnsupportedEncodingException */ public void initStoreAndFolder() throws UnsupportedEncodingException, MessagingException { /** * 接收郵件時,郵箱的協議爲POP3,SMTP爲郵件傳輸協議,這裏別搞混了 * 而且檢查你的郵箱設置POP3功能是否開啓 */ emailService = new EmailServiceEnity("", "",EmailServiceEnity.MAIL_PROTOCOL_POP3); /** * javax.mail.Store類用於鏈接郵件接收服務器,並訪問郵件接收服務器上的各個郵箱夾 * javax.mail.Folder類表示郵件夾 * 經過一個Session咱們能夠拿到一個郵箱對應的Store */ store = emailService.getSession().getStore(emailService.getMailProtocol()); store.connect(emailService.getHostPort(), EmailServiceEnity.username, EmailServiceEnity.password); /** * 經過Store拿到收件箱文件夾 * INBOX 標識獲取到郵件夾裏的收件箱 (對於POP3協議僅INBOX可用--蛋疼哦) * 並以只讀方式打開收件箱 */ folder = store.getFolder("INBOX"); folder.open(Folder.READ_ONLY); } // main 方法簡單測試 public static void main(String[] args) { try { new LookEmailService().lookEmail(); } catch (IOException e) { e.printStackTrace(); } catch (MessagingException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } } /***************GET********************SET***********************/ public EmailServiceEnity getEmailService() { return emailService; } public void setEmailService(EmailServiceEnity emailService) { this.emailService = emailService; } public Store getStore() { return store; } public void setStore(Store store) { this.store = store; } public Folder getFolder() { return folder; } public void setFolder(Folder folder) { this.folder = folder; } }
ReplyEmailService 類 (郵件回覆業務類)
package com.cplatform.movie.back.javamail; import java.io.IOException; import java.io.UnsupportedEncodingException; import javax.mail.Address; import javax.mail.Message; import javax.mail.MessagingException; import javax.mail.internet.InternetAddress; /** * 郵件回覆業務類 * @author liuyt * @date 2014-10-27 上午8:48:29 */ public class ReplyEmailService { // 服務實體類 private transient EmailServiceEnity emailService; // 回覆內容 private transient String content; /** * 郵件回覆方法 * 思路:先獲取要回復的郵件,而後獲取郵件的各個詳情,把詳情附加給新建郵件,發送 * @throws MessagingException * @throws IOException */ public void replyEmail () throws MessagingException, IOException { // 獲取郵件,和查看郵件相同,調用方法便可 LookEmailService lookEmail = new LookEmailService(); emailService = new EmailServiceEnity("", "",EmailServiceEnity.MAIL_PROTOCOL_POP3); lookEmail.setEmailService(emailService); Message message = lookEmail.getMessageByIndex(lookEmail.getAllMessage().length); /*************上面爲獲取郵件************到此處是一個分水嶺****************下面爲發送郵件****************/ Message reply = this.newReplyMessage(message); // 布爾值,true爲回覆給全部人,false爲只回復給發送者 reply.reply(true); // 發送回覆 emailService.getTransport().connect(); emailService.getTransport().sendMessage(reply, reply.getAllRecipients()); emailService.getTransport().close(); } /** * 組裝要回復的郵件 * @param message * @return * @throws MessagingException * @throws IOException */ public Message newReplyMessage(Message message) throws MessagingException, IOException { // 出新初始化一個服務類,由於以前爲獲取郵件,協議爲POP3,當前要發送郵件,協議爲SMTP emailService = new EmailServiceEnity("", "", EmailServiceEnity.MAIL_PROTOCOL_SMTP); // 新建立一個郵件 Message reply = emailService.getMessage(); // 獲取原郵件的發件人--》爲新郵件的接收人 Address[] addressTo = message.getFrom(); // 獲取原郵件內容(暫支持文本和HTML單部件,多部件另需遞歸循環原郵件,並新增) Object content = message.getContent(); // 獲取原郵件主題 String subObject = message.getSubject(); // 獲取郵件發送時間 String date = message.getSentDate().toString(); /** 組裝新郵件*/ // 設置回覆內容,新內容+原文 reply.setContent(this.content + "<br/><br/><br/>" + date +","+ InternetAddress.toString(addressTo) + "寫到:<br/>> " + content, "text/html;charset=utf-8"); // 設置郵件回覆主題 reply.setSubject("Re:" + subObject); // 設置收件人:原發件人 reply.addRecipients(Message.RecipientType.TO, addressTo); return reply; } // 簡單main方法測試 public static void main(String[] args) { try { ReplyEmailService replySend = new ReplyEmailService(); replySend.setContent("你好,郵件已收到! <a href='http://www.cnblogs.com/liuyitian'><<--點擊進入個人博客-->></a>"); replySend.replyEmail(); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } catch (MessagingException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } /**********************GET***********************SET****************************/ public EmailServiceEnity getEmailService() { return emailService; } public void setEmailService(EmailServiceEnity emailService) { this.emailService = emailService; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } }
代碼部分都是在以前的基礎上進行累加的,沒變化的類直接進行摺疊。到目前:發、收、回基本解決。
本章小結:
至此重要功能都講的差很少了,這幾天來陸陸續續不停的再對代碼進行加強,接下來等到這週末了再對其餘功能進行封裝,這周要休養生息了,看看別的值得學習的東西,換個思路,還會再回來的,還有>>>>若是對你有幫助,還請動下小指別忘推薦哦。
javamail API 系列篇:
寫做不易,不免有疏漏和錯誤,還請慷慨指正,不錯請推薦
ps:歡迎轉載,轉載請註明出處:http://www.cnblogs.com/liuyitian/p/4054437.html
天天多學一點點 代碼少敲一點點