您的位置:首页 > 编程语言 > Java开发

使用JAMES & JavaMail搭建邮件系统

2009-06-20 20:41 351 查看
使用JAMES & JavaMail搭建邮件系统[/b]
一、简介
Apache James(Java Apache Mail Enterprise Server)是Apache组织的子项目之一,完全采用纯Java技术开发,实现了SMTP、POP3与NNTP等多种邮件相关协议。
James也是一个邮件应用平台,可以通过Mailet扩充其功能,如Mail2SMS、Mail2Fax等。James提供了比较完善的配置方案,尤其是关于邮件内容存储和用户信息存储部分,可以选择在文件、数据库或其他介质中保存。
James性能稳定、可配置性强,还是开源项目,所有源代码不存在版权问题,因此,James在项目中的应用日益广泛,现在常用版本为2.1,但最新版本2.3已经推出,在本文中,我们将仍以James2.1作为介绍蓝本。
二、安装与配置[/b][/b]
James的安装配置过程非常简单。
第一步:安装JDK
请使用JDK1.3以上版本(推荐使用JDK1.4),假设安装在c:/jdk1.3。
第二步:下载James,并解压
可以到Apache网站上下载James2.1,下载将得到一个压缩文件james-2.1.zip,大小为4.45M,将此包解压到c:/james。
第三步:直接运行或需要配置J***A_HOME
这时,可以尝试直接双击c:/james/bin/run.bat,若启动无误,将提示如下:
Using PHOENIX_HOME: C:/james

Using PHOENIX_TMPDIR: C:/james/temp

Using J***A_HOME:



Phoenix 4.0.1



James 2.1

Remote Manager Service started plain:4555

POP3 Service started plain:110

SMTP Service started plain:25

NNTP Service Disabled

Fetch POP Disabled
也有可能启动不了,并报J***A_HOME找不到,这时,需要指定J***A_HOME,比较简单的方法是在c:/james/bin/run.bat中指定J***A_HOME,修改后的run.bat如下:
……

rem

rem Determine if J***A_HOME is set and if so then use it

rem

set J***A_HOME= c:/jdk1.3

if not "%J***A_HOME%"=="" goto found_java

……
三、项目应用[/b] [/b]
某单位,有16个职能处室,共78台电脑(操作系统为Win98/2000/xp),其中有1台为专用服务器(Win2000),已连成局域网。为使单位内部的信息交流,尤其是文件交互更加便捷,单位决定在局域网内部架设一套E-mail系统。
1、解决方案
在专用服务器上安装James2.1,客户端使用操作系统自带的Outlook Express。
(1)、服务器端配置
首先找出专用服务器的名字,假设叫unitname。
然后打开文件c:/james/apps/james/SAR-INF/config.xml。
在config.xml文件中,找到<postmaster>Postmaster@localhost</postmaster>,把此项改为<postmaster>Postmaster@unitname</postmaster>,同理,找到<servername>localhost</servername>,把此项改为<servername>unitname</servername>。其实,改这两项就是把默认的localhost改为机器名,这样做是为了让其它机器也能访问邮件系统,当然,前提是在局域网上没有与服务器重名的机器。
(2)、客户端配置
假设有一个账号,用户名为holen,密码为123456,如何在Outlook中配置呢?
首先,根据用户名,可以得出该用户邮箱地址为holen@unitname ,然后在输入POP3和SMTP服务器时,直接使用服务器机器名unitname即可。
(3[/b])、用Telnet[/b]管理用户 [/b]
  用cmd进入MS-DOS,输入telnet localhost 4555 (注:localhost是邮件服务器名,4555是管理端口,可在/apps/james/SAR-INF/config.xml文件中配置,在此我们使用其默认配置)

  然后输入用户名和密码(在配置文件config.xml中,默认为用户名:root密码:root)

出现如下信息说明登陆成功:
在<administrator_accounts>节中可以修改默认帐户密码
在remotemanager中可以修改登陆端口

在postmaster中可以修改邮箱域名
登陆成功后,我们就可以开始对用户信息进行增、删、查、改等操作了。

