邮件详解
邮件协议
1 收发邮件
发邮件是从客户端把邮件发送到邮件服务器,收邮件是把邮件服务器的邮件下载到客户端。我们在163、126、QQ、sohu、sina等网站注册的Email账户,其实就是在邮件服务器中注册的。这些网站都有自己的邮件服务器。
2 邮件协议概述
与HTTP协议相同,收发邮件也是需要有传输协议的。
SMTP:(Simple Mail Transfer Protocol,简单邮件传输协议)发邮件协议;
POP3:(Post Office Protocol Version 3,邮局协议第3版)收邮件协议;
IMAP:(Internet Message Access Protocol,因特网消息访问协议)收发邮件协议。
3 理解邮件收发过程
其实你可以把邮件服务器理解为邮局!如果你需要给朋友寄一封信,那么你需要把信放到邮筒中,这样你的信会“自动”到达邮局,邮局会把信邮到另一个省市的邮局中。然后这封信会被送到收信人的邮箱中。最终收信人需要自己经常查看邮箱是否有新的信件。
其实每个邮件服务器都由SMTP服务器和POP3服务器构成,其中SMTP服务器负责发邮件的请求,而POP3负责收邮件的请求。当然,有时我们也会使用163的账号,向126的账号发送邮件。这时邮件是发送到126的邮件服务器,而对于163的邮件服务器是不会存储这封邮件的。
4 邮件服务器名称
smtp服务器的端口号为25,服务器名称为smtp.xxx.xxx。
pop3服务器的端口号为110,服务器名称为pop3.xxx.xxx。
例如:
163:smtp.163.com和pop3.163.com;
126:smtp.126.com和pop3.126.com;
qq:smtp.qq.com和pop3.qq.com;
sohu:smtp.sohu.com和pop3.sohu.com;
JavaMail
1 JavaMail概述
Java Mail是由SUN公司提供的专门针对邮件的API,主要Jar包:mail.jar、activation.jar。
在使用MyEclipse创建web项目时,需要小心!如果只是在web项目中使用java mail是没有什么问题的,发布到Tomcat上运行一点问题都没有!但是如果是在web项目中写测试那就出问题了。在MyEclipse中,会自动给web项目导入javax.mail包中的类,但是不全(其实是只有接口,而没有接口的实现类),所以只靠MyEclipse中的类是不能运行java mail项目的,但是如果这时你再去自行导入mail.jar时,就会出现冲突。
处理方案:到下面路径中找到javaee.jar文件,把javax.mail删除!!!
D:\myeclipse\Common\plugins\com.genuitec.eclipse.j2eedt.core_10.0.0.me201110301321\data\libraryset\EE_5
2 JavaMail中主要类
java mail中主要类:javax.mail.Session、javax.mail.internet.MimeMessage、javax.mail.Transport。
Session:表示会话,即客户端与邮件服务器之间的会话!想获得会话需要给出账户和密码,当然还要给出服务器名称。在邮件服务中的Session对象,就相当于连接数据库时的Connection对象。
MimeMessage:表示邮件类,它是Message的子类。它包含邮件的主题(标题)、内容,收件人地址、发件人地址,还可以设置抄送和暗送,甚至还可以设置附件。
Transport:用来发送邮件。它是发送器!
3 JavaMail之Hello World
在使用telnet发邮件时,还需要自己来处理Base64编码的问题,但使用JavaMail就不必理会这些问题了,都由JavaMail来处理。
第一步:获得Session
Session session = Session.getInstance(Properties prop, Authenticator auth); //其中prop需要指定两个键值,一个是指定服务器主机名,另一个是指定是否需要认证!我们当然需要认证! Properties prop = new Properties(); prop.setProperty(“mail.host”, “smtp.163.com”);//设置服务器主机名 prop.setProperty(“mail.smtp.auth”, “true”);//设置需要认证 //其中Authenticator是一个接口表示认证器,即校验客户端的身份。我们需要自己来实现这个接口,实现这个接口需要使用账户和密码。 Authenticator auth = new Authenticator() { public PasswordAuthentication getPasswordAuthentication () { new PasswordAuthentication(“xxx”, “yyy”);//用户名和密码,该密码为授权码 } }; //通过上面的准备,现在可以获取得Session对象了: Session session = Session.getInstance(prop, auth);
第二步:创建MimeMessage对象
//创建MimeMessage需要使用Session对象来创建: MimeMessage msg = new MimeMessage(session); //然后需要设置发信人地址、收信人地址、主题,以及邮件正文。 msg.setFrom(new InternetAddress(“xxx@163.com”));//设置发信人 msg.addRecipients(RecipientType.TO, “yyy1@qq.com,yyy2@sina.com”);//设置多个收信人 msg.addRecipients(RecipientType.CC, “zzz1@sohu.com,zzz2@126.com”);//设置多个抄送 msg.addRecipients(RecipientType.BCC, ”kkk@163.com”);//设置暗送 msg.setSubject(“测试邮件”);//设置主题(标题) msg.setContent(“hello world!”, “text/plain;charset=utf-8”);//设置正文
第三步:发送邮件
Transport.send(msg);//发送邮件
4 JavaMail发送带有附件的邮件(了解)
一封邮件可以包含正文、附件N个,所以正文与N个附件都是邮件的一个部份。
上面的hello world案例中,只是发送了带有正文的邮件!所以在调用setContent()方法时直接设置了正文,如果想发送带有附件邮件,那么需要设置邮件的内容为MimeMultiPart。
MimeMulitpart parts = new MimeMulitpart();//多部件对象,可以理解为是部件的集合 msg.setContent(parts);//设置邮件的内容为多部件内容。 //然后我们需要把正文、N个附件创建为“主体部件”对象(MimeBodyPart),添加到MimeMuiltPart中即可。 MimeBodyPart part1 = new MimeBodyPart();//创建一个部件 part1.setCotnent(“这是正文部分”, “text/html;charset=utf-8”);//给部件设置内容 parts.addBodyPart(part1);//把部件添加到部件集中。 //下面我们创建一个附件: MimeBodyPart part2 = new MimeBodyPart();//创建一个部件 part2.attachFile(“F:/Lebron.jpeg”);//设置附件 part2.setFileName(“hello.jpg”);//设置附件名称 parts.addBodyPart(part2);//把附件添加到部件集中 //注意,如果在设置文件名称时,文件名称中包含了中文的话,那么需要使用MimeUitlity类来给中文编码: //part2.setFileName(MimeUitlity.encodeText(“美女.jpg”));
应用实例1(普通方式发送):
1 import java.io.File; 2 import java.util.Properties; 3 import javax.mail.Authenticator; 4 import javax.mail.Message.RecipientType; 5 import javax.mail.PasswordAuthentication; 6 import javax.mail.Session; 7 import javax.mail.Transport; 8 import javax.mail.internet.InternetAddress; 9 import javax.mail.internet.MimeBodyPart; 10 import javax.mail.internet.MimeMessage; 11 import javax.mail.internet.MimeMultipart; 12 import javax.mail.internet.MimeUtility; 13 import org.junit.Test; 14 public class Demo1 { 15 //发送普通邮件 16 @Test 17 public void fun1() throws Exception { 18 //1. 得到session 19 Properties props = new Properties(); 20 props.setProperty("mail.host", "smtp.163.com"); 21 props.setProperty("mail.smtp.auth", "true"); 22 Authenticator auth = new Authenticator() { 23 @Override 24 protected PasswordAuthentication getPasswordAuthentication() { 25 return new PasswordAuthentication("xxx", "yyy");//注意:该密码为授权码 26 } 27 }; 28 Session session = Session.getInstance(props, auth); 29 //2. 创建MimeMessage 30 MimeMessage msg = new MimeMessage(session); 31 msg.setFrom(new InternetAddress("xxx@163.com"));//设置发件人 32 msg.setRecipients(RecipientType.TO, "zzz@qq.com");//设置收件人 33 msg.setSubject("测试邮件"); 34 msg.setContent("hello world!", "text/html;charset=utf-8"); 35 //3. 发 36 Transport.send(msg); 37 } 38 //带有附件的邮件 39 @Test 40 public void fun2() throws Exception { 41 //1. 得到session 42 Properties props = new Properties(); 43 props.setProperty("mail.host", "smtp.163.com"); 44 props.setProperty("mail.smtp.auth", "true"); 45 Authenticator auth = new Authenticator() { 46 @Override 47 protected PasswordAuthentication getPasswordAuthentication() { 48 return new PasswordAuthentication("xxx", "yyy"); 49 } 50 }; 51 Session session = Session.getInstance(props, auth); 52 //2. 创建MimeMessage 53 MimeMessage msg = new MimeMessage(session); 54 msg.setFrom(new InternetAddress("xxx@163.com"));//设置发件人 55 msg.setRecipients(RecipientType.TO, "zzz@qq.com");//设置收件人 56 msg.setSubject("测试邮件有附件"); 57 /* 58 * 当发送包含附件的邮件时,邮件体就为多部件形式! 59 * 1. 创建一个多部件的部件内容!MimeMultipart 60 * MimeMultipart就是一个集合,用来装载多个主体部件! 61 * 2. 我们需要创建两个主体部件,一个是文本内容的,另一个是附件的。 62 * 主体部件叫MimeBodyPart 63 * 3. 把MimeMultipart设置给MimeMessage的内容! 64 */ 65 MimeMultipart list = new MimeMultipart();//创建多部分内容 66 // 创建MimeBodyPart 67 MimeBodyPart part1 = new MimeBodyPart(); 68 // 设置主体部件的内容 69 part1.setContent("这是一封包含附件的邮件", "text/html;charset=utf-8"); 70 // 把主体部件添加到集合中 71 list.addBodyPart(part1); 72 // 创建MimeBodyPart 73 MimeBodyPart part2 = new MimeBodyPart(); 74 part2.attachFile(new File("F:/Lebron.jpeg"));//设置附件的内容 75 part2.setFileName(MimeUtility.encodeText("篮球明星.jpg"));//设置显示的文件名称,其中encodeText用来处理中文乱码问题 76 list.addBodyPart(part2); 77 msg.setContent(list);//把它设置给邮件作为邮件的内容。 78 //3. 发 79 Transport.send(msg); 80 } 81 }
应用实例2(封装工具类方式发送):
1 import java.io.File; 2 import javax.mail.Session; 3 import org.junit.Test; 4 public class Demo2 { 5 @Test 6 public void fun3() throws Exception { 7 //1. 得到session 8 Session session = MailUtils.createSession("smtp.163.com", 9 "xxx", "yyy"); 10 //2. 创建邮件对象 11 Mail mail = new Mail("xxx@163.com", 12 "zzz@qq.com", 13 "测试邮件", "正文"); 14 //创建两个附件对象 15 AttachBean ab1 = new AttachBean(new File("F:/Lebron.jpeg"), "小美女.jpg"); 16 AttachBean ab2 = new AttachBean(new File("F:/big.jpg"), "衣服.jpg"); 17 // 添加到mail中 18 mail.addAttach(ab1); 19 mail.addAttach(ab2); 20 //3. 发送 21 MailUtils.send(session, mail); 22 } 23 }
1 import java.io.File; 2 3 /* 4 * 附件类,只有文件,即附件才文件名 5 */ 6 public class AttachBean { 7 private String cid; 8 private File file; 9 private String fileName; 10 11 public String getCid() { 12 return cid; 13 } 14 15 public void setCid(String cid) { 16 this.cid = cid; 17 } 18 19 public File getFile() { 20 return file; 21 } 22 23 public void setFile(File file) { 24 this.file = file; 25 } 26 27 public String getFileName() { 28 return fileName; 29 } 30 31 public void setFileName(String fileName) { 32 this.fileName = fileName; 33 } 34 35 public AttachBean() { 36 37 } 38 39 public AttachBean(File file, String fileName) { 40 super(); 41 this.file = file; 42 this.fileName = fileName; 43 } 44 }
1 import java.util.ArrayList; 2 import java.util.List; 3 4 /** 5 * 表示邮件类,你需要设置:账户名和密码、收件人、抄送(可选)、暗送(可选)、主题、内容,以及附件(可选) 6 * 7 * 在创建了Mail对象之后 8 * 可以调用它的setSubject()、setContent(),设置主题和正文 9 * 也可以调用setFrom()和 addToAddress(),设置发件人,和添加收件人。 10 * 也可以调用addAttch()添加附件 11 * 创建AttachBean:new AttachBean(new File("..."), "fileName"); 12 */ 13 public class Mail { 14 private String from;//发件人 15 private StringBuilder toAddress = new StringBuilder();//收件人 16 private StringBuilder ccAddress = new StringBuilder();//抄送 17 private StringBuilder bccAddress = new StringBuilder();//暗送 18 19 private String subject;//主题 20 private String content;//正文 21 22 // 附件列表 23 private List<AttachBean> attachList = new ArrayList<AttachBean>(); 24 25 public Mail() {} 26 27 public Mail(String from, String to) { 28 this(from, to, null, null); 29 } 30 31 public Mail(String from, String to, String subject, String content) { 32 this.from = from; 33 this.toAddress.append(to); 34 this.subject = subject; 35 this.content = content; 36 } 37 38 /** 39 * 返回发件人 40 * @return 41 */ 42 public void setFrom(String from) { 43 this.from = from; 44 } 45 46 /** 47 * 返回发件人 48 * @return 49 */ 50 public String getFrom() { 51 return from; 52 } 53 54 /** 55 * 返回主题 56 */ 57 public String getSubject() { 58 return subject; 59 } 60 61 /** 62 * 设置主题 63 */ 64 public void setSubject(String subject) { 65 this.subject = subject; 66 } 67 68 /** 69 * 获取主题内容 70 */ 71 public String getContent() { 72 return content; 73 } 74 75 /** 76 * 设置主题内容 77 * @param content 78 */ 79 public void setContent(String content) { 80 this.content = content; 81 } 82 83 /** 84 * 获取收件人 85 * @return 86 */ 87 public String getToAddress() { 88 return toAddress.toString(); 89 } 90 91 /** 92 * 获取抄送 93 * @return 94 */ 95 public String getCcAddress() { 96 return ccAddress.toString(); 97 } 98 99 /** 100 * 获取暗送 101 * @return 102 */ 103 public String getBccAddress() { 104 return bccAddress.toString(); 105 } 106 107 /** 108 * 添加收件人,可以是多个收件人 109 * @param to 110 */ 111 public void addToAddress(String to) { 112 if(this.toAddress.length() > 0) { 113 this.toAddress.append(","); 114 } 115 this.toAddress.append(to); 116 } 117 118 /** 119 * 添加抄送人,可以是多个抄送人 120 * @param cc 121 */ 122 public void addCcAddress(String cc) { 123 if(this.ccAddress.length() > 0) { 124 this.ccAddress.append(","); 125 } 126 this.ccAddress.append(cc); 127 } 128 129 /** 130 * 添加暗送人,可以是多个暗送人 131 * @param bcc 132 */ 133 public void addBccAddress(String bcc) { 134 if(this.bccAddress.length() > 0) { 135 this.bccAddress.append(","); 136 } 137 this.bccAddress.append(bcc); 138 } 139 140 /** 141 * 添加附件,可以添加多个附件 142 * @param attachBean 143 */ 144 public void addAttach(AttachBean attachBean) { 145 this.attachList.add(attachBean); 146 } 147 148 /** 149 * 获取所有附件 150 * @return 151 */ 152 public List<AttachBean> getAttachs() { 153 return this.attachList; 154 } 155 }
1 import java.io.IOException; 2 import java.util.List; 3 import java.util.Properties; 4 5 import javax.mail.Authenticator; 6 import javax.mail.Message.RecipientType; 7 import javax.mail.MessagingException; 8 import javax.mail.PasswordAuthentication; 9 import javax.mail.Session; 10 import javax.mail.Transport; 11 import javax.mail.internet.InternetAddress; 12 import javax.mail.internet.MimeBodyPart; 13 import javax.mail.internet.MimeMessage; 14 import javax.mail.internet.MimeMultipart; 15 import javax.mail.internet.MimeUtility; 16 17 /** 18 * 本类只有这么一个方法,用来发邮件! 19 */ 20 public class MailUtils { 21 public static Session createSession(String host, final String username, final String password) { 22 Properties prop = new Properties(); 23 prop.setProperty("mail.host", host);// 指定主机 24 prop.setProperty("mail.smtp.auth", "true");// 指定验证为true 25 26 // 创建验证器 27 Authenticator auth = new Authenticator() { 28 public PasswordAuthentication getPasswordAuthentication() { 29 return new PasswordAuthentication(username, password); 30 } 31 }; 32 33 // 获取session对象 34 return Session.getInstance(prop, auth); 35 } 36 37 /** 38 * 发送指定的邮件 39 * 40 * @param mail 41 */ 42 public static void send(Session session, final Mail mail) throws MessagingException, 43 IOException { 44 45 MimeMessage msg = new MimeMessage(session);// 创建邮件对象 46 msg.setFrom(new InternetAddress(mail.getFrom()));// 设置发件人 47 msg.addRecipients(RecipientType.TO, mail.getToAddress());// 设置收件人 48 49 // 设置抄送 50 String cc = mail.getCcAddress(); 51 if (!cc.isEmpty()) { 52 msg.addRecipients(RecipientType.CC, cc); 53 } 54 55 // 设置暗送 56 String bcc = mail.getBccAddress(); 57 if (!bcc.isEmpty()) { 58 msg.addRecipients(RecipientType.BCC, bcc); 59 } 60 61 msg.setSubject(mail.getSubject());// 设置主题 62 63 MimeMultipart parts = new MimeMultipart();// 创建部件集对象 64 65 MimeBodyPart part = new MimeBodyPart();// 创建一个部件 66 part.setContent(mail.getContent(), "text/html;charset=utf-8");// 设置邮件文本内容 67 parts.addBodyPart(part);// 把部件添加到部件集中 68 69 /////////////////////////////////////////// 70 71 // 添加附件 72 List<AttachBean> attachBeanList = mail.getAttachs();// 获取所有附件 73 if (attachBeanList != null) { 74 for (AttachBean attach : attachBeanList) { 75 MimeBodyPart attachPart = new MimeBodyPart();// 创建一个部件 76 attachPart.attachFile(attach.getFile());// 设置附件文件 77 attachPart.setFileName(MimeUtility.encodeText(attach 78 .getFileName()));// 设置附件文件名 79 String cid = attach.getCid(); 80 if(cid != null) { 81 attachPart.setContentID(cid); 82 } 83 parts.addBodyPart(attachPart); 84 } 85 } 86 87 msg.setContent(parts);// 给邮件设置内容 88 Transport.send(msg);// 发邮件 89 } 90 }