Apache James 简称 James, 是 Java Apache Mail Enterprise Server的缩写。James 是100%基于Java的电子邮件服务器。它是一种独立的邮件服务器,并提供了一个完整的电子邮件解决方案,用来收、发电子邮件。

 

       本文不赘述James服务器的参数细节,这个以后有机会再详细讨论,这里先从服务器搭建开始,用搭建的服务器收、发电子邮件来熟悉一下Apache James。本人也是新手,希望能得到各位高手的指点,使大家能悟到进阶的方向。

 

       开始之前,先声明一下本文操作的系统环境:

       1. JDK 6u10b

       2. JMail API v1.4.2

       3. JAF API v1.1(JavaBean Activation Framework)

       4. Apache James 2.3.1

       5. Eclipse 3.4 for J2EE Developers

       6. Windows 2000 Server sp4

 

    

       

       1。请下载安装JDK,并设置好其环境变量:JAVA_HOME=…… 、PATH=…… 、CLASSPATH=…… Eclipse 3.4 是目前的最新版本,可以从http://www.eclipse.org/下载。

      

       2。请下载JMail API、JAF API,可以在www.java.sun.com找到他们,找不到也不要紧,本文附件示例代码免费提供一份(^_^)。

 

       3。Apache James 的官方网站为:http://james.apache.org/,当前 Server 的最新版为 2.3.1版. 安装非常简单,下载后得到james-binary-2.3.1.zip 文件,解压后即可。这里假设解压到D盘(D:\james-2.3.1),目录结构如下:

      

       D:\james-2.3.1

               |--- apps

               |--- bin

               |

       …………

 

       4。启动 James 服务器

       双击或在命令行下执行D:\james-2.3.1\bin 目录下的 run.bat文件,即可启动 James 服务器。

 

       启动后能在控制台看到如下信息,说明启动成功:

Using PHOENIX_HOME: D:\james-2.3.1 
Using PHOENIX_TMPDIR: D:\james-2.3.1\temp 
Using JAVA_HOME: D:\Java\jdk1.6.0_10 

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

   

      

       要关闭 James 服务,请使用 Ctrl + C

 

       说明:启动前请确保您的JDK环境变量如JAVA_HOME等已经设置好;James 启动时,其SMTP 服务默认在 25 端口启动,POP3 服务默认在 110 端口启动, NNTP 服务默认在 119 端口启动, 请确保这些端口未被占用。比如本系统下就已经安装了Microsoft的 SMTP 服务,造成 James无法启动,解决方法为:开始--->设置--->控制面板--->管理工具--->服务,打开后找到“Simple Mail Transport Protocol(SMTP)”服务项,关闭即可。

 

     

       5。配置服务

       服务器启动后会在本机配置一个默认的服务,这可以用来在本机上本服务器范围内收发邮件,但是邮件发不到163等外网邮箱。我们这里关注的重点就是配置一个能发到外网如163这样的邮箱的邮件,这样才有价值。不过由于本人是在本机上测试,一时不能获取公司的域名参数,无法测试接收外网邮箱(如163)的邮件,见晾,不过做法都是一样的,至少我们可以向外网邮箱发送邮件,局域网内可以收、发邮件。

      

        打开D:\james-2.3.1\apps\james\SAR-INF 下的 config.xml 文件,初次启动James之前,不会有这个文件,只有当James服务启动一次之后才自动构件该文件。

      

        找到

…… 
<postmaster>Postmaster@localhost</postmaster> 
…… 
<servernames autodetect="true" autodetectIP="true"> 
	<servername>localhost</servername> 
</servernames> 
…… 

  

  

        把localhost该成你自己想要的邮箱域名, 把自动探测IP属性设置为“false”这里假设改成 zhaipuhong.com 如果开了一个帐号 zph ,那么他的邮件地址就是 zph@zhaipuhong.com (^_^)修改结果如下:

 

…… 
<postmaster>Postmaster@zhaipuhong.com</postmaster> 
…… 
<servernames autodetect="false" autodetectIP="false"> 
	<servername>zhaipuhong.com</servername> 
</servernames> 
……

   

        找到

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

   

        将其注释,结果如下:

<!--mailet match="RemoteAddrNotInNetwork=127.0.0.1" class="ToProcessor"> 
	<processor> relay-denied </processor> 
	<notice>550 - Requested action not taken: relaying denied</notice> 