常用的用户信息操作命令参见下表:
Currently implemented commands: 常用实现命令
help display this help 显示帮助信息
listusers display existing accounts 显示现有账户
countusers display the number of existing accounts 显示现有账户数量
adduser [username] [password] add a new user 添加一个新用户
verify [username] verify if specified user exist 核实指定用户是否存在
deluser [username] delete existing user 删除存在的用户
setpassword [username] [password] sets a user's password 设置用户密码
setalias [user] [alias] locally forwards all email for 'user' to 'alias' 设置邮箱别名
showalias [username] shows a user's current email alias 显示别名
unsetalias [user] unsets an alias for 'user' 删除用户别名
setforwarding [username] [emailaddress] forwards a user's email to another email address 转发用户的电子邮件地址到另一个电子邮件地址
showforwarding [username] shows a user's current email forwarding 显示用户的当前邮件转发
unsetforwarding [username] removes a forward 删除转发
user [repositoryname] change to another user repository 改变另一个用户库
shutdown kills the current JVM (convenient when James is run as a daemon) 关闭当前的服务
quit close connection 关闭连接
(4[/b])、Java Mail[/b]
1.包准备:mail.jar和activation.jar
2.发送邮件需要做如下一些事情:
配置邮件服务器属性信息,
配置邮件接收地址,
使用SMTP认证获得会话(Session),
构建邮件体(MimeMessage),
发送邮件。
(5[/b])、Message[/b]存储结构[/b]

Message是邮件发送的最终对象,我们一般使用他的子类对象MimeMessage,其子类对象里包含有邮件的MessageID、Subject、Flag、From、Sender、Content等信息,Content是邮件的内容体,其一般是一个Multipart对象(或其子类对象MimeMultipart),所有的邮件内容都存在于Multipart中的。一个Multipart包含有一个或多个BodyPart对象(或其子类对象MimeBodyPart),BodyPart对象用于存储邮件的内容,可以是文本形式,也可以是附件形式。

(6[/b])、Session[/b]
Session类定义了一个基本邮件会话,它是Javamail API最高层入口类,所有其它类都必须经由Session对象才得以生效。Session对象管理配置选项和用于与邮件系统交互的用户认证信息,它使用java.util.Properties对象获取信息,如邮件服务器、用户名、密码及整个应用程序中共享的其它信息。

  Session类的构造器是私有的,它不能被继承,也不能使用new语句来创建实例,但它提供了两个表态方法getInstance和getDefaultInstance来获取Session实例,前者创建一个独立的会话,否则获取缺省的共享会话。
(7[/b])、Address[/b]
Address类表示电子邮件地址,它是一个抽象类。其子类(最经常使用的子类是javax.mail.internet.InternetAddress)提供具体实现,且通常可串行化。

在创建了Session和Message,并设置了消息内容后,可以用Address确定邮件消息的发送者和接收者地址。
(8[/b])、Authenticator[/b]
Authenticator代表一个可以为网络连接获取认证信息的对象,它通常通过提示用户输入用户名和密码来收集认证信息,使连接可以访问受保护的资源。对于Javamail API来说,这些资源就是邮件服务器。Javamail Authenticator在javax.mail包中,它和java.net中同名的类Authenticator不同。

  要使用Authenticator,必须先创建一个它的子类实例,并且在会话对象创建时为会话注册该Authenticator对象。在需要认证的时候,就会通知Authenticator。程序可以弹出窗口,也可以从配置文件中(虽然没有加密是不安全的)读取用户名和密码,并使用它们作为构造函数参数创建一个PasswordAuthentication对象返回给调用程序。
(9[/b])、Transport[/b]
javax.mail.Transport

  消息发送的最后步骤是使用Transport类。该类使用指定协议发送消息(通常是SMTP)。Transport是抽象类,它的工作方式与Session有些类似,可以通过静态方法或实例方法发送消息。Transport继承自Service类,而后者提供了很多通用方法,如命名传输、连接服务器、监听传输事件等等。
(10[/b])、Store [/b]
javax.mail.Store

  Store是一个抽象类,它模拟了消息存储器及其内部目录(Folder)访问协议,以存储和读取消息,其子类提供具体实现。

  Store定义的存储器包括一个分层的目录体系,消息存储在目录内,。客户程序可以通过获取一个实现了数据库访问协议的Store对象来访问消息存储器,绝大多数存储器要求用户在访问前提供认证信息,connect方法执行了该认证过程。

  Store store = session.getStore("pop3");//指定协议

  store.connect(host,usename,password);//
