Apache James

来源:互联网 发布:剑三毒哥捏脸数据图片 编辑:程序博客网 时间:2024/04/27 21:07

Apache James(Java Apache Mail Enterprise Server)是Apache组织的子项目之一,完全采用纯Java技术开发,实现了SMTP、POP3与NNTP等多种邮件相关协议.
James也是一个邮件应用平台,可以通过Mailet扩充其功能,如Mail2SMS、Mail2Fax等。James提供了比较完善的配置方案,尤其是关于邮件内容存储和用户信息存储部分,可以选择在文件、数据库或其他介质中保存。
James性能稳定、可配置性强,还是开源项目,所有源代码不存在版权问题,因此,James在项目中的应用日益广泛,现在常用版本为2.1,但最新版本2.3已经推出.
相关信息及下载:http://james.apache.org/

安装配置:
第一步:安装JDK
请使用JDK1.3以上版本(推荐使用JDK1.4),假设安装在c:/jdk1.3
第二步:下载James,并解压
可以到Apache网站上下载james-binary-2.3.1.zip 下载将得到一个压缩文件james-2.3.zip,将此包解压到为d:/james
第三步:直接运行或需要配置JAVA_HOME
这时,可以尝试直接双击d:/james/bin/run.bat,若启动无误,将提示如下:Using PHOENIX_HOME:   d:/james
------------------------------------------------------

Using PHOENIX_TMPDIR:d:/james/temp
Using JAVA_HOME:
Phoenix 4.0.1

James 2.3
Remote Manager Service started plain:4555
POP3 Service started plain:110
SMTP Service started plain:25
NNTP Service Disabled
Fetch POP Disabled
-------------------------------------------------------

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

rem
rem Determine if JAVA_HOME is set and if so then use it
rem
set JAVA_HOME= c:/jdk1.3
if not "%JAVA_HOME%"=="" goto found_java
……
------------------------------------------------------
修改完后再运行run.bat,应该就可以正常启动了

服务器端配置
然后打开文件d:/james/apps/james/SAR-INF/config.xml(前提是已运行run.bat将产生此文件!)
在config.xml文件中,找到
<postmaster>Postmaster@localhost</postmaster>
更改为:
<postmaster>Postmaster@test.com</postmaster>
同理,找到
<servername>localhost</servername>
更改为:
<servername>test.com</servername>
名称可以任意起了.(不要忘了增加test.com机器名->C:/WINDOWS/system32/drivers/etc/hosts)

帐号管理
James的账号管理是通过telnet完成的,登录命令为:
------------------------------------------------------

telnet test.com 4555
------------------------------------------------------

其中test.com也可以换成IP,4555是端口号。登录时需要用户名和密码,初始的用户名和密码均为root。若登录成功,提示如下:
------------------------------------------------------

JAMES Remote Administration Tool 2.3
Please enter your login and password
Login id:
Password:
Welcome root. HELP for a list of commands
------------------------------------------------------

需要注意的是,所有敲入的命令都不显示在屏幕上。
输入help,将出现命令的帮助,信息如下:
------------------------------------------------------

JAMES Remote Administration Tool 2.1
Please enter your login and password
Login id:
Password:
Welcome root. HELP for a list of commands
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 [alias] [user]                 locally forwards all email for 'alias' t
o 'user'
unsetalias [alias]                       unsets an alias
setforwarding [username] [emailaddress] forwards a user's email to another email
address
unsetforwarding [username]         removes a forward
user [repositoryname]                 change to another user repository
shutdown                                 kills the current JVM (convenient when J
ames is run as a daemon)
quit                                         close connection
------------------------------------------------------

常用的命令有listusers、countusers、adduser、deluser、setpassword等。
其中添加用户为adduser,例如:adduser test 123456
通过这个后台管理界面,管理员就可以实现账号管理及其他相应的管理功能

这只是简单的james的配置,想深入学习还得查资料.....

具体代码:
我们在Java开发中,对于发送邮件,Sun给出了JavaMail框架。但是这个框架调用比较复杂,所以出了很多封装来简化使用。比如Spring就对JavaMail进行了封装。今天介绍的是Apache的Common-email组件.
相关信息及下载:http://commons.apache.org/email/

