邮件的发送与接收原理
邮件服务器和电子邮箱
要在Internet上提供电子邮件功能,必须有专门的电子邮件服务器。例如现在Internet很多提供邮件服务的厂商:sina、sohu、163等等他们都有自己的邮件服务器。
这些邮件服务器类似于现实生活中的邮局,它主要负责接收用户投递过来的邮件,并把邮件投递到邮件接收者的电子邮箱中。
电子邮箱(E-Mail地址)的获得需要在邮件服务器上进行申请,确切地说,电子邮箱其实就是用户在邮件服务器上申请的一个账户,用户在邮件服务器上申请了一个帐号后,邮件服务器就会为这个账号分配一定的空间,用户从而可以使用这个帐号以及空间发送电子邮件和保存别人发送过来的电子邮件。
邮件传输协议
在了解发送邮件的原理之前,先要知道两个协议,SMTP和POP3
SMTP协议
SMTP:Simple Mail Transfer Protocol,即简单邮件传输协议,发送邮件的协议,默认端口,25
用户连接上邮件服务器之后,要想给它发送一封电子邮件,需要遵循一定的通讯规则,SMTP协议就是用来定义这种通讯规则的。因此,我们通常也把处理用户smtp请求(邮件发送请求)的服务器称之为SMTP服务器(邮件发送服务器)。
POP3协议
POP3:Post Office Protocol 3,即邮局协议,接收邮件的协议,默认端口,110
同样,用户若想从邮件服务器管理的电子邮箱当中接收一封电子邮件话,它连上邮件服务器后,也要遵循一定的通讯格式,POP3协议就是用来定义这种通讯格式的。因此,我们通常也把处理用户pop3请求(邮件接收请求)的服务器称之为POP3服务器(邮件接收服务器)。
电子邮件的发送和接收过程
知道了这两个协议,下面来说说邮件发送和接收的原理图,分两种,相同邮件(QQ邮箱给QQ邮箱)和不同邮件(QQ邮箱给163邮箱)是不一样的。
为了方便起见,将新浪邮箱,list@sina.com称为用户A,将搜狐邮箱,wangwu@sohu.com 称为用户B
- 用户A(新浪邮箱,list@sina.com)给用户B(搜狐邮箱,wangwu@sohu.com)发送一封邮件,那么整个过程就为图中的实线部分,用户A通过OutLook(浏览器或者客户端)登录自己的邮箱帐号,编写邮件,使用Smtp协议发送给Sina的邮件服务器中的Smtp服务器(专门用来发送的服务器),然后在通过SMTP协议,传输给Sohu的邮件服务器中的Smtp服务器,然后通过Sohu的Smtp服务器将邮件发送给用户B的存储设备进行存储(每个用户都会有一个存储空间用来存储邮件的),到这里,用户A就相当于发送成功了,因为已经到达了目的地,如果B用户需要查看邮件内容,必须通过POP3服务器将从自己的存储设备中拿到,然后返回到浏览器或者客户端中显示。
- 用户B给用户A发送一封邮件,那么整个过程就为图中的虚线部分,是和A给B发一样的步骤
- 用户A给一个同样使用新浪邮箱的用户C发送一封邮件,那么其过程就简单的多了,先通过Smtp服务器,然后smtp服务器会将其发送到用户C的存储设备上,A发送邮件就成功了,用户C要显示自己邮箱中的邮件,那么就通过POP3服务器从自己存储设备中拿取所有邮件进行查看。
通过Java代码实现发送邮件
概述
我们将用代码完成邮件的发送。这在实际项目中应用的非常广泛,比如注册需要发送邮件进行账号激活,再比如OA项目中利用邮件进行任务提醒等等。
RFC882文档简单说明
RFC882文档规定了如何编写一封简单的邮件(纯文本邮件),一封简单的邮件包含邮件头和邮件体两个部分,邮件头和邮件体之间使用空行分隔。
邮件头包含的内容有:
- from字段? --用于指明发件人
- to字段? ????--用于指明收件人
- subject字段??--用于说明邮件主题
- cc字段? ???-- 抄送,将邮件发送给收件人的同时抄送给另一个收件人,收件人可以看到邮件抄送给了谁
- bcc字段? ?-- 密送,将邮件发送给收件人的同时将邮件秘密发送给另一个收件人,收件人无法看到邮件密送给了谁
邮件体指的就是邮件的具体内容。
准备jar包
核心:mail.jar
依赖:activation.jar, 邮件需要发送附件时使用
将jar包复制到项目的lib下(没有就手动创建)
然后再右键那个mail-1.4.7.jar包选择 add as library
使用qq邮箱发送邮件
QQ邮箱中获取对应的权限
QQ邮箱需要安全验证,我们需要获取他对应的权限;
QQ邮箱–>邮箱设置–>账户
简易文本邮件发送的实现
步骤:
1.创建session对象
2.创建Transport对象
3.使用邮箱的用户名和授权码连上邮件服务器
4.创建一个Message对象(需要传递session)
5.发送邮件
6.关闭连接 ![在这里插入图片描述](https://img-blog.csdnimg.cn/8f313393d45a47b7bc41f5ab45b844b5.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBASkTlvLrlrZA=,size_20,color_FFFFFF,t_70,g_se,x_16)
public class MailDemo01 {
public static void main(String[] args) throws Exception {
Properties prop=new Properties();
prop.setProperty("mail.host","smtp.qq.com");
prop.setProperty("mail.transport.protocol","smtp");
prop.setProperty("mail.smtp.auth","true");
MailSSLSocketFactory sf=new MailSSLSocketFactory();
sf.setTrustAllHosts(true);
prop.put("mail.smtp.ssl.enable","true");
prop.put("mail.smtp.ssl.socketFactory",sf);
Session session=Session.getDefaultInstance(prop, new Authenticator() {
@Override
public PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication("XXXX@qq.com","授权码");
}
});
session.setDebug(true);
Transport ts=session.getTransport();
ts.connect("smtp.qq.com","XXXX@qq.com","授权码");
MimeMessage message=new MimeMessage(session);
message.setFrom(new InternetAddress("XXXX@qq.com"));
message.setRecipient(Message.RecipientType.TO,new InternetAddress("XXXX@qq.com"));
message.setSubject("发送的标题");
message.setContent("内容","text/html;charset=UTF-8");
ts.sendMessage(message,message.getAllRecipients());
ts.close();
}
}
发送包含内嵌图片和附件的复杂邮件
在我们的实际开发当中,一封邮件既可能包含图片,又可能包含有附件,在这样的情况下,RFC882文档规定的邮件格式就无法满足要求了。
MIME(多用途互联网邮件扩展类型)
MIME协议是对RFC822文档的升级和补充,它描述了如何生产一封复杂的邮件。通常我们把MIME协议描述的邮件称之为MIME邮件。MIME协议描述的数据称之为MIME消息。 对于一封复杂邮件,如果包含了多个不同的数据,MIME协议规定了要使用分隔线对多段数据进行分隔,并使用Content-Type头字段对数据的类型、以及多个数据之间的关系进行描述。
JavaMail创建的邮件是基于MIME协议的。因此可以使用JavaMail创建出包含图片,包含附件的复杂邮件。
MimeBodyPart类
javax.mail.internet.MimeBodyPart类 表示的是一个MIME消息,它和MimeMessage类一样都是从Part接口继承过来。
MimeMultipart类
javax.mail.internet.MimeMultipart是抽象类 Multipart的实现子类,它用来组合多个MIME消息。一个MimeMultipart对象可以包含多个代表MIME消息的MimeBodyPart对象。
创建包含内嵌图片的邮件
前面的例子中是单独的使用HTML或者是纯文本内容,但是有时候我们需要在纯文本中使用内嵌的方式显示一些图片,因此就要将纯文本和内嵌图片单独存放在MimeBodyPart中然后再将其存放在一个Mimemultipart对象中即可。
public class SendImageEmail {
public static void main(String[] args) throws Exception {
Properties prop = new Properties();
prop.setProperty("mail.host", "smtp.qq.com"); 设置QQ邮件服务器
prop.setProperty("mail.transport.protocol", "smtp");
prop.setProperty("mail.smtp.auth", "true");
MailSSLSocketFactory sf = new MailSSLSocketFactory();
sf.setTrustAllHosts(true);
prop.put("mail.smtp.ssl.enable", "true");
prop.put("mail.smtp.ssl.socketFactory", sf);
Session session = Session.getDefaultInstance(prop, new Authenticator() {
public PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication("24736743@qq.com", "授权码");
}
});
session.setDebug(true);
Transport ts = session.getTransport();
ts.connect("smtp.qq.com", "24736743@qq.com", "授权码");
MimeMessage message = new MimeMessage(session);
message.setFrom(new InternetAddress("24736743@qq.com"));
message.setRecipient(Message.RecipientType.TO, new InternetAddress("24736743@qq.com"));
message.setSubject("带图片的邮件");
MimeBodyPart image = new MimeBodyPart();
DataHandler dh = new DataHandler(new FileDataSource("src/resources/bz.jpg"));
image.setDataHandler(dh);
image.setContentID("bz.jpg");
MimeBodyPart text = new MimeBodyPart();
text.setContent("这是一封邮件正文带图片<img src='cid:bz.jpg'>的邮件", "text/html;charset=UTF-8");
MimeMultipart mm = new MimeMultipart();
mm.addBodyPart(text);
mm.addBodyPart(image);
mm.setSubType("related");
message.setContent(mm);
message.saveChanges();
ts.sendMessage(message, message.getAllRecipients());
ts.close();
}
}
带图片和附件的复杂邮件发送
public class SendFileMail {
public static void main(String[] args) throws MessagingException, GeneralSecurityException {
Properties properties = new Properties();
properties.setProperty("mail.host","smtp.qq.com");
properties.setProperty("mail.transport.protocol","smtp");
properties.setProperty("mail.smtp.auth", "true");
MailSSLSocketFactory sf = new MailSSLSocketFactory();
sf.setTrustAllHosts(true);
properties.put("mail.smtp.ssl.enable", "true");
properties.put("mail.smtp.ssl.socketFactory", sf);
Session session = Session.getDefaultInstance(properties, new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication("24736743@qq.com", "授权码");
}
});
session.setDebug(true);
Transport tp = session.getTransport();
tp.connect("smtp.qq.com","24736743@qq.com","授权码");
MimeMessage mimeMessage = imageMail(session);
tp.sendMessage(mimeMessage,mimeMessage.getAllRecipients());
tp.close();
}
public static MimeMessage imageMail(Session session) throws MessagingException {
MimeMessage mimeMessage = new MimeMessage(session);
mimeMessage.setFrom(new InternetAddress("24736743@qq.com"));
mimeMessage.setRecipient(Message.RecipientType.TO, new InternetAddress("24736743@qq.com"));
mimeMessage.setSubject("我也不知道是个什么东西就发给你了");
MimeBodyPart body1 = new MimeBodyPart();
body1.setDataHandler(new DataHandler(new FileDataSource("src/resources/yhbxb.png")));
body1.setContentID("yhbxb.png");
MimeBodyPart body2 = new MimeBodyPart();
body2.setContent("请注意,我不是广告<img src='cid:yhbxb.png'>","text/html;charset=utf-8");
MimeBodyPart body3 = new MimeBodyPart();
body3.setDataHandler(new DataHandler(new FileDataSource("src/resources/log4j.properties")));
body3.setFileName("log4j.properties");
MimeBodyPart body4 = new MimeBodyPart();
body4.setDataHandler(new DataHandler(new FileDataSource("src/resources/1.txt")));
body4.setFileName("");
MimeMultipart multipart1 = new MimeMultipart();
multipart1.addBodyPart(body1);
multipart1.addBodyPart(body2);
multipart1.setSubType("related");
MimeBodyPart contentText = new MimeBodyPart();
contentText.setContent(multipart1);
MimeMultipart allFile =new MimeMultipart();
allFile.addBodyPart(body3);
allFile.addBodyPart(body4);
allFile.addBodyPart(contentText);
allFile.setSubType("mixed");
mimeMessage.setContent(allFile);
mimeMessage.saveChanges();
return mimeMessage;
}
}
|