</mailet-->

    

         找到下面元素,去掉其注释

<authRequired>true</authRequired>

  

 

         这样邮箱访问需要帐号验证,你不希望别人用你的帐号收发消息吧……^_^

        

         如此,James服务配置已经完成。

 

 

        6。创建邮件帐号

        创建邮件帐号后,就可以用来收发邮件了。James的账号管理是通过基于Telnet客户机的远程管理器,这点颇为不爽,尤其是我的操作系统下的命令行控制台是不显示telnet命令输入字符的,经常出错。

 

        现在进入命令行控制台,在telnet localhsot 4555 进入James管理器,操作如下:

C:\Documents and Settings\db2admin>telnet localhost 4555 

  

 

        将进入

JAMES Remote Administration Tool 2.3.1 Please enter your login and password Login id:

   

 

        默认的登陆id 为root 密码也为 root ,登陆成功后结果如下:

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

 

       创建新用户的命令是:adduser username password

    这里创建了两个账户来作为演示使用: zhaipuhong/zhangpuhong ;      zph/zph

 

      说明:你可以输入help来获取命令帮助

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] emoves 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 关闭连接

  

 

 

 

      账号创建成功后,使用quit退出管理器。现在我们可以开始部署我们的JMail应用了。

 

 

      7。用James收发邮件

      现在我们来写两个简单的程序来体验一下如何使用James收发邮件。请注意,示例程序是通用的。关于如何用JMail API收发邮件,这里不详细介绍,如果还没有接触过请参考一下我之前的文章:

      http://zhaipuhong.javaeye.com/admin/blogs/213005

     

      关于接受邮件部分,我们在代码中通过注释来描述。另外我们来回忆一下上述步骤配置James服务器的参数:

      1。smtp 服务器:192.168.1.98或者localhost     192.168.1.98是我的局域网IP,由于我James服务就装在我的机器上,所以我可以用localhost

      2。两个邮件帐号:zhaipuhong/zhaipuhong   对应邮箱地址: zhaipuhong@zhaipuhong.com

                                zph/zph                            对应邮箱地址: zph@zhaipuhong.com

      注意:邮箱域名我们配置的是zhaipuhong.com

 

      示例程序:

 

package com.zhaipuhong.j2ee.jmail;

import java.io.IOException;
import java.util.Properties;

import javax.mail.Authenticator;
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Store;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeUtility;

public class HelloJMail {
	
	//发送邮件
	public static void sendMail() {
		//String host = "192.168.1.98"; // 指定的smtp服务器,本机的局域网IP
		String host = "localhost"; // 本机smtp服务器
		//String host = "smtp.163.com"; // 163的smtp服务器
		String from = "zhaipuhong@zhaipuhong.com"; // 邮件发送人的邮件地址
		String to = "zph@zhaipuhong.com"; // 邮件接收人的邮件地址
		final String username = "zhaipuhong";  //发件人的邮件帐户
		final String password = "zhaipuhong";   //发件人的邮件密码

		// 创建Properties 对象
		Properties props = System.getProperties();

		// 添加smtp服务器属性
		props.put("mail.smtp.host", host);
		props.put("mail.smtp.auth", "true");

		// 创建邮件会话
		Session session = Session.getDefaultInstance(props, new Authenticator(){
			@Override
			public PasswordAuthentication getPasswordAuthentication() {
				return new PasswordAuthentication(username, password);
			}
			
		});

		try {
			// 定义邮件信息
			MimeMessage message = new MimeMessage(session);
			message.setFrom(new InternetAddress(from));
			message.addRecipient(Message.RecipientType.TO, new InternetAddress(
					to));
			//message.setSubject(transferChinese("我有自己的邮件服务器了"));
			message.setSubject("I hava my own mail server");
			message.setText("From now, you have your own mail server, congratulation!");

			// 发送消息
			session.getTransport("smtp").send(message);  
			//Transport.send(message); //也可以这样创建Transport对象发送
			System.out.println("SendMail Process Over!");

		} catch (MessagingException e) {
			e.printStackTrace();
		}
	}
	
