Java实践之路——JavaMail

今天讲述java组件JavaMail实现邮件的发送功能

 

应用一下百度百科上面JavaMail的描述

 

=================================================================

 

       JavaMail,顾名思义,提供给开发者处理电子邮件相关的编程接口。它是Sun发布的用来处理email的API。它可以方便地执行一些常用的邮件传输。我们可以基于JavaMail开发出类似于Microsoft Outlook的应用程序  
 
        虽然JavaMail是Sun的API之一,但它目前还没有被加在标准的java开发工具包中(Java Development Kit),这就意味着你在使用前必须另外下载JavaMail文件。除此以外,你还需要有Sun的JavaBeans Activation Framework (JAF)。JavaBeans Activation Framework的运行很复杂,在这里简单的说就是JavaMail的运行必须得依赖于它的支持。在Windows 2000下使用需要指定这些文件的路径,在其它的操作系统上也类似。
  JavaMail是可选包,因此如果需要使用的话你需要首先从java.sun.com下载。目前最新版本是JavaMail1.4,使用JavaMail的时候需要Javabean Activation Framework的支持,因此你也需要下载JAF。安装JavaMail只是需要把他们加入到CLASSPATH中去,如果你不想修改CLASSPATH的话,可以直接把他们的jar包直接copy到JAVA_HOME/lib/ext下。这样JavaMail就安装好了。
  JavaMail包中用于处理电子邮件的核心类是:Session,Message,Address,Authenticator,Transport,Store,Folder等。Session定义了一个基本的邮件会话,它需要从Properties中读取类似于邮件服务器,用户名和密码等信息。
 
===============================================================
 
原理性的东西还是需要懂一些的,不然就只是盲从了,我就属于这种。呵呵,毕竟是初期接触,以后慢慢理解了。
 
在网上找了一些资料,根据自己的理解整理了一下,其中还是遇到了很多问题,下面讲述一下具体的过程
 
 
首先开发JavaMail,必须借助JavaMail的API,这些API在j2se的jdk中一般不存在,需要自己下载。然而我用的是jee5,里面自带了JavaMail的API和JAF,感觉方面,庆幸
 
按照“ Java实践之路——Jsp+Servlet+JavaBean”中的项目框架来实现,我们先写实体类,这里我们不对数据进行存储,所以就没必要整db和dao层的东西了
 
entity包中的Email.java,代码如下
package entity;

import java.util.Vector;

public class Email {
	private String mailTo = null;
	private String mailFrom = null;
	private String smtpHost = null;
	private String messageBasePath = "";
	private String subject;
	private String msgContent;
	private Vector attachedFileList;
	private String mailAccount = null;
	private String mailPass = null;
	private String messageContentMimeType = "text/html; charset=gb2312";
	private String mailbccTo = null;
	private String mailccTo = null;
	
	
	public String getMailTo() {
		return mailTo;
	}
	public void setMailTo(String mailTo) {
		this.mailTo = mailTo;
	}

	public String getMailFrom() {
		return mailFrom;
	}

	public void setMailFrom(String mailFrom) {
		this.mailFrom = mailFrom;
	}

	public String getSmtpHost() {
		return smtpHost;
	}

	public void setSmtpHost(String smtpHost) {
		this.smtpHost = smtpHost;
	}

	public String getMessageBasePath() {
		return messageBasePath;
	}

	public void setMessageBasePath(String messageBasePath) {
		this.messageBasePath = messageBasePath;
	}

	public String getSubject() {
		return subject;
	}

	public void setSubject(String subject) {
		this.subject = subject;
	}

	public String getMsgContent() {
		return msgContent;
	}

	public void setMsgContent(String msgContent) {
		this.msgContent = msgContent;
	}

	public Vector getAttachedFileList() {
		return attachedFileList;
	}

	public void setAttachedFileList(Vector attachedFileList) {
		this.attachedFileList = attachedFileList;
	}

	public String getMailAccount() {
		return mailAccount;
	}

	public void setMailAccount(String mailAccount) {
		this.mailAccount = mailAccount;
	}

	public String getMailPass() {
		return mailPass;
	}

	public void setMailPass(String mailPass) {
		this.mailPass = mailPass;
	}

	public String getMessageContentMimeType() {
		return messageContentMimeType;
	}

