首页 > 代码库 > 基于web的java Mail的邮件发送系统的详解

基于web的java Mail的邮件发送系统的详解

本系统是基于web的,引用了第三方的API:mail.jar开发包。

一.目录结构的介绍

我们可以到Oracle官网下载mail.jar开发包,我下载的版本是1.4.5。下载成功后,会得到一个javamail1_4_5.zip的文件,然后解压。

首先是根目录下的mail.jar是它的核心包


 在lib子目录下有对应如下的jar包,其中mailapi.jar封装了创建邮件内容和面向普通开发人员调用邮件发送和接收的API类,其它三个jar文件(imap.jar、pop3.jar、smtp.jar)则是封装了它们名称相对应协议的服务实现程序。mailapi.jar与其它三个jar文件的关系,犹如JDBC API与各个数据库所实现jdbc驱动程序之间的关系一样。在编译Java邮件程序时,只需要mailapi.jar文件即可,但是,在运行时必须要有相应邮件协议的底层服务实现程序。本次应用程序中只使用到邮件发送功能,所以可以只导入smtp.jar和mailapi.jar这两个文件,如果应用程序需要使用邮件的接收功能,则可以安装pop3.jar或imap.jar和mailapi.jar这两个jar文件,而不用导入整个mail.jar文件。


二.相关协议的介绍

1.SMTP协议

SMTP(Simple Mail Transfer Protocol)即简单邮件传输协议,它是一组用于由源地址到目的地址传送邮件的规则,由它来控制信件的中转方式。SMTP协议属于TCP/IP协议族,它帮助每台计算机在发送或中转信件时找到下一个目的地。通过SMTP协议所指定的服务器,就可以把E-mail寄到收信人的服务器上了,整个过程只要几分钟。SMTP服务器则是遵循SMTP协议的发送邮件服务器,用来发送或中转发出的电子邮件。

2.POP协议

POP 代表邮局协议(Post Office Protocol)。目前用的是版本 3,也称 POP3,RFC 1939 定义了这个协议。POP 是一种机制,因特网上大多数人用它得到邮件。它规定每个用户一个邮箱的支持。这就是它所能做的,而这也造成了许多混淆。使用 POP 时,用户熟悉的许多性能并不是由 POP 协议支持的,如查看有几封新邮件消息这一性能。这些性能内建于如 Eudora 或 Microsoft Outlook 之类的程序中,它们能记住一些事,诸如最近一次收到的邮件,还能计算出有多少是新的。

3.IMAP协议

IMAP 是更高级的用于接收消息的协议。在 RFC 2060 中被定义,IMAP 代表因特网消息访问协议(Internet Message Access Protocol),目前用的是版本 4,也称 IMAP4。在用到 IMAP 时,邮件服务器必需支持这个协议。不能仅仅把使用 POP 的程序用于 IMAP,并指望它支持 IMAP 所有性能。假设邮件服务器支持 IMAP,基于 JavaMail 的程序可以利用这种情况 — 用户在服务器上有多个文件夹(folder),并且这些文件夹可以被多个用户共享。

       因为有这一更高级的性能,您也许会认为所有用户都会使用 IMAP。事实并不是这样。要求服务器接收新消息,在用户请求时发送到用户手中,还要在每个用户的多个文件夹中维护消息。这样虽然能将消息集中备份,但随着用户长期的邮件夹越来越大,到磁盘空间耗尽时,每个用户都会受到损失。使用 POP,就能卸载邮件服务器上保存的消息了。

最后介绍一下MIME,MINE 代表多用途因特网邮件扩展标准(Multipurpose Internet Mail Extensions)。它不是邮件传输协议。但对传输内容的消息、附件及其它的内容定义了格式。

好,以上是邮件发送和接受的基本知识,有了基本知识,我们在结合代码对java Mail进行深入的了解和学习

邮件发送和接受的示意图


邮件发送的示意图


三.Mail发送邮件的封装

public class Mail {   
  
    private MimeMessage mimeMsg; //MIME邮件对象   
    private Session session; //邮件配置对象   
    private Properties props; //系统属性   
    @SuppressWarnings("unused")
	private boolean needAuth = false; //smtp是否需要认证   
    //smtp认证用户名和密码   
    private String username;   
    private String password;   
    private Multipart mp; //Multipart对象,邮件内容,标题,附件等内容均添加到其中后再生成MimeMessage对象   
       
    /** 
     * Constructor 
     * @param smtp 邮件发送服务器 
     */  
    public Mail(String smtp){   
        setSmtpHost(smtp);   
        createMimeMessage();   
    }   
  
    /** 
     * 设置邮件发送服务器 
     * @param hostName String  
     */  
    public void setSmtpHost(String hostName) {   
           
        if(props == null)  
            props = System.getProperties(); //获得系统属性对象    
        props.put("mail.smtp.host",hostName); //设置SMTP主机   
    }   
  
  
    /** 
     * 创建MIME邮件对象   
     * @return 
     */  
    public boolean createMimeMessage()   
    {   
        try {   
            System.out.println("准备获取邮件会话对象!");   
            session = Session.getDefaultInstance(props,null); //获得邮件会话对象   
        }   
        catch(Exception e){   
            System.err.println("获取邮件会话对象时发生错误!"+e);   
            return false;   
        }   
      
        System.out.println("准备创建MIME邮件对象!");   
        try {   
            mimeMsg = new MimeMessage(session); //创建MIME邮件对象   
            mp = new MimeMultipart();   
          
            return true;   
        } catch(Exception e){   
            System.err.println("创建MIME邮件对象失败!"+e);   
            return false;   
        }   
    }     
      
    /** 
     * 设置SMTP是否需要验证 
     * @param need 
     */  
    public void setNeedAuth(boolean need) {   
        System.out.println("设置smtp身份认证:mail.smtp.auth = "+need);   
        if(props == null) props = System.getProperties();   
        if(need){   
            props.put("mail.smtp.auth","true");   
        }else{   
            props.put("mail.smtp.auth","false");   
        }   
    }   
  
    /** 
     * 设置用户名和密码 
     * @param name 
     * @param pass 
     */  
    public void setNamePass(String name,String pass) {   
        username = name;   
        password = pass;   
    }   
  
    /** 
     * 设置邮件主题 
     * @param mailSubject 
     * @return 
     */  
    public boolean setSubject(String mailSubject) {   
        System.out.println("设置邮件主题!");   
        try{   
            mimeMsg.setSubject(mailSubject);   
            return true;   
        }   
        catch(Exception e) {   
            System.err.println("设置邮件主题发生错误!");   
            return false;   
        }   
    }  
      
    /**  
     * 设置邮件正文 
     * @param mailBody String  
     */   
    public boolean setBody(String mailBody) {   
        try{   
            BodyPart bp = new MimeBodyPart();   
            bp.setContent(""+mailBody,"text/html;charset=GBK");   
            mp.addBodyPart(bp);   
          
            return true;   
        } catch(Exception e){   
        System.err.println("设置邮件正文时发生错误!"+e);   
        return false;   
        }   
    }   
    /**  
     * 添加附件 
     * @param filename String  
     */   
    public boolean addFileAffix(String filename) {   
      
        System.out.println("增加邮件附件:"+filename);   
        try{   
            BodyPart bp = new MimeBodyPart();   
            FileDataSource fileds = new FileDataSource(filename);   
            bp.setDataHandler(new DataHandler(fileds));   
            bp.setFileName(fileds.getName());   
              
            mp.addBodyPart(bp);   
              
            return true;   
        } catch(Exception e){   
            System.err.println("增加邮件附件:"+filename+"发生错误!"+e);   
            return false;   
        }   
    }   
      
    /**  
     * 设置发信人 
     * @param from String  
     */   
    public boolean setFrom(String from) {   
        System.out.println("设置发信人!");   
        try{   
            mimeMsg.setFrom(new InternetAddress(from)); //设置发信人   
            return true;   
        } catch(Exception e) {   
            return false;   
        }   
    }   
    /**  
     * 设置收信人 
     * @param to String  
     */   
    public boolean setTo(String to){   
        if(to == null)return false;   
        try{   
            mimeMsg.setRecipients(Message.RecipientType.TO,InternetAddress.parse(to));   
            return true;   
        } catch(Exception e) {   
            return false;   
        }     
    }   
      
    /**  
     * 设置抄送人 
     * @param copyto String   
     */   
    public boolean setCopyTo(String copyto)   
    {   
        if(copyto == null)return false;   
        try{   
        mimeMsg.setRecipients(Message.RecipientType.CC,(Address[])InternetAddress.parse(copyto));   
        return true;   
        }   
        catch(Exception e)   
        { return false; }   
    }   
      
    /**  
     * 发送邮件 
     */   
    public boolean sendOut()   
    {   
        try{   
            mimeMsg.setContent(mp);   
            mimeMsg.saveChanges();   
            System.out.println("正在发送邮件....");   
              
            Session mailSession = Session.getInstance(props,null);   
            Transport transport = mailSession.getTransport("smtp");   
            transport.connect((String)props.get("mail.smtp.host"),username,password);   
            transport.sendMessage(mimeMsg,mimeMsg.getRecipients(Message.RecipientType.TO));   
            transport.sendMessage(mimeMsg,mimeMsg.getRecipients(Message.RecipientType.CC));   
            //transport.send(mimeMsg);   
              
            System.out.println("发送邮件成功!");   
            transport.close();   
              
            return true;   
        } catch(Exception e) {   
            System.err.println("邮件发送失败!"+e);   
            return false;   
        }   
    }   
  
    /** 
     * 调用sendOut方法完成邮件发送 
     * @param smtp 
     * @param from 
     * @param to 
     * @param subject 
     * @param content 
     * @param username 
     * @param password 
     * @return boolean 
     */  
    public static boolean send(String smtp,String from,String to,String subject,String content,String username,String password) {  
        Mail theMail = new Mail(smtp);  
        theMail.setNeedAuth(true); //需要验证  
          
        if(!theMail.setSubject(subject)) return false;  
        if(!theMail.setBody(content)) return false;  
        if(!theMail.setTo(to)) return false;  
        if(!theMail.setFrom(from)) return false;  
        theMail.setNamePass(username,password);  
          
        if(!theMail.sendOut()) return false;  
        return true;  
    }  
      
    /** 
     * 调用sendOut方法完成邮件发送,带抄送 
     * @param smtp 
     * @param from 
     * @param to 
     * @param copyto 
     * @param subject 
     * @param content 
     * @param username 
     * @param password 
     * @return boolean 
     */  
    public static boolean sendAndCc(String smtp,String from,String to,String copyto,String subject,String content,String username,String password) {  
        Mail theMail = new Mail(smtp);  
        theMail.setNeedAuth(true); //需要验证  
          
        if(!theMail.setSubject(subject)) return false;  
        if(!theMail.setBody(content)) return false;  
        if(!theMail.setTo(to)) return false;  
        if(!theMail.setCopyTo(copyto)) return false;  
        if(!theMail.setFrom(from)) return false;  
        theMail.setNamePass(username,password);  
          
        if(!theMail.sendOut()) return false;  
        return true;  
    }  
      
    /** 
     * 调用sendOut方法完成邮件发送,带附件 
     * @param smtp 
     * @param from 
     * @param to 
     * @param subject 
     * @param content 
     * @param username 
     * @param password 
     * @param filename 附件路径 
     * @return 
     */  
    public static boolean send(String smtp,String from,String to,String subject,String content,String username,String password,String filename) {  
        Mail theMail = new Mail(smtp);  
        theMail.setNeedAuth(true); //需要验证  
          
        if(!theMail.setSubject(subject)) return false;  
        if(!theMail.setBody(content)) return false;  
        if(!theMail.addFileAffix(filename)) return false;   
        if(!theMail.setTo(to)) return false;  
        if(!theMail.setFrom(from)) return false;  
        theMail.setNamePass(username,password);  
          
        if(!theMail.sendOut()) return false;  
        return true;  
    }  
      
    /** 
     * 调用sendOut方法完成邮件发送,带附件和抄送 
     * @param smtp 
     * @param from 
     * @param to 
     * @param copyto 
     * @param subject 
     * @param content 
     * @param username 
     * @param password 
     * @param filename 
     * @return 
     */  
    public static boolean sendAndCc(String smtp,String from,String to,String copyto,String subject,String content,String username,String password,String filename) {  
        Mail theMail = new Mail(smtp);  
        theMail.setNeedAuth(true); //需要验证  
          
        if(!theMail.setSubject(subject)) return false;  
        if(!theMail.setBody(content)) return false;  
        if(!theMail.addFileAffix(filename)) return false;   
        if(!theMail.setTo(to)) return false;  
        if(!theMail.setCopyTo(copyto)) return false;  
        if(!theMail.setFrom(from)) return false;  
        theMail.setNamePass(username,password);  
          
        if(!theMail.sendOut()) return false;  
        return true;  
    }  
      
}
代码分析:

