好了,進入這個系列教程最主要的步驟了,前面郵件的理論知識咱們都瞭解了,那麼這篇博客咱們將用代碼完成郵件的發送。這在實際項目中應用的很是普遍,好比註冊須要發送郵件進行帳號激活,再好比OA項目中利用郵件進行任務提醒等等。咱們這裏所講的就是利用 JavaMail 完成郵件的發送和接收功能。html
PS:本篇博客源碼下載連接:https://github.com/YSOcean/cnblogsjava
JavaMail 是sun公司(現以被甲骨文收購)爲方便Java開發人員在應用程序中實現郵件發送和接收功能而提供的一套標準開發包,它支持一些經常使用的郵件協議,如前面所講的SMTP,POP3,IMAP,還有MIME等。咱們在使用JavaMail API 編寫郵件時,無須考慮郵件的底層實現細節,只要調用JavaMail 開發包中相應的API類就能夠了。git
JavaMail 下載地址: https://github.com/javaee/javamail/releasesgithub
下載這個版本的JavaMail,包含了SMTP, IMAP, 和 POP3 協議的實現。服務器
JavaMail API 按照功能能夠劃分爲以下三大類:網絡
①、建立和解析郵件的APIsession
②、發送郵件的API併發
③、接收郵件的APIpost
以上三種類型的API在JavaMail 中由多個類組成,可是主要有四個核心類,咱們在編寫程序時,記住這四個核心類,就很容易編寫出Java郵件處理程序。編碼
①、Message 類:javax.mail.Message 類是建立和解析郵件的核心 API,這是一個抽象類,一般使用它的子類javax.mail.internet.MimeMessage 類。它的實例對象表示一份電子郵件。客戶端程序發送郵件時,首先使用建立郵件的 JavaMail API 建立出封裝了郵件數據的 Message 對象,而後把這個對象傳遞給郵件發送API(Transport 類) 發送。客戶端程序接收郵件時,郵件接收API把接收到的郵件數據封裝在Message 類的實例中,客戶端程序在使用郵件解析API從這個對象中解析收到的郵件數據。
②、Transport 類:javax.mail.Transport 類是發送郵件的核心API 類,它的實例對象表明實現了某個郵件發送協議的郵件發送對象,例如 SMTP 協議,客戶端程序建立好 Message 對象後,只須要使用郵件發送API 獲得 Transport 對象,而後把 Message 對象傳遞給 Transport 對象,並調用它的發送方法,就能夠把郵件發送給指定的 SMTP 服務器。
③、Store 類:javax.mail.Store 類是接收郵件的核心 API 類,它的實例對象表明實現了某個郵件接收協議的郵件接收對象,例如 POP3 協議,客戶端程序接收郵件時,只須要使用郵件接收 API 獲得 Store 對象,而後調用 Store 對象的接收方法,就能夠從指定的 POP3 服務器得到郵件數據,並把這些郵件數據封裝到表示郵件的 Message 對象中。
④、Session 類:javax.mail.Session 類用於定義整個應用程序所需的環境信息,以及收集客戶端與郵件服務器創建網絡鏈接的會話信息,例如郵件服務器的主機名、端口號、採用的郵件發送和接收協議等。Session 對象根據這些信息構建用於郵件收發的 Transport 和 Store 對象,以及爲客戶端建立 Message 對象時提供信息支持。
在理解下面經過代碼實現郵件的發送時,咱們能夠將郵件發送假想爲火箭運載這衛星發送。其中Message 是衛星,Transport 是火箭,而衛星和火箭的構建都須要 Session 的幫助,這樣的關係更加便於記憶。
package com.ys.mail; import java.io.ObjectInputStream.GetField; import java.util.Date; import java.util.Properties; import javax.mail.Address; import javax.mail.Message; import javax.mail.MessagingException; import javax.mail.Session; import javax.mail.Transport; import javax.mail.internet.AddressException; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeMessage; import javax.swing.text.html.MinimalHTMLWriter; public class SendMailText { //發件人地址 public static String senderAddress = "xxx@163.com"; //收件人地址 public static String recipientAddress = "xxx@qq.com"; //發件人帳戶名 public static String senderAccount = "xxx"; //發件人帳戶密碼 public static String senderPassword = "xxx"; public static void main(String[] args) throws Exception { //一、鏈接郵件服務器的參數配置 Properties props = new Properties(); //設置用戶的認證方式 props.setProperty("mail.smtp.auth", "true"); //設置傳輸協議 props.setProperty("mail.transport.protocol", "smtp"); //設置發件人的SMTP服務器地址 props.setProperty("mail.smtp.host", "smtp.163.com"); //二、建立定義整個應用程序所需的環境信息的 Session 對象 Session session = Session.getInstance(props); //設置調試信息在控制檯打印出來 session.setDebug(true); //三、建立郵件的實例對象 Message msg = getMimeMessage(session); //四、根據session對象獲取郵件傳輸對象Transport Transport transport = session.getTransport(); //設置發件人的帳戶名和密碼 transport.connect(senderAccount, senderPassword); //發送郵件,併發送到全部收件人地址,message.getAllRecipients() 獲取到的是在建立郵件對象時添加的全部收件人, 抄送人, 密送人 transport.sendMessage(msg,msg.getAllRecipients()); //若是隻想發送給指定的人,能夠以下寫法 //transport.sendMessage(msg, new Address[]{new InternetAddress("xxx@qq.com")}); //五、關閉郵件鏈接 transport.close(); } /** * 得到建立一封郵件的實例對象 * @param session * @return * @throws MessagingException * @throws AddressException */ public static MimeMessage getMimeMessage(Session session) throws Exception{ //建立一封郵件的實例對象 MimeMessage msg = new MimeMessage(session); //設置發件人地址 msg.setFrom(new InternetAddress(senderAddress)); /** * 設置收件人地址(能夠增長多個收件人、抄送、密送),即下面這一行代碼書寫多行 * MimeMessage.RecipientType.TO:發送 * MimeMessage.RecipientType.CC:抄送 * MimeMessage.RecipientType.BCC:密送 */ msg.setRecipient(MimeMessage.RecipientType.TO,new InternetAddress(recipientAddress)); //設置郵件主題 msg.setSubject("郵件主題","UTF-8"); //設置郵件正文 msg.setContent("簡單的純文本郵件!", "text/html;charset=UTF-8"); //設置郵件的發送時間,默認當即發送 msg.setSentDate(new Date()); return msg; } }
上述的代碼有詳細的註釋,你們不懂得能夠留言。注意:你們本身在運行時請將收件人,發件人等信息更改爲本身的。
執行完上述代碼,而後咱們查看收件箱:
那麼一封簡單的純文本文件就發送完畢了。
①、發件人的郵箱帳戶名和密碼:有的郵箱設置了獨立密碼,還有的必須用受權碼登陸(qq郵箱),這在 手工體驗smtp和pop3協議 這篇博客中有介紹。
②、發件人的SMTP服務器地址:通常是 smtp.xxx.com,好比163郵箱是smtp.163.com,qq郵箱是smtp.qq.com。
③、有可能你收件人地址,發件人地址等信息都正確了,控制檯也打印了正確的信息,可是在收件箱就是收不到信息。這是由於可能收件箱服務器拒收了你發的郵件(好比認爲你的郵件是廣告),這時候可能在垃圾箱裏能找到,可能找不到。解決辦法是重複的郵件內容不要屢次發送,或者更換收件箱試試。
④、本實例使用的是JavaMail1.6版本,支持的JDK必須是jdk1.7版本!!!
因爲接收郵件的用處很少,這裏咱們就簡單的給出一個實例:
package com.ys.mail; import java.util.Properties; import javax.mail.Address; import javax.mail.Folder; import javax.mail.Message; import javax.mail.Session; import javax.mail.Store; public class RecipientMail { //收件人地址 public static String recipientAddress = "xxx@163.com"; //收件人帳戶名 public static String recipientAccount = "xxx"; //收件人帳戶密碼 public static String recipientPassword = "xxx"; public static void main(String[] args) throws Exception { //一、鏈接郵件服務器的參數配置 Properties props = new Properties(); //設置傳輸協議 props.setProperty("mail.store.protocol", "pop3"); //設置收件人的POP3服務器 props.setProperty("mail.pop3.host", "pop3.163.com"); //二、建立定義整個應用程序所需的環境信息的 Session 對象 Session session = Session.getInstance(props); //設置調試信息在控制檯打印出來 //session.setDebug(true); Store store = session.getStore("pop3"); //鏈接收件人POP3服務器 store.connect("pop3.163.com", recipientAccount, recipientPassword); //得到用戶的郵件帳戶,注意經過pop3協議獲取某個郵件夾的名稱只能爲inbox Folder folder = store.getFolder("inbox"); //設置對郵件帳戶的訪問權限 folder.open(Folder.READ_WRITE); //獲得郵件帳戶的全部郵件信息 Message [] messages = folder.getMessages(); for(int i = 0 ; i < messages.length ; i++){ //得到郵件主題 String subject = messages[i].getSubject(); //得到郵件發件人 Address[] from = messages[i].getFrom(); //獲取郵件內容(包含郵件內容的html代碼) String content = (String) messages[i].getContent(); } //關閉郵件夾對象 folder.close(); //關閉鏈接對象 store.close(); } }
咱們先看項目結構,在src目錄下包含圖片和附件:
而後看代碼:
package com.ys.mail; import java.util.Date; import java.util.Properties; import javax.activation.DataHandler; import javax.activation.FileDataSource; import javax.mail.Message; import javax.mail.MessagingException; import javax.mail.Session; import javax.mail.Transport; import javax.mail.internet.AddressException; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeBodyPart; import javax.mail.internet.MimeMessage; import javax.mail.internet.MimeMultipart; import javax.mail.internet.MimeUtility; public class SendMailText_Picture_Enclosure { //發件人地址 public static String senderAddress = "xxx@163.com"; //收件人地址 public static String recipientAddress = "xxx@qq.com"; //發件人帳戶名 public static String senderAccount = "xxx"; //發件人帳戶密碼 public static String senderPassword = "xxx"; public static void main(String[] args) throws Exception { //一、鏈接郵件服務器的參數配置 Properties props = new Properties(); //設置用戶的認證方式 props.setProperty("mail.smtp.auth", "true"); //設置傳輸協議 props.setProperty("mail.transport.protocol", "smtp"); //設置發件人的SMTP服務器地址 props.setProperty("mail.smtp.host", "smtp.163.com"); //二、建立定義整個應用程序所需的環境信息的 Session 對象 Session session = Session.getInstance(props); //設置調試信息在控制檯打印出來 session.setDebug(true); //三、建立郵件的實例對象 Message msg = getMimeMessage(session); //四、根據session對象獲取郵件傳輸對象Transport Transport transport = session.getTransport(); //設置發件人的帳戶名和密碼 transport.connect(senderAccount, senderPassword); //發送郵件,併發送到全部收件人地址,message.getAllRecipients() 獲取到的是在建立郵件對象時添加的全部收件人, 抄送人, 密送人 transport.sendMessage(msg,msg.getAllRecipients()); //五、關閉郵件鏈接 transport.close(); } /** * 得到建立一封郵件的實例對象 * @param session * @return * @throws MessagingException * @throws AddressException */ public static MimeMessage getMimeMessage(Session session) throws Exception{ //1.建立一封郵件的實例對象 MimeMessage msg = new MimeMessage(session); //2.設置發件人地址 msg.setFrom(new InternetAddress(senderAddress)); /** * 3.設置收件人地址(能夠增長多個收件人、抄送、密送),即下面這一行代碼書寫多行 * MimeMessage.RecipientType.TO:發送 * MimeMessage.RecipientType.CC:抄送 * MimeMessage.RecipientType.BCC:密送 */ msg.setRecipient(MimeMessage.RecipientType.TO,new InternetAddress(recipientAddress)); //4.設置郵件主題 msg.setSubject("郵件主題(包含圖片和附件)","UTF-8"); //下面是設置郵件正文 //msg.setContent("簡單的純文本郵件!", "text/html;charset=UTF-8"); // 5. 建立圖片"節點" MimeBodyPart image = new MimeBodyPart(); // 讀取本地文件 DataHandler dh = new DataHandler(new FileDataSource("src\\mailTestPic.png")); // 將圖片數據添加到"節點" image.setDataHandler(dh); // 爲"節點"設置一個惟一編號(在文本"節點"將引用該ID) image.setContentID("mailTestPic"); // 6. 建立文本"節點" MimeBodyPart text = new MimeBodyPart(); // 這裏添加圖片的方式是將整個圖片包含到郵件內容中, 實際上也能夠以 http 連接的形式添加網絡圖片 text.setContent("這是一張圖片<br/><a href='http://www.cnblogs.com/ysocean/p/7666061.html'><img src='cid:mailTestPic'/></a>", "text/html;charset=UTF-8"); // 7. (文本+圖片)設置 文本 和 圖片"節點"的關係(將 文本 和 圖片"節點"合成一個混合"節點") MimeMultipart mm_text_image = new MimeMultipart(); mm_text_image.addBodyPart(text); mm_text_image.addBodyPart(image); mm_text_image.setSubType("related"); // 關聯關係 // 8. 將 文本+圖片 的混合"節點"封裝成一個普通"節點" // 最終添加到郵件的 Content 是由多個 BodyPart 組成的 Multipart, 因此咱們須要的是 BodyPart, // 上面的 mailTestPic 並不是 BodyPart, 全部要把 mm_text_image 封裝成一個 BodyPart MimeBodyPart text_image = new MimeBodyPart(); text_image.setContent(mm_text_image); // 9. 建立附件"節點" MimeBodyPart attachment = new MimeBodyPart(); // 讀取本地文件 DataHandler dh2 = new DataHandler(new FileDataSource("src\\mailTestDoc.docx")); // 將附件數據添加到"節點" attachment.setDataHandler(dh2); // 設置附件的文件名(須要編碼) attachment.setFileName(MimeUtility.encodeText(dh2.getName())); // 10. 設置(文本+圖片)和 附件 的關係(合成一個大的混合"節點" / Multipart ) MimeMultipart mm = new MimeMultipart(); mm.addBodyPart(text_image); mm.addBodyPart(attachment); // 若是有多個附件,能夠建立多個屢次添加 mm.setSubType("mixed"); // 混合關係 // 11. 設置整個郵件的關係(將最終的混合"節點"做爲郵件的內容添加到郵件對象) msg.setContent(mm); //設置郵件的發送時間,默認當即發送 msg.setSentDate(new Date()); return msg; } }
執行程序後,咱們查看郵箱:
那麼一封包含圖片(點擊圖片跳轉到指定超連接),和附件的郵件就生成了。