	public void setMessageContentMimeType(String messageContentMimeType) {
		this.messageContentMimeType = messageContentMimeType;
	}

	public String getMailbccTo() {
		return mailbccTo;
	}

	public void setMailbccTo(String mailbccTo) {
		this.mailbccTo = mailbccTo;
	}

	public String getMailccTo() {
		return mailccTo;
	}

	public void setMailccTo(String mailccTo) {
		this.mailccTo = mailccTo;
	}

	public Email(){}
	
	
}

这里定义了Email的基本数据,和一些数据接口
 
然后定义业务逻辑,bean中的EmailBean.java,代码如下
 
package bean;

import java.io.IOException;
import java.util.Date;
import java.util.Enumeration;
import java.util.Properties;

import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.AuthenticationFailedException;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
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 mail.MailAuthenticator;
import entity.Email;

public class EmailBean {
	private Email email;
	// 是否采用调试方式
	private boolean debug = false;

	public Email getEmail() {
		return email;
	}

	public void setEmail(Email email) {
		this.email = email;
	}
	
	public EmailBean(){}
	
	public EmailBean(Email email)
	{
		this.email=email;
	}

	private void fillEmail(Session session, MimeMessage msg) throws IOException,
			MessagingException {
		String fileName = null;
		Multipart mPart = new MimeMultipart();
		if (email.getMailFrom() != null) {
			msg.setFrom(new InternetAddress(email.getMailFrom()));
			System.out.println("发送人Mail地址:" + email.getMailFrom());
		} else {
			System.out.println("没有指定发送人邮件地址!");
			return;
		}
		if (email.getMailTo() != null) {
			InternetAddress[] address = InternetAddress.parse(email.getMailTo());
			msg.setRecipients(Message.RecipientType.TO, address);
			System.out.println("收件人Mail地址:" + email.getMailTo());
		} else {
			System.out.println("没有指定收件人邮件地址!");
			return;
		}
		if (email.getMailccTo() != null) {
			InternetAddress[] ccaddress = InternetAddress.parse(email.getMailccTo());
			System.out.println("CCMail地址:" + email.getMailccTo());
			msg.setRecipients(Message.RecipientType.CC, ccaddress);
		}
		if (email.getMailbccTo() != null) {
			InternetAddress[] bccaddress = InternetAddress.parse(email.getMailbccTo());
			System.out.println("BCCMail地址:" + email.getMailbccTo());
			msg.setRecipients(Message.RecipientType.BCC, bccaddress);
		}
		msg.setSubject(email.getSubject());
		InternetAddress[] replyAddress = { new InternetAddress(email.getMailFrom()) };
		msg.setReplyTo(replyAddress);
		// create and fill the first message part
		MimeBodyPart mBodyContent = new MimeBodyPart();
		if (email.getMsgContent() != null)
			mBodyContent.setContent(email.getMsgContent(), email.getMessageContentMimeType());
		else
			mBodyContent.setContent("", email.getMessageContentMimeType());
		mPart.addBodyPart(mBodyContent);
		// attach the file to the message
		if (email.getAttachedFileList() != null) {
			for (Enumeration fileList = email.getAttachedFileList().elements(); fileList
					.hasMoreElements();) {
				fileName = (String) fileList.nextElement();
				MimeBodyPart mBodyPart = new MimeBodyPart();
				// attach the file to the message
				FileDataSource fds = new FileDataSource(email.getMessageBasePath()
						+ fileName);
				System.out.println("Mail发送的附件为:" + email.getMessageBasePath() + fileName);
				mBodyPart.setDataHandler(new DataHandler(fds));
				mBodyPart.setFileName(fileName);
				mPart.addBodyPart(mBodyPart);
			}
		}
		msg.setContent(mPart);
		msg.setSentDate(new Date());
	}