(先添加一个用户:adduser ugly 123456)
package com.hygj.service;
import org.apache.commons.mail.EmailAttachment;
import org.apache.commons.mail.EmailException;
import org.apache.commons.mail.HtmlEmail;
import org.apache.commons.mail.MultiPartEmail;
import org.apache.commons.mail.SimpleEmail;
/**
* 使用 apache开源项目commons-email发送邮件
*
* commons-email是apache提供的一个开源的API,是对javamail的封装,因此在使用时要将javamail.jar加到 class path中,主要包括SimpleEmail,MultiPartEmail,HtmlEmail,EmailAttachment四个类
* SimpleEmail:发送简单的email,不能添加附件
* MultiPartEmail:文本邮件,可以添加多个附件
* HtmlEmail:HTML格式邮件,同时具有MultiPartEmail类所有“功能”
* EmailAttchment:附件类,可以添加本地资源,也可以指定网络上资源,在发送时自动将网络上资源下载发送
*
* @author 徐嘉伟
* Email: [email=[ft=,2,Verdana]auglyboy@163.cn]auglyboy@163.cn[/email]
*/
public class MailService {

/**
   * 简单邮件测试类
   */
public void sendSimpleMail(){
   //创建单一邮件对象
   SimpleEmail email = new SimpleEmail();
   //设置服务器
 
   email.setHostName("test.com");
   try {
   //设置发送人
   email.setFrom("[email=[ft=,2,Verdana]ugly@test.com]ugly@test.com[/email]", "ugly");
   //设置接收人
   email.addTo("[email=[ft=,2,Verdana]ugly@test.com]ugly@test.com[/email]", "ugly");
   //用户验证
   email.setAuthentication("ugly", "123456");
   //设置邮件主题
   email.setSubject("james使用");
   //设置邮件内容
   email.setMsg("This is a test mail!");
   //发送
   email.send();
  
   } catch (EmailException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
   }
 
}


/**
   * 发送带有附件的邮件信息
   */
public void sendMultiPartMail(){
   //创建附件邮件对象
   MultiPartEmail multipartMail = new MultiPartEmail();
   multipartMail.setHostName("test.com");
 
   //创建一个附件(附件可以是一个本地路径也可以是一个网络url)
   EmailAttachment emailAttachment = new EmailAttachment();
   emailAttachment.setPath("f://附件.rar");
   emailAttachment.setDescription(EmailAttachment.ATTACHMENT);
   emailAttachment.setDescription("This is a attach test!");
   //设置附件名称(一定要加上附件类型后缀否则会出现乱码)
   //emailAttachment.setName("我是附件");
   try {
   multipartMail.setFrom("[email=[ft=,2,Verdana]ugly@test.com]ugly@test.com[/email]", "ugly");
   multipartMail.addTo("[email=[ft=,2,Verdana]ugly@test.com]ugly@test.com[/email]", "ugly");
   multipartMail.setAuthentication("ugly", "123456");
   multipartMail.setSubject("附件邮件测试信息");
   multipartMail.setMsg("存在附件呀");
  
   //添加附件
   multipartMail.attach(emailAttachment);
   //发送
   multipartMail.send();
   
   } catch (Exception e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
   }
}


/**
   * 发送html格式且带有附件的邮件信息
   */
public void sendHtmlEmail(){
 
   //创建html格式的邮件对象
   HtmlEmail htmlEmail = new HtmlEmail();
   htmlEmail.setHostName("test.com");
 
   //创建一个附件
   EmailAttachment emailAttachment = new EmailAttachment();
   emailAttachment.setPath("f://附件.rar");
   emailAttachment.setDescription(EmailAttachment.ATTACHMENT);
   emailAttachment.setDescription("This is a attach test!");
   emailAttachment.setName("attach.rar");
 
   try {
   htmlEmail.setFrom("ugly[email=[ft=,2,Verdana]@test.com]u@test.com[/email]", "first");
   htmlEmail.addTo("ugly[email=[ft=,2,Verdana]@test.com]u@test.com[/email]", "first");
   htmlEmail.setSubject("发送html格式的邮件信息");
   htmlEmail.setHtmlMsg("<h1>Hello World!</h1>");
   //加附件
   htmlEmail.attach(emailAttachment);
   htmlEmail.send();
   } catch (EmailException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
   }
}
 

/**
   * @param args
   */
public static void main(String[] args) {
   // TODO Auto-generated method stub
   new MailService().sendHtmlEmail();
}
}
--------------------------------------------------------------------------------------------------
基本是实现了本地邮件的发送,当然你会问,能不能用james给外网(163,126,yahoo..)发邮件呢?

答案是肯定可以,修改config.xml呀。

----配置外网邮件发送----

找到并打开../james-2.3.2/apps/james/SAR-INF/config.xml文件

1. 找到<servernames autodetect="true" autodetectIP="true">
    设成autodetect="false" autodetectIP="false"> autodetct设为true会自动侦测你的主机名,
   设成false会用你指定的server name. autodetectIP设为true会为你的servername加上ip.

2. 设置servername 将默认的为localhost改成你的server名字 如king.cn, 然后打开
    C:/WINDOWS/system32/drivers/etc/hosts文件,添加 127.0.0.1 test.com

3. 注释掉
<mailet match="RemoteAddrNotInNetwork=127.0.0.1" class="ToProcessor">
    <processor> relay-denied </processor>
    <notice>550 - Requested action not taken: relaying denied</notice>
</mailet>

4. 配置DNS Server
    在cmd中用ipconfig /all 命令查看你的dns server ip
    DNS Servers . . . . . . . . . . . : 202.96.209.6
    192.168.1.1
查找并修改处信息
   <dnsserver>
      <servers>
        <!--Enter ip address of your DNS server, one IP address per server -->
       
<server>127.0.0.1</server>
<server>202.102.152.3</server>
      </servers>
      <!-- Change autodiscover to false if you would like to turn off autodiscovery -->
      <!-- and set the DNS servers manually in the <servers> section -->
      <autodiscover>false</autodiscover>
      <authoritative>false</authoritative>

      <!-- Maximum number of entries to maintain in the DNS cache -->
      <maxcachesize>50000</maxcachesize>
   </dnsserver>
