James+Javamail构建邮件服务

James+Javamail构建邮件服务

本文描述如何使用James搭建具备一定邮件过滤、邮件操作功能的邮件服务器,以及使用Javamail实现对James服务器邮件的收发功能。

1 关于James与Javamail

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

  Javamail API是一个用于阅读、编写和发送电子消息的可选包(标准扩展),可以用来建立基于标准的电子邮件客户机,它支持各种因特网邮件协议,包括:SMTP、POP、IMAP、MIME、NNTP、S/MIME及其它协议。

  在本文档中,我们使用James 2.3.1+Javamail 1.4.1作为介绍蓝本。

2 James服务器快速入门

  我们可以从Apache James 的官方站点下载到我们所需要的James服务器及源码

  James服务器(ZIP版)下载地址:

  http://apache.mirror.phpchina.com/james/server/binaries/james-binary-2.3.1.zip

  James源码下载地址:

  http://apache.mirror.phpchina.com/james/server/source/james-2.3.1-src.zip

  其他版本的服务器及源码可到官方下载页面下载:

  http://james.apache.org/download.cgi

2.1 启动James

第一步:

  将james-binary-2.3.1.zip解压到纯英文目录下

第二步:

  运行bin目录下的run.bat(在运行之前请确保您的Java环境变量已配置成功,否则将提示运行失败)

显示以下内容表示James服务器已启动成功:

服务器启动成功后,将自动在apps目录下根据james.sar文件生成相应的James发布文件包,我们后面讨论的配置文件config.xml即存在于此发布文件包中。

2.2 用Telnet管理用户

  用cmd进入MS-DOS,输入telnet localhost 4555 (注:localhost是邮件服务器名,4555是管理端口,可在\apps\james\SAR-INF\config.xml文件中配置,在此我们使用其默认配置)

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

出现如下信息说明登陆成功:

登陆成功后,我们就可以开始对用户信息进行增、删、查、改等操作了。

常用的用户信息操作命令参见下表:

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

  我们可以输入命令:adduser chenfengcn 881213来添加一个的邮件用户,则其用户名为:chenfengcn,密码为:881213,邮箱地址为:chenfengcn[email protected](用户名后的域名跟服务器配置的域名相同,在config.xml文件中配置,我们将在后面部分讨论如何配置邮件服务器域名)。这样,我们就完成了一个最简单的邮件服务器的搭建操作。下面就让我们使用Foxmail来测试一下我们的邮箱帐户是否真正可以使用吧。

2.3 使用Foxmail测试邮箱帐户

  打开Foxmail,点击“邮箱”->“新建邮箱帐户”

  电子邮件地址:[email protected]

  密码为:881213

  POP3服务器:localhost

  SMTP服务器:localhost

  其余选项均使用默认即可,新建完成后,Foxmail将发送一测试邮件到我们新建的邮箱里,点击“收取”,即可收取我们邮件帐户里面的邮件了。当收到Foxmail发送的测试邮件,就说明我们的邮件帐户可以正常使用了。

  作为程序设计人员,我们当然希望能使用自己写的程序来测试我们的邮件服务器是否搭建成功,而不是Foxmail。下面就让我们用Javamail来实现这一切吧。

3
Javamail快速入门

  进行Javamail开发需要用到两个包:mail.jar和activation.jar,在开始Javamail编程之前,请自己将这两个包添加到IDE的Build
path中或将这两个包的路径配置到环境变量中。

3.1 使用Javamail向James的邮箱帐户发送邮件

3.1.1 业务描述

  本例将使用Javamail实现邮件的发送功能。发送邮件需要配置邮件服务器属性信息,配置邮件接收地址,使用SMTP认证获得会话(Session),构建邮件体(MimeMessage),发送邮件。具体编码如下:

