31、邮件原理(JavaEE笔记)

一、邮件开发涉及到的一些基本概念

  • 邮件服务器和电子邮箱
  • 邮件传输协议
  • 电子邮件的发送和接收过程

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 配置易邮邮件服务器

当我们没有网络时,做实验的时候需要用到

    1. 工具-选中作为局域网邮件服务器,同时将单域名选中,而框中的域名可以取名为yj.com,那么之后我们创建一个帐号aaa,则此账户的邮箱就是aaa@yj.com-确定。
    1. 帐号-填写帐号aaa,密码123-确定。其他内容可以不填。这样我们就创建好了一个邮箱帐号。
  • 3.实验,我们可以再创建一个帐号bbb,使用手动方式从aaa给bbb发送一封邮件,可以看到bbb账户的邮件数量从一开始的1变为了2。表示收到了。这里我们还可以使用outlook进行接收,接收后bbb帐号的邮件数量将变为0。
    这里我们使用本地服务器来进行试验:
telnet localhost 25
Paste_Image.png
ehlo yj
auth login
YWFh
MTIz
mail from:<aaa@yj.com>
rcpt to:<bbb@yj.com>
data
some information
.
quit
1.png

手工进行接收:

telnet localhost 110
user bbb
pass 123
stat
retr 1
.
quit
2.png

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头字段
    此头字段用于指定邮件阅读程序处理数据内容的方式,有inlineattachment两种标准方式,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;
    }
}

说明:相关的发送过程是用户提交注册请求之后我们开启额外的线程想用户发送一封邮件。而我们实际开发中一般在像用户发送注册页面的时候一般会附带一个隐藏字段,用户注册之后点击邮件中的超链接会附带一些信息,这样就激活了。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,390评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,821评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,632评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,170评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,033评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,098评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,511评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,204评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,479评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,572评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,341评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,893评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,171评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,486评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,676评论 2 335

推荐阅读更多精彩内容