用JAMES实现自己的邮件服务器

James 是一个企业级的邮件服务器,它完全实现了smtp 和 pops 以及nntp 协议。同时,james服务器又是一个邮件应用程序平台。James的核心是Mailet API,而james 服务齐是一个mailet的容器。它可以让你非常容易的实现出很强大的邮件应用程序。James开源项目被广泛的应用于与邮件有关的项目中。你可以通过它来搭建自己的邮件服务器。我们可以利用Mailet API,编程接口来实现自己所需的业务。James集成了Avalon 应用程序框架以及 Phoenix Avalon 框架容器。 Phoenix james 服务器提供了强大的支持。需要说明的是 Avalon 开源项目目前已经关闭。
   我这次使用的安装包是 james 2.3.1 。大家可以从这里下载到 http://james.apache.org/download.cgi
  现在让我们开始我们激动人心的 james 之旅。首先我们将 james-binary-2.3.1.zip 解压缩下载到你的安装目录。我们可以把这个过程理解为安装的过程。我在这里将它解压到 c:\. 并且把它改名为 james. 这样我们的 james 就安装好了。目录为 C:\james 。很简单吧!
 
准备知识 - 学习一些必要的知识
在我使用 james 的时候让我感觉首先理解 james 的应用程序结构是很重要的。否则你会在使用中感到很困惑。
它的应用程序结构是这样的:
 James
       |_ _apps
       |_ _bin
       |_ _conf
       |_ _ext
       |_ _lib
       |_ _logs
       |_ _tools
我们重点介绍一下两个文件夹 bin apps.
bin 目录中的 run.bat run.sh James 的启动程序。只要记住这个重要文件就可以。
启动之后控制台显示如下:
Using PHOENIX_HOME:   C:\james
Using PHOENIX_TMPDIR: C:\james\temp
Using JAVA_HOME:      C:\j2sdk1.4.2_02

Phoenix 4.2

James Mail Server 2.3.1
Remote Manager Service started plain:4555
POP3 Service started plain:110
SMTP Service started plain:25
NNTP Service started plain:119
FetchMail Disabled

  Apps 目录下有个james的子目录这个目录是它的核心。
               james
|_ _SAR-INF
|_ _conf
|_ _logs
|_ _var
    |_mail
       |_address-error
       |_error
       |_indexes
       |_outgoing
       |_relay-denied
       |_spam
       |_spool
    |_nntp
       |_....
       …
    |_users
SAR-INF 下有一个 config.xml james 中的核心配置文件。
Logs 包含了与 james 有关的 Log 。调试全靠它了。
Var 包含了一些文件夹通过它们的名字我们大概也能猜测出它们的用途。 Mail 主要用于存储邮件。 nntp 主要用于新闻服务器。 Users 用于存储所有邮件服务器的用户。也就是邮件地址前面的东东。如: pig@sina.compig 就是所谓用用户。
 
创建用户:
 我们在 James 上建若干用户,用来测试收发邮件。当然如果你不用 james 本身的用户也可以。 James telnet 的方式提供了接口用来添加用户。下面我来演示一下。
首先使用 telnet 来连接 james remote manager .
1.telnet localhost 4555  回车
2. 然后输入管理员用户名和密码( user/pwd root/root 是默认设置这个可以在 config.xml 中修改)
JAMES Remote Administration Tool 2.3.1
Please enter your login and password
Login id:
root
Password:
root
Welcome root. HELP for a list of commands
 
3. 添加用户
adduser kakaxi kakaxi
User kakaxi added
 
Adduser mingren mingren
User mingren added
 
4. 查看添加情况
listusers
Existing accounts 2
user: mingren
user: kakaxi
得到上面的信息说明我们已经添加成功。
 
 
发送器
  这个类主要用来测试我们的邮件服务器,可以不用将其打入包中。