3.1.2 编码实现

  发送邮件需要两个类:一个是SMTP用户身份认证类(James在默认情况下,是需要SMTP身份认证的);另一个就是我们的邮件发送类,为简单起见,我们直接将邮件的相关信息,如:标题、内容、发送者、接收者等信息直接写在类中,运行main()函数即发送。当然,你同样可以为自己的邮件发送系统构造一个邮件发送介面,通过Servlet将相关参数传递至后台进行处理与发送。其主要代码也就是此main()函数中的内容,故不赘述。

SmtpAuth.java用户身份认证代码

Java代码

  1. package com.newland.javamail.sample1;
  2. class SmtpAuth extends javax.mail.Authenticator {
  3. private String user, password;
  4. public void setUserinfo(String getuser, String getpassword) {
  5. user = getuser;
  6. password = getpassword;
  7. }
  8. protected javax.mail.PasswordAuthentication getPasswordAuthentication() {
  9. return new javax.mail.PasswordAuthentication(user, password);
  10. }
  11. public String getPassword() {
  12. return password;
  13. }
  14. public void setPassword(String password) {
  15. this.password = password;
  16. }
  17. public String getUser() {
  18. return user;
  19. }
  20. public void setUser(String user) {
  21. this.user = user;
  22. }
  23. }

SendMail.java发送邮件代码

