JavaMail发送邮件

Posted on 2007-05-26 09:38 E.ven 阅读(1966) 评论(2)  编辑  收藏

昨天写一个JavaMail的程序,发现原来自己忘记了那么多呢,现在补上资料,方便以后回忆。

1.介绍:

Java Mail API的开发是SUN为Java开发者提供公用API框架的持续努力的良好例证。提倡公用框架,反对受限于供应商的解决方案,充分预示着一个日益开放的开发环境的建立。
  Java Mail API的结构本身证明了它的开发者的基本目标之一--软件开发的工作量应该取决于应用程序本身的复杂程度以及开发者所要求的控制程度。换句话说,Java Mail API尽可能地保持简单。乍看起来,JavaMail API所拥有的类总数以及类之间的关系可能让人误解为要花费漫长的学习时间。实际上,一旦正式开始使用,你就会发现该API不失为在应用程序中加入健壮的邮件/通讯支持的简单工具。

2.安装:

安装前要确保你的机子上安装得有标准版的JDK和Web服务器,并且已配置好,有关它们的安装方法,请参考其它文章(网上到处都有).

(1).安装JavaMail API。现在最常用的 JavaMail API 版本是1.3.
  要使用 JavaMail 1.3 API,请下载 JavaMail 1.3 实现,解开Javamail-1_3.zip 文件,并将 mail.jar 文件添加到 CLASSPATH 中。除了核心类,随版本 1.3 实现一起提供的还有 SMTP、IMAP4 和 POP3 供应商。
  
(2).JavaBeans Activation Framework(1.0.2版) 的安装
JavaMail API 的所有版本都需要 JavaBeans Activation Framework 来支持任意数据块的输入及相应处理。功能似乎不多,但目前许多浏览器和邮件工具中都能找到这种基本的 MIME 型支持。下载完框架后,解开 jaf1_0_2.zip 文件,并将 activation.jar 文件添加到 CLASSPATH 中。
  

注: 如果您使用的JDK是J2EE,就没有什么特定的事非要用基本 JavaMail API来做不可;J2EE 的类就能处理了,因为它本身就包含有JavaMail API和JAF,您只需要确将 j2ee.jar 文件添加到您的CLASSPATH 中并已全部设置好。
 

3.JavaMail的常用类介绍

事先说明:

没用过JavaMail的人可能看不懂这些介绍,不过不要紧,后面的文章有具体的实例,到时也可倒回来查看这些类的用法.


(1) javax.mail.Properties类
  JavaMail需要Properties来创建一个session对象。它将寻找字符串"mail.smtp.host",属性值就是发送邮件的主机.

用法:
 Properties props = new Properties ();
   props.put("mail.smtp.host", "smtp.163.com");//可以换上你的smtp主机名。


(2) javax.mail.Session类
  这个Session类代表JavaMail 中的一个邮件session. 每一个基于 JavaMail的应用程序至少有一个session但是可以有任意多的session。 在这个例子中, Session对象需要知道用来处理邮件的SMTP 服务器。

用法:
   Session sendMailSession;
   sendMailSession = Session.getInstance(props, null);


(3) javax.mail.Transport类
  邮件是既可以被发送也可以被受到。JavaMail使用了两个不同的类来完成这两个功能:Transport 和Store. Transport 是用来发送信息的,而Store用来收信。对于这的教程我们只需要用到Transport对象。

用法:
Transport transport;
  transport = sendMailSession.getTransport("smtp");

  用JavaMail Session对象的getTransport 方法来初始化Transport。传过去的字符串申明了对象所要使用的协议,如"smtp"。这将为我们省了很多时间。因为JavaMail以境内置了很多协议的实现方法。

 注意: JavaMail并不是绝对支持每一个协议,目前支持IMAP、 SMTP和 POP3.


(4) javax.mail.MimeMessage类
  Message对象将存储我们实际发送的电子邮件信息,Message对象被作为一个MimeMessage对象来创建并且需要知道应当选择哪一个JavaMail session。

  用法:
Message newMessage = new MimeMessage(sendMailSession);


(5) javax.mail.InternetAddress类
一旦您创建了 Session 和 Message,并将内容填入消息后,就可以用Address确定信件地址了。和 Message 一样,Address 也是个抽象类。您用的是Javax.mail.internet.InternetAddress 类.

