郵件開發的應用
註冊,填寫生日; 後期系統會自動發送生日祝賀
發貨,發貨提醒!郵件提醒!
郵件功能
1. 發郵件;【程序中如何發郵件!】
2. 收郵件;【很多客戶端工具, foxmail
點擊打開鏈接】
郵件傳輸協議
SMTP協議
全稱爲Simple Mail Transfer Protocol(簡單郵件傳輸協議),它定義了郵件客戶端軟件與SMTP服務器之間、以及兩臺SMTP服務器之間的通訊規則。
POP3協議
全稱爲Post Office Protocol(郵局協議),它定義了郵件客戶端軟件與POP3服務器的通訊規則。
IMAP協議
全稱爲Internet Message Access Protocal(Internet消息訪問協議),它是對POP3協議的一種擴展,定義了郵件客戶端軟件與IMAP服務器的通訊規則。
通過telnet命令手工發送郵件
注意:下面指令,建議直接一行一行復制(不要複製註釋),這樣不會出錯,因爲指令輸錯了不能修改。
手動通過163賬戶發送郵件的過程
telnet smtp.163.com 25 //連接163郵箱smtp服務器
---------------------------------------------------以下屬於smtp協議的內容
ehlo lzy //向服務器打招呼
auth login //請求認證,服務器提示輸入用戶名(zyliu1993對應enlsaXUxOTkz)和密碼(Base64加密後的密碼xxxxxxx爲了避免您反編譯破解我的密碼,所以我省略)(必須是Base64編碼後的)
enlsaXUxOTkz
- xxxxxxxxxxxx //爲了避免您反編譯破解我的密碼,所以我省略
mail from:<zyliu1993@163.com> //發件人
rcpt to:<1012421396@qq.com> //收件人
data //說明郵件的內容開始
----------------------------------------------------以下屬於郵件頭
from:zyliu1993@163.com
to:1012421396@qq.com
subject:這是2封手工發送的郵件
----------------------------------------------------注意這裏必須空行
//注意郵件頭和郵件體必須空行,因爲RFC822文檔規定了郵件頭和郵件體,兩者使用空行分隔
---------------------------------------------------以下屬於郵件體
this my first email content by my hand! //郵件內容
. //結束內容
---------------------------------------------------協議內容結束
quit //退出
通過Java程序手動發送郵件
注意:我只能在debug調試模式下,一句句運行郵件纔會發送,直接運行倒是不行,很奇怪。速度太快了麼???
package com.cn.mail;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;
public class MailClient {
public static void main(String[] args) throws Exception {
Socket socket = new Socket("smtp.163.com", 25);//telnet smtp.163.com 25
InputStream in = socket.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(in));// 接收服務器的反饋信息
OutputStream out = socket.getOutputStream();//向服務器發送信息
out.write("ehlo lzy\r\n".getBytes());
System.out.println(br.readLine());
System.out.println(br.readLine());
System.out.println(br.readLine());
System.out.println(br.readLine());
System.out.println(br.readLine());
System.out.println(br.readLine());
System.out.println(br.readLine());
out.write("auth login\r\n".getBytes());
System.out.println(br.readLine());
out.write("enlsaXUxOTkz\r\n".getBytes());
System.out.println(br.readLine());
out.write("xxxxxxxxxxxx\r\n".getBytes());//爲了避免我的密碼泄露,請修改xxxxxx爲你的真實密碼base64加密後的碼值
System.out.println(br.readLine());
out.write("mail from:<[email protected]>\r\n".getBytes());//這裏郵箱地址必須是真實郵箱
System.out.println(br.readLine());
out.write("rcpt to:<[email protected]>\r\n".getBytes());
System.out.println(br.readLine());
out.write("data\r\n".getBytes());
System.out.println(br.readLine());
out.write("from:[email protected]\r\n".getBytes());//這裏郵箱可以冒充
out.write("to:[email protected]\r\n".getBytes());
out.write("subject:手工發送的郵件\r\n".getBytes());
out.write("\r\n".getBytes());
out.write("大家好,我是木丁西,希望我的博文能幫到您,歡迎在博文下留言評論交流,共同進步。\r\n".getBytes());
out.write(".\r\n".getBytes());
socket.close();// quit
}
}
郵件的傳輸過程
什麼是JavaMail
要自己寫程序發送和接收郵件,可以直接採用Socket編程連接上遠程的郵件服務器,然後按照郵件協議與郵件服務器進行交互,涉及較多細節。另外,要想自己編程創建出複雜的MIME格式的郵件,是一件非常困難和麻煩的事情。
JavaMail 是Sun公司爲方便Java開發人員在應用程序中實現郵件發送和接收功能而提供的一套標準開發包,它支持一些常用的郵件協議,如SMTP、POP3、IMAP。
開發人員使用JavaMail API編寫郵件處理軟件時,無須考慮郵件協議的底層實施細節,只要調用JavaMail開發包中相應的API類就可以了。
JavaMail 也提供了能夠創建出各種複雜MIME格式的郵件內容的相關API。
JavaMail API
創建和解析郵件內容的API
Message類是創建和解析郵件的核心API,它的實例對象代表一封電子郵件。
發送郵件的API
Transport類是發送郵件的核心API類,它的實例對象代表實現了某個郵件發送協議的郵件發送對象,例如SMTP協議。
接收郵件的API
Store類是接收郵件的核心API類,它的實例對象代表實現了某個郵件接收協議的郵件接收對象,例如POP3協議。
Session類
Session類用於定義整個應用程序所需的環境信息,以及收集客戶端與郵件服務器建立網絡連接的會話信息,如郵件服務器的主機名、端口號、採用的郵件發送和接收協議等。Session對象根據這些信息構建用於郵件收發的Transport和Store對象,以及爲客戶端創建Message對象時提供信息支持。
複雜郵件內容的組織結構
1.RFC822郵件格式
2.MIME協議-MIME
英文全稱爲“Multipurpose Internet Mail Extensions”,即多用途互聯網郵件擴展,是目前互聯網電子郵件普遍遵循的郵件技術規範,在MIME出現之前,互聯網電子郵件主要遵循由RFC 822所制定的標準,電子郵件一般只用來傳遞基本的ASCII碼文本信息,MIME在 RFC 822的基礎上對電子郵件規範做了大量的擴展,引入了新的格式規範和編碼方式,在MIME的支持下,圖像、聲音、動畫等二進制文件都可方便的通過電子郵件來進行傳遞,極大地豐富了電子郵件的功能。目前互聯網上使用的基本都是遵循MIME規範的電子郵件。
MIME中的組合關係
複雜郵件的組成關係
在局域網中,郵件開發準備:
準備工作, 環境搭建:
1. 本地搭建一個郵件服務器
易郵服務器,eyoumailserversetup.exe
點擊打開鏈接
在局域網下使用這個服務器:工具->服務器設置->系統服務->“作爲 局域網 郵件服務器”->單域名,隨便設置(比如lzy.com)
新建郵箱賬號
例如賬號:zhangsan
密碼:888888
例如賬號:lisi
密碼:666666
3. 安裝foxmail
配置郵件發送服務器(smtp):localhost端口號25
郵件接收服務器(pop3):localhost 端口號110
然後剛剛註冊的賬號,就能在本地局域網中發送郵件了。
JavaMail開發步驟
activation.jar 【(注意:Javamail的API依賴jaf(Java Activation Framework)框架,還需要導入jaf的jar包。如果使用的是JDK6及以上版本,就不需要了,但是加上爲妙)】
mail.jar 【郵件發送核心包】
注意:如果是web項目,因爲javaee自帶的有郵件功能,可能存在問題!我們要用自己的mail.jar文件功能!需要刪除javaee中mail包!
案例:
需求:
1.發送一封普通郵件
2.發送帶圖片資源的郵件
3.發送帶圖片資源和附件的郵件
java項目結構
Java代碼
package com.cn.mail;
import java.io.File;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.Date;
import java.util.Properties;
import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.Message.RecipientType;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import org.junit.Test;
/**
* Author:Liu Zhiyong(QQ:1012421396)
* Version:Version_1
* Date:2017年5月6日21:29:16
* Desc:發送郵件,局域網下,使用自己的郵箱服務器寫的案例
*/
public class SendMail {
//初始化參數
private static Properties properties;
private static InternetAddress sender;
private String filePath;
//發件人
static{
properties = new Properties();
properties.put("mail.transport.protocol", "smtp");//指定協議
properties.put("mail.smtp.host", "localhost");//主機 stmp.qq.com
properties.put("mail.smtp.port", 25);//端口
properties.put("mail.smtp.auth", "true");//用戶密碼驗證
properties.put("mail.debug", "true");//調試模式
try {
sender = new InternetAddress("[email protected]");
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* 發送一封普通郵件
* @throws Exception
*/
@Test
public void testSendMail() throws Exception {
//1.創建包含郵件服務器的網絡連接信息的Session會話對象
Session session = Session.getDefaultInstance(properties);
//2.創建代表郵件內容的Message對象(整封郵件對象)
MimeMessage message = new MimeMessage(session);
//3.設置郵件體參數
message.setSubject("木丁西([email protected])的發送的郵件郵件");//郵件標題
message.setSentDate(new Date());//郵件發送時間
message.setSender(new InternetAddress("[email protected]"));//發件人
message.setRecipient(RecipientType.TO, new InternetAddress("[email protected]"));//收件人
// message.setText("郵件正文。。。。hello this is my first mail to you !");//簡單純文本郵件
message.setContent("<a href='www.baidu.com'>百度</a>", "text/html;charset=utf-8");//發送超鏈接
message.saveChanges();//保存郵件(可選)
//4.創建Transport對象
Transport trans = session.getTransport();
//5.連接服務器
trans.connect("mdx", "mdx");//注意這裏是發件人的用戶名和密碼
//6.發送郵件
trans.sendMessage(message, message.getAllRecipients());
//7.關閉連接
trans.close();
}
/**
* 發送帶圖片資源的郵件
* @throws Exception
*/
@Test
public void testSendMailWithImage() throws Exception {
//1.創建郵件會話
Session session = Session.getDefaultInstance(properties);
//2.創建郵件對象
MimeMessage message = new MimeMessage(session);
//3.設置參數:標題、發件人、收件人、發送時間、內容
message.setSubject("發送帶圖片資源的郵件");
message.setSender(sender);
message.setRecipient(RecipientType.TO, new InternetAddress("[email protected]"));
message.setSentDate(new Date());
//4.設置發送內容:多功能用途郵件(related)
// message.setContent("<img src='I:\\MyEclipse Professional Workspaces\\mail\\src\\com\\cn\\mail\\hh.png'/>", "text/html;charset=utf-8");
//4.1構建一個多功能郵件塊
MimeMultipart related = new MimeMultipart("related");
//4.2構建多功能郵件塊內容=文本+圖片資源
MimeBodyPart content = new MimeBodyPart();
MimeBodyPart resource = new MimeBodyPart();
//4.3設置具體內容:文本
content.setText("這裏是普通文本內容");
//4.4設置具體內容:a.資源(圖片)
// String filePath = SendMail.class.getResource("hh.png").getPath();//類路徑獲取資源文件路徑,但是路徑中有空格或者中文等特殊字符會亂碼,導致路徑不對
/**
* 解決方式1:
*/
// filePath = filePath.replace("%20", " ");//路徑中的空格爲20%,所以也可以用空格進行字符串替換,但是對中文亂碼又無法解決
/**
* 解決方式2:
*/
// String filePath = SendMail.class.getResource("hh.png").getPath();
// filePath = URLDecoder.decode(filePath, "gbk");//只能解決一部分,若路徑中含有+,也是不能解決的,原因是URL並不是完全用URLEncoder.encode(str,"UTF-8")編碼的,+號被解碼後,卻變成了空格。
/**
* 解決方式3:(推薦)
*/
String filePath = SendMail.class.getResource("hh.png").toURI().getPath();
System.out.println(".........................." + filePath);
FileDataSource ds = new FileDataSource(new File(filePath));
DataHandler handler = new DataHandler(ds);
resource.setDataHandler(handler);
resource.setContentID("hh.png");//設置資源名稱給外界引用,可以隨便取名
//設置具體內容:b.文本
content.setContent("<img src='cid:hh.png'/> 我長得帥嗎????哈哈哈","text/html;charset=utf-8");
related.addBodyPart(content);
related.addBodyPart(resource);
//4.5 把構建的複雜郵件塊,添加到郵件中
message.setContent(related);
//5.創建Transport對象
Transport trans = session.getTransport();
//6.連接服務器
trans.connect("mdx", "mdx");//注意這裏是發件人的用戶名和密碼
//7.發送郵件呢
trans.sendMessage(message, message.getAllRecipients());
//8.關閉連接
trans.close();
}
/**
* 發送帶圖片資源和附件的郵件
* @throws Exception
*/
@Test
public void testSendMailWithImageAndAttachment() throws Exception {
//1.創建郵件會話
Session session = Session.getDefaultInstance(properties);
//2.創建郵件對象
MimeMessage message = new MimeMessage(session);
//3.設置參數:標題、發件人、收件人、發送時間、內容
message.setSubject("發送帶圖片資源的郵件");
message.setSender(sender);
message.setRecipient(RecipientType.TO, new InternetAddress("[email protected]"));
message.setSentDate(new Date());
/************************************帶附件郵件功能開發**********************************************/
//構建一個總的郵件塊
MimeMultipart mixed = new MimeMultipart("mixed");
//總郵件塊設置到郵件對象中
message.setContent(mixed);
//左側:(文本+圖片資源)
MimeBodyPart left = new MimeBodyPart();
//右側:附件
MimeBodyPart right = new MimeBodyPart();
//設置到總郵件塊中
mixed.addBodyPart(left);
mixed.addBodyPart(right);
/********************************附件***************************************************/
String attachmentFile = this.getClass().getResource("../../../a.zip").toURI().getPath();
System.out.println("。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。" + attachmentFile);
FileDataSource ds = new FileDataSource(new File(attachmentFile));
DataHandler attachmentHandler = new DataHandler(ds);
right.setDataHandler(attachmentHandler);
right.setFileName("a.zip");//注意這裏的名字,應該和附件名一樣,特別是其後綴。
/************************************設置發送內容:多功能用途郵件(related)**********************************************/
//4.設置發送內容:多功能用途郵件(related)
// message.setContent("<img src='I:\\MyEclipse Professional Workspaces\\mail\\src\\com\\cn\\mail\\hh.png'/>", "text/html;charset=utf-8");
//4.1構建一個多功能郵件塊
MimeMultipart related = new MimeMultipart("related");
//設置到總郵件塊的左側中
left.setContent(related);
//4.2構建多功能郵件塊內容=文本+圖片資源
MimeBodyPart content = new MimeBodyPart();
MimeBodyPart resource = new MimeBodyPart();
//4.3設置具體內容:文本
content.setText("這裏是普通文本內容");
//4.4設置具體內容:a.資源(圖片)
// String filePath = SendMail.class.getResource("hh.png").getPath();//類路徑獲取資源文件路徑,但是路徑中有空格或者中文等特殊字符會亂碼,導致路徑不對
/**
* 解決方式1:
*/
// filePath = filePath.replace("%20", " ");//路徑中的空格爲20%,所以也可以用空格進行字符串替換,但是對中文亂碼又無法解決
/**
* 解決方式2:
*/
// String filePath = SendMail.class.getResource("hh.png").getPath();
// filePath = URLDecoder.decode(filePath, "gbk");//只能解決一部分,若路徑中含有+,也是不能解決的,原因是URL並不是完全用URLEncoder.encode(str,"UTF-8")編碼的,+號被解碼後,卻變成了空格。
/**
* 解決方式3:(推薦)
*/
String filePath = SendMail.class.getResource("hh.png").toURI().getPath();
FileDataSource ds2 = new FileDataSource(new File(filePath));
DataHandler handler = new DataHandler(ds2);
resource.setDataHandler(handler);
resource.setContentID("hh.png");//設置資源名稱給外界引用,可以隨便取名
//設置具體內容:b.文本
content.setContent("<img src='cid:hh.png'/> 我長得帥嗎????哈哈哈","text/html;charset=utf-8");
related.addBodyPart(content);
related.addBodyPart(resource);
//5.創建Transport對象
Transport trans = session.getTransport();
//6.連接服務器
trans.connect("mdx", "mdx");//注意這裏是發件人的用戶名和密碼
//7.發送郵件呢
trans.sendMessage(message, message.getAllRecipients());
//8.關閉連接
trans.close();
}
}
在互聯網中發送郵件(普通文本+圖片+附件)
package com.cn.mail;
import java.io.File;
import java.io.FileOutputStream;
import java.util.Properties;
import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.Message.RecipientType;
import javax.mail.Session;
import javax.mail.Transport;
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;
import org.junit.Before;
import org.junit.Test;
public class MailDemo {
private Properties properties;//環境變量設置,發送郵件時才需要,若是隻保存本地,則不需要
@Before
public void testPrepare() throws Exception {
properties = new Properties();
properties.put("mail.transport.protocol", "smtp");//發送郵件使用的協議smtp
properties.setProperty("mail.host", "smtp.163.com");//發送服務器的主機地址
properties.put("mail.smtp.port", 25);//端口,可省略
properties.setProperty("mail.smtp.auth", "true");//請求身份驗證
properties.setProperty("mail.debug", "true");//調試模式
}
@Test
public void testSendMail() throws Exception {
//創建包含郵件服務器的網絡連接信息的Session會話對象
Session session = Session.getDefaultInstance(properties);
MimeMessage message = new MimeMessage(session);//代表一封郵件
message.setSender(new InternetAddress("[email protected]"));//設置發件人
message.setRecipients(RecipientType.TO, "[email protected]");//設置收件人
message.setSubject("我的郵件主題");//設置郵件主題
//文本和超文本部分
MimeBodyPart textHypertextPart = new MimeBodyPart();
textHypertextPart.setContent("there is 正文內容喲. <a href='http://www.baidu.com' target='_blank'>超鏈接</a><img src='cid:hh'/>", "text/html;charset=utf-8");//這裏cid是指資源的ContentID
//內嵌圖片部分
MimeBodyPart imagePart = new MimeBodyPart();
//把磁盤上的文件讀到郵件上來:藉助JAF框架
String path = this.getClass().getResource("hh.png").toURI().getPath();
DataHandler handler1 = new DataHandler(new FileDataSource(new File(path)));
imagePart.setDataHandler(handler1);
imagePart.setContentID("hh");
//描述imagePart和textPart兩者關係:文本和內嵌圖片合體related
MimeMultipart multipart1 = new MimeMultipart();
multipart1.addBodyPart(textHypertextPart);
multipart1.addBodyPart(imagePart);
multipart1.setSubType("related");//說明兩部分是有關係的
MimeBodyPart textImagePart = new MimeBodyPart();
textImagePart.setContent(multipart1);
//附件部分
MimeBodyPart attachmentPart = new MimeBodyPart();
DataHandler handler2 = new DataHandler(new FileDataSource(this.getClass().getResource("../../../abc附件.zip").toURI().getPath()));
String fileName = handler2.getName();//獲取文件2名
attachmentPart.setDataHandler(handler2);
attachmentPart.setFileName(MimeUtility.encodeText(fileName));//手工設置文件名,中文文件名要注意編碼
//全部合體
MimeMultipart multipart = new MimeMultipart();
multipart.addBodyPart(textImagePart);//文件加內嵌圖片
multipart.addBodyPart(attachmentPart);//附件
multipart.setSubType("mixed");//複雜關係
//設置郵件內容主體
message.setContent(multipart);
// message.saveChanges();//這個可寫可不寫
message.writeTo(new FileOutputStream(new File("d:/2.eml")));//把郵件存到本地磁盤上
//獲取Transport對象
Transport trans = session.getTransport();
//連接服務器
trans.connect("zyliu1993", "xxxxxx");//注意這裏的密碼XXXXX是163郵箱的授權碼用戶名zyliu1993或者郵箱[email protected]都行
//發送郵件
trans.sendMessage(message, message.getAllRecipients());//發送郵件給所有收件人
//關閉
trans.close();
}
@Test
public void testDemo() throws Exception {
properties.setProperty("mail.transport.protocol", "smtp");//發送使用的協議
properties.setProperty("mail.host", "smtp.163.com");//發送服務器的主機地址
properties.setProperty("mail.smtp.auth", "true");//請求身份驗證
Session session = Session.getDefaultInstance(properties);
MimeMessage message = new MimeMessage(session);//代表一封郵件
message.setFrom(new InternetAddress("[email protected]"));//設置發件人
message.setRecipients(RecipientType.TO, "[email protected]");//設置收件人
message.setSubject("這是JavaMail發出的第一封郵件");//設置主體
//設置郵件的正文內容
message.setText("嘿嘿!JavaMail發送的郵件哦");
message.saveChanges();
//發送郵件
Transport ts = session.getTransport();//得到火箭
ts.connect("zyliu1993","XXXX");//連接,注意這裏的密碼XXXXX是163郵箱的授權碼
ts.sendMessage(message, message.getAllRecipients());
ts.close();
}
}
附加:設置自定義發件人暱稱
//設置自定義發件人暱稱
String nick=javax.mail.internet.MimeUtility.encodeText("荊韻書香商城系統");//對中文進行編碼
message.setFrom(new InternetAddress(nick+"<[email protected]>"));//後面的發件人地址必須加,還必須對