Java代码

  1. package com.newland.javamail.sample1;
  2. import java.util.Properties;
  3. import javax.activation.DataHandler;
  4. import javax.activation.DataSource;
  5. import javax.activation.FileDataSource;
  6. import javax.mail.Message;
  7. import javax.mail.MessagingException;
  8. import javax.mail.Session;
  9. import javax.mail.Transport;
  10. import javax.mail.URLName;
  11. import javax.mail.internet.AddressException;
  12. import javax.mail.internet.InternetAddress;
  13. import javax.mail.internet.MimeBodyPart;
  14. import javax.mail.internet.MimeMessage;
  15. import javax.mail.internet.MimeMultipart;
  16. public class SendMail {
  17. public SendMail() {
  18. // TODO Auto-generated constructor stub
  19. }
  20. public static void main(String[] args) {
  21. // 初始化信息
  22. String sender = "chenfengcn";
  23. String password = "881213";
  24. String smtpServer = "localhost";
  25. String recipient = "[email protected]";
  26. String subject = "测试邮件主题";
  27. String fileAttachment = "";   //附件
  28. String content = "测试邮件内容";
  29. // 配置服务器属性
  30. Properties proper = new Properties();
  31. proper.put("mail.smtp.host", smtpServer); // smtp服务器
  32. proper.put("mail.smtp.auth", "true"); // 是否smtp认证
  33. proper.put("mail.smtp.port", "25"); // 设置smtp端口
  34. proper.put("mail.transport.protocol", "smtp"); // 发邮件协议
  35. proper.put("mail.store.protocol", "pop3"); // 收邮件协议
  36. // 配置邮件接收地址
  37. InternetAddress[] receiveAddress = new InternetAddress[1];
  38. try {
  39. receiveAddress[0] = new InternetAddress(recipient);
  40. catch (AddressException e) {
  41. // TODO Auto-generated catch block
  42. e.printStackTrace();
  43. }
  44. // smtp认证,获取Session
  45. SmtpAuth sa = new SmtpAuth();
  46. sa.setUserinfo(sender, password);
  47. Session session = Session.getInstance(proper, sa);
  48. session.setPasswordAuthentication(new URLName(smtpServer), sa
  49. .getPasswordAuthentication());
  50. // 构建邮件体
  51. MimeMessage sendMess = new MimeMessage(session);
  52. MimeBodyPart mbp = new MimeBodyPart();
  53. MimeMultipart mmp = new MimeMultipart();
  54. try {
  55. // 邮件文本内容
  56. mbp.setContent(content, "text/plain; charset=GBK");
  57. mmp.addBodyPart(mbp);
  58. // 附件处理
  59. if(fileAttachment!=null&&fileAttachment!=""){
  60. DataSource source = new FileDataSource(fileAttachment);
  61. String name = source.getName();
  62. mbp = new MimeBodyPart();
  63. mbp.setDataHandler(new DataHandler(source));
  64. mbp.setFileName(name);
  65. mmp.addBodyPart(mbp);
  66. }
  67. // 邮件整体
  68. sendMess.setSubject(subject);
  69. sendMess.setContent(mmp);
  70. // 发送邮件
  71. sendMess.setFrom(new InternetAddress(sender));
  72. sendMess.setRecipients(Message.RecipientType.TO, receiveAddress);
  73. Transport.send(sendMess);
  74. System.out.println("发送成功");
  75. catch (MessagingException ex) {
  76. ex.printStackTrace();
  77. }
  78. }
  79. }

值得一提的是,本程序已经实现了带附件邮件的发送功能,如果要发送带附件的邮件,则只需要将附件的路径传到fileAttachment变量中就可以了。邮件发送成功后,程序将在后台打印出“发送成功”,这样我们就完成了邮件发送功能。那么,我们应该如何检验服务器是否确实收到我们发送的测试邮件呢?Javamail可以发送邮件,当然也能接收邮件啦,下面让我们一起使用Javamail编写邮件接收功能来检验吧。

3.2 使用Javamail接收邮件

3.2.1 业务描述

  在上一节,我们已经向James的chenfengcn用户发送了一封测试邮件,我们应该如何使用Javamail来收取这封邮件呢?

  为读取邮件,必须首先设置服务器属性(Properties),获取一个会话(Session),然后获取并连接邮箱所在的存储器(Store对象),打开该用户的邮箱(Folder),获取所希望阅读的消息,最后关闭目录和连接。

  下面的程序实现了接收[email protected]邮箱中所有邮件,并将发送人和主题打印出来。

3.2.2 编码实现

Java代码

  1. package com.newland.javamail.sample1;
  2. import java.util.Properties;
  3. import javax.mail.Folder;
  4. import javax.mail.Message;
  5. import javax.mail.MessagingException;
  6. import javax.mail.NoSuchProviderException;
  7. import javax.mail.Session;
  8. import javax.mail.Store;
  9. public class ReceiveMail {
  10. public ReceiveMail() {
  11. }
  12. public static void main(String[] args) {
  13. // 初始化主机
  14. String host = "localhost";
  15. String username = "chenfengcn";
  16. String password = "881213";
  17. // 配置服务器属性
  18. Properties props = new Properties();
  19. props.put("mail.smtp.host", "localhost"); // smtp服务器
  20. props.put("mail.smtp.auth", "true"); // 是否smtp认证
  21. props.put("mail.smtp.port", "25"); // 设置smtp端口
  22. props.put("mail.transport.protocol", "smtp"); // 发邮件协议
  23. props.put("mail.store.protocol", "pop3"); // 收邮件协议
  24. // 获取会话
  25. Session session = Session.getDefaultInstance(props, null);
  26. // 获取Store对象,使用POP3协议,也可能使用IMAP协议
  27. try {
  28. Store store = session.getStore("pop3");
  29. // 连接到邮件服务器
  30. store.connect(host, username, password);
  31. // 获取该用户Folder对象,并以只读方式打开
  32. Folder folder = store.getFolder("inbox");
  33. folder.open(Folder.READ_ONLY);
  34. // 检索所有邮件,按需填充
  35. Message message[] = folder.getMessages();
  36. for (int i = 0; i < message.length; i++) {
  37. // 打印出每个邮件的发件人和主题
  38. System.out.println(i + ":" + message[i].getFrom()[0] + "\t"
  39. + message[i].getSubject());
  40. }
  41. folder.close(false);
  42. store.close();
  43. catch (NoSuchProviderException e) {
  44. // TODO Auto-generated catch block
  45. e.printStackTrace();
  46. catch (MessagingException e) {
  47. // TODO Auto-generated catch block
  48. e.printStackTrace();
  49. }
  50. }
  51. }

程序运行成功后,将会把chenfengcn用户的邮件从James服务器中取出,并将此邮箱中所有邮件的发件人、主题打印在后台。若要打印该邮件的内容等信息,则只要将message[i]对象中的邮件内容等信息读取出来就可以了。

  注:鉴于邮件的存储结构(将在第五章介绍),读取邮件附件是一个比较复杂的过程,因为邮件的文本内容和附件信息都是保存在BodyPart对象中的,BodyPart用于标识类型的标记不明确,造成对附件的判断较为复杂。对于附件的操作本人将在今后的改进版本中加以介绍。

4 Mailet快速入门

  Mailet
API是一个用来创建邮件处理程序的简单的API,它被配置在邮件服务器端执行,分匹配器Matcher和Mailet的接口两种,匹配器根据特定的条件匹配邮件消息,并触发相应的Mailet.

  Mailet这个词是跟Servlet相似,功能也相似,他们的共同之处都是在服务器端触发并执行,只是Servlet的Matcher通常是url的pattern,跟Servlet的接口一样,Mailet也有init()方法,service()方法和destroy()方法.即他们都有类似的生命周期. Mailet的简单可编程接口可以用来做一些邮件处理,比如反垃圾邮件,检查邮件病毒以及邮件博客等等,利用移动设备可发送email的功能,可以做到手机通过mail发送信息到邮件服务器交给Mailet处理,形成移动博客的模型.

  Mailet的运行需要mailet-2.3.jar和mailet-api-2.3.jar两个包的支持,James本身就有这两个包,可不作修改,但在开发的时候还是需要开发者自己将这两个包导入到工程的Build path中或配置到系统环境变量中。

4.1 用Mailet做一个Hello的例子

4.1.1 业务描述

  我们要实现当外部发送给James服务器中名字含hello的邮箱时,服务器在这封邮件的主题前加入“Hello”,并在服务器后台输出“Received a piece of Email”。如前所述,Mailet包括匹配器Matcher和Mailet两种接口,现在就让我们用Mailet API实现这两个接口吧。

4.1.2 编码实现

匹配器BizMatcher.java

Java代码

  1. package com.newland.james.mailet.sample1;
  2. import org.apache.mailet.GenericRecipientMatcher;
  3. import org.apache.mailet.MailAddress;
  4. public class BizMatcher extends GenericRecipientMatcher {
  5. public boolean matchRecipient(MailAddress recipient) {
  6. // 邮件地址必须包含hello的
  7. if (recipient.getUser().indexOf("hello") != -1) {
  8. return true;
  9. }
  10. return false;
  11. }
  12. }

BizMaillet.java

Java代码

  1. package com.newland.james.mailet.sample1;
  2. import java.io.IOException;
  3. import javax.mail.MessagingException;
  4. import javax.mail.internet.MimeMessage;
  5. import org.apache.mailet.GenericMailet;
  6. import org.apache.mailet.Mail;
  7. public class BizMaillet extends GenericMailet {
  8. public void init() throws MessagingException {
  9. }
  10. public void service(Mail mail) throws MessagingException {
  11. MimeMessage mmp;
  12. mmp = (MimeMessage) mail.getMessage();
  13. mmp.setSubject("Hello "+mmp.getSubject());
  14. System.out.println("Received a piece of Email");
  15. }
  16. }

4.1.3 配置部署

  Mailet跟Servlet一样,是服务器端程序,是不能直接在客户端运行的,必须要部署到服务器端方可生效。部署具体步骤如下:

1、 将我们编写的Matcher和Mailet打包成jar文件;

2、在\james-2.3.1\apps\james\SAR-INF目录下新建一个lib文件夹;

3、 将打包好的jar文件复制到刚刚新建的lib文件夹下;

4、 打开config.xml配置文件,找到以下这段代码:

Xml代码

  1. <</span>mailetpackages>
  2. <</span>mailetpackage>org.apache.james.transport.mailets</</span>mailetpackage>
  3. <</span>mailetpackage>org.apache.james.transport.mailets.smime</</span>mailetpackage></</span>mailetpackages>
  4. <</span>matcherpackages>
  5. <</span>matcherpackage>org.apache.james.transport.matchers</</span>matcherpackage>
  6. <</span>matcherpackage>org.apache.james.transport.matchers.smime</</span>matcherpackage></</span>matcherpackages>

前半部分是用于配置Mailet包所在位置,后半部分是用于配置Matcher包所在位置,我们把我们刚编写的Mailet和Matcher所在位置配置进去就可以了。配置后的结果如下:

Xml代码

  1. <</span>mailetpackages>
  2. <</span>mailetpackage>com.newland.javamail.sample1</</b>mailetpackage>
  3. <</span>mailetpackage>org.apache.james.transport.mailets</</span>mailetpackage>
  4. <</span>mailetpackage>org.apache.james.transport.mailets.smime</</span>mailetpackage>
  5. </</span>mailetpackages>
  6. <</span>matcherpackages>
  7. <</span>matcherpackage>com.newland.javamail.sample1</</b>matcherpackage>
  8. <</span>matcherpackage>org.apache.james.transport.matchers</</span>matcherpackage>
  9. <</span>matcherpackage>org.apache.james.transport.matchers.smime</</span>matcherpackage>
  10. </</span>matcherpackages>

  这样就完成了包的配置。我们都知道,Mailet的工作过程是:首先由Matcher来匹配所接收到的邮件,然后提交给相应的Mailet处理,但是哪个匹配器对应哪个Mailet呢?我们还需要配置Mailet的对应关系。同样在config.xml中找到下面的代码:

Xml代码

  1. <</span>mailet match="All" class="PostmasterAlias"/>

在这段代码下面加入我们自己的Mailet:

Xml代码

  1. <</span>mailet match="All" class="PostmasterAlias"/>

Xml代码

  1. <</span>mailet match="BizMatcher" class="BizMaillet"/>

这样就完成了我们自定义的Mailet的配置部署工作了。重启James服务器,则此Mailet即可生效。

4.1.4 测试Mailet

  前面我们已经完成了Mailet的编码和部署工作,现在就让我们来测试一下我们的Mailet是否生效吧。首先,需要在James服务器上新建一个名称含Hello的用户。前面已介绍过新建用户的方法了,在此就不重复叙述了。

  使用adduser helloworld 881213命令新建一个helloworld用户。

  使用第三章所谈及的“使用Javamail向James的邮箱帐户发送邮件”来向[email protected]发送一封邮件(当然,你同样可以使用Foxmail或Outlook向此地址发送邮件),邮件发送成功后,James服务器后台将输出“Receive a piece of email”。运行效果如下图所示:

时间: 2024-10-21 23:44:05

James+Javamail构建邮件服务的相关文章

JavaMail(JAVA邮件服务) API详解

一.JavaMail API简介JavaMail API是读取.撰写.发送电子信息的可选包.我们可用它来建立如Eudora.Foxmail.MS Outlook Express一般的邮件用户代理程序(Mail User Agent,简称MUA).而不是像sendmail或者其它的邮件传输代理(Mail Transfer Agent,简称MTA)程序那样可以传送.递送.转发邮件.从另外一个角度来看,我们这些电子邮件用户日常用MUA程序来读写邮件,而MUA依赖着MTA处理邮件的递送.在清楚了到MUA

james+javamail入门

James+Javamail构建邮件服务(一) 本文描述如何使用James搭建具备一定邮件过滤.邮件操作功能的邮件服务器,以及使用Javamail实现对James服务器邮件的收发功能. 1关于James与Javamail Apache James(Java Apache Mail Enterprise Server)是Apache组织的子项目之一,完全采用纯Java技术开发,实现了SMTP.POP3与NNTP等多种邮件相关协议.James是一个 邮件应用平台,可以通过Mailet扩充其功能,如M

搭建Apache James邮件服务

什么是邮件服务器 邮件服务器是一种用来负责电子邮件收发管理的设备,而邮件服务就是责邮件的收信和发信功能,其最主要有pop和smtp两个协议.关于这两个协议,有着很多的知识点涵盖其中,这里不过多介绍.下面是我接触过的两个可以实现邮件服务的解决方案. 1.易邮邮件服务 在windows系统下,可以使用 易邮邮件服务 ,这个服务器简单而且实用,用在平时开发,测试或者局域网间的邮件收发还是挺方便的,不过我没有找到官方的,可以将易邮邮件服务安装在Linx的相关资料,因此不使用这个.这是易邮邮件服务的官方网

Java邮件服务学习之一:邮件服务概述

java可以提供邮件服务:一般理解的邮件服务就是可以发送和接收邮件的客户端,但是使用java编写邮件服务端: 一.邮件客户端: web应用根据依赖的API,常用的有两种: 第一种:J2EE中提供的java mail API(javax.mail.*) Javamail API是一个用于阅读.编写和发送电子消息的可选包(标准扩展),可以用来建立基于标准的电子邮件客户机,它支持各种因特网邮件协议,包括:SMTP.POP.IMAP.MIME.NNTP.S/MIME及其它协议. 第二种:spring 对

电商邮件服务平台性能优化谈

从今年一月份开始,团队陆续完成了邮件服务的架构升级.新平台上线运行的过程中也发生了一系列的性能问题,即使很多看起来微不足道的点也会让整个系统运行得不是那么平稳,今天就将这段时间的问题以及解决方案统一整理下,希望能起到抛砖的作用,让读者在遇到类似问题的时候能多一个解决方案. 新平台上线后第一版架构如下: 这版架构上线后,我们遇到的第一个问题:数据库读写压力过大后影响整体服务稳定. 表现为: 1.数据库主库压力高,同时伴有大量的读,写操作. 2.远程服务接口性能不稳定,业务繁忙时数据库的插入操作延迟

邮件服务(三):实践服务器搭建

背景 邮件服务系列博文中,前两篇介绍了邮件系统的基本功能和安全体系,本文记录了搭建邮箱服务器的实践. Sendmail 是一种多用途.支援多种协定的跨网络电子邮件传送代理软件,于 1983 年随着 BSD 4.1c 首次发行,2001 年时的调查,互联网上的邮件服务器有 42%使用 Sendmail,但之后由于多次被发现重大的安全性漏洞,且其设定档过于复杂造成较高的学习门槛等因素,导致市占率下滑. Postfix 被 Wietse Zweitze Venema 创造出来以取代 Sendmail.

构建微服务:Spring boot 入门篇

构建微服务:Spring boot 入门篇 什么是spring boot Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程.该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置.用我的话来理解,就是spring boot其实不是什么新的框架,它默认配置了很多框架的使用方式,就像maven整合了所有的jar包,spring boot整合了所有的框架(不知道这样比喻是否合适). 使用spring boot有什

JavaMail 保证邮件发送成功的方法总结

使用过JavaMail的api发送邮件的人可能会有这样一个疑惑:我如何知道我调用该api发送的邮件是否成功呢?一般的开放的api给我们调用都会有个返回值或者状态码,来告诉我们执行成功与否.但是JavaMail却没有提供这样一个返回值. 所以在调用JavaMail发送邮件的时候,我们只能通过catch异常的方式来判断邮件是否发送成功.我们认为只要没有异常发生,那么邮件就能发送成功.那么我们就来分析一下JavaMail为什么没有提供返回值,和通过异常判断邮件发送成功状态是否靠谱. JavaMail发

邮件服务实现

pom.xml <!-- 邮件发送 --> <dependency> <groupId>javax.mail</groupId> <artifactId>mail</artifactId> <version>1.4.1</version> </dependency> EmailService package net.deniro.email; /** * 邮件服务 * * @author denir