	public String sendEmail() throws IOException, MessagingException {
		
		Properties props = System.getProperties();
		props.put("mail.smtp.host", email.getSmtpHost());
		props.put("mail.smtp.auth", "true");
		props.setProperty("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");     
        props.setProperty("mail.smtp.socketFactory.fallback", "false");     
        props.setProperty("mail.smtp.port", "465");     
        props.setProperty("mail.smtp.socketFactory.port", "465");   

		MailAuthenticator auth = new MailAuthenticator();
		Session session = Session.getInstance(props, auth);
		session.setDebug(debug);
		MimeMessage msg = new MimeMessage(session);
		Transport trans = null;
		
		String result="";
		
		try {
			fillEmail(session, msg);
			// send the message
			trans = session.getTransport("smtp");
			try {
				trans.connect(email.getSmtpHost(), MailAuthenticator.MAIL_USER,
						MailAuthenticator.MAIL_PASSWORD);
			} catch (AuthenticationFailedException e) {
				e.printStackTrace();
				result = "连接邮件服务器错误";
				return result;
			} catch (MessagingException e) {
				result = "连接邮件服务器错误";
				return result;
			}
			Transport.send(msg);
			trans.close();
		} catch (MessagingException mex) {
			result = "发送邮件失败";
			mex.printStackTrace();
			Exception ex = null;
			if ((ex = mex.getNextException()) != null) {
				System.out.println(ex.toString());
				ex.printStackTrace();
			}
			return result;
		} finally {
			try {
				if (trans != null && trans.isConnected())
					trans.close();
			} catch (Exception e) {
				System.out.println(e.toString());
			}
		}
		System.out.println("发送邮件成功!");
		return "";
	}

}

这里定义了一个业务逻辑,就是发送邮件,用到了大量的JavaMail的API,还用刀了JAF中的DataHandler和FileDataSource类,主要用来处理附件的发送。程序中还有一个类MailAuthenticator,这是一个自定义的关于认证授权的类,它继承自Authenticator类,代码如下
package mail;

import javax.mail.Authenticator;
import javax.mail.PasswordAuthentication;

public class MailAuthenticator extends Authenticator {
	
    public static String MAIL_USER = "[email protected]"; 
    public static String MAIL_PASSWORD = "xx"; 

    public MailAuthenticator() 
    { 
    } 

    protected PasswordAuthentication getPasswordAuthentication() 
    { 
        return new PasswordAuthentication(MAIL_USER, MAIL_PASSWORD); 
    } 


}
这里从新自定义的目的是为了方便测试,程序中固定发送者的账号和密码,就不用每次输入了。我把它放在了mail包中
 
接下来是服务类,EmailService.java,代码如下
 
package service;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Vector;

import javax.mail.MessagingException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import bean.EmailBean;
import entity.Email;

public class EmailService {
	
	private HttpServletRequest req;
	private HttpServletResponse res;
	
	public HttpServletRequest getReq() {
		return req;
	}

	public void setReq(HttpServletRequest req) {
		this.req = req;
	}

	public HttpServletResponse getRes() {
		return res;
	}

	public void setRes(HttpServletResponse res) {
		this.res = res;
	}

	public EmailService()
	{
		
	}
	
	public EmailService(HttpServletRequest req,HttpServletResponse res)
	{
		this.req=req;
		this.res=res;
	}
	
