一、邮件服务器和电子邮箱
邮件服务器:要在 Internet 上提供电子邮件功能,必须有专门的电子邮件服务器。这些服务器类似于现实生活中的邮局,它主要负责接收用户投递回来的邮件,并把邮件投递到邮件接收者的电子邮箱中。
电子邮箱:其实就是用户在邮件服务器上申请的一个账户,邮件服务器为这个账户分配一定的空间,用户从而可以使用这个帐号以及空间发送和保存别人发送来的电子邮件。
二、SMTP协议和 POP3协议
1、用户连接上邮件服务器以后,要想给它发送一封电子邮件,需要遵循一定的通讯规则,SMTP 协议就是用于定义这种通讯规则的。因而我们也把处理 SMTP 邮件发送请求的邮件服务器称为 SMTP 服务器。在 25 号端口上运行。
2、用户若想从邮件服务器管理的电子邮箱中接收一封电子邮件,在他连上邮件服务器以后,也要遵循一定的通讯格式,POP3 协议用于定义这种通讯格式。通常我们把处理用户 POP3 邮件接收请求的邮件服务器称为 POP3 服务器。在 110 号端口上运行。
3、RFC822 文档:RFC822文档规定了如何编写一封简单邮件。邮件头和邮件体使用空行分隔。邮件头:from、to、subject、cc、bcc(cc代表抄送,bcc代表暗送)
用户根据 smtp 协议的格式将邮件发送给新浪的 smtp 服务器。
新浪的 smtp 服务器检查该邮件是否属于自己的服务器管理,如果不是,则还以 smtp 方式就秒年个 邮件转投给 sohu 的 smtp 服务器。
sohu 的 smtp 服务器将该邮件存储到用户的电子邮箱空间中。
收信用户以 POP3 协议的格式请求服务器。
sohu 中的 POP3 服务器接收到请求,验证后,将用户的电子邮件以 POP3 协议形式回送给用户。
注:(sina 和 sohu 之间的交互:两台邮件服务器之间的交互是不需要用户名、密码等信息的,在 sina 以 smtp 协议将用户邮件转投给 sohu 时,会在 ehlo头字段中增加 smtp.sina.com 的信息,表明来者不是客户,是一个邮件服务器。当 sohu 中的 smtp 服务器接收到请求的时候,sohu 服务器会从 DNS 中调取 smtp.sina.com 的 A 记录,来核实来访者的 IP ,如果匹配则不需要登录,直接收取邮件,否则让用户登录。当 sina 中的 smtp 服务器收到邮件时,发现要转投给 sohu 那么 sina 服务器会在 DNS 中查找 sohu 的 Mx 记录,找到 sohu 服务器的位置,通过查到的 IP 将邮件转投给 sohu)
编写发送和接受邮件的 Socket 程序
package cn.dk.mail;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
public class Telnet {
public static void main(String[] args) throws UnknownHostException,
IOException {
Socket socket = new Socket("smtp.qq.com", 25);//pop.qq.com 110
Thread t1 = new Thread(new Send(socket));
Thread t2 = new Thread(new Receive(socket));
t2.start();
t1.start();
}
}
class Send implements Runnable {
private Socket socket;
public Send(Socket socket) {
this.socket = socket;
}
public void run() {
while (true) {
try {
OutputStream outputStream = socket.getOutputStream();
InputStream ir = System.in;
byte[] b = new byte[1024];
int len = 0;
while ((len = ir.read(b)) != -1) {
outputStream.write(b, 0, len);
}
ir.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
class Receive implements Runnable {
private Socket socket;
public Receive(Socket socket) {
this.socket = socket;
}
public void run() {
while (true) {
try {
InputStream inputStream = socket.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(
inputStream));
String msg = br.readLine();
if (msg != null)
System.out.println(msg);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
三、MIME 协议
1、MIME 协议是对 RFC822 文档的升级和补充,它描述了如何生成一封复杂的邮件。通常我们把 MIME 协议描述的邮件称为 MIME 邮件,MIME 协议描述的数据称为 MIME 消息。对于一封复杂邮件,如果包含了多个不同的数据,MIME 协议规定了要实用哦个分隔线对多段数据进行分隔,并使用 Content-Type 头字段对数据的类型、数据间的关系进行描述。
2、MIME 复杂邮件。对于一封邮件,在 Java 中可以使用 MImeMessage 进行封装。MimeMessage 中的每一部分数据使用 MImeBodyPart 进行描述,指定数据的类型,设置数据。对数据进行描述好了以后,再使用 MimeMultipart 将数据封装到容器中,并描述多个数据间的关系。related 表示两个数据的引用关系。mixed 表示两个数据间没有关系。最后将容器中的内容增加到 MImeMessage 中,保存并发送。
邮件增加图片:
package cn.dk.mail;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;
import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.MessagingException;
import javax.mail.Session;
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;
public class SendMIMEMail {
public static void main(String[] args) throws AddressException, MessagingException, FileNotFoundException, IOException {
Session session = Session.getDefaultInstance(new Properties());
MimeMessage message = new MimeMessage(session);
message.setFrom(new InternetAddress("asf@qq.com"));
message.setRecipient(MimeMessage.RecipientType.TO, new InternetAddress("sdf@qq.com"));
message.setSubject("测试");
MimeBodyPart text = new MimeBodyPart();
text.setContent("sadfsdfs<img src='1.jpg'>", "text/html");
MimeBodyPart img = new MimeBodyPart();
img.setDataHandler(new DataHandler(new FileDataSource("src\\1.jpg")));
img.setContentID("1.jpg");
MimeMultipart mm = new MimeMultipart();
mm.setSubType("related");
mm.addBodyPart(text);
mm.addBodyPart(img);
message.setContent(mm);
message.saveChanges();
message.writeTo(new FileOutputStream("d:\\2.eml"));
}
}
带附件的邮件:
package cn.dk.mail;
import java.io.FileOutputStream;
import java.util.Properties;
import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.Session;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
public class SendAttachMail {
public static void main(String[] args) throws Exception {
Session session = Session.getDefaultInstance(new Properties());
MimeMessage message = new MimeMessage(session);
message.setFrom(new InternetAddress("123@qq.com"));
message.setRecipient(MimeMessage.RecipientType.TO, new InternetAddress("sf@qq.com"));
MimeBodyPart text = new MimeBodyPart();
text.setContent("电子邮件", "text/html");
MimeBodyPart attach = new MimeBodyPart();
attach.setDataHandler(new DataHandler(new FileDataSource("1.mp3")));
attach.setFileName("1.mp3");
MimeMultipart mm = new MimeMultipart();
mm.addBodyPart(text);
mm.addBodyPart(attach);
mm.setSubType("mixed");
message.setContent(mm);
message.saveChanges();
message.writeTo(new FileOutputStream("d:/1.eml"));
}
}
带图片,带附件的邮件
package cn.dk.mail;
import java.io.FileOutputStream;
import java.util.Properties;
import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.Session;
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 Mail {
public static void main(String[] args) throws Exception {
Session session = Session.getDefaultInstance(new Properties());
MimeMessage message = new MimeMessage(session);
message.setFrom(new InternetAddress("sadf@qq.com"));
message.setRecipient(MimeMessage.RecipientType.TO,new InternetAddress("sdf@qq.com"));
MimeBodyPart text = new MimeBodyPart();
text.setContent("正文。。。<img src='cid:1.jpg'>", "text/html;charset=utf-8");
MimeBodyPart img = new MimeBodyPart();
img.setDataHandler(new DataHandler(new FileDataSource("src/1.jpg")));
img.setContentID("1.jpg");
MimeBodyPart attach = new MimeBodyPart();
attach.setDataHandler(new DataHandler(new FileDataSource("src/1.mp3")));
attach.setFileName(MimeUtility.encodeText("1.mp3"));
MimeMultipart mm = new MimeMultipart();
mm.addBodyPart(text);
mm.addBodyPart(img);
mm.setSubType("related");
MimeBodyPart body = new MimeBodyPart();
body.setContent(mm);
MimeMultipart last = new MimeMultipart();
last.addBodyPart(body);
last.addBodyPart(attach);
last.setSubType("mixed"); //可省略
message.setContent(last);
message.saveChanges();
message.writeTo(new FileOutputStream("d:/2.eml"));
}
}
四、发送邮件
在指定 MimeMessage 时,需要一个 Session 对象,该对象就封装了发送邮件所需要的会话信息。Session 需要使用配置文件包装连接信息。需要指定要连接的服务器类型和主机名、采用的连接协议和协议名、是否需要验证和开关等。 在发送邮件时,我们还需要一个 Transport 对象,这个对象由 Session 获得,需要指定连接信息 (用户名、密码),和要发送的邮件、接收人。
package cn.dk.mail;
import java.util.Properties;
import javax.activation.DataHandler;
import javax.activation.FileDataSource;
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;
public class SendMail {
public static void main(String[] args) throws Exception {
Properties properties = new Properties();
properties.setProperty("mail.smtp.host", "smtp.qq.com");
properties.setProperty("mail.transport.protocol", "smtp");
properties.setProperty("mail.smtp.auth", "true");
Session session = Session.getDefaultInstance(properties);
MimeMessage message = new MimeMessage(session);
message.setFrom(new InternetAddress("80714286@qq.com"));
message.setRecipient(MimeMessage.RecipientType.TO, new InternetAddress("80714286@qq.com"));
message.setSubject("邮件");
MimeBodyPart text = new MimeBodyPart();
text.setContent("发了一封邮件,送个美女:<img src='cid:1.jpg'>", "text/html;charset:utf-8");
MimeBodyPart img = new MimeBodyPart();
img.setDataHandler(new DataHandler(new FileDataSource("src/1.jpg")));
img.setContentID("1.jpg");
MimeBodyPart music = new MimeBodyPart();
music.setDataHandler(new DataHandler(new FileDataSource("src/加勒比海盗.mp3")));
music.setFileName(MimeUtility.encodeText("加勒比海盗.mp3"));
MimeMultipart mm = new MimeMultipart();
mm.addBodyPart(text);
mm.addBodyPart(img);
mm.setSubType("related");
MimeBodyPart content = new MimeBodyPart();
content.setContent(mm);
MimeMultipart mm1 = new MimeMultipart();
mm1.addBodyPart(content);
mm1.addBodyPart(music);
mm1.setSubType("mixed");
message.setContent(mm1);
message.saveChanges();
Transport transport = session.getTransport();
transport.connect("xxx@qq.com", "xxx");
transport.sendMessage(message, message.getAllRecipients());
transport.close();
}
}
模拟网站注册发送邮件
package cn.dk.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import cn.dk.domain.User;
import cn.dk.service.UserService;
public class RegistServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String username = request.getParameter("username");
String passwrod = request.getParameter("password");
String email = request.getParameter("email");
final User user = new User(username,passwrod,email);
final UserService service = new UserService();
try {
new Thread(){public void run(){
try {
service.SendEmail(user);
} catch (Exception e) {
throw new RuntimeException(e);
}
}}.start();
request.setAttribute("message", "注册成功,请查收邮件");
} catch (Exception e) {
request.setAttribute("message", "注册失败~");
}
request.getRequestDispatcher("/message.jsp").forward(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
package cn.dk.service;
import java.util.Properties;
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 cn.dk.domain.User;
public class UserService {
public void SendEmail(User user) throws Exception {
Properties properties = new Properties();
properties.setProperty("mail.smtp.host", "smtp.qq.com");
properties.setProperty("mail.transport.protocol", "smtp");
properties.setProperty("mail.smtp.auth", "true");
Session session = Session.getDefaultInstance(properties);
MimeMessage message = new MimeMessage(session);
message.setFrom(new InternetAddress("80714286@qq.com"));
message.setRecipient(MimeMessage.RecipientType.TO, new InternetAddress(
user.getEmail()));
message.setSubject("xx网站注册消息");
MimeBodyPart text = new MimeBodyPart();
text.setContent(" 你好,感谢您注册,您的用户名:" + user.getUsername() + " 密码:"
+ user.getPassword() + "请妥善保管", "text/html;charset=utf-8");
MimeMultipart mm = new MimeMultipart();
mm.addBodyPart(text);
message.setContent(mm);
message.saveChanges();
Transport transport = session.getTransport();
transport.connect("80714286@qq.com", "MINGLOVE202shb");
transport.sendMessage(message, message.getAllRecipients());
transport.close();
}
}