	//接受邮件
	public static void getMail(){
		String host = "localhost";
	    final String username = "zph";
		final String password = "zph";

		// 创建Properties 对象
	    Properties props = new Properties();

		// 创建邮件会话
		Session session = Session.getDefaultInstance(props, new Authenticator(){
			@Override
			public PasswordAuthentication getPasswordAuthentication() {
				return new PasswordAuthentication(username, password);
			}
			
		});

	    
		try {
			// 获取邮箱的pop3存储
			Store store = session.getStore("pop3");
			store.connect(host, username, password);

	        // 获取inbox文件
		    Folder folder = store.getFolder("INBOX");
		    folder.open(Folder.READ_ONLY);  //打开,打开后才能读取邮件信息

		    // 获取邮件消息
		    Message message[] = folder.getMessages();

		    for (int i=0, n=message.length; i<n; i++) {
		    	System.out.println(i + ": " + message[i].getFrom()[0]
		    	                               + "\t" + message[i].getSubject());
		    	try {
					message[i].writeTo(System.out);
				} catch (IOException e) {
					e.printStackTrace();
				}

		    }

		    // 关闭资源
		    folder.close(false);
		    store.close();
		    
		} catch (MessagingException e) {
			e.printStackTrace();
		}
		
		System.out.println("GetMail Process Over!");

	}
	
	//邮件主题中文字符转换
	public static String transferChinese(String strText){
		try{
			strText = MimeUtility.encodeText(new String(strText.getBytes(), "GB2312"), "GB2312", "B");
		}catch(Exception ex){
			ex.printStackTrace();
		}
		return strText;
	}

	public static void main(String[] args) {
		HelloJMail.sendMail();
		//HelloJMail.getMail();
	}

}

  

 

 

 

      说明: 执行测试时,先执行发送,在main方法中注释掉邮件接受方法调用,等待片刻,再注释掉邮件发送方法调用,执行邮件接受方法调用。因为就算163这样优秀的企业级邮箱也不可能瞬间就能收到发送的邮件。

      在邮件发送方法中:sendMail(), 可以尝试一下又本邮件服务器向163邮箱发送邮件,如果想通过163邮件服务器想本地发送邮件,你需要配置DSN。

  

       以下为本机接收James邮件服务器提供服务的邮件结果:

 

0: zhaipuhong@zhaipuhong.com	I hava my own mail server
Return-Path: <zhaipuhong@zhaipuhong.com>
Delivered-To: zph@zhaipuhong.com
Received: from 127.0.0.1 ([127.0.0.1])
          by ZPH (JAMES SMTP Server 2.3.1) with SMTP ID 693
          for <zph@zhaipuhong.com>;
          Wed, 9 Jul 2008 19:58:38 +0800 (CST)
Date: Wed, 9 Jul 2008 19:58:38 +0800 (CST)
From: zhaipuhong@zhaipuhong.com
To: zph@zhaipuhong.com
Message-ID: <11627000.01215604718796.JavaMail.db2admin@ZPH>
Subject: I hava my own mail server
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

From now, you have your own mail server, congratulation!

  

 

 

       从上面的结果可以看出,该邮件是由zhaipuhong@zhaipuhong.com 发给 zph@zhaipuhong.com 的。

     

       多发几封电子邮件,就会发现,James 的邮件接收是一个栈结构,最近收到的邮件编号为0,依次类推……

  

 

 

  • practice.rar (370.3 KB)
  • 描述: 项目的示例代码
  • 下载次数: 81
  • config.rar (14.7 KB)
  • 描述: James 的配置文件,可以直接替换使用
  • 下载次数: 54
评论
carrot 昨天
试用了一下, 但是SMTP认证不起作用, 根本不需要smtp认证都可以发邮件,
楼主,是否有测试 ?
zhai puhong 2008-08-09
lsk,你的这个问题我没有遇到,我示例中也没遇到这中情况,但是我知道会发生你说的这种情况的可能。

我早网上找到一点资料,你看看合不合用:

该问题是由于反垃圾邮件软件引起的,已经和sina 确认过,他们最近部署了一套反垃圾邮件的系统

在默认条件下,邮件服务器在发出helo命令与远端的邮件服务
器通过25端口建立会话时还会送出自己的FQDN名字。目前流行的一
些反垃圾邮件软件可能会通过邮件服务器送出的FQDN名字对其
进行反向解析,对于反向解析失败的连接将断开该连接。