第三行中 MimeMessage,前面介绍了MINE 代表多用途因特网邮件扩展标准,它继承自 Message类,javax.mail.Message 类是创建和解析邮件的核心API,它的实例对象可以理解为一封电子邮件

第四行中Session类,它是一个很容易被误解的类,这归咎于混淆视听的类名。千万不要以为这里的Session像HttpSession一样代表真实的交互会话,但创建Session对象时,并没有对应的物理连接,它只不过是一对配置信息的集合。Session的主要作用包括两个方面:

       1)接收各种配置属性信息:通过Properties对象设置的属性信息;

       2)初始化JavaMail环境:根据JavaMail的配置文件,初始化JavaMail环境,以便通过Session对象创建其他重要类的实例。

       所以,如果把Session更名为Configure也许更容易理解一些

第五行 Properties对象,他表示属性对象   

由于JavaMail需要和邮件服务器进行通信,这就要求程序提供许多诸如服务器地址、端口、用户名、密码等信息,JavaMail通过Properties对象封装这些属性的信息

第三十八行 是创建MINE邮件对象的过程,可以看出是通过session配置相应的properties对象信息,从而完成邮件的创建。

第185行是发送邮件的代码,可以看出先是通过session类初始化javaMail的初始环境,获取Properties对象;然后在调用session的Transport方法,(其实session有传输和存储两种方法,但是本web应用中只用到了邮件的发送,所以Store的相关方法不细讲)

Transport transport = mailSession.getTransport("smtp");   
 transport.connect((String)props.get("mail.smtp.host"),username,password); 

表示通过session获取指定类型的Transport,然后配置服务器端口,用户名和密码等相关验证信息。

第195行 表示消息发送

此处是使用  Transport 类。这个类用协议指定的语言发送消息(通常是 SMTP)。它是抽象类,它的工作方式与 Session 有些类似。仅调用静态 send() 方法

第273行用于验证发送是否成功。

上面我们对,邮件的发送进行了很好的封装,下面我们就通过一个web页面来进行调用测试

首先是一个我们的邮件发送客户端

<body>
	<center>
		<p>Send Email using JSP</p>
	</center>
	<form action="SendMailServlet" method="post" enctype="multipart/form-data">
	收件人:<input type="text"  name="to"><br>
	发件人:<input type="text"  name="from"><br>
	发件人密码:<input type="password"  name="password"><br>
	标题:<input type="text"  name="subject"><br>
	内容<br>
	<textarea name="content" rows="10" cols="80"></textarea><br>
	<input type="submit" value=http://www.mamicode.com/"提交">>交由后台的sendMailServlet处理,它的代码如下

public class SendMailServlet extends HttpServlet {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		// TODO Auto-generated method stub
		this.doPost(req, resp);
	}

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		String smtp = "smtp.163.com";
		String from = req.getParameter("from");
		String to = req.getParameter("to");
		String copyto = "601922@qq.com";
		String subject = req.getParameter("subject");
		String content = req.getParameter("content");
		String username=req.getParameter("from");
		String password=req.getParameter("password");
	 	
	 	
		Mail.sendAndCc(smtp, from, to, copyto, subject, content, username, password);
		
		if(Mail.send(smtp, from, copyto, subject, content, username, password)){
			req.setAttribute("result", "发送成功请到邮箱查收");
		}else{
			req.setAttribute("result", "发送失败");
		}
		
		req.getRequestDispatcher("MailResult.jsp").forward(req, resp);
	}

}
处理页面

<body>
          结果显示:${result}
  </body>
最后附上web.xml的配置文件

<servlet>
    <description>This is the description of my J2EE component</description>
    <display-name>This is the display name of my J2EE component</display-name>
    <servlet-name>SendMailServlet</servlet-name>
    <servlet-class>com.qzp.servlet.SendMailServlet</servlet-class>
  </servlet>
<servlet-mapping>
    <servlet-name>SendMailServlet</servlet-name>
    <url-pattern>/SendMailServlet</url-pattern>
  </servlet-mapping>

点击提交完成邮件发送。


以上就是一个完整的基于web的邮件发送系统。如有理解不到位的望大家指正。

基于web的java Mail的邮件发送系统的详解