一、邮件相关基本概念
a)邮件服务器:某厂商提供的电子邮件服务器的集群(或群集)
b)电子邮箱:邮件服务器上提供的个人或企业的邮件空间
c)邮件传输协议:邮件服务器之间,和个人或企业与邮件服务器之间传递或接收邮件的规则
发送:SMTP协议 --- 简单邮件传输协议。
接收:POP3协议
创建邮件:MIME协议
d)电子邮件的发送和接收过程
补充:卸载,安装和配置易邮服务器(包含 SMTP邮件发送服务器(端口号:25), P0P3邮件接收服务器(端口号:110)),并进行手工发送接收邮件
二、加密与解密算法
一】Base64算法,Sun公司提供.Mail专用。
核心类:BASE64Encoder类 、BASE64Decoder类
code:
//加密 String username = "jack"; String password = "123456"; BASE64Encoder encoder = new BASE64Encoder(); username = encoder.encode(username.getBytes()); password = encoder.encode(password.getBytes()); System.out.println(username + " : " + password); //解密 BASE64Decoder decoder = new BASE64Decoder(); byte[] userbuf = decoder.decodeBuffer(username); byte[] pswbuf = decoder.decodeBuffer(password); username = new String(userbuf, "UTF-8"); password = new String(pswbuf, "UTF-8"); System.out.println(username + " : " + password);
二】通过Socket类来发送接收邮件
//客户端发送邮件 public class Demo2 { public static void main(String[] args) throws Exception{ //参数一:表示易邮服务器位于的IP地址 //参数二:SMTP邮件发送服务器的固定端口 Socket s = new Socket("127.0.0.1",25); //构造行字符读入流 BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream())); //构造字节输出流 OutputStream os = s.getOutputStream(); System.out.println(br.readLine()); os.write("ehlo zhaojun ".getBytes()); System.out.println(br.readLine()); System.out.println(br.readLine()); os.write("auth login ".getBytes()); System.out.println(br.readLine()); os.write("YWFhQHpoYW9qdW4uY29t ".getBytes());//用户名 System.out.println(br.readLine()); os.write("MTIzNDU2 ".getBytes());//密码 System.out.println(br.readLine()); os.write("mail from:<aaa@zhaojun.com> ".getBytes()); System.out.println(br.readLine()); os.write("rcpt to:<bbb@qq.com> ".getBytes()); System.out.println(br.readLine()); os.write("data ".getBytes()); System.out.println(br.readLine()); os.write("from:aaa@zhaojun.com ".getBytes()); os.write("to:bbb@qq.com ".getBytes()); os.write("subject:test ".getBytes()); os.write("Hello! How are you doing! ".getBytes()); os.write(". ".getBytes()); System.out.println(br.readLine()); os.write("quit ".getBytes()); //关闭流 os.close(); br.close(); } }
三、协议:
一】SMTP协议:用于发送邮件。
ehlo: 主机名
auth login: 经过base64编码后的用户名和密码
mail from: <from@skygao.com>
rcpt to: <to@skygao.com>
data: 发送的邮件内容。 (.号代表邮件内容的结束。)
二】P0P3协议:用于接收邮件。
user: username(明文)
pass: password (明文)
stat: 返回邮箱的统计信息(字节数)
list: 返回某一封邮箱的统计信息。
retr: 显示某一封邮件的信息
quit: 退出
三】MIME协议:用于创建邮件。
MimeBodyPart:表示复杂邮件的一个组成部分,它可以表示文本,附件,图片
DataHandler:表示可以读取图片或附件
MimeMultipart:表示二个邮件组成部分的关系,文本和图片的关系是"related"关系,文本和附件的关系是"mixed"关系,即默认
Content-ID:表示图片的编号.
Content-Type: 文本内容。
Content-Dispostion头:有附件。
**注意:MimeMultipart加入的顺利与邮件显示附件的顺序无关
四、 基于JavaMail创建邮件
核心类:
MimeMessage:表示整封邮件对象。
MimeBodyPart:表示邮件的一个Mime消息,即:一部分内容。
MimeMultiPart:表示由一个或多个MimeBodyPart组合成的Mime消息。
a)简单邮件
MimeMessage:表示一个符合MIME协议的邮件
InternetAddress:表示电子邮件地址
RecipientType.TO:表示发送邮件的类型:例如TO(目标),CC(明抄送),BCC(密送)
简单邮件只含有文本
Content-Type:文本类型
code:
public class SimpleEmailDemo { public static void main(String[] args) throws AddressException, MessagingException, FileNotFoundException, IOException { //创建邮件对象 MimeMessage message = new MimeMessage(Session.getDefaultInstance(new Properties())); //设置From message.setFrom(new InternetAddress("jack@skygao.com")); //设置to message.setRecipient(RecipientType.TO, new InternetAddress("merry@skygao.com")); //设置subject属性 message.setSubject("comment text"); //设置Content属性 message.setContent("Today is fine day!", "text/html;charset=UTF-8"); //将该邮件保存到硬盘 message.writeTo(new FileOutputStream("D:\simpleEmail.eml")); } }
b)复杂邮件
文本+图片
code:
public class TextImgEmailDemo { public static void main(String[] args) throws AddressException, MessagingException, FileNotFoundException, IOException { //创建邮件 MimeMessage message = new MimeMessage(Session.getDefaultInstance(new Properties())); //设置From属性 message.setFrom(new InternetAddress("jack@skygao.com")); //设置To属性 message.setRecipient(RecipientType.TO, new InternetAddress("merry@skygao.com")); //设置Subject属性 message.setSubject("Text And Image Email"); //创建文本Text部分对象 MimeBodyPart textPart = new MimeBodyPart(); textPart.setContent("this is a picture<br/> <img src='cid:imageID'/>", "text/html;chartset=UTF-8"); //创建图片Img部分对象 MimeBodyPart imgPart = new MimeBodyPart(); //读取img.jpg图片 DataHandler handler = new DataHandler(new FileDataSource("src\com\ccst\email\test.jpg")); imgPart.setDataHandler(handler); //为图片设置一个唯一ID imgPart.setContentID("imageID"); //设置文本Text和图片Img的关系-->依赖关系: related MimeMultipart mm = new MimeMultipart(); mm.addBodyPart(textPart); mm.addBodyPart(imgPart); mm.setSubType("related"); //将内容放入邮件中 message.setContent(mm); message.writeTo(new FileOutputStream("D:\textImgEmail.eml")); } }
文本+附件
MimeMultipart:表示二个邮件组成部分的关系,文本和附件的关系是"mixed"关系,即默认
MimeMultipart加入的顺利与邮件显示附件的顺序无关
code:
public class TextAttachEmailDemo { public static void main(String[] args) throws AddressException, MessagingException, FileNotFoundException, IOException { //创建邮件对象 MimeMessage message = new MimeMessage(Session.getDefaultInstance(new Properties())); //设置From message.setFrom(new InternetAddress("jack@skygao.com")); //设置To message.setRecipient(RecipientType.TO, new InternetAddress("merry@skygao.com")); //设置Subject message.setSubject("text and attach"); //设置Content //创建文本Text部分 MimeBodyPart textPart = new MimeBodyPart(); textPart.setContent("text and attach email", "text/html;charset=UTF-8"); //附件1 //创建附件Attach部分 MimeBodyPart attPart1 = new MimeBodyPart(); //创建数据对象 DataHandler dh1 = new DataHandler(new FileDataSource("src\com\ccst\email\FastStoneCapturecn.zip")); attPart1.setDataHandler(dh1); //设置附件1的名称 attPart1.setFileName(dh1.getName()); //附件2 //创建附件Attach部分 MimeBodyPart attPart2 = new MimeBodyPart(); //创建数据对象 DataHandler dh2 = new DataHandler(new FileDataSource("src\com\ccst\email\Momentum_v0.31.crx")); attPart2.setDataHandler(dh2); //设置附件2的名称 attPart2.setFileName(dh2.getName()); //合并文字Text和两附件,顺序无影响.可以将MimeMultipart看成一个容器 MimeMultipart mm = new MimeMultipart(); mm.addBodyPart(textPart); mm.addBodyPart(attPart1); mm.addBodyPart(attPart2); mm.setSubType("mixed");//此句可省略。因为mixed为默认关系。 //将Mime协议的内容放入到邮件对象中 message.setContent(mm); message.writeTo(new FileOutputStream(new File("D:\textAttachEmail.eml"))); } }
**注意:位置关系特别注意和加入的顺利要一致
文本+图片+附件(将Text和Img看成一个部分:MimeBodyPart)
code:
public class TextImgAttachEmailDemo { public static void main(String[] args) throws MessagingException, FileNotFoundException, IOException { //创建邮箱对象 MimeMessage message = new MimeMessage(Session.getDefaultInstance(new Properties())); //创建文本部分 MimeBodyPart textPart = new MimeBodyPart(); textPart.setContent("this is a picture<br/> <img src='cid:imgID'/>", "text/html;charset=UTF-8"); //创建图片部分 MimeBodyPart imgPart = new MimeBodyPart(); DataHandler dh = new DataHandler(new FileDataSource("src\com\ccst\email\test.jpg")); imgPart.setDataHandler(dh); imgPart.setContentID("imgID"); //组合文本、图片部分 MimeMultipart textImgMM = new MimeMultipart(); textImgMM.addBodyPart(imgPart); textImgMM.addBodyPart(textPart); textImgMM.setSubType("related"); //将文本、图片部分作为消息一部分 MimeBodyPart commPart = new MimeBodyPart(); commPart.setContent(textImgMM); //创建附件部分 MimeBodyPart attPart = new MimeBodyPart(); DataHandler attDh = new DataHandler(new FileDataSource("src\com\ccst\email\FastStoneCapturecn.zip")); attPart.setDataHandler(attDh); attPart.setFileName(attDh.getName()); //将文本、图片组合体 与 附件部分组合成MIME消息内容 MimeMultipart totalMM = new MimeMultipart(); totalMM.addBodyPart(commPart); totalMM.addBodyPart(attPart); totalMM.setSubType("mixed"); //将内容加入邮件对象 message.setContent(totalMM); //保存邮件 message.writeTo(new FileOutputStream(new File("D:\totalEmail.eml"))); } }
文本+附件+图片(将Text和Attach看成一个部分:MimeBodyPart)
(与上同理。略)
**注意:对于,复杂类型的邮件,位置关系特别注意和加入的顺利要一致
数据的关系如下:
multipart/related图片、 multipart/mixed(附件)、
multipart/form-data(上传文件)
4 如何解决邮件中的乱码问题
(1)主题:不存在乱码问题
(2)正文:
text.setContent("这是一副<br/><img src='cid:imageID'/><br/>图片<br/>","text/html;charset=UTF-8");
(3)附件名:(dh.getName()的时候不是乱码,set的时候才产生乱码)
append.setFileName(MimeUtility.encodeText(dh.getName()));
5 解决平台冲突,使用JavaEE1.4 + activation.jar + mail.jar
a)在JavaSE,即非Web应用中,JavaEE5/6平台中的mail包有冲突问题
b)JavaEE1.4 + activation.jar(支持) + mail.jar(核心)
c)对于Web应用,不存在以上冲突问题
*6 基于JavaMail发送邮件
Session:客户端和邮件服务器之间的环境信息
Transport:客户端和邮件服务器之间的传递对象
Message:表示邮件
code:
public class SendDemo1 { public static void main(String[] args) throws Exception { // 1, 创建Session对象 Properties props = new Properties(); props.put("mail.transport.protocol", "smtp");// 指明协议,为smtp发送协议,若接收邮件则为pop3协议 props.put("mail.host", "127.0.0.1");// 指明接收放ip Session session = Session.getDefaultInstance(props); // 2, 通过Session获得Transport对象 Transport transport = session.getTransport(); // 3, 创建邮件对象Message Message message = createMessage(session); // 4, 连接邮件发送服务器 transport.connect(); // 5, 发送邮件 transport.send(message); // 6, 关闭邮件传输流对象 transport.close(); } private static Message createMessage(Session session) throws Exception { MimeMessage message = new MimeMessage(session); // 设置From message.setFrom(new InternetAddress("jack@skygao.com")); // 设置to message.setRecipient(RecipientType.TO, new InternetAddress("merry@skygao.com")); message.setSubject("BBS论坛"); message.setContent("恭喜你注册成功!", "text/html;charset=UTF-8"); return message; } }
*7 基于Web应用的邮件发送功能
a)对于二个不相干的操作,可以使用线程方式来处理
补充: 手工发送、接收邮件的步骤:
WindowXP平台下,进入cmd命令状态:
------------------------------------jack@skygao.com向merry@skygao.com手工发送邮件
不相同域:
telnet 127.0.0.1 25(SMTP服务器端口)<回车>
ehlo skygao<回车
>
auth login<回车>
YWFhQHpoYW9qdW4uY29t(jack@skygao.com)<回车>
MTIzNDU2(123456)<回车>
mail from:<jack@skygao.com><回车>
rcpt to:<merry@qq.com><回车>
data<回车>
from:jack@skygao.com<回车>
to:merry@qq.com<回车>
subject:test<回车>
Hello! How are you doing!<回车>
.<回车>
quit<回车>
------------------------------------merry@skygao.com手工接收邮件
相同域
telnet 127.0.0.1 110(POP3服务器端口)<回车>
user merry<回车>
pass 123456<回车>
stat<回车>可选
list 2<回车>可选
retr 2<回车>
quit<回车>
不同域
telnet 127.0.0.1 110(POP3服务器端口)<回车>
user merry@qq.com<回车>
pass 123456<回车>
stat<回车>可选
list 2<回车>可选
retr 2<回车>
quit<回车>
------------------------------------sina发/收邮件地址
stmp.sina.com(邮件发送服务器)
pop.sina.com(邮件接收服务器)
telnet smtp.sohu.com 25
telnet pop.sina.com 110