反向解析失败的原因如下:

在国内,很多管理员在做域名解析时没严格按要求做,认为通了就行。建议的做法是:对域名abc.com要做这些解析(根据需要增减)
1、主机A记录abc.com
2、主机A记录mail.abc.com
3、主机A记录www.abc.com
4、主机A记录ftp.abc.com
5、abc.com 到 mail.abc.com的MX记录
6、反向解析记录
  很多人在做邮件服务器时会忘掉做MX记录和反向解析记录,abc.com和mail.abc.com不是同一台主机的话,忘了MX记录会出很多这样那样的问题,过后在解决故障的过程中把它加上。但愿意做反向解析的管理员是少之又少,在国外,很多UNIX主机会检查你发邮件时使用的域名,如果反向解析不通,你的邮件就会被“咔嚓”。
  那么我们做了这些解析是不是发邮件给新浪、网易、搜狐、163.net和263就没问题了?当然不是!!!!
  用新浪来说吧,新浪的邮件是两套系统:收费和免费,两套系统的MX地址也不一样。免费的后缀为@sina.com,收费的为@vip.sina.com。免费邮件系统除了在邮箱容量上的限制,还会在邮件数目做做出限制:即在一段时间范围内,如果从同一IP发到新浪免费邮箱的邮件数量超过了一定的数目限制,该IP地址将会被免费邮件系统封锁,封锁时间内就无法发送邮件到新浪免费邮件系统。
  大概过15-20分钟之后,如果该IP地址没有再往它那发送邮件,该IP地址将会自动从IP地址列表中删除。另:这个问题是在8月初总结的,现在新浪的收费邮件系统有没有这个规则没问过新浪。
  如果你的IP在规定的时间内没有解除封锁,那就边哭边给新浪的管理员打电话吧,给他说:大哥,我求你了,你就当我是个屁,把我放了吧……
  这个规则不仅新浪有,搜狐、163、263等都有。这是一个防止垃圾邮件的好方法,但也造成邮件列表无法正常发送。用以上邮箱收不到很多服务商的邮件列表就是这个原因。
  这个规则是管理员在服务器上做的设置,普通用户暂时别想。使用IMail的管理员可以让你的老板花银子买Declude插件来实现这个功能。


尝试以下排错方法:
1. Ping 邮件服务器的FQDN名字,并确认是否可以解析出所对
应的IP地址。
如果不能,在Internet DNS服务器上是否有邮件服务器的
A记录

2.通过NSlookup查询是否为所有能够向外直接发送邮件的
邮件服务器添加了MX记录

http://mail.sina.com.cn/FAQ.html#q3
1.为什么新浪服务器会产生553的退信信息?
这是由于邮件发送方服务器的HELO域设置不规范造成的。如果新浪服务器无法对该域进行正确的DNS解析, 将会导致新浪反垃圾系统认为该服务器是垃圾邮件发送者从而拒收. 不规范的HELO域的示例如下:

HELO office
HELO mailserver
HELO localhost.localdomain

解决方法: 参考本文档后半部分提供的设置方法,正确设置贵方SMTP服务器的HELO域, 使新浪能过对该域名进行正确的DNS解析

2.SMTP服务器能否设置为公司内网的域名?
请设置贵公司的服务器对外发送的HELO域为正确的贵公司域名,否则将因为和第一条同样的原因造成新浪拒收。


3.SMTP服务器的HELO域已设置正确,怎么还产生553的退信信息?
这是由于发邮件服务器在内网的某个网段中。如果邮件经防火墙发送, 而防火墙没有对邮件的源IP地址进行映射, 新浪的服务器就会认为防火墙的IP是发件方SMTP服务器的IP地址,而邮件源IP地址与HELO域名MX解析不一致. 这种情况也会使新浪拒收邮件。解决方法: 使HELO后面的域名MX解析为防火墙的IP地址, 或者使防火墙把经过它的邮件的IP映射为其真正的IP地址, 即不要改变邮件的源IP地址.


4.SMTP服务器的HELO域能否包含特殊字符?
不可以。如果发邮件服务器的HELO域中包含有无法识别的字符, 就会导致新浪对其DNS解析失败, 从而拒绝接收其邮件.
包含有无法识别字符的HELO域示例: eev?bj?md02.vatech


5.国外网站应如何正确设置SMTP服务器?
新浪要求所有中国大陆境外的CMTP服务器必须提供反向DNS解析。对于中国境外的CMTP服务器,如果不提供反向DNS解析,新浪将认为该服务器为垃圾邮件发送者的服务器并拒收该地址发来的邮件。
解决方法: 注册SMTP服务器公网IP地址的RDNS服务, 并把它对应的域名写到服务器的HELO域中.


6.MS Exchange2000服务器HELO域的设置方法
具体位置在: SERVER---主名---SMTP---DEFAULT SMTP VIRTUAL---属性---DELIVERY---ADVANCED---MASQUERADE NAME


7.Notes服务器HELO域的设置方法
具体位置在:服务器---基本---全限定的Internet主机名

8.imail的HELO应该是 localhost 的general面板上的 Host Name
如Host Name这里是HI.com 那么imail 所用的就是helo HI.com
另外 Imail管理面板-》服务-》SMTP-》advance->Hello Message->HIi.com 只不过修改是smtp的banner信息

总的来说,给163,sina发送不正常都是对方反垃圾的问题。

以上引用来自:http://bbs.51cto.com/archiver/tid-92580.html
lsk 2008-08-07
我想问下lz:

为什么要起邮件服务器? 因为需要给用户或者客户发邮件.ok问题来了.你起的邮件服务器发出去的邮件都被163,或者sohu,sina认为是垃圾邮件.包括gmail,msn都有可能. 这个问题你是怎么处理的?
myy 2008-08-07
zhai puhong 写道
myy 能不能详细的讲一讲这个基本机制呢。

简单说,就跟现实中的邮局类似。

http://homepage.scau.edu.cn/club/sugh/ReadNews.asp?NewsID=282
zhai puhong 2008-08-07
myy 能不能详细的讲一讲这个基本机制呢。
zhuyx808 2008-08-06
引用
这些都是邮件服务器最基本的工作机制,根本用不着你操心。


我对邮件服务器了解不是很多,但是老大给布置的N个课外研究课题中就其中就有我说的这个哦,他们自己架起来的邮件服务器,有这个课题就说明了肯定有我说的这个问题的存在,可能我比较孤陋,还请多指点
myy 2008-08-06
zhuyx808 写道
我想问一下,假如我架构了一个服务器,我能不能控制这个服务器什么时候发送,什么时候接收那?具体点就是:在一个邮件服务器中,不同时间段的发送(接收)的邮件数不同,我想在邮件过多的时候就把一些邮件给缓下来,等到空闲的时候在发送,也就是把各个时间段的邮件给平均一下,不至于有时候服务器忙的要死有时候又没事干


这些都是邮件服务器最基本的工作机制,根本用不着你操心。
zhai puhong 2008-08-06
zhuyx808 这个问题我还没想到,感谢你给我指出了方向
zhuyx808 2008-08-06
我想问一下,假如我架构了一个服务器,我能不能控制这个服务器什么时候发送,什么时候接收那?具体点就是:在一个邮件服务器中,不同时间段的发送(接收)的邮件数不同,我想在邮件过多的时候就把一些邮件给缓下来,等到空闲的时候在发送,也就是把各个时间段的邮件给平均一下,不至于有时候服务器忙的要死有时候又没事干
zhai puhong 2008-07-28
地址已经更改过来了,见凉,编辑的时候一时没考虑周全,那个地址只有我自己可以访问^_^
deepsea0001 2008-07-27
非常棒的文章!期待下文。。。
再有:http://zhaipuhong.javaeye.com/admin/blogs/213005
楼主的这个地址打不开,很想看一下,不知道哪里还有这文章
sp42 2008-07-22
谢谢 帮助我学习James,期待(二)!
zhenjia 2008-07-14
thanks 期待(二)!
发表评论

提醒: 该博客已发表在公共论坛,博客所有留言会成为论坛回贴,留言请注意遵守论坛发贴规则

您还没有登录,请登录后发表评论

zhai puhong
搜索本博客
我的相册
E0a7b3bb-231d-3450-9fc0-34d40819425a-thumb
decoratorpattern_standar
共 2 张
最近加入圈子
存档
最新评论