同时设置autodiscover为false

5.重启server


----用户名密码加密问题-----
通过telnet添加新用户时,比如adduser holen 123456,你可以查看数据库中的记录,第一个字段是holen,第二字段是密码,但密码并非123456,而一串“乱码”(zhwQUMTwdMqWfm/h0biB51Gf)——这是加密码后的密码内容,再看后面的字段是“SHA”,显然用的是SHA加密方式。

通过telnet方式添加新用户,用户密码将自动加密,然后插入数据库中。但通过telnet方式进行用户管理有着诸多不便,尽管你可以借助James的一个RMI工具包,提高效率,但仍然没有本质改变,当需要用作商业用途时,你更不能要求你的客户熟记那一堆命令符。

一般我们可以做一个Web前端,通过网页形式,添加修改用户,界面友好,傻瓜化使用,如263或163一样。若这样做,我们就需要直接操作数据库,添加用户记录或修改删除用户记录了。但别忘了,James默认对用户密码是加密的,既然我们要直接操作数据库,那么我们只有两个选择:要么我们研究其密码机制,添加记录时,我们对新增用户的密码进行同样加密,要么我们去掉James的加密机制,使其明码保存。

这两种选择都是可行的。我们从Apache网站下载James的源码包,下载后的文件为james-src.zip,通过分析源码,我们发现,与用户密码相关的文件是DefaultUser.java,部分源码如下:

package org.apache.james.userrepository;
/**
     * Method to verify passwords.
     *
     * @param pass the String that is claimed to be the password for this user
     * @return true if the hash of pass with the current algorithm matches
     * the stored hash.
     */
    public boolean verifyPassword(String pass) {
        try {
            String hashGuess = DigestUtil.digestString(pass, algorithm);
            return hashedPassword.equals(hashGuess);
        } catch (NoSuchAlgorithmException nsae) {
        throw new RuntimeException("Security error: " + nsae);
    }
    }

    /**
     * Sets new password from String. No checks made on guessability of
     * password.
     *
     * @param newPass the String that is the new password.
     * @return true if newPass successfuly hashed
     */
    public boolean setPassword(String newPass) {
        try {
            hashedPassword = DigestUtil.digestString(newPass, algorithm);
            return true;
        } catch (NoSuchAlgorithmException nsae) {
            throw new RuntimeException("Security error: " + nsae);
        }
}

第一个方法verifyPassword()是用来做密码认证,传入的参数是明文密码,通过DigestUtil.digestString()方法,转换成密文密码,然后与数据库中密码作比较,返回比较结果。请注意这里的DigestUtil.digestString()方法,在后面还在提到。

第二个方法setPassword()是用于密码转换的,把明文转成密文,用的同样是DigestUtil.digestString()方法。

谈到这里,相信你应该知道怎么在自己的程序中进行密码转换和密码认证了吧!其实并不是要你自己去写一个SHA的加密算法,既然James已经提供了此功能,你调用便是了。

应该注意的是,用上面的方法应当先导入james.jar、mail.jar(james-2.3.2/work/james-1252566991062/SAR-INF/lib),否则报错啦!
代码如下:

package com.xyl.test;

import java.security.NoSuchAlgorithmException;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.james.security.DigestUtil;

/**
* 实现james加密
* @author Xu-yan-li
*/
public class Test {

    public static void main(String[] args){
        try {
            String pwd = DigestUtil.digestString("123456789", "SHA");//密码SHA加密
            System.out.println(pwd+"==================================================");
        } catch (NoSuchAlgorithmException ex) {
            Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}


还有一种情况,开发者需要在数据库中必须用明文保存密码,这样就不必在自己写的程序中进行密码转换了,而且当多个应用系统采用统一用户模型时,最好只有一个用户实例。要实现这个需求,就只能修改James源代码了,把verifyPassword()方法和setPassword()改成:

public boolean verifyPassword(String pass) {      
            return hashedPassword.equals(pass);      
}  
public boolean setPassword(String newPass) {     
            hashedPassword = newPass;
            return true;      
}

其实就是把转换过程去掉,保存和认证就都采用明文进行了。

你要是觉得SHA方式不妥,也可以挂接别的加密方式,同样是修改这两个方法。

注意,当你修改了James的源码后,你需要用Ant重新build James项目,build后将在james-2.1-src/dist/james-2.1/apps下面找到新生成的james.sar文件。把该文件覆盖James原来james.sar,并删除与james.sar同级的james目录,重启动james即可。建议保留原来的config.xml,免得又配一次。

通过以上探讨,我们明白了如何通过Web方式进行用户注册和用户登记等。需要说明一点是,James自动生成的users表中只有7个字段,而且都是系统需要使用的。一般注册时需要输入的信息项比较多,这时建议开发者自己再建一个新表USERINFO,用username把两个表关联起来,不建议修改users表的内容(如果想试试,请参考file &://conf/sqlResources.xml)。