java 代码
  1. package com.yy.jamesstudy;   
  2.   
  3. import java.util.Date;   
  4. import java.util.Properties;   
  5.   
  6. import javax.mail.Authenticator;   
  7. import javax.mail.Message;   
  8. import javax.mail.PasswordAuthentication;   
  9. import javax.mail.Session;   
  10. import javax.mail.Transport;   
  11. import javax.mail.internet.InternetAddress;   
  12. import javax.mail.internet.MimeMessage;   
  13.   
  14. public class Mail {   
  15.     private String mailServer, From, To, mailSubject, MailContent;   
  16.   
  17.     private String username, password;   
  18.   
  19.     private Session mailSession;   
  20.   
  21.     private Properties prop;   
  22.   
  23.     private Message message;   
  24.   
  25.     // Authenticator auth;//认证   
  26.     public Mail() {   
  27.         // 设置邮件相关   
  28.         username = "kakaxi";   
  29.         password = "kakaxi";   
  30.         mailServer = "localhost";   
  31.         From = "kakaxi@localhost";   
  32.         To = "mingren@localhost";   
  33.         mailSubject = "Hello Scientist";   
  34.         MailContent = "How are you today!";   
  35.     }   
  36.     public void send(){   
  37.         EmailAuthenticator mailauth =    
  38. new EmailAuthenticator(username, password);   
  39.         // 设置邮件服务器   
  40.         prop = System.getProperties();   
  41.         prop.put("mail.smtp.auth""true");   
  42.         prop.put("mail.smtp.host", mailServer);   
  43.         // 产生新的Session服务   
  44.         mailSession = mailSession.getDefaultInstance(prop,   
  45.                 (Authenticator) mailauth);   
  46.         message = new MimeMessage(mailSession);   
  47.   
  48.         try {   
  49.         message.setFrom(new InternetAddress(From)); // 设置发件人   
  50.         message.setRecipient(Message.RecipientType.TO,    
  51. new InternetAddress(To));// 设置收件人   
  52.         message.setSubject(mailSubject);// 设置主题   
  53.         message.setContent(MailContent, "text/plain");// 设置内容   
  54.         message.setSentDate(new Date());// 设置日期   
  55.         Transport tran = mailSession.getTransport("smtp");   
  56.         tran.connect(mailServer, username, password);   
  57.         tran.send(message, message.getAllRecipients());   
  58.         tran.close();   
  59.         } catch (Exception e) {   
  60.             e.printStackTrace();   
  61.         }   
  62.     }   
  63.     public static void main(String[] args) {   
  64.         Mail mail;   
  65.         mail = new Mail();   
  66.         System.out.println("sending......");   
  67.         mail.send();   
  68.         System.out.println("finished!");   
  69.     }   
  70.   
  71. }   
  72.   
  73. class EmailAuthenticator extends Authenticator {   
  74.     private String m_username = null;   
  75.   
  76.     private String m_userpass = null;   
  77.   
  78.     void setUsername(String username) {   
  79.         m_username = username;   
  80.     }   
  81.   
  82.     void setUserpass(String userpass) {   
  83.         m_userpass = userpass;   
  84.     }   
  85.   
  86.     public EmailAuthenticator(String username, String userpass) {   
  87.         super();   
  88.         setUsername(username);   
  89.         setUserpass(userpass);   
  90.     }   
  91.   
  92.     public PasswordAuthentication getPasswordAuthentication() {   
  93.         return new PasswordAuthentication(m_username, m_userpass);   
  94.     }   
  95. }   
<v:shapetype id="_x0000_t75" path="m@4@5l@4@11@9@11@9@5xe" o:preferrelative="t" filled="f" stroked="f" coordsize="21600,21600" o:spt="75"> </v:shapetype>
 
实现-Matcher 和 Mailet编写
     我先解释一下大概的流程:当 james 接收到一个 smtp 请求时首先会交给 matcher 来进行一系列过滤动作。然后由 matcher 交给相应的 mailet 来进行处理。 James 就相当于一个 matcher mailet 的容器。就像 tomcat 之于 servlet 。而 mailet servlet 很是相似。
     我们这里要完成的功能很简单,就是当 james 邮件服务器接收到鸣人(人名)后把发送者和邮件正文打印到控制台。我们分析这个需求发现我们需要写一个 matcher 以及一个 mailet.matcher 用来过滤而 mailet 用来将邮件内容打印到控制台。为了简单起见,我这次只是继承了 GenericMailet GenericRecipientMatcher 两个已经实现的 mailet matcher. 具体的 Matcher Mailet 的使用我以后会整理成另外一篇文章。
 
Matcher 的实现
  1. package com.yy.jamesstudy;   
  2.   
  3. import javax.mail.MessagingException;   
  4. import org.apache.mailet.GenericRecipientMatcher;   
  5. import org.apache.mailet.MailAddress;   
  6. /**  
  7.  * System   jamesstudy  
  8.  * Package  com.yy.jamesstudy  
  9.  *   
  10.  * @author Yang Yang  
  11.  * Created on 2007-9-14下午02:17:07  
  12.  */  
  13. public class BizMatcher extends GenericRecipientMatcher {   
  14.   
  15.     public boolean matchRecipient(MailAddress recipient) throws MessagingException {   
  16.         //只接受邮件地址包含鸣人的邮件   
  17.           if (recipient.getUser().indexOf("mingren")!=-1) {   
  18.               return true;   
  19.           }   
  20.         return false;   
  21.     }   
  22. }   
GenericRecipientMatcher 是一个针对收件人进行过滤的 matcher .
 
Mailet 的实现
  1. package com.yy.jamesstudy;   
  2.   
  3. import java.io.IOException;   
  4. import javax.mail.MessagingException;   
  5. import javax.mail.internet.MimeMessage;   
  6. import org.apache.mailet.GenericMailet;   
  7. import org.apache.mailet.Mail;   
  8. import org.apache.mailet.MailAddress;   
  9. /**  
  10.  * System   jamesstudy  
  11.  * Package  com.yy.jamesstudy  
  12.  *   
  13.  * @author  Yang Yang  
  14.  * Created on 2007-9-14下午02:16:31  
  15.  */  
  16. public class BizMaillet extends GenericMailet {   
  17.   
  18.     public void service(Mail mail)  {   
  19.         MailAddress ma = mail.getSender();   
  20.         System.out.println("sender:"+ma.toInternetAddress().toString());   
  21.         try {   
  22.             MimeMessage mm = mail.getMessage();   
  23.             System.out.println("content:"+(String)mm.getContent().toString());   
  24.         } catch (IOException e) {   
  25.             e.printStackTrace();   
  26.         } catch (MessagingException e) {   
  27.             e.printStackTrace();   
  28.         }   
  29.     }   
  30. }   