(11[/b])、.Folder [/b]
javax.mail.Folder

  Folder是一个抽象类,用于分级组织邮件,其子类提供针对具体协议的实现。Folder代表的目录可以容纳消息或子目录,存储在目录内的消息被顺序计数(从1开始到消息总数),该顺序被称为“邮箱顺序”,通常基于邮件消息到达目录的顺序。邮件顺序的变动将改变消息的序列号,这种情况仅发生在客户程序调用Expunge方法擦除目录内设置了Flags.Flag.DELETED标志位的消息时。执行擦除操作后,目录内消息将重新编号。

  客户程序可以通过消息序列号或直接通过相应的Message对象应用目录中的消息,由于消息序列号在会话中很可能改变,因此应尽可能保存Message对象而非序列号来反复引用对象。

  连接到Store之后,接下来可以获取一个文件夹(Folder)。该文件夹必须先使用open()方法打开,然后才能读取里面的消息:

Folder folder = store.getDefaultFolder();

//或 : Folder folder = store.getFolder("inbox");

folder.open(Folder.READ_WRITE);

Message message[] = folder.getMessage();

  open()方法指定了要打开的文件夹及打开方式(如Folder.READ_WRITE)。 inbox是POP3唯一可以使用的文件夹。如果使用IMAP,还可以用其它的文件夹。获得Message之后,就可以用getContent()获得其内容,或者用writeTo()将内容写入输出流。getContent()方法之能得到消息内容,而writeTo()的输出却包含消息头.读完邮件之后要关闭与Folder和Store的连接:

folder.close(aBoolean);

store.close();
2[/b]、发送核心代码[/b]
第一步,设置系统的一系列属性
Properties props = System.getProperties();
props.put("mail.smtp.host", mailServer);
第二步,取得一个Session对象,代表一次发送会话
Session sendmailsession = Session.getDefaultInstance(props, null);
第三步 ,得到一个实际发送邮件的信息对象
MimeMessage message = new MimeMessage(sendmailsession);
第四步,得到一个用于发送邮件的类,指定发送的协议
Transport transport = sendmailsession.getTransport("smtp");
/* 以下是服务器需要认证时所要的方法 */
transport.connect(mailServer, name, password);
transport.sendMessage(message, message.getAllRecipients());
transport.close();

注意:发送邮件要指定发件人密码, 接受邮件需要接受人的密码
(1[/b])、接受邮件[/b]
获取系统的属性对象
Properties props = System.getProperties();
// 指定邮件服务器的名称
props.put("mail.smtp.host", mailServer);
// 指定邮件服务器接收邮件的协议
props.put("mail.store.protocol", "pop3");
取得一个Session对象,代表一个邮件会话
Session savemailsession = Session.getDefaultInstance(props, null);
得到一个邮件对象
Store store = savemailsession.getStore("pop3");
// 根据用户名和密码连接上指定邮箱地址
store.connect(mailServer, name, password);
// 得到一个邮件夹
Folder folder = store.getFolder("INBOX");
// 指定访问的能力
folder.open(Folder.READ_WRITE);
读邮件
关闭邮件夹和邮箱
folder.close(true);
store.close();
(2[/b])、SendEmail[/b]
Properties pro = System.getProperties();
pro.setProperty("mail.smtp.host", server);
Session sendsession = Session.getDefaultInstance(pro, null);
MimeMessage message = new MimeMessage(sendsession);
message.setSubject(subject, "gbk");
message.setText(context, "gbk");
message.setSentDate(new Date());
message.setFrom(new InternetAddress(from));
message.addRecipient(Message.RecipientType.TO, new InternetAddress(to));
//认证
Transport tran = sendsession.getTransport("smtp");
tran.connect(server, uname, upwd);
tran.sendMessage(message, message.getAllRecipients());
tran.close();
(3[/b])、GetEmail[/b]
Properties pro = System.getProperties();
pro.setProperty("mail.smtp.host", server);
pro.setProperty("mail.store.protocol", "pop3");
Session session = Session.getDefaultInstance(pro, null);
Store store= session.getStore("pop3");
store.connect(server, uname, upwd);
Folder foler = store.getFolder("inbox");
foler.open(Folder.READ_WRITE);
int total = foler.getUnreadMessageCount();
System.out.println("未读邮件数:"+total);
int newemail = foler.getNewMessageCount();
System.out.println("新邮件数:"+total);
Message[] message = foler.getMessages();
for(Message m: message){
System.out.println("主题:"+m.getSubject()+" 正文:"+m.getContent());
m.setFlag(Flags.Flag.DELETED, true);
}
foler.close(true);
store.close();
略有分享,不足之处,还望指正!!![/i][/b][/i][/b]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: