一、邮件开发涉及到的一些基本概念
- 邮件服务器和电子邮箱
- 邮件传输协议
- 电子邮件的发送和接收过程
1.1邮件服务器和电子邮箱
邮件服务器
要在Internet上提供电子邮件功能,必须有专门的电子邮件服务器。例如现在Internet很多都提供邮件服务器的厂商:sina、sohu等都有自己的邮件服务器。这些服务器类似于现实生活中的邮局,它主要负责接收用户投递过来的邮件,并把邮件投递到邮件接受者的电子邮箱中。电子邮箱
电子邮箱(Email地址)的获得需要在邮件服务器上进行申请,确切地说,电子邮箱其实就是用户在邮件服务器上申请的一个账户。用户在邮件服务器上申请了一个帐号后,邮件服务器就会为这个帐号分配一定的空间,用户从而可以使用这个帐号以及空间,发送电子邮件和保存别人发送过来的邮件。
1.2 邮件传输协议和邮件服务器类型
SMTP协议
用户连上邮件服务器后,要想给它发送一封电子邮件,需要遵循一定的通讯规则,SMTP协议就是用于定义这种通讯规则的。因而,通常我们也把处理用户smtp请求(邮件发送请求)的邮件服务器称之为smtp服务器,一般其端口是25。也就是这是一个发送规则。POP3协议
同样,用户若想从邮件服务器管理的电子邮箱中接收一封电子邮件的话,它连上邮件服务器后,也需要遵循一定的通讯格式,POP3协议用于定义这种通讯格式。因而,通常我们也把处理用户pop3请求(邮件接收请求)的邮件服务器称之为pop3服务器,其端口一般是110。也就是这是一个接收规则。
1.3 手工演示电子邮件的发送
1.连上qq邮箱的邮件发送服务器:
telnet smtp.exmail.qq.com 25
2.
ehlo yj
3.发送登录命令:
auth login
输入用户名:xxxxx
输入密码:xxxx
注意:这里用户名和密码必须使用其Base64编码。我们使用编码程序进行生成用户名和密码的编码:(工程day23
)
Base64Util.java
package cn.itcast.demo;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import sun.misc.BASE64Encoder;
public class Base64Util
{
public static void main(String args[]) throws IOException
{
System.out.print("请输入用户名:");
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
String userName = in.readLine();
System.out.print("请输入密码:");
String password = in.readLine();
BASE64Encoder encoder = new BASE64Encoder();
System.out.println("编码后的用户名为:"
+ encoder.encode(userName.getBytes()));
System.out.println("编码后的密码为:"
+ encoder.encode(password.getBytes()));
}
}
4.填写发件人:
mail from:<1601313326@qq.com>
填写收件人:rcpt to:<yjaal1314@163.com>
5.填写发送具体信件信息:
data
xxxxxxxxxxxxxxxxxxxxxxxxxx
单独一行发送一个点号(".")结束填写
- 6.
quit
这样就会在收件箱中看到我们手工发送的邮件,但是这个邮件只有我们填写的信息,和平时我们写的邮件不一样:没有发件人、收件人和主题等等。这是因为这些信息也需要我们去填写,如下所示:
1.连上qq邮箱的邮件发送服务器:
telnet smtp.exmail.qq.com 25
2.
ehlo yj
3.发送登录命令:auth login
输入用户名:xxxx
输入密码:xxx
4.填写发件人:
mail from:<1601313326@qq.com>
填写收件人:rcpt to:<yjaal1314@163.com>
5.填写发送具体信件信息:
data
from:1601313326@qq.com
to: yjaal1314@163.com
subject:xxx
注意:这里一定要空一行。
xxxxxxxxxxxxxxxxxxxxxxxxxx
单独一行发送一个点号(".")结束填写
- 6.
quit
说明:在使用qq邮箱进行试验的时候需要一个授权码,同时还要开启上面说的两个协议的服务。有时候涉及到相关权限的问题总喜欢出现问题,而且我们在发送命令时最好将命令先写好,之后复制粘贴,因为在命令行中写错了是不能修改的。之前试验成功了,但是之后试验总是不行,使用qq服务器总是提示要授权码,但是这个授权码是否需要进行编码?而且这个授权码是替换密码还是用户名?这里我们可以使用后面提到的易邮邮件服务器进行试验。
1.4 SMTP协议
ehlo 主机名
auth login//经过base64编码后的用户名和密码
mail from:<1601313326@qq.com>
rcpt to:<yjaal1314@163.com>
data “.”号代表邮件内容结束
quit
1.5 创建邮件-RFC822文档
此文档规定了如何编写一封简单的邮件
- 邮件头和邮件体:使用空行分隔
- 邮件头:
from字段、头to字段、subject字段、cc和bcc字段 - 邮件体
邮件内容
说明:按照此格式就可以在邮件上添加一些头信息等。
1.6 POP3协议
user<SP>username<CRLF>
pass<SP>password<CRLF>
-
stat<CRLF>
返回邮箱的统计信息,可选 -
list<SP>[msg#]<CRLF>
返回某一封邮件的统计信息,可选 -
retr<SP>[msg#]<CRLF>
最重要的一个命令 quit<CRLF>
说明:使用此协议手工接收邮件,之前我们收邮件都是通过网页收的,通过使用此协议就可以手工的接收查看邮件了。注意:在接收邮件时首先需要连接上服务器:telnet pop3.sina.com 110
。
- 1.
telnet pop3.163.com 110
- 2.
user yjaal1314
(这是163邮箱用户名) - 3.
pass 1601313326
- 4.
stat
(此处会显示出邮箱中有多少封邮件) - 5.
retr 3
(选择接收第三封邮件) - 6.
quit
1.7 创建邮件-MIME协议
- 此协议是对RFC822文档的升级和补充,它描述了如何生成一封复杂邮件。通常我们把此协议描述的邮件称之为MIME邮件,MIME协议描述的数据称之为MIME消息。对于RFC822类型的邮件只能发送一些文本信息,但是这显然是不够的,我们有时候需要添加一些图片和附件等,所以需要使用MIME协议。
- 对于一封复杂邮件,如果包含了多个不同的数据,MIME协议规定了要使用分割线对多段数据进行分隔,并使用
Content-Type
头字段对数据的类型、以及多个数据之间的关系进行描述。
1.8 配置易邮邮件服务器
当我们没有网络时,做实验的时候需要用到
- 工具-选中作为局域网邮件服务器,同时将单域名选中,而框中的域名可以取名为yj.com,那么之后我们创建一个帐号aaa,则此账户的邮箱就是aaa@yj.com-确定。
- 帐号-填写帐号aaa,密码123-确定。其他内容可以不填。这样我们就创建好了一个邮箱帐号。
- 3.实验,我们可以再创建一个帐号bbb,使用手动方式从aaa给bbb发送一封邮件,可以看到bbb账户的邮件数量从一开始的1变为了2。表示收到了。这里我们还可以使用outlook进行接收,接收后bbb帐号的邮件数量将变为0。
这里我们使用本地服务器来进行试验:
telnet localhost 25
ehlo yj
auth login
YWFh
MTIz
mail from:<aaa@yj.com>
rcpt to:<bbb@yj.com>
data
some information
.
quit
手工进行接收:
telnet localhost 110
user bbb
pass 123
stat
retr 1
.
quit
1.9 outlook的配置
1.工具-账户设置-新建-下一步-勾选手动设置服务器。。。-下一步
2.根据自己的想法进行填写,但是这里注意:我们的账户类型若是pop3,则此账户只能进行接收邮件,同时接收邮件服务器和发送邮件服务器都要填写localhost,因为我们不实用网络,都是从本机发本机收。填写完之后还有点击其他设置-发送服务器-勾选我的发送服务器(SMTP)要求验证-确定-下一步即可。
注意:之后我们做实验的时候会收到.eml格式的文件,outlook是打不开的,我们需要使用火狐,使用的时候先将outlook帐号导入进火狐进行接收,之后我们可以打开.eml格式的文件了。
二、使用java程序发送邮件
例:
SendMail.java
package cn.itcast.demo;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
public class SendMail {
public static void main(String[] args) throws UnknownHostException, Exception {
Socket socket = new Socket("smtp.sohu.com",25);
OutputStream out = socket.getOutputStream();
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
System.out.println(in.readLine());
out.write("ehlo flx\r\n".getBytes());//注意结尾要加上换行
System.out.println(in.readLine());
System.out.println(in.readLine());
System.out.println(in.readLine());
out.write("auth login\r\n".getBytes());
System.out.println(in.readLine());
out.write("aXRjYXN0MTExMQ==\r\n".getBytes());
System.out.println(in.readLine());
out.write("MTIzNDU2\r\n".getBytes());
System.out.println(in.readLine());
out.write("mail from:<itcast1111@sohu.com>\r\n".getBytes());
System.out.println(in.readLine());
out.write("rcpt to:<itcast1111@sina.com>\r\n".getBytes());
System.out.println(in.readLine());
out.write("data\r\n".getBytes());
System.out.println(in.readLine());
out.write("aaaaaaaaaaaaaaa\r\n".getBytes());
out.write(".\r\n".getBytes());
System.out.println(in.readLine());
}
}
说明:这是完全按照之前手工方式的步骤进行发送的,实际开发中显然不能是这样。
2.1 MIME协议常用头字段
-
content-type
:头字段
数据类型:
以“主类型/子类型”的形式出现,主类型有text、image、audio、video、application、message
等,分别表示文本、图片、音频、视频、应用程序、组合结构、消息等。每个主类型下面都有多个子类型,例如text主类型包含plain、html、xml、css
等子类型。
数据的关系:
multipart/mixed、multipart/related、multipart/alternative
这里的关系是指图片等信息是作为附件还是直接显示。其中multipart/related
就表示直接显示。
-
content-disposition
头字段
此头字段用于指定邮件阅读程序处理数据内容的方式,有inline
和attachment
两种标准方式,inline
表示直接处理,而attachment
表示当作附件处理。如果将此字段设置为attachment
,在其后还可以指定filename
属性,如下所示:
content-disposition:attachment;filename="1.bmp"
上面的MIME头字段表示MIME消息体的内容为邮件附件,附件名为1.bmp
-
content-ID
头字段
此头字段用于为"multipart/related"
组合消息中的内嵌资源指定一个唯一标识号,在html格式的正文中可以使用这个唯一标识符来引用该内嵌资源。例如,假设将一个表示内嵌图片的MIME消息的content-ID
头字段设置为如下形式:
Content-ID:1.gif
那么,在html正文中就需要使用如下html语句来引用该图片资源:
<img src="1.gif">
注意:在引用此头字段标识的内嵌资源时,要在资源的唯一标识符前面加上”cid”,以说明要采用唯一标识符对资源进行引用。
2.2 邮件组织结构相关的API
-
MimeMessage
类表示整封邮件 -
MimeBodyPart
类表示邮件的一个MIME消息。 -
MimeMultipart
类表示一个由多个MIME消息组合而成的组合MIME消息。
2.3 使用 javaMail API 收发邮件
-
javaMail API按其功能通常可以分为如下三大类:
- 1.创建和解析邮件内容的API:Message类是创建和解析的核心API,它的实力对象代表一封电子邮件。
- 2.发送邮件的API:Transport类是发送邮件的核心API类。它的实力对象代表实现了某个邮件发送协议的的邮件发送对象,例如smtp协议。
- 3.接收邮件的API:Store类是接收邮件的核心API类,它的实力对象代表实现了某个邮件接收协议的邮件接收对象,例如:pop3协议。
Session类
此类用于定义整个应用程序所需的环境信息,以及收集客户端服务器建立网络链接的会话信息,如邮件服务器的主机名、端口号、采用的邮件发送和接收协议等,Session对象根据这些信息构建用于邮件收发的Transport和Store对象,以及为客户端创建Message对戏那个时提供信息支持。
2.4 例1:发送一封简单邮件SimpleMail.java
首先需要导入相关的jar包,因为这里是java工程:
activation-2.2.1.jar、javamail-1.4.5.jar
package cn.itcast.mail;
import java.io.FileOutputStream;
import java.util.Properties;
import javax.mail.Message;
import javax.mail.Session;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
public class SimpleMail {
public static void main(String[] args) throws Exception {
Session session = Session.getInstance(new Properties());
MimeMessage message = new MimeMessage(session);
//设置邮件的基本信息
message.setFrom(new InternetAddress("bbb@yj.com"));//设置发送地址
message.setRecipient(Message.RecipientType.TO, new InternetAddress("bbb@yj.com"));//设置接收地址
message.setSubject("test");//设置主题
message.setContent("aaa", "text/html");//邮件的文本信息和文本格式
message.saveChanges();//保存收件箱的变化
message.writeTo(new FileOutputStream("d:\\3.eml"));//这里我们将邮件保存在了本机中
}
}
2.5 例2:一封带图片的邮件ImageMail.java
package cn.itcast.mail;
import java.io.FileOutputStream;
import java.util.Properties;
import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.Message;
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 ImageMail {
/**
* 带图片的邮件
*/
public static void main(String[] args) throws Exception {
Session session = Session.getInstance(new Properties());//得到邮件会话Session
MimeMessage message = new MimeMessage(session);
//设置邮件的基本信息
message.setFrom(new InternetAddress("aaa@yj.com"));//设置发送地址
//第一个参数表示收件人的类型:收件人、抄送人、密送人
message.setRecipient(Message.RecipientType.TO, new InternetAddress("aaa@yj.com"));//收件人
message.setSubject("test");//邮件主题
//准备邮件数据,每一部分数据都是使用MimeBodyPart表示
//准备邮件正文数据
MimeBodyPart text = new MimeBodyPart();
text.setContent("xxxx<img src='cid:xxx.jpg'>xxxxxxxxx", "text/html");//将图片和文本直接显示
//准备图片数据
MimeBodyPart image = new MimeBodyPart();
DataHandler dh = new DataHandler(new FileDataSource("src\\1.jpg"));//将数据处理器和图片的地址相关联即可
image.setDataHandler(dh);//不需要设置图片数据的类型,会自动识别图片类型
image.setContentID("xxx.jpg");
//描述数据关系
MimeMultipart mm = new MimeMultipart();
mm.addBodyPart(text);
mm.addBodyPart(image);
mm.setSubType("related");//描述正文和图片的关系,关系是相关的,即图片不是附件,这样会直接显示出来,而不是作为附件
message.setContent(mm);//把邮件加到容器里面去
message.saveChanges();
message.writeTo(new FileOutputStream("d:\\1.eml"));
}
}
说明:MimeMessage
对象是用来设置一些头信息的,同时还需要使用此对象将邮件发送出去,MimeBodyPart
对象可以表示没部分信息,或者说邮件中每部分(文本、图片、附件等)都是使用此对象表示的,MimeMultipart
对象可以设置各部分数据之间的关系,同时还是各部分数据的容器。
当然发送带图片的邮件还有另一种方式,但是不安全,这里不推荐:
ImageMail2.java
package cn.itcast.mail;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
public class ImageMail2 {
public static void main(String[] args) throws AddressException, MessagingException, FileNotFoundException, IOException {
Session session = Session.getInstance(new Properties());
MimeMessage message = new MimeMessage(session);
message.setFrom(new InternetAddress("bbb@yj.com"));
message.setRecipient(Message.RecipientType.TO, new InternetAddress("bbb@yj.com"));
message.setSubject("test");
//3.jpg
message.setContent("aaaaa<br/><img src='c:\\3.jpg?email=bbb@yj.com'>", "text/html");//这种方式不安全
message.saveChanges();
message.writeTo(new FileOutputStream("f:\\1.eml"));
}
}
2.6 例3:一封带附件的邮件AttachMail.java
package cn.itcast.mail;
import java.io.FileOutputStream;
import java.util.Properties;
import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.Message;
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 AttachMail {
public static void main(String[] args) throws Exception {
Session session = Session.getInstance(new Properties());
MimeMessage message = new MimeMessage(session);
//设置邮件的基本信息
message.setFrom(new InternetAddress("bbb@yj.com"));
message.setRecipient(Message.RecipientType.TO, new InternetAddress("bbb@yj.com"));
message.setSubject("test");
//创建邮件正文
MimeBodyPart text = new MimeBodyPart();
text.setContent("aaaaaaaaaaa", "text/html");
//创建邮件附件
MimeBodyPart attach = new MimeBodyPart();
DataHandler dh = new DataHandler(new FileDataSource("src\\1.jpg"));
attach.setDataHandler(dh);
attach.setFileName(dh.getName()); //显示附件名
//创建容器描述数据关系(正文和附件没有关系,即mixed)
MimeMultipart mp = new MimeMultipart();
mp.addBodyPart(text);
mp.addBodyPart(attach);
mp.setSubType("mixed");//设置邮件中图片作为附件
message.setContent(mp);//把邮件加到容器里面去
message.saveChanges();//邮件的数据更新我们需要保存一下
message.writeTo(new FileOutputStream("f:\\2.eml"));//在F盘中我们可以看到此邮件,但是outlook是打不开的
//这里我们使用火狐就可以打开,同时outlook对于附件或正文图片都是默认打开的,而火狐是如果图片作为附件是不会打开的,只有当作为正文才会打开
}
}
说明:其实发送过程基本类似,只是数据之间的关系不同,这里只是将图片作为一个附件,同时额外加上显示附件名字。
2.7 例4:最复杂的邮件MixedMail.java
其实邮件最复杂的形式就是又直接显示带图片,同时又带有相关的附件,其实过程基本类似。
package cn.itcast.mail;
import java.io.FileOutputStream;
import java.util.Properties;
import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.Message;
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;
import javax.mail.internet.MimeUtility;
public class MixedMail {
/**
* 最复杂的邮件
*/
public static void main(String[] args) throws Exception {
Session session = Session.getInstance(new Properties());
MimeMessage message = new MimeMessage(session);
//设置邮件的基本信息
message.setFrom(new InternetAddress("bbb@yj.com"));
message.setRecipient(Message.RecipientType.TO, new InternetAddress("bbb@yj.com"));
message.setSubject("测试");//主题不会出现乱码问题
//正文
MimeBodyPart text = new MimeBodyPart();
text.setContent("xxx这是女的xxxx<br/><img src='cid:aaa.jpg'>","text/html;charset=UTF-8");//指定编码,防止乱码,这里解决正文乱码问题
//图片
MimeBodyPart image = new MimeBodyPart();
image.setDataHandler(new DataHandler(new FileDataSource("src\\1.jpg")));
image.setContentID("aaa.jpg");
//附件1
MimeBodyPart attach = new MimeBodyPart();
DataHandler dh = new DataHandler(new FileDataSource("src\\2.jpg"));
attach.setDataHandler(dh);
attach.setFileName(dh.getName());
//附件2
MimeBodyPart attach2 = new MimeBodyPart();
DataHandler dh2 = new DataHandler(new FileDataSource("src\\狮子.zip"));
attach2.setDataHandler(dh2);
/*attach2.setFileName(dh2.getName());这里会出现文件名乱码问题*/
attach2.setFileName(MimeUtility.encodeText(dh2.getName()));//这个方法会将此文件设置为一个附件
//描述关系:正文和图片,将正文和图片封装到mp1(MimeMultipart)中
MimeMultipart mp1 = new MimeMultipart();
mp1.addBodyPart(text);
mp1.addBodyPart(image);
mp1.setSubType("related");
//描述关系:正文和附件,将两个附件封装到mp2(MimeMultipart)中
MimeMultipart mp2 = new MimeMultipart();
mp2.addBodyPart(attach);
mp2.addBodyPart(attach2);
MimeBodyPart content = new MimeBodyPart(); //代表正文的bodypart
//之前的正文和图片组成了新的正文,MimeMultipart不能直接封装到MimeMultipart中,应该先将mp1封装到MimeBodyPart
//之后再封装到MimeMultipart
content.setContent(mp1);
mp2.addBodyPart(content);//将之前文本和图片组成的MimeBodyPart加入到mp2中
mp2.setSubType("mixed");
message.setContent(mp2);
message.saveChanges();
message.writeTo(new FileOutputStream("f:\\3.eml"));
}
}
说明:
- 首先我们将文本和图片组成一个
MimeMultipart
,同时两个附件也组成一个MimeMultipart
,然后我们需要将这两个MimeMultipart
组成一个MimeMultipart
发送出去,但是MimeMultipart
只能封装MimeBodyPart
,而不能直接封装MimeMultipart
,于是我们先加图片和文本组成的MimeMultipart
封装到一个MimeBodyPart
,之后再封装到两个附件组成的MimeMultipart
,然后发送出去。 - 最后还要注意中文乱码问题。对于主题不会出现乱码,出现乱码有两个地方,一个是正文,一个是中文文件名。对于正文乱码我们直接加上编码即可,而中文文件名的解决我们使用工具
MimeUtility
解决。
2.8 发送邮件
上面的例子都只是创建了邮件同时保存在了本地,但是没有发送出去,下面我们创建一封邮件并发送出去。
Sendmail.java
package cn.itcast.mail;
import java.util.Properties;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.NoSuchProviderException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
public class Sendmail {
public static void main(String[] args) throws Exception {
Properties prop = new Properties();
prop.setProperty("mail.host", "smtp.sohu.com");
prop.setProperty("mail.transport.protocol", "smtp");
prop.setProperty("mail.smtp.auth", "true");
//1创建session
Session session = Session.getInstance(prop);
session.setDebug(true);
//2通过session得到transport对象
Transport ts = session.getTransport();
//3连上邮件服务器
ts.connect("smtp.sohu.com", "itcast1111", "123456");
//4发送邮件
Message message = makeMessage(session);
ts.sendMessage(message, message.getAllRecipients());
ts.close();
}
public static Message makeMessage(Session session) throws Exception, MessagingException{
MimeMessage message = new MimeMessage(session);
message.setFrom(new InternetAddress("itcast1111@sohu.com"));//发件人
message.setRecipient(Message.RecipientType.TO, new InternetAddress("itcast1111@sohu.com"));//收件人
message.setSubject("test");
message.setContent("aaa", "text/html");
return message;//返回这封邮件
}
}
三、模拟网站注册之后给用户发送一封邮件
(工程day23_web
)
RegisterServlet.java
package cn.itcast.web.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import cn.itcast.domain.User;
public class RegisterServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
try{
User user = new User();
String username = request.getParameter("username");
String password = request.getParameter("password");
String email = request.getParameter("email");
user.setUsername(username);
user.setPassword(password);
user.setEmail(email);
System.out.println("注册");
//发送邮件
//由于发送邮件有时候可能很耗时,所以直接使用工具类发送是不行的,所以我们需要将发送邮件的方法做成一个单独的线程
//WebUtils.sendMail(user);
SendMail send = new SendMail(user);
send.start();//启动线程
request.setAttribute("message", "注册成功");
request.getRequestDispatcher("/message.jsp").forward(request, response);
}catch(Exception e){
e.printStackTrace();
request.setAttribute("message", "注册失败");
request.getRequestDispatcher("/message.jsp").forward(request, response);
}
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
SendMail.java
package cn.itcast.web.servlet;
import java.util.Properties;
import javax.mail.Message;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import cn.itcast.domain.User;
public class SendMail extends Thread {
private String from = "aaa@yj.com";
private String username = "aaa";
private String password = "123456";
private String host = "localhost";
private User user; //bbb@yj.com
public SendMail(User user){
this.user = user;
}
@Override
public void run() {
try{
Properties prop = new Properties();
prop.setProperty("mail.smtp.host", host);
prop.setProperty("mail.transport.protocol", "smtp");
prop.setProperty("mail.smtp.auth", "true");
Session session = Session.getInstance(prop);
//这里我们可以使用JNDI技术,让服务器为我们创建一个Session,这里需要在META-INF/context.xml
//文件中进行相应的配置。这样上面个代码就不需要了,可以直接从容器中获取。同时这里还必须将mail的两个jar包拷贝到tomcat的lib中去
//但是这里会出现一个ClassCastException异常,就是因为tomcat没有完全采用父类委托机制,这里的解决办法是将程序部署之后将WEB-INF/lib
//下的两个jar包删掉,但是注意:不能将工程中的jar删掉。从browse中进入到部署的工程中进行删除
/*Context initCtx = new InitialContext();//初始化一个JNDI
Context envCtx = (Context) initCtx.lookup("java:comp/env");//拿到tomcat的JNDI容器
Session session = (Session) envCtx.lookup("mail/Session"); //Session s = session检索出Session
session.setDebug(true);*/
Transport ts = session.getTransport();
ts.connect(username, password);
Message message = makeMessage(session,user);
ts.sendMessage(message, message.getAllRecipients());
ts.close();
}catch (Exception e) {
throw new RuntimeException(e);
}
}
public Message makeMessage(Session session,User user) throws Exception{
MimeMessage message = new MimeMessage(session);
message.setFrom(new InternetAddress(from));
message.setRecipient(Message.RecipientType.TO, new InternetAddress(user.getEmail()));
message.setSubject("用户注册邮件");
String info = "恭喜您注册成功,您的用户名:" + user.getUsername() + ",您的密码:" + user.getPassword() + ",请妥善保管,如有问题请联系网站客服!!";
message.setContent(info, "text/html;charset=UTF-8");
message.saveChanges();
return message;
}
}
说明:相关的发送过程是用户提交注册请求之后我们开启额外的线程想用户发送一封邮件。而我们实际开发中一般在像用户发送注册页面的时候一般会附带一个隐藏字段,用户注册之后点击邮件中的超链接会附带一些信息,这样就激活了。