GenericMailet 是一个 mailet 的基本实现。
编译
    我们把这两个 java 文件的 class 文件编译成一个名字为: jamesstudy.jar jar 文件。
 
发布-Matcher 和 Mailet以及config.xml
    1. 发布 jar 文件
            我们把这个 jar 文件发布到 C:\james\apps\james\SAR-INF\lib。
            注意:如果没有找到相关目录,则需要先启动一遍james,相关的文件夹才会被创建。还有一点需要特别说明:lib目录是通过我们手动创建的。
     2. Matcher Mailet 发布到 config.xml 中, config.xml james\apps\james\SAR-INF\
       1 )我们首先找到如下内容
  1. <mailetpackages>  
  2.       <mailetpackage>org.apache.james.transport.mailetsmailetpackage>  
  3.       <mailetpackage>org.apache.james.transport.mailets.smimemailetpackage>  
  4.    mailetpackages>  
  5.    <matcherpackages>  
  6.       <matcherpackage>org.apache.james.transport.matchersmatcherpackage>  
  7.       <matcherpackage>org.apache.james.transport.matchers.smimematcherpackage>  
  8.    matcherpackages>  
      2 )加入包声明
  1. <mailetpackages>  
  2.       <mailetpackage>com.yy.jamesstudymailetpackage>  
  3.       <mailetpackage>org.apache.james.transport.mailetsmailetpackage>  
  4.       <mailetpackage>org.apache.james.transport.mailets.smimemailetpackage>  
  5.    mailetpackages>  
  6.   
  7.    <matcherpackages>  
  8.       <matcherpackage>com.yy.jamesstudy matcherpackage>  
  9.       <matcherpackage>org.apache.james.transport.matchersmatcherpackage>  
  10.       <matcherpackage>org.apache.james.transport.matchers.smimematcherpackage>  
  11.    matcherpackages>  
 
  3 )加入 Matcher Mailet 的关联关系
     找到 <processor name="root"></processor> 元素在它的下面加入
xml 代码
  1. <mailet match="BizMatcher" class="BizMaillet"/>  
Mailet 元素代表了一个 matcher 和一个 mailet 的组合。 Match 属性:是指 matcher 的类名。而 class 属性:是指 mailet 的类名。
 最后别忘了,保存退出。并且重新启动james服务器。
测试- 验证我们的mail应用程序
我们主要通过 mail 类来测试我们的应用。还记得我们刚才写的那个 mail 类吗?!在那个类中我们初始化了相关的信息 .
                   username = "kakaxi";
                   password = "kakaxi";
                   mailServer = "localhost";
                   From = "kakaxi@localhost";
                   To = "mingren@localhost";
                   mailSubject = "Hello Scientist";
                   MailContent = "How are you today!";
发件人是卡卡西,收件人是 mingren. 这两个用户我们在前面都已经创建完毕。我们用他们来测试 james 的邮件收发以及 mailet api 的应用。
根据需求假设我们发给 james 服务器(这里是 james 的默认配置: localhost 的邮件的收件人是鸣人。那么我们就能通过 matcher 监测到这封邮件,并且调用相应的 maile t 来进行处理。由 mailet 打印出相应的邮件发送者和正文。 运行 Mail 类后得到
Using PHOENIX_HOME:   C:\james
Using PHOENIX_TMPDIR: C:\james\temp
Using JAVA_HOME:      C:\j2sdk1.4.2_02

Phoenix 4.2

James Mail Server 2.3.1
Remote Manager Service started plain:4555
POP3 Service started plain:110
SMTP Service started plain:25
NNTP Service started plain:119
FetchMail Disabled


sender:kakaxi@localhost
content:How are you today!

总结

最终我们看到 发送者和正文的信息。 That’s all !  大功告成。
         其实 james 的功能是非常非常强大的,尤其是它的 Mailet API 能够帮助我们完成很多与邮件邮件有关的工作如过滤垃圾邮件。用它我们甚至可以搭建我们自己的企业邮件服务器。我们最近的项目中就使用到了。我们通过 james 接收到的邮件,然后用 matcher 找到我们想要处理的邮件,然后通过 mailet 做一些业务上的处理。这篇文章涵盖的面很小。如果大家有兴趣可以研究一下 james 项目。 Config.xml 实际上是最重要的文件,如果你把它研究透彻了那么就就算把 Mailet API 研究透了。以后我可能会写一篇相关的文章,在这就不多说了。希望这篇文章能够对大家有所启发!有所帮助!祝大家工作顺利!
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值