用法:
InternetAddress from=new InternetAddress("xxf@cafe.com");


(6) javax.mail.Store类
Store类实现特定邮件协议上的读、写、监视、查找等操作。通过Javax.mail.Store类可以访问Javax.mail.Folder类。

用法:
Store store=s.getSorte("pop3");//s为一个邮件会话
store.connect(popserver,username,password);//通过你提供的pop地址,用户名和密码登录你的邮箱


(7) javax.mail.Folder类
Folder类用于分级组织邮件,并提供照Javax.mail.Message格式访问email的能力。

用法:
Folder folder=store.getFolder("INBOX");
folder.open(Folder.READ_ONLY);


(8) javax.mail.Internet.MimeMultpart
一般保存电子邮件内容的容器是Multipart抽象类,它定义了增加和删除及获得电子邮件不同部分内容的方法.由于Multipart是抽象类,我们必须为它使用一个具体的子类,JavaMail API提供javax.mail.Internet.MimeMultpart类来使用MimeMessage对象.

用法:
MimeMultipart multipart=new MimeMultipart();

注:我们使用MimeMultipart对象的一个方法是addBodyPart(),它在我们的电子邮件内容里添加BodyPart(BodyPart类在下面紧接着要介绍)对象.消息可以有很多部分,一个BodyPart可以代表一个部分.


(9) javax.mail.Internet.MimeBodyPart类

MimeBodyPart是BodyPart具体用于mimeMessage的一个子类.
MimeBodyPart对象代表一个MimeMessage对象内容的一部分.每个MimeBodyPart被认为有两部分:
⊙一个MIME类型
⊙匹配这个类型的内容

用法:
MimeBodyPart mdp=new MimeBodyPart();
String text="Hello JavaMail!";
mdp.setContent(text,"text/plain");//定义MIME类型为text/plain,并设置MimeBodyPart的内容.


(10) javax.activation.DataHandler类(包含在JAF中)
JavaMail API不限制信息只为文本,任何形式的信息都可能作茧自缚MimeMessage的一部分.除了文本信息,作为文件附件包含在电子邮件信息的一部分是很普遍的.JavaMail API通过使用DataHandler对象,提供一个允许我们包含非文本BodyPart对象的简便方法.

用法:
DataHandler dh=new DataHandler(text,type);
mdp.setDatahandler(dh);//mdp是一个MimeBodyPart对象


(11) javax.activation.FileDataSource类(包含在JAF中)
一个FileDataSource对象可以表示本地文件和服务器可以直接访问的资源.一个本地文件可以通过创建一个新的MimeBodyPart对象附在一个mimeMessage对象上.

用法:
MimeMultipart mm=new MimeMultipart();
MimeBodyPart mdp=new MimeBodyPart();
FileDataSource fds=new FileDataSource("c:/exam.txt");
mdp.setDataHandler(new DataHandler(fds)); //设置数据源
mm.addBodyPart(mdp); //为当前消息MimeMultipart对象增加MimeBodyPart


(12) javax.activation.URLDataSource类(包含在JAF中)
远程资源,URL不会指向它们,由一个URLDataSource对象表示.一个远程资源可以通过创建一个新mimeBodyPart对象附在一个mimeMessage对象上(同FileDataSource差不多).

用法:
与FileDataSource唯一不同的是数据源的设置:
URLDataSource uds=new URLDataSource( http://www.cnjsp.com/logo.gif );
 

4.试着编写第一个发送程序

在前面我们已对JavaMail作了一些介绍,下面我们可试着写自己的程序了.

首先,我们先写一个撰写邮件的html程序index.htm,如下:
-------------------------------------------------------------------------------------------
< html >
< head >
< meta http-equiv="Content-Type" content="text/html; charset=gb2312" >
< title > 撰写邮件 < /title >
< /head >

< body >
< form name="form1" method="post" action="testmail.jsp" >
< table width="75" border="0" align="center" cellspacing="1" bgcolor="#006600" class="black" >
< tr bgcolor="#FFFFFF" >
< td width="24%" > 收信人地址: < /td >
< td width="76%" >
< input name="to" type="text" id="to" >< /td >
< /tr >
< tr bgcolor="#FFFFFF" >
< td > 主题: < /td >
< td >
< input name="title" type="text" id="title" >< /td >
< /tr >
< tr >
< td height="107" colspan="2" bgcolor="#FFFFFF" >
< textarea name="content" cols="50" rows="5" id="content" >< /textarea >< /td >
< /tr >
< tr align="center" >
< td colspan="2" bgcolor="#FFFFFF" >
< input type="submit" name="Submit" value="发送" >
< input type="reset" name="Submit2" value="重置" >
< /td >
< /tr >
< /table >
< /form >
< /body >
< /html >


接着,我们再写一个处理程序testmail.jsp,如下:
-----------------------------------------------------------------------------------------
< %@ page contentType="text/html;charset=GB2312" % >
< %request.setCharacterEncoding("gb2312");% >< !--中文处理代码-- >

< !--引入要用到的类库-- >
< %@ page import="java.util.*,javax.mail.*"% >
< %@ page import="javax.mail.internet.*"% >

< html >
< head >
< meta http-equiv="Content-Type" content="text/html; charset=gb2312" >
< title > 发送成功 < /title >
< /head >

< body >
< %
try{

//从html表单中获取邮件信息
String tto=request.getParameter("to");
String ttitle=request.getParameter("title");
String tcontent=request.getParameter("content");

Properties props=new Properties();//也可用Properties props = System.getProperties();
props.put("mail.smtp.host","smtp.163.net");//存储发送邮件服务器的信息
props.put("mail.smtp.auth","true");//同时通过验证
Session s=Session.getInstance(props);//根据属性新建一个邮件会话
s.setDebug(true);

MimeMessage message=new MimeMessage(s);//由邮件会话新建一个消息对象

//设置邮件
InternetAddress from=new InternetAddress("boy@163.net");
message.setFrom(from);//设置发件人
InternetAddress to=new InternetAddress(tto);
message.setRecipient(Message.RecipientType.TO,to);//设置收件人,并设置其接收类型为TO
message.setSubject(ttitle);//设置主题
message.setText(tcontent);//设置信件内容
message.setSentDate(new Date());//设置发信时间

//发送邮件
message.saveChanges();//存储邮件信息
Transport transport=s.getTransport("smtp");
transport.connect("smtp.163.net","boy","iloveyou");//以smtp方式登录邮箱
transport.sendMessage(message,message.getAllRecipients());//发送邮件,其中第二个参数是所有
//已设好的收件人地址
transport.close();

% >
< div align="center" >
< p >< font color="#FF6600" > 发送成功! < /font >< /p >
< p >< a href="recmail.jsp" > 去看看我的信箱 < /a >< br >
< br >
< a href="index.htm" > 再发一封 < /a > < /p >
< /div >
< %
}catch(MessagingException e){
out.println(e.toString());
}
% >
< /body >
< /html >

**********************************注意***************************************

有好多书上和网上的文章在关键部分都是这样写testmail.jsp的,如下:

String tto=request.getParameter("to");
String ttitle=request.getParameter("title");
String tcontent=request.getParameter("content");
Properties props=new Properties();
props.put("mail.smtp.host","smtp.163.net");
Session s=Session.getInstance(props);
MimeMessage message=new MimeMessage(s);

InternetAddress from=new InternetAddress("boy@163.net");
message.setFrom(from);
InternetAddress to=new InternetAddress(tto);
message.setRecipient(Message.RecipientType.TO,to);

message.setSubject(ttitle);
message.setText(tcontent);
message.setSentDate(new Date());

Store store=s.getStore("pop3");
store.connect("pop.163.net","boy","iloveyou");//以pop3的方式登录邮箱
Transport transport=s.getTransport("smtp");
transport.send(message);
store.close();

事实上,这种方式并不可靠,因为很多电子邮局的smtp服务器要求我们通过验证,所以用这种方式发邮件时,只能发给同类邮箱(即相同smtp的邮箱),甚至有时同类邮箱也发不出去.以上两种方式我试过很多次,结果证明第一种方式是最可靠的.


好了,我相信你应该会写最简单的Email发送程序了.OK,下一次我们将说说怎样写发送HTML格式的邮件.
 
5.发送HTML格式的邮件

所谓HTML格式,就是超文本格式.你的邮件可以用HTML代码编写,发给对方后,对方收到的将是信息将是超文本,超文本比纯文本好看多了.下以面是在以前例子的基础上修改的程序:

< %@ page contentType="text/html;charset=GB2312" % >
< %request.setCharacterEncoding("gb2312");% >
< %@ page import="java.util.*,javax.mail.*"% >
< %@ page import="javax.mail.internet.*"% >
< html >
< head >
< meta http-equiv="Content-Type" content="text/html; charset=gb2312" >
< title > 发送成功 < /title >
< /head >

< body >
< %
try{
String tto=request.getParameter("to");
String ttitle=request.getParameter("title");
String tcontent=request.getParameter("content");
Properties props=new Properties();
props.put("mail.smtp.host","127.0.0.1");
props.put("mail.smtp.auth","true");
Session s=Session.getInstance(props);
s.setDebug(true);

MimeMessage message=new MimeMessage(s);

//给消息对象设置发件人/收件人/主题/发信时间
InternetAddress from=new InternetAddress("xxf@cafe.com");
message.setFrom(from);
InternetAddress to=new InternetAddress(tto);
message.setRecipient(Message.RecipientType.TO,to);
message.setSubject(ttitle);
message.setSentDate(new Date());


//给消息对象设置内容
BodyPart mdp=new MimeBodyPart();//新建一个存放信件内容的BodyPart对象
mdp.setContent(tcontent,"text/html;charset=gb2312");//给BodyPart对象设置内容和格式/编码方式
Multipart mm=new MimeMultipart();//新建一个MimeMultipart对象用来存放BodyPart对
//象(事实上可以存放多个)
mm.addBodyPart(mdp);//将BodyPart加入到MimeMultipart对象中(可以加入多个BodyPart)
message.setContent(mm);//把mm作为消息对象的内容

message.saveChanges();
Transport transport=s.getTransport("smtp");
transport.connect("127.0.0.1","xxf","coffee");
transport.sendMessage(message,message.getAllRecipients());
transport.close();
% >
< div align="center" >
< p >< font color="#FF6600" > 发送成功! < /font >< /p >
< p >< a href="recmail.jsp" > 去看看我的信箱 < /a >< br >
< br >
< a href="index.htm" > 再发一封 < /a > < /p >
< /div >
< %
}catch(MessagingException e){
out.println(e.toString());
}
% >
< /body >
< /html >

注:撰写邮件的html文件仍然和前面(请参考jsp和Java Mail(三))那个一样,不需要作任何修改.

怎么样,这个程序是不是很简单呢?如果还有什么不懂的话,请在下面留言.下一次我们将要讲一讲怎样发送附件.
 
七.编写灵活的发送程序

本小节没加什么新鲜的东西,但是综合了以前的所有内容,可以让你灵活地发送你想要发的邮件.看了本小节之后对你会感觉到非常有用.

更改后的撰写界面程序如下:
-------------------------------------------------------------------------------------------
< html >
< head >
< meta http-equiv="Content-Type" content="text/html; charset=gb2312" >
< title > 撰写邮件 < /title >
< /head >
< body >
< form action="testall.jsp" method="post" name="form1" >
< table width="75" border="0" align="center" cellspacing="1" bgcolor="#006600" class="black" >
< tr bgcolor="#FFFFFF" >
< td width="24%" > 收信人地址: < /td >
< td width="76%" > < input name="to" type="text" id="to" >< /td >
< /tr >
< tr bgcolor="#FFFFFF" >
< td > 主题: < /td >
< td > < input name="title" type="text" id="title" >< /td >
< /tr >
< tr >
< td height="18" colspan="2" bgcolor="#FFFFFF" > 信件类型
< select name="emailtype" id="emailtype" >
< option value="text/plain" selected > Text < /option >
< option value="text/html" > Html < /option >
< /select >< /td >
< /tr >
< tr >
< td height="53" colspan="2" bgcolor="#FFFFFF" >< textarea name="content" cols="50" rows="5" id="content" >< /textarea >< /td >
< /tr >
< tr align="center" >
< td colspan="2" bgcolor="#FFFFFF" > 附件1(自定义):
< input name="fj1" type="text" id="fj1" >
(输入文本信息) < /td >
< /tr >
< tr align="center" valign="bottom" >
< td colspan="2" bgcolor="#FFFFFF" > 附件2(本地):
< input name="fj2" type="file" id="fj2" size="10" >< /td >
< /tr >
< tr align="center" >
< td colspan="2" bgcolor="#FFFFFF" > 附件3(远程):
< input name="fj3" type="text" id="fj3" value="http://" >
(输入URL) < /td >
< /tr >
< tr align="center" >
< td colspan="2" bgcolor="#FFFFFF" > < input type="submit" name="Submit" value="发送" >
< input type="reset" name="Submit2" value="重置" >< /td >
< /tr >
< /table >
< /form >
< /body >
< /html >


处理邮件的JSP程序如下:
----------------------------------------------------------------------------------------
< %@ page contentType="text/html;charset=GB2312" % >
< %request.setCharacterEncoding("gb2312");% >
< %@ page import="java.util.*,javax.mail.*"% >
< %@ page import="javax.mail.internet.*"% >
< %@ page import="javax.activation.*"% >< !--要发送附件必须引入该库-- >
< %@ page import="java.net.*"% >< !--要用到URL类-- >
< html >
< head >
< meta http-equiv="Content-Type" content="text/html; charset=gb2312" >
< title > 发送成功 < /title >
< /head >
< body >
< %
try{
String tto=request.getParameter("to");
String ttitle=request.getParameter("title");
String emailtype=request.getParameter("emailtype");//获取email类型
String tcontent=request.getParameter("content");
String tfj1=request.getParameter("fj1");
String tfj2=request.getParameter("fj2");
String tfj3=request.getParameter("fj3");

Properties props=new Properties();
props.put("mail.smtp.host","127.0.0.1");
props.put("mail.smtp.auth","true");
Session s=Session.getInstance(props);
s.setDebug(true);

MimeMessage message=new MimeMessage(s);

//给消息对象设置发件人/收件人/主题/发信时间
InternetAddress from=new InternetAddress("xxf@cafe.com");
message.setFrom(from);
InternetAddress to=new InternetAddress(tto);
message.setRecipient(Message.RecipientType.TO,to);
message.setSubject(ttitle);
message.setSentDate(new Date());

Multipart mm=new MimeMultipart();//新建一个MimeMultipart对象用来存放多个BodyPart对象

//设置信件文本内容
BodyPart mdp=new MimeBodyPart();//新建一个存放信件内容的BodyPart对象
mdp.setContent(tcontent,emailtype+";charset=gb2312");//给BodyPart对象设置内容和格式/编码方式
mm.addBodyPart(mdp);//将含有信件内容的BodyPart加入到MimeMultipart对象中

//设置信件的附件1(自定义附件:直接将所设文本内容加到自定义文件中作为附件发送)
mdp=new MimeBodyPart();//新建一个存放附件的BodyPart
DataHandler dh=new DataHandler(tfj1,"text/plain;charset=gb2312");
//新建一个DataHandler对象,并设置其内容和格式/编码方式
mdp.setFileName("text.txt");//加上这句将作为附件发送,否则将作为信件的文本内容
mdp.setDataHandler(dh);//给BodyPart对象设置内容为dh
mm.addBodyPart(mdp);//将含有附件的BodyPart加入到MimeMultipart对象中

//设置信件的附件2(用本地上的文件作为附件)
mdp=new MimeBodyPart();
FileDataSource fds=new FileDataSource(tfj2);
dh=new DataHandler(fds);
int ddd=tfj2.lastIndexOf("\\");
String fname=tfj2.substring(ddd);//提取文件名
String ffname=new String(fname.getBytes("gb2312"),"ISO8859-1");//处理文件名是中文的情况
mdp.setFileName(ffname);//可以和原文件名不一致,但最好一样
mdp.setDataHandler(dh);
mm.addBodyPart(mdp);

//设置信件的附件3(用远程文件作为附件)
mdp=new MimeBodyPart();


URL urlfj=new URL(tfj3);
URLDataSource ur=new URLDataSource(urlfj);
//注:这里用的参数只能为URL对象,不能为URL字串,在前面类介绍时有误(请谅解),这里纠正一下.
dh=new DataHandler(ur);
int ttt=tfj3.lastIndexOf("/");
String urlname=tfj3.substring(ttt);
//String urlfname=new String(urlname.getBytes("gb2312"),"ISO8859-1");//不知怎么回事,这里不能处理中文问题
mdp.setFileName(urlname);
mdp.setDataHandler(dh);
mm.addBodyPart(mdp);

message.setContent(mm);//把mm作为消息对象的内容

message.saveChanges();
Transport transport=s.getTransport("smtp");
transport.connect("127.0.0.1","xxf","coffee");
transport.sendMessage(message,message.getAllRecipients());
transport.close();
% >
< div align="center" >
< p >< font color="#FF6600" > 发送成功! < /font >< /p >
< p >< a href="recmail.jsp" > 去看看我的信箱 < /a >< br >
< br >
< a href="index.htm" > 再发一封 < /a > < /p >
< /div >
< %
}catch(MessagingException e){
out.println(e.toString());
}
% >
< /body >
< /html >

到目前为止,我们基本上已学会了发各种类型的邮件了.
这里最加上一些在实践工程中遇到的一些问题:
1    发送Email认证。现在很多Email服务器在SMTP发送前需要做用户名密码认证。
不然会抛出javax.mail.AuthenticationFailedException,
解决办法:
final String username = "username";
        final String password = "password";
       
        //使用验证
        Session session = Session.getDefaultInstance(props,
                new Authenticator() {
                    protected javax.mail.PasswordAuthentication getPasswordAuthentication() {
                        return new javax.mail.PasswordAuthentication(username,
                                password);
                    }
                });

把username,password改成你邮箱的用户名和密码

2当要发邮件的对象不单是一个,是很多个的时候:
String to[] = request.getParameterValues("check_box");//获取收件人email地址
  ArrayList arraylist = new ArrayList();
  for(int i=0;i < to.length;i++)
     {
      arraylist.add(new InternetAddress(to[i]));
     }   //收件地址放进队列
Message msg = new MimeMessage(s);
     msg.setFrom(new InternetAddress(from));//设置发件人
  msg.setRecipients(Message.RecipientType.TO, (InternetAddress[])arraylist.toArray(new InternetAddress[arraylist.size()]));
     msg.setSubject(subject);//设置主题
     msg.setSentDate(new Date());//设置发信时
  BodyPart mdp=new MimeBodyPart();//新建一个存放信件内容的BodyPart对象
msg.setRecipients(Message.RecipientType.TO, (InternetAddress[])arraylist.toArray(new InternetAddress[arraylist.size()]));

以上是邮件经常遇到的问题,特此纪录

Feedback

# re: JavaMail发送邮件  回复  更多评论   

2007-06-22 16:13 by PLACE
渠道网(低价注册公司)专业从事注册香港公司、海外公司注册、深圳公司注册、注册商标、注册国际书刊号及提供注册公司后企业运作的配套服务,公司注册成立后是企业运作的开始,渠道网并提供:项目融资、项目投资、企业形象资金、公司注册验资及全国打款、国际框架组建、品牌概念合作、品牌加盟、投资移民、技术移民、海外形象代言人、海外股东信托、代理记帐报税、企业营销咨询、企业合理避税、品牌规划、香港上市、新加坡上市、美国上市公关、GOOGLE左侧排名、网站建设、网站推广、企业无抵押无担保融资等系列配套服务。并提供快速消费渠道信息,实现渠道信息共享!如何注册公司请立即咨询:罗鸿汇先生13510141316

# re: JavaMail发送邮件  回复  更多评论   

2007-10-30 14:53 by mashiguang
"(10) javax.activation.DataHandler类(包含在JAF中)
JavaMail API不限制信息只为文本,任何形式的信息都可能作茧自缚MimeMessage的一部分.除了文本信息,作为文件附件包含在电子邮件信息的一部分是很普遍的.JavaMail API通过......"

"作茧自缚"这个词是这样用的吗?

只有注册用户登录后才能发表评论。


网站导航:
 

posts - 27, comments - 15, trackbacks - 0, articles - 1

Copyright © E.ven