	public void sendEmail(String stmp,String from,String to,
			String subject,String content,String atachs){
		Email email=new Email();
		
		email.setSmtpHost(stmp);
		email.setMailFrom(from);
		email.setMailTo(to);
		email.setSubject(subject);
		email.setMsgContent(content);
		Vector vec=new Vector();
		
		String[] atach_list=atachs.split(";");
		
		for(String atach:atach_list)
		{
			vec.add(atach);
		}
		String result="";
		email.setAttachedFileList(vec);
		
		EmailBean bean=new EmailBean(email);
		
		try {
			result=bean.sendEmail();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (MessagingException e) {
			e.printStackTrace();
		}
		
		try {
			PrintWriter out = this.res.getWriter();
			
			if(result.equals(""))
			{
				out.print("success");
			}
			else
			{
				out.print(result);
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

这里也只提供了一个服务,就是发送邮件的服务。根据传送进来的数据,构建一个Email对象,然后放到业务逻辑bean中
 
然后就是请求的处理servlet中的EmailServlet.java了,代码如下
package 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 service.EmailService;
import service.UserService;

public class EmailServlet extends HttpServlet {

	private EmailService service;
	/**
	 * Constructor of the object.
	 */
	public EmailServlet() {
		super();
	}

	/**
	 * Destruction of the servlet. 
*/ public void destroy() { super.destroy(); // Just puts "destroy" string in log // Put your code here } /** * The doGet method of the servlet.
* * This method is called when a form has its tag value method equals to get. * * @param request the request send by the client to the server * @param response the response send by the server to the client * @throws ServletException if an error occurred * @throws IOException if an error occurred */ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request,response); } /** * The doPost method of the servlet.
* * This method is called when a form has its tag value method equals to post. * * @param request the request send by the client to the server * @param response the response send by the server to the client * @throws ServletException if an error occurred * @throws IOException if an error occurred */ public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html"); response.setCharacterEncoding("UTF-8"); request.setCharacterEncoding("UTF-8"); service=new EmailService(request,response); String action=""; action=request.getParameter("action"); if(action==null || action.equals("")) { return; } //集中处理请求类型 if(action.toUpperCase().equals("SENDEMAIL")) { String stmp=request.getParameter("stmp_host"); String from=request.getParameter("mail_from"); String to=request.getParameter("mail_to"); String subject=request.getParameter("mail_subject"); String content=request.getParameter("mail_content"); String atachs=request.getParameter("mail_atach_list"); service.sendEmail(stmp,from,to,subject,content,atachs); } } /** * Initialization of the servlet.
* * @throws ServletException if an error occurs */ public void init() throws ServletException { // Put your code here } }

注意在web.xml中进行配置,这里就贴代码了
 
最后就是程序入口,web呈现层,代码如下
 
 
stmp服务器:
发送者地址:
接收者地址:
主题:
内容:
附件
ajax处理请求的js代码
当然要借助jquery了,注意这里要采用post的请求方式。
 
顺便把集中常用邮箱的stmp和pop服务器贴上来
怎样设置邮箱收发服务器(pop3\stmp)
163邮箱
  POP3服务器:pop3.163.com
  SMTP服务器:smtp.163.com
Yahoo邮箱
   POP3服务器:pop.mail.yahoo.com.cn
   SMTP服务器:smtp.mail.yahoo.com
搜狐邮箱
  POP3服务器:pop3.sohu.com 
  SMTP服务器:smtp.sohu.com
新浪邮箱
  POP3服务器:pop.sina.com.cn 或pop3.sina.com.cn 
  SMTP服务器:smtp.sina.com.cn
     请选择smtp服务器要求身份验证选项
139邮箱
  POP3服务器:pop3.139.com 
  SMTP服务器:smtp.139.com
Gmail邮箱
    POP3服务器:pop.gmail.com  端口:995  开启ssl
    SMTP服务器:smtp.gmail.com  端口:465 或者587  开启ssl
    帐号即用户名,密码相同,邮件地址为[email protected]
QQ邮箱
  POP3服务器:pop.qq.com 
  SMTP服务器:smtp.qq.com
      SMTP服务器需要身份验证
tom邮箱
  POP3服务器:pop.tom.com.cn
  SMTP服务器:smtp.tom.com.cn

完整可运行的代码就贴完了,做的过程中还是遇到了很多问题,这这里总结一下
 
总结:
 
1、因为我采用的是jee5中自带的JavaMail的API,然后tomcat中部署运行时,出现了如下错误
      
java.lang.ClassNotFoundException: javax.mail.MessagingException

这是因为,tomcat没有识别到JavaMail的API类的原因,现在不庆幸当时自带的方便了。本来以为所有的API都可以在javaee.jar中找到,所以把这个jar包拷贝到WEB-INF下的lib目录下,结果不行。拷贝到tomcat的lib目录中,报错如下
java.lang.NoSuchMethodError: javax.servlet.ServletContext.getContextPath ()Ljava/lang/String;  

在网上找了一下资料,其实是jar冲突问题,所以把tomcat目录下的lib目录中刚拷贝的javaee.jar删除,可以启动服务器。但是还是没有解决tomcat无法找到JavaMail API的问题,没办法,只有去下载了一个mail.jar放到WEB-INF下的lib目录中,结果就可以了
 
2、测试时,我采用了google的gmail作为发送者,结果还是发送失败,那是因为,gmail必须设置端口号和开启ssl,从上面的stmp和pop服务器列表说明上就可以看出,其他的应该不设置也应该可以发送
 
3、这里没有测试大附件的发送,没有测试出现超时的情况等
 
 

 基本上就这些了,有任何问题欢迎交流学习

你可能感兴趣的:(java)