今天讲述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 = "xx@gmail.com";
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. <br>
*/
public void destroy() {
super.destroy(); // Just puts "destroy" string in log
// Put your code here
}
/**
* The doGet method of the servlet. <br>
*
* 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. <br>
*
* 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. <br>
*
* @throws ServletException if an error occurs
*/
public void init() throws ServletException {
// Put your code here
}
}
注意在web.xml中进行配置,这里就贴代码了
最后就是程序入口,web呈现层,代码如下
<div id="mail">
<div><span>stmp服务器:</span><span><input type="text" id="stmp_host" value="smtp.gmail.com"/></span></div>
<div><span>发送者地址:</span><span><input type="text" id="from" value="xx@gmail.com"/></span></div>
<div><span>接收者地址:</span><span><input type="text" id="to" value="xx@126.com"/></span></div>
<div><span>主题:</span><span><input type="text" id="subject" value="javaemail"/></span></div>
<div><span>内容:</span><span><input type="text" id="content" value="do you recieve my message"/></span></div>
<div>
<span>附件</span>
<span><input type="file" id="atach" /></span>
<span><input type="button" value="add" οnclick="newAtach();" /></span>
</div>
<div id="atach_list">
</div>
<div><span><input type="button" value="send" οnclick="sendEmail();"/></span></div>
<div id="email_result"></div>
</div>
ajax处理请求的js代码
<script type="text/javascript">
var atach_list=[];
function sendEmail()
{
var stmp=$("#stmp_host").val();
var from=$("#from").val();
var to=$("#to").val();
var subject=$("#subject").val();
var content=$("#content").val();
alert(atach_list[0]);
var atachs="";
$.each(atach_list,function(n,atach){
atachs+=atach+";";
});
atachs=atachs.substring(0,atachs.length-1);
alert(atachs);
$.post("EmailServlet",{action:"SENDEMAIL",
stmp_host:stmp,
mail_from:from,
mail_to:to,
mail_subject:subject,
mail_content:content,
mail_atach_list:atachs},
function(data){
if(data=="success")
{
$("#email_result").append("邮件发送成功");
}
else
{
$("#email_result").append(data);
}
});
}
function newAtach()
{
var atach=$("#atach").val();
if(atach!="")
{
atach_list[atach_list.length]=atach;
$("#atach_list").append('<div id="atach'+atach_list.length+'">'+atach+'</div>');
$("#atach").val("");
}
else
{
return;
}
}
</script>
当然要借助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
帐号即用户名,密码相同,邮件地址为username@gmail.com
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、这里没有测试大附件的发送,没有测试出现超时的情况等
基本上就这些了,有任何问题欢迎交流学习